从原理聊JVM(一):染色标记和垃圾回收算法

💡 原文中文,约5200字,阅读约需13分钟。
📝

内容提要

本文介绍了JVM的内存分配、GC、编译等知识,并详细解释了JVM的运行时内存划分、对象的内存布局、标记的方法和流程、分代模型、垃圾回收算法等内容。

🔎

延伸解读

方法区实现变迁:永久代到元空间

JDK1.8之前,HotSpot用永久代实现方法区,内存分配在JVM虚拟机中;1.8之后改为元空间,使用本地内存。这一变化是因为运行期间加载的类所占空间不可控,使用本地内存可避免对JVM内存造成影响。方法区无法满足内存分配需求时,会抛出OutOfMemoryError。

三色标记法的并发问题与解决方案

三色标记法在并发标记时可能出现对象漏标:黑色对象新增对白色对象的引用,或灰色对象删除对白色对象的引用,都可能导致存活对象被误清除。增量更新(如CMS)在黑色对象新增引用时将其改回灰色,后续重新扫描;原始快照(如G1、Shenandoah)则记录灰色对象删除的引用,结束后重新扫描,但会产生浮动垃圾。

分代模型与跨代引用优化

基于弱分代、强分代和跨代引用假说,堆分为年轻代和年老代。年轻代对象朝生夕灭,GC频繁;年老代对象存活久,GC较少。跨代引用极少,因此使用记忆集记录非收集区域指向收集区域的指针,卡表是其粗粒度实现,通过写屏障维护,可减少Minor GC时扫描整个年老代的开销。

垃圾回收算法的适用场景

标记-清除会产生内存碎片;标记-复制无碎片但需两倍空间,优化后使用Eden和Survivor区(8:1:1),仅浪费10%空间,适合年轻代;标记-整理避免碎片和空间浪费,但移动对象成本高,适合年老代。实际中可先标记-清除,碎片率高时再标记-整理。

❓

Q&A

JVM的运行时内存划分包括哪些区域?

JVM的运行时内存划分包括方法区、堆、虚拟机栈、本地方法栈和程序计数器。

什么是三色标记法,它的作用是什么?

三色标记法用于可达性分析,通过将对象标记为白色、灰色和黑色来判断对象的存活状态。

JVM中如何判断对象是否需要被回收?

可以通过引用计数法和可达性算法来判断对象是否需要被回收。

什么是分代模型,它的基本假设是什么?

分代模型将对象分为年轻代和年老代,基本假设是大多数对象是短命的,存活时间越长的对象越难以被回收。

标记-清除算法的缺点是什么?

标记-清除算法的缺点是会产生内存碎片,可能导致后续无法找到足够的连续内存。

JVM中OopMap的作用是什么?

OopMap用于快速找到GC Root,帮助垃圾收集器在回收时定位对象引用。

🏷️

标签

➡️

继续阅读