zoukankan      html  css  js  c++  java
  • GC垃圾收集器

    垃圾收集器

      简介:

        在JVM中,实现了多种垃圾收集器,包括:串行垃圾收集器,并行垃圾收集器,CMS(并发)垃圾收集器,G1垃圾收集器;

      1.串行垃圾收集器

        只有一个线程在进行垃圾回收,其他线程都要停止(STW),不适合用在交互性较高的应用当中通过设置VM Options参数制定我们采用串行垃圾收集器,并且打印垃圾收集信息

        模拟实战代码如下:

    public class GCTest {
        public static void main(String[] args) throws InterruptedException {
            List<Object> objList = new ArrayList<>();
            while (true) {
                //延迟时间
                int sleep = new Random().nextInt(100);
                //当时间戳为偶数情况下,将集合数据清空
                if (System.currentTimeMillis() % 2 == 0) {
                    objList.clear();
                } else {
                    for (int i = 0; i <10000; i++) {
                        objList.add(i,"value_"+i);
                    }
                    Thread.sleep(sleep);
                }
            }
        }

      点击进去

       在VM options中添加如下代码: 

        -XX:+UseSerialGC -XX:+PrintGCDetails -Xms16m -Xmx16m

        解析:

          -XX:+UseSerialGC

            指定年轻代和老年代都是用串行垃圾收集器

          -XX:+PrintGCDetails

            打印垃圾回收的详细信息

          -Xms16m -Xmx16m

            将堆的初始和最大内存都设置为16M

      效果如下:

        GC日志信息解读:

          年轻代的内存GC前后的大小:

            DefNew:表示使用的是串行垃圾收集器

            4416K->512K(4928K):表示年轻代GC前,占有4416K内存,GC后,占有512K内存,总大小4928K

            0.0040300 secs:表示GC所用的时间,单位为毫秒

            9962K->7977K(15872K):表示GC前,堆内存占有9962K;GC后,占有7977K,总大小为15872K

            Full GC:表示,内存空间全部进行GC

      2.并行垃圾收集器

        多个线程进行垃圾回收,导致STW,缩短垃圾清理时间
        1.ParNew垃圾收集器
          工作在年轻代,通过-XX:UseParNewGC
              直接修改VM options中的如下代码:

       效果如下:

      可以看出ParNew:使用的是ParNew收集器。其他信息和串行收集器一致;我们可以对比一下可以发现并行比串行速度要快一些

        2.ParallelGC垃圾收集器
          与ParNew垃圾收集器机制相同,都是通过多个线程同时进行垃圾收集,同样会导致应用程序STW,可以通过参数设置提高程序吞吐量设置程序VM Options参数制定年轻代和年老代都是ParallelGC,并且设置垃圾收集停顿时间最大为100ms(年轻代和年老代默认使用该GC)
          -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xms16m -Xmx16m

        参数说明:

            -XX:+UseParallelGC

              年轻代使用ParallelGC垃圾回收期,老年代使用串行回收器;

            -XX:+UseParallelOldGC

              年轻代使用ParallelGC垃圾回收期,老年代使用ParallelOldGC垃圾回收器;

            -XX:MaxGCPauseMillis

              设置最大的垃圾收集时的停顿时间,单位为毫秒;

              需要注意的是,ParallelGC为了达到设置的停顿时间,可能会调整堆大小或其他的参数,如果堆的大小设置的较小,就会导致GC工作变得很频繁,反而可能会影响性能;

              带参数使用需谨慎;

            -XX:GCTimeRatio

              设置垃圾回收时间啊占程序运行时间的百分比,公式为1/(1+n);

              它的值为0~100之间的数字,默认值为99,也就是垃圾回收时间不能超过1%;

            -XX:UseAdptiveSizePolicy

              自适应GC模式,垃圾回收器将自动调整年轻代,老年代等参数,达到吞吐量,堆大小,停顿时间之间的平衡;

              一般用于,手动调整参数比较困难的场景,让收集器自动进行调整;

        效果如下:

         如上信息可以看出,年轻代和老年代都使用了ParallelGC垃圾回收器;

        3.CMS垃圾收集器

          串行和并行在进行垃圾收集时都会导致应用线程的停止,CMS可以同应用程序同步执行,该收集器是针对老年代,使用标记清除法进行垃圾回收
          1.只有标记阶段会导致应用程序停止,然后其他阶段都是与应用程序并行

          

          初始化标记(CMS-inital-mark):标记root,会导致stw;

          并发标记(CMS-concurrent-mark):与用户线程同时运行;

          预清理(CMS-concurrent-preclean):与用户线程同时运行;

          重新标记(CMS-remark):会导致stw;

          并发清除(CMS-concurrent-sweep):与用户线程同时运行;

          调整堆大小:设置CMS在清理之后进行内存压缩,目的是清理内存中的碎片;

          并发重置状态等待下次CMS的触发(CMS-concurrent-reset):与用户线程同时运行;

        实战测试:    

          -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xms16m -Xmx16m

        效果如下:

       优点及缺点:

        CMS主要优点:

          并发收集;

          低停顿;

        CMS主要缺点:

          对CPU资源敏感;

          无法处理浮动垃圾;

          它使用的回收算法“标记-清除”算法会导致收集结束时会有大量空间碎片产生;

        4.G1垃圾收集器

          将原有的内存模型划分成了每一个区域,包含Eden区,还包含S区,还包含O区,以及H区,其中H区存放短暂的占用空间50%以上的大对象

        在G1划分的区域中,年轻代的垃圾收集依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者Survivor空间,G1收集器通过将对象从一个区域复制到另外一个区域,完成了清理工作;

        这意味着,在正常的处理过程中,G1完成了堆的压缩(至少是部分对的压缩),这样也就不会有cms内存碎片问题的存在了;

        在G1中,有一中特殊的区域,叫Humongous区域:

          1.如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象;

          2.这些巨型对象,默认直接会被分配在老年代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响;

          3.为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC;

        YoungGC回收:

          1.专门回收Eden区的数据,当Eden区内存满了的情况下,会进行垃圾回收,Eden区的数据存活的对象会转移到Survivor区域,如果Survivor区域内存太小,那么Eden区就会将这个数据提升到Old区当中
          2.当suvivor区域满了会将数据转移到Old区
          3.Rset:记录引用地址,方便于快速定位,节省资源
          在垃圾回收的时候,我们需要定位到根对象,找根对象的引用关系,之前没有G1时,我们进行内存对象的全部扫描,G1提供一个Rset
          Rset专门存储引用的对象的位置,在哪一个区域,在哪一个Card当中
          G1垃圾收集器会将每一块Region分为若干个Card,每一个Card默认大小为512KB

        MixedGC:

          当越来越多的数据晋升到Old区域当中的情况下, 为了避免内存不足的情况,JVM虚拟机会启用MiexdGC,进行混合数据的回收,包含YongGC以及部分OldGC
          当老年代数据占用堆内存整体45%的时候会触发,可以通过 -XX:InitiatingHeapOccupancyPercent=n进行设置
          MixedGC回收的两个部分:
            1.全局标记
              初始化标记
              根节点扫描
              全局标记
              重新标记
              清除垃圾:并不是真正清除,而是恢复状态
            2.对象拷贝阶段
              将要回收的区域的存活对象复制到另外一个Region当中,然后进行垃圾清理
              G1参数:设置启用G1 设置暂停时间 设置堆内存大小
              -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xmx32m

            效果如下:

            优化建议:
              1.不要设置年轻代内存大小
              2.暂停时间不要太苛刻

  • 相关阅读:
    Core Animation 文档翻译—附录C(KVC扩展)
    Core Animation 文档翻译—附录B(可动画的属性)
    Core Animation 文档翻译—附录A(Layer样貌相关属性动画)
    Core Animation 文档翻译 (第八篇)—提高动画的性能
    Core Animation 文档翻译 (第七篇)—改变Layer的默认动画
    Core Animation 文档翻译 (第六篇)—高级动画技巧
    Core Animation 文档翻译 (第五篇)—构建Layer的层次结构
    用Markdown快速排版一片文章
    Core Animation 文档翻译 (第四篇)—让Layer的content动画起来
    Core Animation 文档翻译(第三篇)—设置Layer对象
  • 原文地址:https://www.cnblogs.com/ws1149939228/p/12427408.html
Copyright © 2011-2022 走看看