问题
如何判断对象已经死亡?
引用计数算法
当有一个地方引用该对象,就为对象的引用计数器加1,当引用失效的时候就减1。当计数器为0的时候代表当前对象无引用。
虽然引用计数算法的效率很好,但是java主流的虚拟机并没有选择它来管理内存。其中最主要的就是它难以解决相互引用带来的问题。
添加启动参数:
-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -XX:+PrintGCDateStamps
public class ReferenceGcTest {
public Object instance = null ;
private final int size = 1024 * 1024;
private byte[] tempSize = new byte[ size * 2 ];
public static void testGc(){
ReferenceGcTest gcA = new ReferenceGcTest();
ReferenceGcTest gcB = new ReferenceGcTest();
gcA.instance = gcB;
gcB.instance = gcA;
System.gc();
}
public static void main(String[] args) {
testGc();
}
}
console:
2016-06-07T13:56:02.560+0800: 0.296: [GC [PSYoungGen: 4741K->4448K(37632K)] 4741K->4448K(123776K), 0.0046637 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2016-06-07T13:56:02.564+0800: 0.300: [Full GC (System) [PSYoungGen: 4448K->0K(37632K)] [PSOldGen: 0K->4316K(86144K)] 4448K->4316K(123776K) [PSPermGen: 3326K->3326K(21248K)], 0.0126859 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 37632K, used 1935K [0x00000007d5f60000, 0x00000007d8960000, 0x0000000800000000)
eden space 32256K, 6% used [0x00000007d5f60000,0x00000007d6143e60,0x00000007d7ee0000)
from space 5376K, 0% used [0x00000007d7ee0000,0x00000007d7ee0000,0x00000007d8420000)
to space 5376K, 0% used [0x00000007d8420000,0x00000007d8420000,0x00000007d8960000)
PSOldGen total 86144K, used 4316K [0x0000000781e00000, 0x0000000787220000, 0x00000007d5f60000)
object space 86144K, 5% used [0x0000000781e00000,0x00000007822371e8,0x0000000787220000)
PSPermGen total 21248K, used 3369K [0x000000077cc00000, 0x000000077e0c0000, 0x0000000781e00000)
object space 21248K, 15% used [0x000000077cc00000,0x000000077cf4aaf8,0x000000077e0c0000)
通过日志可以看到,其实hotspot并未采用引用计数法来判断对象是否存货
2 可达性分析算法
可达算法是通过一系列的 “gc roots” 作为对象的的起始点。从这些节点开始往下搜索。搜索走过的路径称之为 引用链 。当一个对象没有任何引用链相连(从gc roots 不可以到达这个对象)。就证明这个对象时不可以用的。
如图:
引用的分类
jdk1.2之后对引用做了扩展。将引用分为4个类型:强引用、软引用、弱引用、虚引用四种。