Java 垃圾回收原理
java 对象存活分析
-
引用计数法
原理:
在堆中存储对象的时候,会在对象头上 维护一个counter计数器,如果一个对象增加了一个引用,则count++,如果一个引用失效则是count--,最终count要是为0的话,那该对象为废弃状态。
缺点:
- jdk从1.2开始增加了多种引用方式:软引用、弱引用、虚引用,且在不同引用情况下程序应进行不同的操作。如果我们只采用一个引用计数法来计数无法准确的区分这么多种引用的情况。
- 如果一个对象A持有对象B,而对象B也持有一个对象A,那发生了类似操作系统中死锁的循环持有,这种情况下A与B的counter恒大于1,会使得GC永远无法回收这两个对象
-
可达性分析算法
原理:
通过一系列名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的
那些可以作为GC Roots呢
- 虚拟机栈(栈桢中的本地变量表)中的引用的对象
- 方法区中的类静态属性引用的对象
- 方法区中的常量引用的对象
- 本地方法栈中JNI(Native方法)的引用的对象
判断对象死亡要经历2个过程
- 第一次标记
在可达性分析后发现到GC Roots没有任何引用链相连时,被第一次标记;
并且进行一次筛选:此对象是否必要执行finalize()方法;
A 没有必要执行
没有必要执行情况
1) 对象没有覆盖finalize()方法;
2) finalize()方法已经被JVM调用过
这个没有必要执行的话,证明对象已死,可以回收
B 有必要执行
对有必要执行finalize()方法的对象,被放入F-Queue队列中;
稍后在JVM自动建立、低优先级的Finalizer线程(可能多个线程)中触发这个方法;
- 第二次标记
GC将对F-Queue队列中的对象进行第二次小规模标记; finalize()方法是对象逃脱死亡的最后一次机会:
(A)、如果对象在其finalize()方法中重新与引用链上任何一个对象建立关联,第二次标记时会将其移出"即将回收"的集合;
(B)、如果对象没有,也可以认为对象已死,可以回收了;
一个对象的finalize()方法只会被系统自动调用一次,经过finalize()方法逃脱死亡的对象,第二次不会再调用;
垃圾回收算法
-
标记清除算法
原理
程序的运行期间,若可使用的内存即将被耗尽的时候,GC就会被触发并将程序暂停,随后使用可达性分析算法,将存活的对象进行标记,未被标记的对象进行回收。
标记 : 就是使用可达性分析算法找出垃圾对象
清除 :就是清除未被标记的垃圾回收对象
缺点
1.效率比较低,因为需要递归和全栈遍历对象,在GC的时候需要停止应用线程,
2.内存上是不连续的,垃圾对象分布在内存的各个角落,为了应付这一点jvm 还得维护一个空闲的内存列表
-
复制算法
-
标记整理算法 和
**TODO