1.概述
hotspot串行GC之full gc主要包括四个步骤,依次是:
1.从根引用出发,标记所有可达对象(如图灰色部分)
2.为每个可达对象计算full gc后将移动到的新位置(图中虚线框其实与contigCompatableSpace是重叠的,分开只是为了更加清晰)
3.将根引用以及所有可达对象中的oop字段修改为指向第二步中计算出的新位置(实线箭头修改为双实线箭头)
4.将所有可达对象移动到第二步中计算出的新位置
2.伪代码
见http://leafinwind.iteye.com/blog/2013687
phase1的关键之处在于依靠一个stack来遍历根引用的所有可达对象。
phase2有两个很精妙的地方,首先是对space从bottom开始的连续的活对象,清除了这些对象的gc_mark标记已经forward字段,因为这些对象最终并不需要移动,space的_first_dead记录了第一个死对象的地址;第二是对连续的死对象,将其中第一个死对象的forward字段置为了右端最近的活对象地址,这样后续的phase3和phase4就可以跳过对这片连续死对象区域的扫描。
phase3遍历所有活对象,将它们的oop字段都修改为第二步中计算出的新位置。这里需要说明的是对[bottom,_first_dead)区间的特殊处理,因为其中的对象在第二步中已经清除gc_mark了。
phase4遍历所有活对象,将它们移动到新的位置。注意处理过程[bottom,_first_dead->forwardee())区间都可以跳过。
3.与hotspot代码的对应关系
phase1对应hotspot代码的GenMarkSweep::mark_sweep_phase1方法
调用gch->gen_process_strong_roots处理根引用,使用的follow_root_closure是一个FollowRootClosure,其do_oop方法在mark当前根引用指向对象的同时,还会将该对象中的所有oop字段压入一个栈中(见MarkSweep::mark_and_push方法),然后从“右侧”深度优先的mark所有间接引用的对象,直到栈为空。
phase2对应GenMarkSweep::mark_sweep_phase2(),要点在伪代码中都已提到,不同之处主要在于:
1.伪代码只用了一个space,而hotspot是三个:依次遍历old gen,eden和from中的对象,将它们的forward地址首先置为old gen中的地址,填满后则依次再使用eden和from。注意这里的一个暗含的意思是full gc会将young gen中的对象直接拷入old gen,与对象年龄什么的都没有关系,并且很可能一次full gc后young gen会被清空。
2.为尽量在old gen的开头获得一片连续的活对象区间,hotspot在一定的设置下允许将部分死对象初始化为无意义的对象填充进去。
phase3对应GenMarkSweep::mark_sweep_phase3。
phase4对应GenMarkSweep::mark_sweep_phase4(),与伪代码的不同也在于hotspot有三个space。另外如果eden和from中的对象都拷入了old gen,那么它们的compact_top指针会等于bottom指针,这时会对相应space做一些清理工作。
相关推荐
HotSpot虚拟机提供了多种GC算法,如串行GC、并行GC、并发标记清除(CMS)和G1垃圾收集器。每种GC策略都有其适用场景和优缺点。 3. **新生代与老年代**:HotSpot虚拟机将堆内存划分为新生代(Young Generation)和老...
新生代的GC策略有串行GC(Serial Copying)、并行回收GC(Parallel Scavenge)和ParNew GC。 串行GC是客户端模式下的默认选择,可以通过`-XX:+UseSerialGC`指定。它使用单线程进行垃圾收集,适合小型应用。新生代的...
- Full GC:针对年轻代、老年代以及永久代的全面垃圾收集操作。 #### 五、垃圾回收器概览 Sun HotSpot JVM提供了多种垃圾回收器,适用于不同的应用场景: 1. **Serial Collector** - 串行收集器,简单高效,...
在Client模式下,默认使用串行GC,而在Server模式下,新生代和旧生代分别使用并行GC和平行标记-清除GC。这些策略旨在平衡垃圾回收效率与应用程序的暂停时间。 回收算法上,CLR有大对象堆(LOH)和小对象堆(SOH)。...
- **GC回收器**:串行GC、并行GC、并行压缩GC、CMS、G1等,每种有其特点和适用场景。 4. **类加载机制**: - **双亲委派模型**:类加载请求先向上委托给父类加载器,只有父类加载不到时才尝试自己加载。 - **类...
- **Full GC**:年老代被写满、持久代被写满、显示调用`System.gc()`、上一次GC之后Heap的各域分配策略动态变化、RMI等的定时触发。 #### 五、JVM监控与故障处理工具 JVM提供了多种工具帮助开发者监控JVM的状态...
到了Java 8,永久代被移除,取而代之的是元空间(Metaspace),这是为了减少Full GC的次数以及解决永久代可能耗尽的问题。Java 9进一步引入了模块化系统并改进了垃圾收集器的一些细节。这些变化意味着随着Java版本的...
- 尽量减少大对象的使用,因为大对象会直接导致老年代空间快速填满,触发Full GC。 - 对于无法避免的大对象,可以使用-XX:PetenureSizeThreshold参数,当对象超过指定大小时直接进入老年代,避免新生代频繁GC。 -...