http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29632145&id=4616836
http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html
以上是两个写的特别好的博客
在java内存运行时区域的各个部分中:程序计数器,虚拟机栈,本地方法栈随线程生和灭,
对于java中的堆和方法区,、只能在程序运行期间才知道会创建哪些对象,这部分内存的分配和回收是动态的,垃圾收集器所关注的主要是这部分内存。
哪些内存需要回收?
什么时候回收?
如何回收?
垃圾收集器对堆进行回收前需先确定哪些对象已经死去(不可能再被任何途径使用的对象)
一般的方法是给对象中添加一个引用计数器,即引用计数算法来管理内存,但是jvm并没有,因为无法解决对象之间相互循环引用的问题。
1:可达性分析
GC Roots
当一个对象到GC Roots没有任何引用链相连时,表明此对象不可达。
四种引用:强引用,软引用,弱引用,虚引用
强引用:类似于new对象的方式,只要强引用还在,GC永远不会回收被引用的对象
软引用:还有用,但非必须。在系统发出内存溢出之前,GC将这些对象列入回收范围进行第二次回收
弱引用:只能生存到下一次垃圾收集之前,无论内存是否足够,都会被回收
虚引用:唯一目的在对象被GC回收时受到一个系统通知。
如果对象在进行可达性分析时发现没有GC Roots相连的引用链,该对象会被第一次标记并且进行一次筛选,筛选条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finali或者finalize方法被虚拟机调用过,jvm都将这两种方式视为没有必要执行。
如果有必要执行,该对象会被放入一个叫做F-Queue队列中,稍后虚拟机自动创建一个低优先级的finalizer线程去执行它,即触发这个方法。稍后GC会对F-Queue中对象进行第二次小规模标记,如果通过finalize拯救了自己,则被移除出即将回收集合,否则就真的被回收
方法区的GC包括:jvm规范中说过可以不要求jvm在方法区实现垃圾收集
永久代垃圾回收的两个主要内容:废弃常量和无用的类
3:垃圾收集算法
标记清除算法
首先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象
不足:效率问题,大量不连续的内存碎片
复制算法
将内存按容量比例划分成两块,只使用一块,当这一块用完,将还存活着的对象复制到另一块上,可实现整个半区的内存回收,不考虑内存碎片。但是可使用的内存缩小
标记整理算法
首先和标记清除算法一样标记处可回收对象,其次让所有存活对象移到一端,然后直接清理掉端边界以外的内存。
分代收集算法
在新生代,每次垃圾回收都有大量对象死去,只有少量存活,可考虑复制算法,而老年代,可考虑标记清理或标记整理算法
GMS收集器
是一种以获取最短回收停顿时间为目标的收集器。
运作过程分为四步:
初始标记
并发标记
重新标记
并发清除