-
程序计数器
线程私有。可以看作是字节码的行号指示器。字节码解释器通过改变该计数器的值来选取下一条字节码指令,分支.循环.跳转.异常处理.线程恢复等都依赖该计数器。
对于java方法,计数器则记录虚拟机字节码指令地址。native方法,计数器的值为空。
此内存区域是java虚拟机规范中唯一没有规定OutOfMemoryError的区域。 -
虚拟机栈
线程私有。与线程的生命周期相同,每个方法执行的同时,创建一个栈帧,用于存储局部变量表.操作数栈.动态链接.方法出口等。方法调用至执行完成,对应着一个栈帧的入栈到出栈的过程。
其中局部变量表存放了编译期可知的基本数据类型,对象引用,和returnAddress类型(指向了一条字节码指令的地址),内存空间在编译期确定,运行期间不会改变。
如果线程的栈请求深度大于虚拟机的允许的深度,抛出stackOverflowError。虚拟机栈动态扩展,无法申请到足够的内存,会抛出OutOfMemory异常。 -
本地方法栈
线程私有。与虚拟机栈相似。区别是:虚拟机栈是java方法服务,本地方法栈是native方法服务。
-
java堆
线程共享。虚拟机启动时创建,唯一目的是存放对象实例。
垃圾收集器管理的主要区域。
堆中没有内存可再分配,且无法再扩展,抛出OutOfMemoryError异常。 -
方法区
线程共享。存储已被虚拟机加载的类信息. 常量. 静态变量.即时编译器编译后的代码等数据。HotSpot虚拟机使用永久代来实现方法区。
方法区无法满足内存分配需求时,抛出OutOfMemoryError异常。 -
运行时常量池
方法区的一部分。class文件常量池中用于存放编译期生成的各种字面量和符号引用,在类加载后进入方法区的运行时常量池。
相比class文件常量池,具备动态性。运行期间也可能将新的常量放入池中,比如String的intern()方法。 -
直接内存
并非虚拟机运行时数据区的一部分,JDK1.4加入的NIO类,可以操作直接内存。避免在java堆和Native堆中来回复制数据,一些场景中能显著提升性能。也可能导致OutOfMemoryError异常。