`
和你在一起
  • 浏览: 678131 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM调优总结(五)-分代垃圾回收详述1

阅读更多

 

为什么要分代

    分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。

 

    在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命周期比较长。但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对象甚至只用一次即可回收。

 

    试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,花费时间相对会长,同时,因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有效果的,因为可能进行了很多次遍历,但是他们依旧存在。因此,分代垃圾回收采用分治的思想,进行代的划分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。

 

如何分代

 

如图所示:

 

    虚拟机中的共划分为三个代:年轻代(Young Generation)、年老点(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。

 

 

年轻代:

    所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个Survivor区(一般而言)。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。

 

年老代:

    在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

 

持久代:

    用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=<N>进行设置。

 

什么情况下触发垃圾回收

    由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GCFull GC

 

Scavenge GC

    一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

 

Full GC

    对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:

· 年老代(Tenured)被写满

· 持久代(Perm)被写满 

· System.gc()被显示调用 

·上一次GC之后Heap的各域分配策略动态变化

33
0
分享到:
评论
14 楼 sparksun007 2019-01-05  
lseeo 写道
pigzee 写道
和zhwayne 一样,不是很理解Survivor的运行机制。lz能详细说一下嘛?

同不理解唉,能再解释下么?

就是survivor区中只有一个区域存活,另一个全部清空【即每次只使用其中一块】
13 楼 tenghoo 2017-01-10  
持久代是HotSpot中的概念,其他虚拟机没有这个概念。
HotSpot中,持久代=方法区。
12 楼 lseeo 2013-04-07  
pigzee 写道
和zhwayne 一样,不是很理解Survivor的运行机制。lz能详细说一下嘛?

同不理解唉,能再解释下么?
11 楼 huangxingfu_0221 2012-11-30  
和你在一起 写道
-XX:MaxTenuringThreshold
对象将会在Survivor来回复制N次,这个N等于MaxTenuringThreshold设置的值,然后才会进入年老代。

laser_lu 写道
您这篇文章在介绍年轻代的时候提到“根据程序需要,Survivor区是可以配置为多个的(多于两个)”。
如何配置?配置参数是什么?


lz上述解释是对的,希望修改一下博文的文字表述,会给人错解的哦,再次感谢楼主
10 楼 pigzee 2011-10-20  
和zhwayne 一样,不是很理解Survivor的运行机制。lz能详细说一下嘛?
9 楼 iyfd 2011-10-06  
有个小失误,"Full GC对整个堆进行整理,包括Young、Tenured和Perm",Perm是non-heap,所以改成“Full GC对整个JVM进行整理,包括Young、Tenured和Perm”更合适。不过也无伤大雅。
8 楼 和你在一起 2011-06-01  
-XX:MaxTenuringThreshold
对象将会在Survivor来回复制N次,这个N等于MaxTenuringThreshold设置的值,然后才会进入年老代。

laser_lu 写道
您这篇文章在介绍年轻代的时候提到“根据程序需要,Survivor区是可以配置为多个的(多于两个)”。
如何配置?配置参数是什么?

7 楼 laser_lu 2011-04-25  
您这篇文章在介绍年轻代的时候提到“根据程序需要,Survivor区是可以配置为多个的(多于两个)”。
如何配置?配置参数是什么?
6 楼 mmhhllren 2010-01-19  
太爽了,看您的文章,寥寥数字就能把问题说得很清楚
5 楼 zhwayne 2009-11-26  
是不是可以认为年轻代是基于复制的GC管理机制
‘Survivor区总有一个是空的’如何理解,你说的如果是两个Survivor区的,并且对称,是不是说Eden区整理的结果放在两者中的概率是相等的,那如何保证有一个是空的。

另:读了博主这个系列的文章有了不少收获,希望继续写下去,谢谢。
4 楼 和你在一起 2009-11-26  
@huangtian549
感谢支持!
其实在JVM这块确实没有太多的书可以参考,比较经典的就是《深入java虚拟机》、jvm spec(这个我也没细读,太痛苦)、然后是sun网站上关于jvm、垃圾回收相关的文档,对于IBM和BEA的虚拟机我了解不多。

JDK几个版本在垃圾回收这块没有本质的变化,主要就是垃圾回收算法的增强和新算法的引入。

对于调优方面的东西,后面的文章会有涉及,希望能对你有帮助。
3 楼 huangtian549 2009-11-25  
看了博主的文章,受益良多,非常感谢,但想请问两个问题
1.看了垃圾回收的原理,但是不知道根据上面的原理,怎么来对现有的系统调优?虽然说每个系统都有自己的特殊情况,但是不知道博主有没有根据以往的项目经验,总结出一些规律没有?
2. 博主对JVM理解的那么深,是通过哪些书上学到的?能不能推荐一下? 以前在网上看到说《Inside JVM》不错,但是又看到有人说那本书太老了,现在新的JDK变化很大,书中很多都不对了,能不能推荐基于JDK1.5的分析JVM的?
2 楼 和你在一起 2009-11-24  
@myali88
Perm区也存在垃圾回收的。因为虚拟机支持动态类装载,因此Perm区中的一些类信息一样会成为“不被引用”信息。
1 楼 myali88 2009-11-24  
引用
对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,

但是从jconsole里运行来看(下图),它把Perm Gen视为非堆内存,对非堆内存,GC也负责垃圾搜集吗?

相关推荐

Global site tag (gtag.js) - Google Analytics