Java内存数据模型
本篇文章带来的是对Java内存数据模型的介绍,这对于我们深入理解Jvm虚拟机工作的原理和Java内存的划分大有裨益,好了,为了让我们理解的更为深刻,我们将会加入图片辅助的方法去理解。
本篇博文的目录:
一:Java内存数据模型的介绍
二:线程私有内存
三:程序计数器
四:Java虚拟机栈
五:本地方法栈
六:Java堆
七:方法区
八:运行时常量池
九:总结
一:java内存数据模型的介绍
java程序在运行的时候会在内存中开辟不同的空间用以管理不用的内存区域,每个区域都有自己的功能,创建和销毁时间,有的区域会随着虚拟机的启动而创建,而有的区域会随着用户线程的创建而销毁。按照空间,分为如下不同的空间,接下来我们将按照不同的区域进行学习,学习它不同区域的功能和用法
图 1-1 :java内存数据模型
二:线程私有内存
我们先来看一下多线程运行原理:其实cpu在运行的时候每次在同一特定的时间点只能运行一个线程(单核的情况下),只不过它切换的速度非常之快,让我们觉的它是在进行多线程运行,本质上它还是单一运行的。所以这就会必然引出一个问题:cpu切换线程如何保证它自身的运行不受其他的线程影响,保证每个线程都是独立不受外部侵扰的,这就产生了线程私有内存这个概念,主要是维持线程的安全、稳定、高效的运转。关于这一点也很好理解,比如我们去一个快速餐厅吃饭,我们点好了菜,会产生菜单小票,这个小票上面有编号,就是每个线程的“私有内存”,服务员再进行不同顾客上菜的时候就有了区分度,这样就可以顺利找到不同的顾客(切换不同的线程);在java线程中,程序计数器、虚拟机栈、本地方法栈都属于线程私有的。
注意点:线程私有不存在多线程并发的资源竞争问题,因为其享有的内存是互不影响的,不存在并发问题
与线程私有相对,就有线程公有内存,这个区域在jvm虚拟机中有个特定的称呼叫做:主内存
三:程序计数器:
对应于图上标记的深红色部分,主要是指程序在运行过程中所执行的字节码(.class)文件的行号指示,也称作行号指示器,程序流程的分支、循环、异常处理等基础功能都需要它的引导来完成。它占有的内存空间比较小,它的运行的原理是:通过改变计数器的值来选取下一条的需要执行的字节码命令,而这个值具体指的是虚拟机在Java方法中字节码指令的地址,但是如果执行的是Native方法,那么它的计数器的值是为空的。
注意:
1:它是java中唯一一个没有内存溢出(out of memory)情况的区域。可以思考一下这点是为什么?它是进行线程运行的指示灯,如果没有了它,程序也就无法运行了。
2:它属于线程私有的:每个线程内部都有一个程序计数器,为了保证每个线程切换前后都能正常运行。
四:Java虚拟机栈:
虚拟机栈主要是作用在java方法运行时候,每个线程在运行到一个方法的入口都会创建一个栈帧,创建栈帧的目的在于存储局部变量、操作数栈、动态链接、方法出口等信息。按照这个原理,那么一个方法在从调用直到完全执行完毕,都会对应一个从入栈到出栈的过程。
这里我们说明一下局部变量,它的含义就是定义在java方法内部中的变量,对应于java中8大基本数据类型,byte、int、float、boolean、char、short、long、reference:(long和double占用2个空间,其余1个)局部变量表里我们需要注意的是,它在编译期已经完全了内存分配,这样栈帧在用局部变量的时候,它占用的内存是已经确认的,不需要再分配,这就一定程度上减少了栈帧的工作量。
注意:
1:当线程请求的栈帧的深度大于虚拟机允许的深度,就会抛出stackOverFlow异常
2:我们平时所说的堆栈,其中的栈就是指的是这里的栈帧
3:它也是线程私有的,并且和线程的生命周期相同。
图 2-1:虚拟机栈
五:本地方法栈:
本地方法栈,顾名思义它代表的就是本地方法Native执行的栈帧,在jdk的源码中我们可以看到很多命名为Native的方法,Native方法很大一部分是采用C/C++写的,但是它对Native采用的数据结构、语言等都没有做具体的要求,这一点完全是由java虚拟机进行实现的。
注意:
1:这个区域会抛出oom或者sof(stackoverflowError)异常
2:同样它属于本地线程私有的
六:Java堆:
Java堆主要是存储对象的地方,同时它也是java内存管理区域最大的一块。当我们在程序中new一个对象出来或者新建一个数组,就会把对象存储这个区域。它是java的最重要的公共区域之一,与线程私有相对,它是属于线程公有的。基本上所有的对象都会存储在此区域,但也不是绝对的(随着JIT技术的成熟,这一点会发生微变)。堆是主要存放对象的地方,同时它就会产生另一个问题就是GC(Garbage Collection),当垃圾进行回收的时候,虚拟机并没有开辟新的空间,还在此区域进行,同时这个区域也叫“GC堆”,再细致划分下去,分为新生代、老年代,同时还分为Eden空间、From survivor空间、To Survior区域。为什么要划分的这么细致呢?其实是为了更加有效率的回收,划分的区域越细致,那么垃圾回收器收集的时候只要去对应的地方直接回收就行,不用加上额外的判断逻辑。
注意点:
1:堆在逻辑上是连续不间断的内存空间,但是在物理上可以是不连续的内存空间
2:在堆中如果没有完成内存的实例分配就会抛出oom
3:java堆是线程公有的,所有的线程共享这一片区域
图 3-1 java堆内存
七:方法区
方法区主要是用来存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,比如我们在代码中定义的Constant常量就会在这个区域存储。在java虚拟机规范中,它是属于堆的逻辑部分。同时在这个区域中,它也会有垃圾回收器工作,这个区域叫做“永久代”,之所以叫做永久代,因为它比新生代和老年代拥有更长的生命周期,但是并不是在这个区域它就会万事大吉了,永久代依然会存在垃圾回收的情况,只不过相对来说较少
注意点:
1:此区域属于线程公有的,线程的类信息、常量、静态变量、编译代码都在此区域进行存储
2:此区域会抛出oom异常,发生在方法区无法进行内存分配时
图:4-1 方法区
八:运行时常量池:
运行时常量池主要是方法区的一部分,class文件除了有类的版本、字段、方法接口等描述信息外,还有一项信息是常量池,用于存储编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区运行时常量池中存放。
注意:此区域同样会发生oom异常
九:总结
本篇博文主要是对java的内存数据模型区域划分进行了简单的介绍,没有深入细致过多的介绍。不过我们在整体上有一个感性的认识,理解java内存区域的划分,以及这样的划分的好处,还有设计到线程的部分,理解并发的问题。这部分属于虚拟机底层的东西,属于进阶。相信看完这篇文章后,我希望能回答以下几个问题。同时这些东西也是考究我们对于底层的认识,面试中也是经常会被提及到的东西
1:java内存模型分为哪几个区域?
2:请说出属于线程私有部分和线程公有部分的区域?
3:我们都知道内存是在按照“代”进行划分的,那么请问java堆中内存分为哪几代?分别位于什么区域?
4:为什么要把java内存划分这么多,划分这么多不嫌麻烦吗?有什么好处
我希望能思考以上问题,学习的时候就要进行多思考,深入思考这是为什么?这篇博文的介绍就到此结束了,下一篇见,对于java内存模型的理解有助于我们处理并发的问题,这是属于javaEE中高端进阶必不可少的基础,在此留个记录,同时分享出来,让大家也能清楚的认识Java内存模型同时提醒自己深入理解。
主要参考资料:
《深入Jvm虚拟机》
Java内存数据模型的更多相关文章
- Java内存溢出
中间件应用Java内存溢出常见的三种情况: 1.OutOfMemoryError: Java heap space 2.OutOfMemoryError: PermGen space 3.OutOfM ...
- JVM学习(3)——总结Java内存模型
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 为什么学习Java的内存模式 缓存一致性问题 什么是内存模型 JMM(Java Memory Model)简 ...
- 浅析java内存模型--JMM(Java Memory Model)
在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步? 在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的. 线程之间通过共享程序公共的状态,通 ...
- JMM(java内存模型)
What is a memory model, anyway? In multiprocessorsystems, processors generally have one or more laye ...
- 《深入理解Java内存模型》读书总结
概要 文章是<深入理解Java内容模型>读书笔记,该书总共包括了3部分的知识. 第1部分,基本概念 包括"并发.同步.主内存.本地内存.重排序.内存屏障.happens befo ...
- java内存泄漏的几种情况
转载于http://blog.csdn.net/wtt945482445/article/details/52483944 Java 内存分配策略 Java 程序运行时的内存分配策略有三种,分别是静态 ...
- java内存区域简介
运行时数据区域 1.程序计数器:是一块较小的内存空间,可以看做当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改变计数器的值来选取下一条需要执行的字节码指令,分支.循环.跳转.异常处理. ...
- cache4j轻量级java内存缓存框架,实现FIFO、LRU、TwoQueues缓存模型
简介 cache4j是一款轻量级java内存缓存框架,实现FIFO.LRU.TwoQueues缓存模型,使用非常方便. cache4j为java开发者提供一种更加轻便的内存缓存方案,杀鸡焉用EhCac ...
- Java内存模型深度解析:final--转
原文地址:http://www.codeceo.com/article/java-memory-6.html 与前面介绍的锁和Volatile相比较,对final域的读和写更像是普通的变量访问.对于f ...
随机推荐
- node-webkit学习之【无边框窗口用JS实现拖动改变大小等】
效果如下图 原生的如下图(原生的用在自己的app上面太丑了,并且还带边框,所以重写了左上角的三个功能键) 1.首先了解一下nw底下的package.json 文件 { "name" ...
- Composer 安装(一)
一.简介 Composer 是 PHP 用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件. ...
- hust1010 kmp
There is a string A. The length of A is less than 1,000,000. I rewrite it again and again. Then I go ...
- css浮动布局,浮动原理,清除(闭合)浮动方法
css浮动 1.什么是浮动:在我们布局的时用到的一种技术,能够方便我们进行布局,通过让元素浮动,我们可以使元素在水平上左右移动,再通过margin属性调整位置 2.浮动的原理:使当前元素脱离普通流,相 ...
- C#基础知识-数据类型(一)
俗话说温故而知新,学习一门知识最好的方法就是不断的去咀嚼回味,学习编程更是如此.对于.NET平台中的C#语言而言,有着强大的类库.不断的在更新迭代几乎每隔一年都会更新一个新的模块,.NET Framw ...
- OC类的介绍
类的本质 类的本质其实也是一个对象(类对象) 类对象 类对象再程序运行时一直存在 类对象是一种数据结构,存储类的基本信息:类大小,类名称,类的版本以及消息与函数的映射表等 类对象所保存的信息在程序编译 ...
- Day1 Python 介绍及基础
******************本文目录******************一.Pyhon基本介绍 1.Why Python? 2. Python 是一门什么样的语言? 3.Python的优缺点: ...
- flume集群日志收集
一.Flume简介 Flume是一个分布式的.高可用的海量日志收集.聚合和传输日志收集系统,支持在日志系统中定制各类数据发送方(如:Kafka,HDFS等),便于收集数据.其核心为agent,agen ...
- Kafka学习-复制
复制 Kafka可以通过可配置的服务器数量复制每个主题分区的日志(可以为每个主题设置复制因子).这允许在集群中的服务器发生故障时自动故障转移到其他副本,因此在存在故障的情况下,消息仍然可用. 其他消息 ...
- jQuery之筛选操作
jQuery之筛选操作 筛选操作分三大类:过滤,查找,串联 eq(),first(),last(),hasClass(),filter(),is() html代码 jQuery代码 效果如下: map ...