目录
一.概念
gc root 指的根引用的集合,在分代模型中,对于收集不同区域,gc root的集合有些许不同。
二.gc root 的具体内容
1.full gc (收集整个堆)
•虚拟机栈中的引用
•JVM的一些静态数据结构里指向GC堆里的对象的引用,例如Universe
•JNI handles,包括global handles和local handles
•类的静态变量的引用 (实例在堆区,引用在instanceKlass?)
•类的运行时常量池里的引用类型常量
•String常量池(StringTable)里的引用 (实例在堆区,引用在方法区?)
2.young gc(只收集年轻代)
在full gc的gc root基础上多了old区,原因是可能存在old区对象对young区对象的引用。由于老年代很大,所以并不会扫描整个老年代,而是采用remember set的形式将老年代分成很多card,只扫描dirty card。(图片来自网络)
3.old gc(只收集老年代,特指cms)
同理,在full gc的gc root基础上多了young区。会扫描整体young区,可能导致cms最终标记时间变长,因此cms可设置XX:+CMSScavengeBeforeRemark来控制在最终标记前执行一次young gc(并不会绝对执行,jvm会做一定判断)。
三.关于跨代引用的思考
如果young gc 时不将old区作为根,会出现old区对象存活而它指向的young区对象被回收的情况,这种情况下old区对象当前应该也是不可达的,这样的话应该也没有什么问题,那么为什么一定要做跨代引用的判断呢?这个问题我想了很久,想到了一种特殊情况:虽然old区对象当前不可达,但是有可能被回收时执行finalize方法而复活了自己,所以一定要做跨代引用的判断。