Java 内存模型
(图源: 深入理解 JVM - 内存模型 (jmm) 和 GC https://www.jianshu.com/p/76959115d486 )
区域名 | 英文名 | 访问权限 | 作用 | 备注 |
---|---|---|---|---|
程序计数器 | Program Counter Register | 线程隔离 | 标记待取的下一条执行的指令 | 执行 Native 方法时为空; JVM 规范中唯一不会发生 OutOfMemoryError 的区域 |
虚拟机栈 | VM Stack | 线程隔离 | 每个 Java 方法执行时创建,用于存储局部变量表,操作栈,动态链接,方法出口等信息 | 方法执行的内存模型 |
本地方法栈 | Native Method Stack | 线程隔离 | Native 方法执行时使用 | JVM 规范没有强制规定,如 Hotspot 将 VM 和 Native 两个方法栈合二为一 |
Java 堆 | Java Heap | 线程共享 | 存放对象实例 | 更好的回收内存 vs 更快的分配内存 |
方法区 | Method Area | 线程共享 | 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 | JVM 规范不强制要求做垃圾收集 |
运行时常量池 | Runtime Constant Pool | 线程共享 | 方法区的一部分 | |
直接内存 | Direct Memory | - | 堆外内存,通过堆的 DirectByteBuffer 访问 | 不是运行时数据区的一部分,但也可能 OutOfMemoryError |
对象的创建 --new 的时候发生了什么
讨论仅限于普通 Java 对象, 不包括数组和 Class 对象.
常量池查找类的常量引用, 如果没有先做类加载
分配内存, 视堆内存是否是规整 (由垃圾回收器是否具有压缩功能而定) 而使用 "指针碰撞" 或 "空闲列表" 模式
内存空间初始化为零值, 可能提前在线程创建时分配 TLAB 时做初始化
设置必要信息, 如对象是哪个类的示例, 元信息, GC 分代年龄等
调用 < init > 方法
垃圾回收器总结
垃圾回收, 针对的都是堆.
分代
新生代: 适合使用复制算法, 以下三个区一般占比为 8:1:1
Eden 新对象诞生区
From Survivor 上一次 GC 的幸存者(见 "GC 种类 - minor GC")
To Survivor 本次待存放幸存者的区域
老年代: 存活时间较久的, 大小较大的对象, 因此使用标记 - 整理或标记 - 清除算法比较合适
永久代: 存放类信息和元数据等不太可能回收的信息. Java8 中被元空间 (Metaspace) 代替, 不再使用堆, 而是物理内存.
分代的原因
不同代的对象生命周期不同, 可以针对性地使用不同的垃圾回收算法
不同代可以分开进行回收
回收算法
名称 | 工作原理 | 优点 | 缺点 |
---|---|---|---|
标记 - 清除 | 对可回收对对象做一轮标记,标记完成后统一回收被标记的对象 | 易于理解,内存利用率高 | 效率问题; 内存碎片; 分配大对象但无空间时提前 GC |
复制 | 内存均分两块,只使用其中一块。回收时将这一块存活对象全部复制到另一块 | 效率高 | 可用空间减少; 空间不够时需老年代分配担保 |
标记 - 整理 | 对可回收对对象做一轮标记,标记完成后将存活对象统一左移,清理掉边界外内存 | 内存利用率高 | 效率问题 |
标记 - X 算法适用于老年代, 复制算法适用于新生代.
GC 种类
Minor GC, 只回收新生代, 将 Eden 和 From Survivor 区的存活对象复制到 To Survivor
Major GC, 清理老年代. 但因为伴随着新生代的对象生命周期升级到老年代, 一般也可认为伴随着 FullGC.
FullGC, 整个堆的回收
Mixed GC,G1 特有, 可能会发生多次回收, 可以参考关于 G1 GC 中 Mixed GC 的分析
垃圾回收器小结
垃圾回收器名称 | 特性 | 目前工作分代 | 回收算法 | 可否与 Serial 配合 | 可否与 ParNew 配合 | 可否与 ParallelScavenge 配合 | 可否与 SerialOld 配合 | 可否与 ParallelOld 配合 | 可否与 CMS 配合 | 可否与 G1 配合 |
---|---|---|---|---|---|---|---|---|---|---|
Serial | 单线程 | 新生代 | 复制 | - | - | - | Y | N | Y | N/A |
ParNew | 多线程 | 新生代 | 复制 | - | - | - | N | N | Y | N/A |
ParallelScavenge | 多线程, 更关注吞吐量可调节 | 新生代 | 复制 | - | - | - | N | N | Y | N/A |
SerialOld | 单线程 | 老年代 | 标记 - 整理 | - | - | - | Y | Y | N | N/A |
ParallelOld | 多线程 | 老年代 | 标记 - 整理 | N | N | Y | - | - | - | N/A |
CMS | 多线程,并发收集,低停顿。但无法处理浮动垃圾,标记 - 清除会产生内存碎片较多 | 老年代 | 标记 - 清除 | Y | Y | N | Y | - | - | N/A |
G1 | 并行并发收集,追求可预测但回收时间,整体内存模型有所变化 | 新生代 / 老年代 | 整体是标记 - 整理,局部 (两 Region) 复制 | N | N | N | N | N | N | - |
来源: https://www.cnblogs.com/wuyuegb2312/p/11839171.html