JVM系列(二)--垃圾收集

来源:互联网 发布:关于网络的作文 高中 编辑:程序博客网 时间:2024/05/17 02:33

如果从垃圾收集进行分析,我觉得可以从两个方面进行:

         1.如何判断某一个对象可以进行回收

         2.在哪些Runtime Data Area进行回收

         3.如何进行回收

一.判断某个对象是否可以回收

主流的商用语言,如Java及C#甚至Lisp都是采用GC Roots Tracing(根搜索算法)判断某个对象是否可以进行回收。具体的做法是选定一些可以作为GC Roots的对象,如:

     a.JVM Stack的Stack Frame中的局部变量表中引用的对象。

     b.Method Area中类的静态属性引用的对象。

     c.Method Area中的常量引用的对象。

     d.Native Method Area中引用的对象。


如果某一个对象到GC Roots没有Reference Chain,则该对象被判定为可以回收。


大致的回收过程如下:

1.以根搜索算法判定某个对象到GC Roots是否存在Reference Chain,进行第一次标记并判断是否有必要执行finalize()方法。

2.如被判定有必要执行finalize()方法,则进入F-Queue队列中,进行第二次标记,如果在finalize()执行过程中未建立到GC Roots的Reference Chain,则该对象注定要被回收,反之则被移除即将会后的集合。


二.在哪些区域进行回收

分析这个问题需要从分配的角度去理解:

前提,Java Heap 可以分为新生代与老年代

      1.大多数情况下,对象在新生代Eden区中分配。

       2.大对象直接进入老年代。

      3.长期存活的对象进入老年代。

根据以上分配策略,可以知道,回收主要发生在Java Heap中。


是否要对Method Area进行回收?

首先我们知道,HotSpot的Method Area存在垃圾回收。

根据以往的数据分析结果,Method Area发生的垃圾回收效率太低,主要因为以下原因:

Method Area中垃圾回收主要针对废弃的常量和无用的类,回收废弃的常量较为容易,但是回收无用的类却较为麻烦,因为一个类是否需要回收的判定条件太苛刻:

1.该类所有的实例都已经被回收,即Java Heap中不存在该类的任何实例

2.加载该类的ClassLoader已经被回收

3.该类对应的java.lang.Class对象没有在任何地方被引用,无法在热河地方通过反射访问该类的方法

当然,可以通过一下几个参数进行控制:

-Xnoclassgc 不回收类


三.如何进行回收

先来看几种垃圾回收算法的原理及优缺点:

      1.Mark-Sweep(标记清除)算法

先标记,后清除。

缺点:容易产生大量的不连续内存(内存碎片),这样在分配大对象时较为麻烦。


     2.Copying(复制算法)

复制算法的思想:

将内存非为两块,每次只使用一块,当这一块用完了,就将这块内存中存活的对象复制到另外一块内存上,然后将第一块内存中的对象进行一次性回收。

优点:高效

缺点:将内存一份为二,代价较高。

现在的商业虚拟机都使用这种算法对新生代进行回收,如HotSpot对新生代进行回收的方式:

将新生代分为Eden空间、From Survivor空间、To Survivor空间,默认比例为8:1:1

每次回收时将Eden空间与其中一块Survivor空间中存活的对象复制到另外一块Survivor空间上,然后进行清除,这其中还涉及到分配担保的概念

3.Mark-Compact(标记整理)算法

针对老年代的回收算法

每次回收时进行整理,将未被标记的对象(存活对象)移动到一端,然后清理掉边界以外的内存。


4.Generational Collection(分代收集)

分代垃圾回收的思想是针对不同区域的特点,在不同区域应用不同的回收算法。

新生代:Mark-Copying-Sweep

老年代: Mark-Compact-Sweep



Minor GC与Full GC

Minor GC即新生代GC,主要针对Java Heap的新生代,Minor GC较为频繁快速。

Full GC即老年代GC,主要针对Java Heap的老年代,Full GC较Minor GC慢10倍左右。


本文出自 “思考者John” 博客,请务必保留此出处http://paladinapple.blog.51cto.com/4502795/1317906

原创粉丝点击