JVM垃圾回收之我见

来源:互联网 发布:js radio 取得 编辑:程序博客网 时间:2024/06/01 09:45

     很久之前就了解过JVM垃圾回收机制,最近又研究了一下,下面总结一下个人的心得体会,有不足之处还请指正。

1、为什么要有垃圾回收?回收的是什么?

    首先要从Java内存模型开始说起,JVM在启动时会创建堆和方法区(可被线程共享),当每增加一个线程时,JVM会创建本地方法栈、虚拟机栈和程序计数器(不可被共享)。线程一旦结束,这三块区域所占的空间也就随之被回收,他们跟垃圾回收似乎没啥关系。所以垃圾回收主要是堆和方法区中对象或变量所占空间的回收。

2、常见垃圾回收算法

    引用计数法(效果不好,不宜在循环时使用)、标记-清楚法(易产生内存碎片)、复制法(略占空间)、标记-整理法(可能效率问题)、分代法。

    着重介绍分代法:分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。目前大部分垃圾收集器对于新生代都采取复制算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。而由于老年代的特点是每次回收都只回收少量对象,一般使用的是标记-整理算法。

 注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。

3、垃圾回收器

   串行收集器(适合单CPU)、并行收集器(数据吞吐量好)、并发收集器(响应时间较好)、G1收集器。

   G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。

4、对象的内存分配

     往大方向上讲就是在堆上分配,对象主要分配在新生代的Eden Space和From Space,少数情况下会直接分配在老年代。如果新生代的Eden Space和From Space的空间不足,则会发起一次GC,如果进行了GC之后,Eden Space和From Space能够容纳该对象就放在Eden Space和From Space。在GC的过程中,会将Eden Space和From  Space中的存活对象移动到To Space,然后将Eden Space和From Space进行清理。如果在清理的过程中,To Space无法足够来存储某个对象,就会将该对象移动到老年代中。在进行了GC之后,使用的便是Eden space和To Space了,下次GC时会将存活对象复制到From Space,如此反复循环。当对象在Survivor区躲过一次GC的话,其对象年龄便会加1,默认情况下,如果对象年龄达到15岁,就会移动到老年代中。


0 0