*** 本文内容源自《深入理解JAVA虚拟机》整理而得。
JVM运行时数据区基本组成部分及其功能:
*灰色部分为线程共享
*蓝色部分为线程私有
1. 程序计数器
程序计数器(Program Counter Register)可以看作是当前线程所执行字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值Laura选取吓一跳需要执行的字节码指令。
Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(单核)都只会执行一条线程中的指令。程序计数器可用于线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间计数器互不影响,独立存储。因此程序计数器为线程私有。
- 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址
- 如果正在执行的是本地(Native)方法,这个计数器值则应为空。
2. Java虚拟机栈
Java虚拟机栈(Java Virtual Machine Stack)也是线程私有的。他的生命周期与线程相同。
每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一份方法被调用直至执行完毕的过程,对应栈帧在虚拟机栈从入栈到出栈的过程。
3. 本地方法栈
本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常类似的,区别只是虚拟机栈执行Java方法(字节码)服务,而本地方法栈则是为虚拟机使用到本地的(Native)方法服务。
4. Java堆
Java堆被所有线程共享,在虚拟机启动时创建。Java堆的唯一目的就是存放对象实例。
Java堆是垃圾收集器管理的内存区域。
从分配内存的角度看,Java堆可以划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer), 简称TLAB,用于提升对象分配时的效率。
5. 方法区
方法区(Method Area)也是被线程共享的内存区域。用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译后的代码缓存等数据。
这个区域内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说回收效果比较难令人满意。
如果方法区无法满足新的内存分配需求,将抛出OutOfMemoryError异常。
6. 运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分。
Class文件中除了类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译器生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
因为运行是常量池是方法区的一部分,当常量池无法申请到内存时会抛出OutOfMemoryError异常。
7. *直接内存
直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分。但是这部分也被频繁使用,而且也可能导致OutOfMemoryError异常出现。
*** 本文内容为《深入理解JAVA虚拟机》总结整理而得。