JVM 内存模型详解
一个请求打到服务器上,JVM 各块内存区域分别承担了什么角色?线程共享和线程私有的边界在哪?
一、JVM 运行时数据区全景
- 1.1 五大区域概览图:堆、方法区、虚拟机栈、本地方法栈、程序计数器
- 1.2 线程共享 vs 线程私有的划分逻辑
二、程序计数器
- 2.1 为什么需要程序计数器——CPU 时间片轮转
- 2.2 线程切换后的字节码”断点”恢复
- 2.3 唯一不会 OOM 的区域
三、Java 虚拟机栈
- 3.1 栈帧结构:局部变量表、操作数栈、动态链接、返回地址
- 3.2 局部变量表——基本类型 vs 对象引用
- 3.3 栈的大小设置
-Xss及 StackOverflowError 发生场景 - 3.4 递归过深与栈溢出排查
四、本地方法栈
- 4.1 native 方法的运行区域
- 4.2 HotSpot 中虚拟机栈与本地方法栈合二为一
五、堆——对象的主战场
- 5.1 堆的分代设计——为什么分新生代和老年代
- 5.2 Eden、Survivor(S0/S1)和 Old 区的比例与动态调整
- 5.3 堆大小参数
-Xms/-Xmx最佳实践 - 5.4 字符串常量池在堆中的变迁
六、方法区 / 元空间
- 6.1 JDK 7 之前:永久代(PermGen)
- 6.2 JDK 8:元空间(Metaspace)取代永久代
- 6.3 为什么移到本地内存——避免
java.lang.OutOfMemoryError: PermGen - 6.4 元空间大小控制
-XX:MetaspaceSize/-XX:MaxMetaspaceSize - 6.5 运行时常量池——Class 文件常量池 vs 运行时常量池
七、直接内存
- 7.1 NIO 中的 DirectByteBuffer
- 7.2 不受
-Xmx限制但受物理内存限制 - 7.3 Direct Memory OOM 排查
八、一个接口请求的内存流转实景
- 8.1 从方法调用到对象创建,各区域的内存分配轨迹
- 8.2 配合
jvisualvm实时观察内存变化
九、总结
- 每个区域的职责一句话总结
- 常见 OOM 与对应区域的映射
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!