垃圾回收机制是怎么判断一个对象是否存活的,为什么要讲这个呢,这个讲完你就明白,新生代是怎么做晋升的,
他的存活有几个方向点,垃圾回收对象是怎么判断存活的,哪几种,首先第一种引用计数法,根搜索法,GC roots,
引用计数法已经被淘汰掉了,他有一个非常致命的缺点,就是循环依赖的问题,引用计数法的原理,比如我new一个对象的时候,
我创建User对象出来了,拿到new User()对象的时候,每个对象有一个年龄,如果小于或者等于15岁的话,它会存放在新生代里面,
如果大于15岁,就会存放在老年代里面,比如你创建一个对象的时候,我每次GC会不定时的去回收,如果对象呗继续使用,被引用,
年龄会加1,如果没有被继续回收,年龄减1,默认年龄是0岁的,你刚出生的时候是0岁的,如果GC的时候你再被引用,你就加1,
如果发现你没有被继续使用,那就减1,如果再次GC的时候你又没有被引用,那就继续减1,变1岁了,如果再次GC的时候你没有被
使用,那就继续减1,那就变成0岁了,如果年龄为0岁的话,会被垃圾回收机制认为是不可达对象,会被清理掉,但是这种算法叫
引用计数法,给每个对象做一个标记,一旦你被使用的情况下,我就加1岁,没有被继续使用的情况下就减1岁,如果是0岁的情况下,
我会认为是不可达对象清理掉了,这个就叫引用计数法,引用计数法其实有一个非常大的缺点,因为引用技术法现在没有被使用掉了
不推荐大家使用引用计数法,他有一个循环依赖的问题,什么是循环依赖问题
package com.learn.test;
public class ReferenceCountingGC{
public Object instance = null;
private static final int OneM = 1024 * 1024;
private byte[] bigSize = new byte[2 * OneM];
public static void testCG(){
/**
* 这里new了两个对象A和B
* 如果你new了A和B以后
*/
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
/**
* B赋给A
*/
objA.instance = objB;
/**
* A赋给B
* GC回收的时候也不会为0
* 就会导致这个对象不会被回收掉
* 有一个非常大的缺陷
* GC日志的一个分析
* GC分析的时候你就会知道一个整体的过程了
* 年龄在计数法里也算是一个标记
* 引用就加1
* 没有引用就减1
* 其实是一个例子
* 就是闭环依赖
* 你把B给了A,然后A给了B
* 如果你再使用循环依赖的情况下
* 那么这个时候怎么样呢
* 你再把两个对象置为空的情况下
* 很难知道他到底是被引用掉了
* 一个是循环依赖的问题
* 循环依赖很难知道这个对象到底有没有被引用
* 很难判断出来
* 所以会产生闭环
* 就很难使用引用计数法标记为0
* 如果你不把他标记为0的情况下
* 这个时候GC就不会被回收掉了
* 这是一个比较大的缺陷
* 一个对象刚创建的时候
* 它会放在EDEN区的时候
* 他如果年龄超过15岁的时候
* 那这个时候会怎样呢
* 会直接进入到老年代里面去的
* 到老年代的时候回收就不是很频繁了
* 就已经非常稳定了
* 引用计数法你也可以去了解一下
* 引用计数法已经淘汰掉了
* 他有一个比较大的缺陷
*/
objB.instance = objA;
/**
* 这边有一个对象
*
*/
objA = null;
objB = null;
System.gc();
}
}