java虚拟机运行时数据区
javajava虚拟机运行时数据区图
一.程序计数器
说明:一块较小的内存空间,java中每条线程独有一个程序计数器,方便处理器线程切换恢复。
作用:当前线程所执行的字节码的行号指示器,字节码解释器就是通过改变计数器的值来选取下一条需要的字节码指令。基础的循环,跳转,异常等都是通过程序计数器来完成。
注:当执行Natvie方法时,计数器值为空,其他方法计数器则记录正在执行虚拟机字节码指令地址。
二.java虚拟机栈
说明:也是每条线程独有,其生命周期与线程相同。
作用:每个方法被执行都会创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。方法的调用至执行完成都对应着栈中的入栈和出栈。
注:该区域规定两种异常状态:线程请求的栈深度过大、虚拟机动态扩展申请的内存过大。
局部变量表
属于java虚拟机栈的一部分,大部分人们说的堆栈指的是局部变量表,存放了编译期可知的基本数据类型、对象引用、字节码指令地址
局部变量表所需的内存空间在编译期完成分配,运行期间不会改变。
本地方法栈
与虚拟机栈相似,甚至所抛出的异常都一样,不同在于本地方法栈为Native方法使用,而虚拟机栈为字节码服务。
java堆
说明:是java虚拟机内存中最大的一块,被所有线程共享,在java启动时创建。
作用:存放对象实例。
注:java堆是垃圾管理的主要区域,所以又称GC堆。堆中可分为年轻代、老年代。其中新生代又细分为:Eden 空间、 From Survivor 和 To Survivor 三块区域。
方法区
说明:是各个线程共享的内存区域
作用:存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等。
注:对于HotSpot虚拟机来说又称永久代。这个区域既可以进行垃圾回收,也可以不回收,主要回收的目标主要为常量池和类型的卸载。当方法区无法满足内存分内时会抛出内存溢出异常
运行时常量池
属于方法区一部分,
作用:用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
注:运行时常量池对于存放,java虚拟机规范没有做任何细节约束,但一般除了保存class文件中描述的符号引用外,还会把翻译出来的直接引用也存在运行时常量池。运行时常量池是动态的,运行期间也会把新的常量放入池中,如String类中的intern()方法。
直接内存
说明:并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,但这部分会被内存频繁使用,也可能产生内存溢出。
注:自jdk1.4中加入NIO,引入基于通道与缓冲区的方式,可以使用Native函数直接分配堆外内存,然后通过一个存储在java里面的DirectByteBuffer对象作为引用使用,这样设计避免了java堆和Native堆中来回复制数据。