JVM 运行时数据区

JVM-memoryJVM-memory

程序计数器

线程私有 作用是标示下一条需要执行的指令的位置,分支、循环、跳转、异常处理、线程恢复等基础功能都是依赖程序计数器完成

如果线程正在执行的是一个 java 方法,这个计数器记录的是正在执行的虚拟机字节码指令地址;如果真正执行的是一个 native 方法,这个计数器值则为空(undifined)

此区域是 Java 虚拟机规范中没有规定任何 OutOfMenoryError 情况的区域

java 虚拟机栈

线程私有 生命周期与线程一致 描述的是 java 方法执行的内存模型: 每个方法在执行的同时都会创建一个栈帧(stack frame) 用于存储 局部变量表;操作数栈;动态链接;方法出口等信息

每个方法的执行过程就对应着一个栈帧在虚拟机中入栈出栈的过程

局部变量表

局部变量表 存放各种基本数据类型(boolean byte char short int long float double)和对象引用(reference 类型)还有 returnAddress 类型(指向一条字节码指令的地址)

局部变量表所需的内存空间在编译期间完成分配,在方法运行期间不会改变局部变量表的大小

当线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;
当可拓展的虚拟机栈无法申请到足够的内存时 抛出 OutOfMemoryError 异常

本地方法栈

作用类似于虚拟机栈

Java 堆

所有线程共享的内存区域 在 jvm 启动时创建 用于存放几乎所有的对象(几乎:JIT 技术的发展,栈上分配,标量替换等等)和数组对象

GC 的主要区域 从内存回收的角度来看,java 堆可以细分为新生代/老生代;再细分有 eden 空间/from survivor/to survivor/

-Xmx -Xms
抛出 OutOfMemoryError 异常

方法区

所有线程共享的内存区域 存放加载的类信息/常量/静态变量/即时编译器编译的代码等数据
所谓"永久代"

抛出 OutOfMemoryError 异常

运行时常量池

方法区的一部分 Class 文件除了类的版本/字段/方法/接口等描述信息外,还有一些常量池,用于存放编译期生成的各种字面变量和符号引用 在类加载后进入方法区的运行时常量池存放

动态性 可以在运行期间加入新的常量(String intern()方法)

抛出 OutOfMemoryError 异常

直接内存

虚拟机以外的数据区
Channel NIO Buffer 通过 native 函数调用堆外内存

抛出 OutOfMemoryError 异常