java6_garbage collection(垃圾回收)

现在觉得回顾或者学习知识,应该先从全局整理了解,然后整理出大纲比较好,这样既让你对这方面的知识有个整体连贯的了解,又利于今后复习,对照大纲哪些不清楚,有针对性的去钻研

说到垃圾回收,回收之前,先要有价值的东西才能产生垃圾                     :java内存的申请、分配

买了东西,当然要有地方放                                                                      :java运行时数据区

现在有地方放东西了,东西放太久了,肯定就产生垃圾了,要有人去回收:垃圾回收器的种类

是蜻蜓点水式了,还是大扫除了                                                               :垃圾回收的方式

地方大了,不好弄                                                                                    :堆的分代

有的地形复杂,有点地形简单,根据不同的地形采用不同的清扫方法       :垃圾回收的算法

什么时候需要搞卫生了                                                                             :什么条件触发GC

哪些地方派遣哪些人                                                                                :根据不同的代选择不同的垃圾回收器

为什么有些地方搞卫生的时间相对而言比较长,而且比较频繁                 :年轻代、老年代和持久代的参数设置问题,即经常产生full GC

卫生任务没有完成,失败                                                                         :出现oom(OutOfMemoryError) ,java内存泄露的监控(找出内存泄露的原因)

有时需要看看这些搞卫生的记录                                                               :打印GC的日志以及日志分析工具gcviewer-1.32

现场看打扫卫生情况                                                                                :图形化工具java自带的jvisualvm和jprofiler,关联hprof文件

怎样快速完成任务                                                                                    :调优(Sun JDK 16 GC ( Garbage Collector) 毕玄

                                                                                                                    http://www.docin.com/p-417999249.html)

 

 

基本收集算法

复制(copy):将堆内分成两个相同空间,从根(ThreadLocal的对象,静态对象)开始访问每一个关联的活跃对象,将空间A的活跃对象全部复制到空间B,然后一次性回收整个空间A。
因为只访问活跃对象,将所有活动对象复制走之后就清空整个空间,不用去访问死对象,所以遍历空间的成本较小,但需要巨大的复制成本和较多的内存

标记清除(mark-sweep):收集器先从根开始访问所有活跃对象,标记为活跃对象。然后再遍历一次整个内存区域,把所有没有标记活跃的对象进行回收处理。该算法遍历整个空间的成本较大暂停时间随空间大小线性增大,而且整理后堆里的碎片很多

标记整理(mark-sweep-compact):综合了上述两者的做法和优点,先标记活跃对象,然后将其合并成较大的内存块。

 

GC收集器类型

串行收集器(Serial Collector):-XX:+UseSerialGC:策略为年轻代串行复制,年老代串行标记整理

并行收集器(Throughput Collector):-XX:+UseParallelGC:这是JDK5 -server的默认值。

             策略为:
                     年轻代:暂停应用程序,多个垃圾收集线程并行的复制收集,线程数默认为CPU个数,CPU很多时,可用-XX:ParallelGCThreads= 设定线程数。
                     年老代:暂停应用程序,与串行收集器一样,单垃圾收集线程标记整理。
                     如上可知该收集器需要2+的CPU时才会优于串行收集器,适用于后台处理,科学计算

并发收集器(Concurrent Low Pause Collector-CMS):-XX:+UseConcMarkSweepGC:

             这是以上两种策略的升级版

             策略为:
             年轻代:同样是暂停应用程序,多个垃圾收集线程并行的复制收集。
             年老代:则只有两次短暂停,其他时间应用程序与收集线程并发的清除。

增量并发收集器(Incremental Concurrent-Mark-Sweep/i-CMS):

             虽然CMS收集算法在最为耗时的内存区域遍历时采用多线程并发操作,但对于服务器CPU资源不够的情况下,其实对性能是没有提升的,反而会导致系统吞吐量 的下降,

             为了尽量避免这种情况的出现,就有了增量CMS收集算法,就是在并发标记、清理的时候让GC线程、用户线程交叉运行,尽量减少GC线程的全程独占 式执行;

          并行、并发的区别

                     并行:指多条垃圾收集线程并行,此时用户线程是没有运行的;

                     并发:指用户线程与垃圾收集线程并发执行,程序在继续运行,而垃圾收集程序运行于另一个个CPU上。

                               并发收集一开始会很短暂的停止一次所有线程来开始初始标记根对象,然后标记线程与应用线程一起并发运行,最后又很短的暂停一次,多线程再次并行运行,

                          为了重新标记之前可能因为并发而漏掉的对象,然后就开始与应用程序并发的清除过程。可见,最长的两个遍历过程都是与应用程序并发执行的,

                          比以前的串行算法改进太多太 多了!!!
                          串行标记清除是等年老代满了再开始收集的,而并发收集因为要与应用程序一起运行,如果满了才收集,应用程序就无内存可用,所以系统默认 68%满的时候就开始收集。

                          内存已设得较大,吃内存又没有这么快的时候,可以用-XX:CMSInitiatingOccupancyFraction= 恰当增大该比率。

 

 

GC的方式

当每个代满了之后都会自动促发collection,各收集器触发的条件不一样,当然也可以通过一些参数进行强制设定。主要分为两种类型:

       Minor Collection:GC用较高的频率对young进行扫描和回收,采用复制算法。

       Major Collection:同时对Young和Old进行内存收集,也叫Full GC;因为成本关系对Old的检查回收频率要比Young低很多,采用标记清除/标记整理算法。

                               可以通过调用代码System.gc()  引发major collection,使用-XX:+DisableExplicitGC禁止它,或设为CMS并发 -XX:+ExplicitGCInvokesConcurrent。

              备注:通常将对新生代进行的回收称为Minor GC;对旧生代进行的回收称为Major GC,但由于Major GC除并发GC外均需对整个堆进行扫描和回收,因此又称为Full GC。

 

内存分配:

                    新生成的对象在Eden区完成内存分配

年轻代GC触发条件:

                     当Eden区满时触发minor collection

年轻代内存回收:Eden及某一Survior space(from space)之内存活的的对象被移到另一个空的Survior space(to space)中,

                     (当然第一次的时 候,就是只有eden区内活着的对象移动,随便选一个作为to space),然后from space和to space角色对调。

                     然后清空Eden和Survior space(from space)(当然第一次就只清空Eden,因为from space都没有对象了),始终保证一个survivor是空的。

年轻代晋升到老年代的条件:

                     当一个对象在两个survivor space之间移动过一定次数(通过XX:MaxTenuringThreshold参数来设置)时,它就足够old了,够资格呆在年老代了。

                     当然,如果survivor space比较小不足以容下所有live objects时,部分live objects也会直接晋升到年老代。


Survior spaces可以看作是Eden和年老代之间的缓冲,通过该缓冲可以检验一个对象生命周期是否足够的长,因为某些对象虽然逃过了一次Minor Collection,并不能说明其生命周期足够长,说不定在下一次Minor Collection之前就挂了。这样一定程度上确保了进入年老代的对象是货真价实的,减少了年老代空间使用的增长速度,也就降低年老代GC的频率。


老年代或永久代GC触发条件:

                      当年老代或者永久代的内存使用达到一定阀值时,System.gc()被显示调用,一次基于所有代的GC就触发了

                      其特定是涉及范围广(量大),耗费的时间相对较长(较慢),但是频率比较低 (次数少),称之为Major Collection(Full Collection)。

老年代或永久代内存回收:

                      通常,首先使用针对年轻代的GC算法进行年轻代的GC,然后使用针对年老代的GC算法对年老代和永久代进行GC

 

 

分代

分代是Java垃圾收集的一大亮点,根据对象的生命周期长短,把堆分为3个代:Young,Old和Permanent,根据不同代的特点采用不同的收集算法,扬长避短

Young(年轻代)复制算法

        Young里面又分为3个区域,一个Eden,所有新建对象都会存在于该区,两个Survivor区,用来实施复制算法。每次复制就是将Eden和第一块 Survior的活对象复制到第2块,然后清空Eden与第一块Survior。Eden与Survivor的比例由 -XX:SurvivorRatio=设置,默认为32。Survivio大了会浪费,小了的话,会使一些年轻对象潜逃到老人区,引起老人区的不安,但这 个参数对性能并不重要

Tenured(年老代) 标记整理算法

     年轻代的对象如果能够挺过数次收集,就会进入老人区。老人区使用标记整理算法。因为老人区的对象都没那么容易死的,采用复制算法就要反复的复制对象,很不合算,只好采用标记清理算法,但标记清理算法其实也不轻松,每次都要遍历区域内所有对象,所以还是没有免费的午餐啊。
-XX:MaxTenuringThreshold= 设置熬过年轻代多少次收集后移入老人区,CMS中默认为0,熬过第一次GC就转入,可以用-XX:+PrintTenuringDistribution查看。

Perm(permanent)持久代

          装载Class信息等基础数据,默认64M,如果是类很多很多的服务程序,需要加大其设置-XX:MaxPermSize=,否则它满了之后会引起 fullgc()或Out of Memory。 注意Spring,Hibernate这类喜欢AOP动态生成类的框架需要更多的持久代内存。一般情况下,持久代是不会进行GC的,除非通过 -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled进行强制设置。

 

Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning(原文):

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

 

Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning(译文):

http://translate.google.com/translate?js=n&prev=_t&ie=UTF-8&tl=cn&u=http%3A%2F%2Fwww.oracle.com%2Ftechnetwork%2Fjava%2Fjavase%2Fgc-tuning-6-140523.html

 

http://blog.csdn.net/sfdev/article/details/4483442

http://blog.csdn.net/calvinxiu/article/details/1614473

posted on 2013-06-14 11:36  lovebeauty  阅读(934)  评论(0编辑  收藏  举报

导航