Java虚拟机管理划分的运行时数据区域

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/name_z/article/details/52556250

《深入理解JAVA虚拟机》的读书笔记-第2章

程序计数器

功能:

当前线程所执行的字节码的行号指示器,字节码解释器工作时,就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等处功能都需要依赖这个计数器来完成。

这和计算机处理器中的计数器功能基本一样,简单来说就是这个任务有N个步骤,从头开始执行:
1.计数器的值为x=0
2.处理器读取计数器的值x
3.处理器执行步骤x
4.如果步骤x不改变接下来的步骤顺序,那么x++(读取下一条指令),否则x=需要执行的步骤号(分支、循环、跳转、异常处理、线程恢复)
5.跳回到步骤2

范围:

因为java有多线程,每个线程都必须拥有自己的计数器,所以程序计数器是线程私有的。

Java虚拟机栈(本地方法栈)

功能:

描述java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,都对应这一个栈帧在虚拟机栈中入栈到出栈的过程。

范围:

线程私有,与线程的生命周期一样。

为什么是线程私有?
因为java虚拟机栈中的局部变量表除了包括方法内的局部变量外,还包括了方法所属对象实例的引用也就是“this”,而且还有传入的参数,更可能的是在方法中调用了所属对象的成员变量,因此是线程私有。

异常:

1.如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverFlowError异常。
2.如果虚拟机可以动态扩展(当前大部分的java虚拟机都可动态扩展,只是也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,会抛出OutOfMemoryError异常。

Java虚拟机栈:

为虚拟机执行java方法(字节码)服务。

本地方法栈:

为虚拟机使用到的native方法服务。native方法简单说就是采用别的语言写的只适用于当前系统的方法,用于底层操作。
更详细的看这里:http://blog.csdn.net/xw13106209/article/details/6989415

Java堆

功能:

存放对象实例,几乎所有的对象实例都在这里分配内存(其余的通过栈上分配、标量替换优化技术)。

Java堆是垃圾收集器管理的主要区域。

范围:

线程共享。

异常:

如果堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。(可通过-Xmx和-Xms来控制堆的大小)

方法区

功能:

用于存储已被虚拟机加载的类的信息、常量、静态变量、即时编译器编译后的代码等数据。

范围:

内存共享

异常:

当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

运行时常量池

功能:

是方法区的一部分。class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(constant pool table),用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
而且并非只有预置入class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中。(例如被用到String类的intern()方法)

范围:

线程共享

异常:

当常量池无法再申请到内存时会抛出OutOfMemory异常

直接内存

功能:

不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。
在NIO类中,引入了一种基于通道与缓冲区的IO方式,它可以使用native函数库直接分配对外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

范围:

异常:

受到物理总内存的限制,当动态扩展无法申请到内存时,将出现OutOfMemory异常

猜你喜欢

转载自blog.csdn.net/name_z/article/details/52556250