JVM 垃圾回收
什么是垃圾对象
在内存中再也不可能会被使用到的对象
判断一个对象是否是垃圾对象的方法(标记):
可达性分析:从根节点开始,如果能够被访问到,则说明这个对象是可用的,否则,就说明这个对象不可达的,即是一个垃圾对象
引用器计数:判断当前的对象是否有其他的引用引用它,如果存在,则说明这个对象不是一个垃圾对象,否则就是一个垃圾对象
引用级别
-
强引用
平常最基本的使用对象,垃圾回收不会回收这些带有强引用的对象。如果内存不足,也不会回收这一部分的引用对象,而是直接抛出
OutOfMemoryError
异常Object obj = new Object();
这就是一个最常见的强引用
-
软引用
对于一个只存在软引用的对象来讲,在内存空间足够的情况下不会回收它。当内存空间不足时,进行垃圾回收将会回收这些只存在软引用的对象
一般会使用软引用实现一些对于内存敏感的缓存
-
弱引用
弱引用的生命周期更短,只要发生
GC
,就会直接将这些只存在若引用的对象直接进行回收,而无论当前的内存是否足够一般使用弱引用来实现一些规范化映射,如
java.util.WeakHashMap
,当key
或者value
不再被引用时可以自动被回收 -
虚引用
虚引用并不决定对象的生命周期,只存在虚引用的对象在任何时刻都有可能会被回收
虚引用的主要目的是为了跟踪对象被垃圾回收器回收的活动,当垃圾回收器准备回收一个对象时,如果发现它还存在虚引用,那么就会把这个虚引用加到与之关联引用队列。
程序可以通过判断引用队列中是否加入了虚引用,来了解被引用的对象是否要进行垃圾回收。如果程序发现某个虚拟引用已经被加入到了引用队列,那么就可以在所引用的对象的内存在回收之前采取必要的行动
垃圾回收算法
标记清除算法
算法流程:
- 标记垃圾节点
- 清除所有垃圾节点,不做任何额外操作
优点:清理速度较快
缺点:容易造成内存碎片化
如下图所示:
标记复制算法
算法流程:
- 将原有内存分为两块,每次只使用其中一块内存
GC
时将存活的对象复制到另一空白内存,同时清空整个当前使用的内存优点:速度快、无内存碎片
缺点:降低了系统的整个实际可用空间
如下图所示:
标记整理算法
算法流程:
- 标记所有的存活节点
- 将所有的存活节点压缩到内存的另一端
- 清除所有的其它节点
优点:不会产生内存碎片、可利用内存空间足
缺点:需要耗费更多的时间(主要使用在老年代)
如下图所示:
垃圾回收器
串行回收器
Serial收集器
Serial 收集器是最基础、历史最悠久的收集器,在 JDK 1.3.1 之前是
HotSpot
虚拟机新生代收集器的唯一选择。
执行流程如下所示(新生代采用 Serial
收集器,老生代采用 Serial Old
收集器):