-
引用计数算法
(1) 思想
给每个对象添加一个引用计数器,每次有引用到这个对象的地方,引用计数器就+1;引用失效就-1;
GC时回收那些引用计数器为0的对象
(2) 问题:互相引用
class A { B b; } class B { A a; } class Test { public static void main(String[] args) { A a = new A(); B b = new B(); a.b = b; b.a = a; a = null; b = null; } }
这时其实应该gc一下a和b对象,但是由于它们互相引用,所以引用计数器都是1,不能回收
所以,JVM没有采用这种方法判断对象是否存活
-
可达性分析算法
(1) JVM采用的是这种算法
(2) 思想
选取一些对象作为__GC Roots__,然后沿着这些对象向下,判断哪些对象在它们的直接/间接引用链上;如果一个对象和GC Roots对象们完全没有关联,说明它们应该被回收
(3) 可作为GC Roots的对象
1° 虚拟机栈中引用的对象
2° 方法区类的静态属性引用的对象
3° 方法区中常量引用的对象
4° 本地方法栈中JNI引用的对象
-
两次标记
(1) 经过可达性分析算法,发现有些对象确实已死,把它们__标记一次__
(2) 在finalize()方法中(一般这个方法不是主动被程序员调用的),如果这些垂死的对象又和GC Roots建立了关联,那么它们就活过来了;如果还是没有,那它们__又被标记了一次__,只能等待GC了
-
方法区的回收
(1) 一般的,堆是GC的重点区域,方法区(或叫HotSpot JVM的永久代)一般回收的少
原因是:回收一次堆可以收到很多“垃圾”,方法区中则收不到多少,不划算
(2) 回收的话主要收的是 废弃常量 和 无用的类
(3) 废弃常量的判断标准
其他地方没有引用这个字面量
(4) 无用的类判断标准(都要满足才行)
1° 类的所有实例被回收
2° 加载该类的ClassLoader被回收
3° 该类对应的java.lang.Class没有被引用,无法通过反射访问该类的方法
事实上,对于大量使用反射、动态代理的框架,JVM都要具备卸载类的功能,因为它们会造成永久代中有大量无用的类信息,有可能引发永久代溢出
chapter03_垃圾收集器与内存分配策略_2_对象已死吗
最新推荐文章于 2024-11-11 15:30:25 发布