「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
1.垃圾回收算法
1⃣️引用计数算法
对象中添加一个引用计数器,每当一个地方引用它时,计数器值加1;引用失效时,计数器值减1。
2⃣️可达性分析算法
一系列被称为"GC Roots"的根对象作为起始节点集,从节点开始根据引用关系向下搜索,搜索走过的路被称为"引用链"。
如果某个对象到GC Roots没有任何引用链相连,那么这个对象就会被判定为可回收对象。
2.何为引用
引用分为强引用、强引用、弱引用、虚引用
- 强引用
引用赋值。如Object o = new Object(); 只要强引用关系在,垃圾回收器就不会回收被引用的对象。
- 软引用
有用但非必需。在系统即将发生内存溢出异常前,将软引用对象放进回收范围进行第二次回收,如果回收之后还是没有足够的内存,才抛出内存溢出异常。(JDK1.2之后提供了SoftReference类实现软引用)
- 弱引用
非必需对象,比软引用更弱。垃圾收集器开始工作时,无论内存是否足够,都会回收掉弱引用对象。(JDK1.2之后提供了WeakReference类实现软引用)
- 虚引用
"幽灵引用"/"幻影引用",最弱。无法通过虚引用获取对象的实例,设置虚引用的唯一目的只是为了虚引用对象被垃圾回收时收到一个系统通知。
3.对象真正"死亡"
宣告一个对象真正死亡,要经过两次标记。
1⃣️可达性分析后,对象与GC Roots之间没有引用链相连。
2⃣️是否需要执行finalize()方法。
任何一个对象的finalize()方法只会被系统自动调用1次。finalize()方法不被推荐使用。
4.方法区的回收
不要求虚拟机在方法区中实现垃圾收集,因为方法区垃圾回收严苛的判定条件,性价比低。
回收的内容
1⃣️废弃的变量
2⃣️不再使用的类型
5.垃圾收集算法
首先,先了解一下分代收集理论
分代收集理论建立在两个假说之上:
1⃣️弱分代假说(对象都是朝生夕灭)
2⃣️强分代假说(熬过越多次垃圾回收的对象就越难以消亡)
由此推出垃圾收集器的设计原则:收集器应该将Java堆划分出不同的区域,将回收对象按照年龄划分到不同的区域。
对象不是孤立的,存在跨代引用。每次进行新生代回收的时候,需要遍历一次老年代所有的对象来确保可达性分析结果的准确,这个操作是很大的负担。
由此,推出了第三条经验法则:
3⃣️跨代引用假说(存在引用关系的对象,倾向于同时生存、同时消亡)
在新生代上建立一个全局数据结构("记忆集"),这个结构把老年代划分为若干块,标识老年代中存在跨代引用的内存。之后进行Minor GC时,只会对标记的内存进行GC Roots扫描。