1、如何判断对象可以被回收
- 引用计数法
- 可达性分析算法
2、可达性分析算法
- java虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
- 扫描堆中的对象,看是否能够沿着GC Root对象为起点的引用链找到该对象,找不到,表示可以回收
3、java中的四种引用
- 强引用
- 软引用
- 弱引用
- 虚引用
- 终结器引用
4、五种引用的特点及应用
-
强引用
只有所有GC Root对象都不通过【强引用】引用该对象,该对象才能被垃圾回收 -
软引用
仅有软引用引用该对象时,在垃圾回收后,内存不足时会再次发出垃圾回收,回收软引用对象
可以配合引用队列来释放软引用自身 -
弱引用
就有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
可以配合引用队列来释放软引用自身 -
虚引用
必须配合引用队列使用,主要配合ByteBuffer使用,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用虚引用相关方法释放直接内存 -
终结器引用
无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由Finalizer线程通过终结器引用找到被引用对象并调用它的finalize方法,第二次GC时才能回收被引用对象
5.垃圾回收算法
- 标记清除算法
标记——清除算法将垃圾回收分为两阶段:标记阶段和清除阶段。在标记阶段首先通过根节点,标记所有从根节点开始的对象,未被标记的对象就是未被引用垃圾对象。然后,在清除阶段,清除所有未被标记的对象。标记清除算法带来的一个问题是会存在大量的空间碎片,因为回收的空间是不连续的
小结:速度快但会产生内部碎片 - 标记整理
标记-压缩算法是一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。首先也需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外的所有空间。这种方法避免了碎片的产生。因此,它的性价比比较高
小结:速度慢,但是没有内部碎片 - 复制算法
将现有的内存空间分为两块,每次只使用其中的一块,在垃圾回收是将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
不会有内部碎片,但是会占用双倍的内存
6.分代的垃圾回收机制
- 对象首先分配在伊甸园区域
- 新生代空间不足时,触发minor gc,伊甸园和from存活的对象使用copy复制到to中,存活的对象年龄加1并且交换from to
- minor gc会引发stop the world,暂停其他用户的线程,等垃圾回收结束,用户线程才恢复
- 当对象寿命超过阙值时,会晋升至老年代,最大寿命是15
- 当老年代空间不足,会尝试触发minor gc,如果之后空间仍不足,那么触发full gc。STW(响应)的时间更长
7.相关jvm参数
9.垃圾回收器
- 串行
单线程,
堆内存较小,适合个人电脑 - 吞吐量优先
多线程,
需要堆内存较大,
有多核cpu支持,
让单位时间内stw的时间最短 - 响应时间优先
多线程,
需要堆内存较大,
有多核cpu支持
尽可能让单次STW时间短
10、垃圾回收器
串行
吞吐量优先
响应时间优先
11、G1收集器
使用场景:
- 同时注重吞吐量和低延迟,默认的暂停目标是200ms
- 超大堆内存,会将堆划分为多个大小相等的Region(区域)
- 整体上是标记+整理算法,两个区域之间是复制算法