如果你还不了解JVM的基本概念和内存划分,请阅读JVM学习笔记-基础知识和JVM学习笔记-内存处理文章。
因为Java中没有留给开发者直接与内存打交道的指针(C++指针),所以如何回收不再使用的对象问题,就丢给了JVM。所以接下来就介绍一下目前主流的垃圾收集器所采用的算法。不过在此之前,有必要先了解Reference
1.引用(Reference)
如果你现在还是JDK1.0或者1.1版本的开发者?可以跳过以下部分内容;如果不是的话,下面这些内容还是有参考价值的。你可能会问,Reference还有什么可讲的?还是有一点,你知道Reference有四中分类吗?这可不是孔乙己的四种“回”字写法可以类比的。讲到引用(Reference),我们最先想到的一般是:
Object obj = new Object();
这种属于Strong Reference(JDK1.2之后引入),这类Reference的特点就是,只要Reference还在,目标对象就不能被干掉。我们可以想一下为什么要干掉一些对象?很简单,因为内存不够了。如果内存狗使用,大家都或者就好了。所以当内存不都时,会先干掉一些“必死无疑的家伙”(下面会解释),如果这时候内存还不够用,就干掉那些“可死可不死的家伙”了。
JDK1.2之后还引入了SoftReference和WeakReference,前者就是那些“可死可不死的家伙”。当进行了一次内存清理(干掉“必死无疑”的家伙)后,还不够用,就再进行一次清理,这次清理的内容就是SoftReference了。如果干掉Soft Reference后还是不够用,JVM就跑出OOM异常了。
好像WeakReference还没说呢?它是干嘛的?其实就是那些“必死无疑的家伙”。每一次JVM进行清理时,都会将这类Reference干掉。所以一个WeakReference出生后,它的死期就是下一次JVM的清理。
“回”字的最后一种写法,是PhantomReference,名字很恐怖吧(Phantom是幽灵的意思)。这类Reference的唯一作用,就是当相应的Object被Clean掉的时候,通知JVM。
虽然有四中“回”字,但是Strong Reference却没有相应的类,java.lang.ref.Reference只有三个子类。
你可能会发现,在Reference这一部分,经常性的提到“清理”。什么“清理”?就是下面要说的 Garbage Collection中对“无用”对象的clean。
这是JVM的核心功能之一,同时也是为什么绝大多数Java工程师不需要像C++程序员那样考虑对象的生存周期问题。至于因此而同时导致Java工程师不能够放任*地控制内存的结果,其实是一个Freedom与Effeciency 之间的trade-off,而C++工程师与Java工程师恰如生存在两个过度的人,好像“幸福生活”的天朝人民与“水生火热”的西方百姓之间的“时而嘲笑、时而艳羡”一般。
言归正传,Garbage Collector(GC )是JVM中筛选并清理Garbage的工具。那么第一个要搞清楚的问题是,什么是Garbage?严谨的说,Garbage就是不再被使用、或者认为不再被使用、甚至是某些情况下选作“牺牲品”的对象。看上去很啰嗦,那就先理解成“不再被使用”吧。这就出现了第二个问题,怎么判断不再被使用?这就是后面将介绍的对象标记算法(Object Marking Algorithms)