JVM 基础笔记(四)垃圾回收JDK 1.8
垃圾回收机制
一、确定什么样的对象是垃圾? 引用计数,可达性分析
-
引用计数
有其他的对象引用我,就不会被回收,但是会有一些问题。
假如 a1 是 a2的引用,而a2又是a1的引用。循环引用,这样两个对象就不会被称之为垃圾,就导致这两个对象不会被回收造成资源的浪费。
-
可达性分析
GC root【上帝视角】,由这个GC root出发,去看看某个对象是否可达。
特点: GC root的生命周期必须足够的长,否则很短的话,被回收了,还怎么去判断某个对象是否可达。
-
什么样的对象才能称之为GC root ?
- 虚拟栈中的局部变量表(存在栈帧中)
- static 成员
- 常量
- 本地方法栈中的变量,也就是C语言调用的链路
- 类加载器
- thread
二、应该如何回收【回收算法】?
- 标记和清除法
如图:
弊端:
1.清除完成之后会存在严重的空间碎片化(内存空间不能连续),导致明明内存够用,但是却不能存贮进来,浪费大量的空间。
2.扫描了两次,而且扫描的是整过堆,比较耗时,效率低。
- 复制法
如图所示
优势:空间连续
弊端:空间浪费
- 标记整理
解决了标记-清除算法和复制算法的弊端。
三、各种垃圾收集器的优势劣势,如何选型?
- 新生代:复制算法(适用于少量对象存活的场景)
- 老年代:本身就是存储一些回收次数超过超过15次的对象,这就意味着在老年代中可能存在很多这种对象,并且这种对象可能还会一直存在,如果是这样的话,假设老年代采用的是复制回收算法,同时也假设老年代中能存在100个对象,这样平分内存空间为s0和s1,s0,s1都能存储50个对象,再假设老年带中目前有30个可能还需要很久才能回收的对象存在s0中。复制算法开始,把这30个对象复制到s1,再把这30个对象复制到s0,反反复复执行许多次,可能只有一个对象被回收了。那我直接标记一下好不好?何必每次都复制来复制去,浪费空间,降低效率,而且也没有什么变化。