JVM垃圾回收机制

JVM垃圾回收

整体思维导图

Paste_Image.png

带着问题理解JVM垃圾回收机制

  1. Java为什么需要垃圾回收机制;

  2. 回收哪部分垃圾;

  3. 如何判断是垃圾;

  4. 垃圾回收算法有哪些;

  5. 有哪些垃圾回收器;

对于以上的问题,基本可以在思维导图中找到答案。接下来我们主要描述一下垃圾回收流程及CMS垃圾回收器。

垃圾回收流程

基本概念

Java分为年轻代,老年代,持久代(但在JDK1.8中持久代已经被元空间替代),GC的类型有Major GC、Full GC、 Minor GC、YGC,我们姑且只需要知道Major GC回收老年代, Minor GC、YGC不同叫法而已,回收年轻代,Full GC整个内存堆(年轻代也包括年老代)就行啦。接下来的描述只用YGC和Full GC。

回收流程

年轻代有个Eden区和两个surivior区,我们首先得意识到surivior区是交换分区,其中必须有一个是空的。创建对象后首先将对象放在Eden区,单Eden区满后,进行垃圾回收,生效存活的对象放在一个surivior区,姑且成为sur1,如果sur1放不下直接放到老年代,接下来创建的对象继续放在Eden区,待到Eden区满时,将Eden+sur1的回收,然后剩余的放在空闲的sur2,接下来就一直这样交互,你可以设置GC多少次还存活的对象到老年代,对于对象优先在Eden区存放,但是对于大的对象也可以直接存放在老年代。

CMS回收器详解

CMS是老年代的垃圾回收机器,默认和它搭配的ParNew的年轻代垃圾回收器。CMS是目标是为了获取最短停顿时间。
它的垃圾清除分为四个阶段:

  1. 初始标记:仅仅是标记和GC ROOT关联的对象,速度很快。需要Stop The World

  2. 并发标记:并发标记阶段就是进行GCRoots Tracing的过程。

  3. 重新标记:为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。需要Stop The World

  4. 并发清除:进行垃圾清理工作。

这个4个阶段可以用打扫卫生来描述:首先妈妈首先整理家里有用的东西(初始标记);接下来找需要清理的物品,但是她不清楚这个到底要不要,她需要进行判断(并发标记阶段,判断的依据可达性分析),在判断垃圾的时候,小孩子调皮捣蛋不停的产生垃圾(这个就是并发引起的,并发标记时用户线程继续工作);接下来妈妈告诉小孩,乖乖坐在沙发上,收拾完垃圾后你再下来;妈妈继续重新标记(这是用户线程停止),收拾好后,孩子下来玩,妈妈将垃圾装到垃圾袋处理掉。

盗用网上一张图片:


缺点:

  1. 对于CPU资源敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程(或者说CPU 资源)而导致应用程序变慢,总吞吐量会降低。CMS 默认启动的回收线程数是(CPU 数量+3)/ 4 。

  2. CMS收集器无法处理浮动垃圾,CMS并发清理的时候用户线程还在工作。这部分用户线程产生的垃圾将没法清除,这一部分垃圾就称为“浮动垃圾”。同时并发清理的时用户线程也在工作的时候,需要给用户线程提供空间,当用户空间不够时,就会出现一次“Concurrent Mode Failure 失败,这时虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,会停顿较长时间。

  3. 收集结束时会产生大量空间碎片。CMS 基于“标记一清除”算法实现。多次垃圾回收后,虽然老年代有很多空间,但是足够大的连续空间来分配当前对象,不得不Full GC。为此可以设置CMS收集器要进行FullGC时开启内存碎片整理。-XX:+UseCMSCompactAtFullCollection默认值为0,表示每次进入FullGC 时都进行碎片整理。

简单的JVM配置

JAVA_OPTS='-Xms2048m -Xmx2048m -XX:PermSize=256M 
-XX:MaxPermSize=512M -XX:MaxTenuringThreshold=4 
-XX:+UseConcMarkSweepGC -XX:SurvivorRatio=5 
-XX:CMSInitiatingOccupancyFraction=70 
-XX:+PrintTenuringDistribution 
-XX:+PrintGCDetails -XX:+PrintGCDateStamps  
-XX:+HeapDumpOnOutOfMemoryError -Ddruid.registerToSysProperty=true'

需要设置属性:配置堆大小,持久代大小,年轻代和老年代的比值,年轻代Een和surivior区比值,垃圾回收器,GC多少次年轻代对象直接到老年代,打印垃圾回收信息等。

配置参考:http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. 前言 网上关于jvm gc的文章有很多,写这篇文章不是有什么新东西要讲,主要原因是工作时也偶尔碰到比如ful...
    aaron1993阅读 5,077评论 0 0
  • JVM架构 当一个程序启动之前,它的class会被类装载器装入方法区(Permanent区),执行引擎读取方法区的...
    cocohaifang阅读 5,656评论 0 7
  • 来自: Android梦想特工队作者: Aaron主页: http://www.wxtlife.com/原...
    技术特工队阅读 9,927评论 0 28
  • 作者:一字马胡 转载标志 【2017-11-12】 更新日志 日期更新内容备注 2017-11-12新建文章初版 ...
    beneke阅读 6,644评论 0 7
  • 垃圾回收算法具体实现 翻译原文 => plumbr Java GC handbook 前文参见: Java垃圾回收...
    foxracle阅读 7,908评论 0 15

友情链接更多精彩内容