JVM - 1. Java 运行时数据内存区域
运行时内存可能抛出的异常
StackOverflowErrorOutOfMemoryError
程序计数器 (Program Counter Register)
作用: 指定虚拟机在各个线程要执行的下一条字节码指令的地址 数量: 线程私有 (每个线程都有一个) 说明:
- 若线程正在执行一个 Java 方法, 这个计数器保存的是正在执行的虚拟机字节码指令的地址
- 若线程正在执行一个 Native 方法, 这个计数器的值为空
异常: 无(PC 是唯一一个在虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域)
Java 虚拟机栈 (JVM Stacks)
作用: 传统意义上的 "堆栈" 中的 栈. 当 Java 方法被执行时, 会有一个 栈帧(Stack Frame) 被创建并压入到 栈 中; 而当 Java 方法执行完成后, 这个 栈帧 会被弹出.
栈帧里包含,
-
局部(本地)变量表, 编译期可知的各种基本类型:
- boolean
- byte
- char
- short
- int
- float
- long (占用 2 个 Slot)
- double (占用 2 个 Slot)
- reference (句柄或者直接指针)
- returnAddress (指向了一条字节码指令的地址)
-
操作数栈
-
动态链接
-
方法出口
数量: 线程私有
异常:
StackOverflowError, 当线程请求的栈深度 > 虚拟机所允许的深度, 比如 递归.OutOfMemoryError, 若支持动态扩展(大多数都支持), 当扩展时入法申请足够恩内存.
本地方法栈 (Native Method Stack)
作用: 用于执行 Native 方法时所用到的栈. 数量: 线程私有 异常: 同 JVM Stacks
Java 堆 (Java Heap)
作用: 用于存放对象实例 (instance object),
堆 是 GC 的主要区域, 按照 GC 的分代回收算法, 堆可以分为,
- 新生代 (Eden, From Survivor, To Survivor)
- 老年代 (Tenured)
- 永久代 (Permanent)
数量: 线程共享 说明: 由于是线程共享, 所以分配时要用锁.
异常: OutOfMemoryError, 当堆中空间用尽, 且无法再扩展时.
线程本地缓冲区 (Thread Local Allocation Buffer, TLAB)
作用: 用于存放线程私有的对象, 默认设定为占用Eden Space的1%。
说明: 在Java程序中很多对象都是小对象且用过即丢,它们不存在线程共享也适合被快速GC,所以对于小对象通常JVM会优先分配在TLAB上,并且TLAB上的分配由于是线程私有所以没有锁开销。因此在实践中分配多个小对象的效率通常比分配一个大对象的效率要高。
方法区 (Method Area)
作用: 存在于堆中, 是堆中的一个逻辑部分, 却被称作 Non-Heap. 存储了:
- 虚拟机加载的类信息
- 常亮
- 静态变量
- JIT 编译后的代码
数目: 线程共享
说明:
- JDK 1.7 之前, HotSpot 用永久代实现了方法区, 字符串常量池在永久代中, 导致了性能问题和内存溢出错误
- JDK 1.7, 字符串常量池移出了永久代
- JDK 1.8, 永久代被删除
异常: OutOfMemoryError, 当空间用尽时抛出.
运行时常量池 (Runtime Constant Pool)
作用: 存在于方法区中, 存储存放:
- 编译期生成的各种字面量和符号引用 (类加载时被载入)
- 运行期产生的新常量 (String.intern())
数目: 同方法区
异常: 同方法区
直接内存 (Direct Memory)
作用: 服务于 NIO, 避免 Java 堆中和 Native 堆中来回复制数据. 不是虚拟机运行时数据区的一部分. 说明:
- 利用 NIO 可以在 Native 内存中直接分配空间, 并通过一个存储在 Java 堆中的
DirectByteBuffer操纵这片内存. - Direct Memory 不收 Java Heap 大小参数的影响 异常:
OutOfMemoryError, 当虚拟机外内存不足的时候
相关虚拟机参数
- -Xmx 虚拟机最大堆内存大小
- -Xms 虚拟机初始堆内存大小
- -Xmn 新生代堆内存大小, 推荐为整个堆的 3/8
- -Xss 每个线程的栈大小
- -XX:NewRation=4 新生代(Eden+Survivor)和老年代的比例, 4 代表 新生代与老年代比例为 1 : 4, 新生代占堆大小 1/5.
- -XX:SurvivorRatio=8 Eden 和 单个 Survivor 的比例为 8:1, 每个 Survivor 占新生代的 1/10. Eden 占 1/8.
- -XX:+/-UseTLAB 指定是否使用 TLAB, 默认开启

浙公网安备 33010602011771号