- 1、本文档共13页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
JVM学习笔记 Java内存模型
一 Java内存模型
1、运行时数据区域
1.1 程序计数器
程序计数器(Program Counter Register)是一块较小的内存空间,可以看成是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取吓一跳需要执行的字节码指令。
线程私有,每条线程都需要有一个独立的程序计数器,各条线程之间互不影响,独立存储。
如果线程正在执行一个Java Method, 这个计数器记录的是正在执行的虚拟机字节码指令的地址;
如果正在执行的 Native Method,这个计数器的值为空(Undefined)。
此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError的区域。
1.2 Java虚拟机栈
Java虚拟机栈(Java Virtual Machine Stacks)
线程私有,生命周期与线程相同。
虚拟机栈描述的Java方法执行的内存模型: 每个方法在执行的同时,都会创建一个栈帧(Stack Frame),用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
局部变量表存放了编译期可知的各种基本数据类型(boolean, byte, char, short, int, float, long ,double), 对象引用(reference类型, 它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)
其中64位长度的 long, double类型的数据会占用2个局部变量空间(slot),其余的数据类型只占用 1 个。
局部变量表 所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在 帧中分配多大的局部变量空间是完全确定的,这个方法在运行期间不会改变局部变量表的大小。
在Java虚拟机规范中,对这个区域规定了两种异常情况:
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
如果虚拟机栈可以动态扩展(当前大部分JVM都可以动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常
1.3 本地方法栈
本地方法栈(Native Method Stack) , 与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行的Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。
有的虚拟机(如:Sun HotSpot)直接将本地方法栈和Java虚拟机展合二为一。
与Java虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。
1.4 Java 堆
Java堆(Java Heap)
对大多数应用来说,Java Heap是Java虚拟机所管理的内存中最大的一块。
Java Heap 是被所有线程共享的一块区域,在虚拟机启动时创建。
此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配。Java虚拟机规范描述的是:所有的对象实例以及数组都要在堆上分配。( The heap is the runtime data area from which memory for all class instances and arrays is allocated )。
但,随着JTI编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术导致一些微妙的变化,使其变得不那么绝对了。
Java Heap是垃圾收集器管理的主要区域,因此很多时候也被称作为“GC”堆(Garbage Collected Heap)。
从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以Java堆中还可以细分为:新生代 和 老年代;再细分: Eden空间, From Survivor空间, To Survivor空间等。(详见后面 GC 部分)
从内存分配的角度来看,线程共享的Java heap中可能划分出多个线程私有的分配缓存区(Thread Local Allocation Buffer, TLAB)。
无论如何划分,都与存放内容无关,无论哪个区域,存储的都仍然是对象实例,进一步划分的目的是为了更好的回收内存,或者更快的分配内存。
根据Java虚拟机规范的规定,Java Heap可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。
在实现时,Java heap可以实现成固定大小,也可以扩展的。当
文档评论(0)