学习垃圾回收与算法-1

1,如何确定垃圾
Java采用引用计数法和可达性分析来确定对象是否应该被回收,其中,引用计数法容易产生循环引用的问题,可达性分析通过根搜索算法来实现,根搜索算法一系列GC Roots的点作为起点向下搜索。在一个对象到任何GC roots都没有引用链相链时,说明其已经死亡,根搜索算法主要针对栈中引用,方法区的静态引用和JNI中的引用展开分析,
A,引用计数法
在java中如果要操作对象,就必须先或获取对象的引用,因此可以通过引用计数法来判断一个对象是否可以被回收,在为对象添加一个引用时,引用计数加1,在对象删除一个引用时,引用计数减1,如果一个对象的引用计数为0,则表示此刻该对象没有被引用,可以被回收。
引用计数法有一个缺陷:无法解决循环引用问题,也就是说当对象 A 引用对象 B,对象B 又引用者对象 A,那么此时 A,B 对象的引用计数器都不为零,也就造成无法完成垃圾回收,所以主流的虚拟机都没有采用这种算法。
b,可达性分析
为了解决引用计数法的循环引用的问题,java还采用了可达性分析来判断对象是否可以被回收,具体做法是首先定义一些GC Roots对象,然后以这些GC Roots对象作为起点向下搜索,如果在GC roots和一个对象没有可达路劲,则称该对象是不可达的。
在 java 中可以作为 GC Roots 的对象有以下几种:
1,虚拟机栈中引用的对象
2,方法区类静态属性引用的对象
3,方法区常量池引用的对象
4,本地方法栈 JNI 引用的对象
虽然这些算法可以判定一个对象是否能被回收,但是当满足上面条件时,一个对象不一定会被回收。当一个对象不可达时,这个对象并不会立马被回收,而是出于一个死缓的阶段,若要被真正的回收需要经历两次标记如果对象在可达性分析中没有与 GC Root 构成引用链,那么此时就会被第一次标记并且进行一次筛选,筛选的条件是是否有必要执行 finalize()方法。当对象没有覆盖 finalize()方法或者已被虚拟机调用过,那么就认为是没必要的。如果该对象有必要执行 finalize()方法,那么这个对象将会放在一个称为 F-Queue 的对队列中,虚拟机会触发一个 Finalize()线程去执行,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这是因为如果 finalize()执行缓慢或者发生了死锁,那么就会造成 FQueue 队列一直等待,造成了内存回收系统的崩溃。GC 对处于 F-Queue 中的对象进行第二次被标记,这时,该对象将被移除”即将回收”集合,等待回收。

posted @ 2020-04-12 18:54  小小白不白  阅读(125)  评论(0)    收藏  举报