垃圾收集器及内存分配

目录

垃圾收集器种类

HotSpot虚拟机所包含的收集器

垃圾收集器部分源码

垃圾收集器后台日志参数说明与配对关系

1、串行垃圾收集器

串行垃圾收集器运行示意图

1)、编写测试代码

2)、设置垃圾回收为串行收集器

3)、启动程序,GC日志信息解读

2、并行垃圾收集器

并行垃圾收集器-ParNew运行示意图

1)、编写测试代码

2)、设置垃圾回收为并行收集器ParNew

3)、启动程序,GC日志信息解读

并行垃圾收集器-ParallelGC运行示意图

1)、编写测试代码

2)、设置垃圾回收为并行收集器ParallelGC

3)、启动程序,GC日志信息解读

3、CMS垃圾收集器

CMS垃圾收集器运行示意图:

1)、编写测试代码

2)、设置CMS垃圾回收参数

3)、启动程序,GC日志信息解读

4、G1垃圾收集器

G1垃圾收集器(将新生代,老年代的物理空间划分取消了),示意图如下

G1垃圾收集器(G1算法将堆划分为若干个区域-Region)

G1垃圾收集器原理

G1垃圾回收模式:Young GC

G1垃圾回收模式:Mixed GC

G1垃圾收集器运行示意图

1)、编写测试代码

2)、G1垃圾收集器相关参数:

3)、设置G1垃圾回收参数

4)、启动程序,GC日志信息解读

G1垃圾收集器 vs CMS垃圾收集器

G1垃圾收集器优化建议

可视化GC日志分析工具

1、GC日志输出参数

2、GC Easy可视化工具

GC Easy查看gc报告


垃圾收集器种类

垃圾收集器及内存分配_第1张图片

HotSpot虚拟机所包含的收集器

垃圾收集器及内存分配_第2张图片

垃圾收集器及内存分配_第3张图片

垃圾收集器部分源码

垃圾收集器及内存分配_第4张图片

垃圾收集器后台日志参数说明与配对关系

  • DefNew - Default New Generation
  • Tenured - Old
  • ParNew - Parallel New Generation
  • PSYoungGen - Parallel Scavenge
  • ParOldGen - Parallel Old Generation

1、串行垃圾收集器

串行垃圾收集器是最基本的、发展历史最悠久的收集器。

特点:单线程、简单高效(与其他收集器的单线程相比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。收集器进行垃圾回收时,必须暂停其他所有的工作线程,直到它结束(Stop The World)。

串行垃圾收集器运行示意图

垃圾收集器及内存分配_第5张图片

1)、编写测试代码

import java.util.UUID;

/**************************************************
 *
 * @title
 *
 **************************************************/
public class TestGC1 {
    /**
     * java -XX:+PrintCommandLineFlags -version
     *
     * @param args
     */
    public static void main(String[] args) {
        String str = "smart";
        while (true) {
            str += str + UUID.randomUUID();
            str.intern();
        }
    }
}

2)、设置垃圾回收为串行收集器

在程序运行参数中添加2个参数,如下:

-XX:+UseSerialGC 指定年轻代和老年代都使用串行垃圾收集器

-XX:+PrintGCDetails 打印垃圾回收的详细信息

3)、启动程序,GC日志信息解读

垃圾收集器及内存分配_第6张图片

2、并行垃圾收集器

并行垃圾收集器在串行垃圾收集器的基础之上做了改进,将单线程改为了多线程进行垃圾回收,这样可以缩短垃圾回收的时间。(这里是指,并行能力较强的机器)

当然了,并行垃圾收集器在收集的过程中也会暂停应用程序,这个和串行垃圾回收器是一样的,只是并行执行,速度更快些,暂停的时间更短一些。

并行垃圾收集器-ParNew运行示意图

垃圾收集器及内存分配_第7张图片

ParNew垃圾收集器

通过-XX:+UseParNewGC参数设置年轻代使用ParNew回收器,老年代使用的依然是串行收集器

通过-XX:+ParallelGCThreads可以限制GC线程数量,默认开启和cpu数目相同的线程数

1)、编写测试代码

同之前的代码

2)、设置垃圾回收为并行收集器ParNew

在程序运行参数中添加1个参数,如下

-XX:+UseParNewGC
-Xms8m
-Xmx8m
-XX:+PrintGCDetails
-XX:+PrintCommandLineFlags

3)、启动程序,GC日志信息解读

垃圾收集器及内存分配_第8张图片

解释:

        ParNew - 年轻代ParallelNew垃圾收集器

        Tenured - 老年代Serial Old垃圾收集器

并行垃圾收集器-ParallelGC运行示意图

垃圾收集器及内存分配_第9张图片

ParallelGC垃圾收集器

ParallelGC收集器工作机制和ParNewGC收集器一样,只是在此基础之上,新增了两个和系统吞吐量相关的参数,使得其使用起来更加的灵活和高效。适合大数据计算。

1)、编写测试代码

同之前代码

2)、设置垃圾回收为并行收集器ParallelGC

ParallelGC垃圾收集器相关参数如下:

-XX:+UseParallelGC

-XX:+UseParallelOldGC

-XX:MaxGCPauseMillis

-XX:ParallelGCThreads=N

解释:

        (1)-XX:+UseParallelGC、-XX:+UseParallelOldGC这两个参数可以相互激活,也就是说,配置一个可以,可以不用配置另外一个;

        (2)-XX:MaxGCPauseMillis - 最大停顿时间,其值为大于0的毫秒数,垃圾收集器尽可能保证回收的耗时不超过设定的值,但是并不是越小越好,如果值设置太小,那么GC的频率会提高,这样吞吐量就降低了。

        (3)-XX:GCTimeRatio=99 - 控制吞吐量大小,其值为0-100的整数,表示吞吐量,默认值是99,表示允许1%的垃圾回收时间占比。

        (4)-XX:ParallelGCThreads=N - 控制垃圾回收线程数,此参数设置年轻代并行收集器的线程数,一般与CPU数量相等,过多的线程数量会影响垃圾回收以及整个程序的性能。

        (5)-XX:UseAdaptiveSizePolicy - ParallelGC可以自动调整Survivor空间,大部分的程序使用自动调整可以满足要求,个别应用在需要的情况下可以关闭自动调整,进行手动调整

具体:请参考https://www.cnblogs.com/ysqzy/p/16930918.html

3)、启动程序,GC日志信息解读

垃圾收集器及内存分配_第10张图片

解释: 

        PSYoungGen - Parallel Scavenge

        ParOldGen -  Parallel Old Generation

3、CMS垃圾收集器

CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,通过参数-XX:+UseConcMarkSweepGC进行设置。适合互联网,响应时间短、CPU核数多的应用。

CMS垃圾收集器运行示意图

垃圾收集器及内存分配_第11张图片

CMS垃圾回收器的执行过程如下:

垃圾收集器及内存分配_第12张图片

执行过程拆解:

        (1)初始标记

        垃圾收集器及内存分配_第13张图片

        (2)并发标记

垃圾收集器及内存分配_第14张图片

        (3)预处理

垃圾收集器及内存分配_第15张图片

垃圾收集器及内存分配_第16张图片

        (4)重新标记

垃圾收集器及内存分配_第17张图片

        (5)并发清理垃圾收集器及内存分配_第18张图片

        (6)重置线程

垃圾收集器及内存分配_第19张图片

1)、编写测试代码

同之前的代码

2)、设置CMS垃圾回收参数

-‐XX:+UseConcMarkSweepGC

注意:开启后将采用ParNew+CMS+Serial Old收集器组合

3)、启动程序,GC日志信息解读

垃圾收集器及内存分配_第20张图片

4、G1垃圾收集器

G1垃圾收集器是在jdk1.7update4中正式使用的全新的垃圾收集器,oracle官方在jdk9中将G1变成默认的垃圾收集器,以替代CMS。

G1的设计原则就是简化JVM性能调优,开发人员只需要简单的三步即可完成调优:

  • 第一步,开启G1垃圾收集器
  • 第二步,设置堆的最大内存
  • 第三步,设置最大的停顿时间
    • G1中提供了三种模式垃圾回收模式,Young GC、Mixed GC 和 Full GC,在不同的条件下被触发

G1垃圾收集器相对比其他收集器而言,最大的区别在于它取消了年轻代、老年代的物理划分,取而代之的是将堆划分为若干个区域(Region),这些区域中包含了有逻辑上的年轻代、老年代区域。这样做的好处就是,我们再也不用单独的空间对每个代进行设置了,不用担心每个代内存是否足够。

G1垃圾收集器(将新生代,老年代的物理空间划分取消了),示意图如下

垃圾收集器及内存分配_第21张图片

G1垃圾收集器(G1算法将堆划分为若干个区域-Region)

垃圾收集器及内存分配_第22张图片

G1垃圾收集器原理

垃圾收集器及内存分配_第23张图片

垃圾收集器及内存分配_第24张图片

解释:

        G1每个堆区域最大32M,默认划分2048个区域,也就是说最大64G内存。

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

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

在G1中,有一种特殊的区域,叫Humongous区域。如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。

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

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

针对Young GC主要是对Eden区进行GC,它在Eden空间耗尽时会被触发。Eden空间的数据移动到Survivor空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间。

Survivor区的数据移动到新Survivor区中,也有部分数据晋升到老年代空间中。最终Eden空间的数据为空,GC停止工作,应用线程继续执行。

G1垃圾回收模式:Young GC

垃圾收集器及内存分配_第25张图片

G1垃圾回收模式:Mixed GC

分2步:

  • 全局并发标记(global concurrent marking)
  • 拷贝存活对象(evacuation)

当-XX:InitiatingHeapOccupancyPercent=N (老年代大小占堆百分比达45%的时候触发mixed GC),触发MixedGC,执行下面流程

G1垃圾收集器运行示意图

垃圾收集器及内存分配_第26张图片

1)、编写测试代码

同之前的代码

2)、G1垃圾收集器相关参数:

-XX:UseG1GC

-XX:MaxGCPauseMillis - 执行最大GC暂停时间

-XX:G1HeapRegionSize=N (1-32M,默认2048个分区,最大64G内存)

-XX:G1ReservePercent=N - 预留空闲空间,避免内存溢出,默认10%,一般不能设置

-XX:ConcGCThreads=N - GC线程数

-XX:InitiatingHeapOccupancyPercent=N (老年代大小占堆百分比达45%的时候触发mixed GC)

3)、设置G1垃圾回收参数

‐XX:+PrintGC 输出GC日志

‐XX:+PrintGCDetails 输出GC的详细日志

‐XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)

‐XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013‐05‐04T21:53:59.234+0800)

‐XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息

‐Xloggc:F://test//gc.log 日志文件的输出路径

4)、启动程序,GC日志信息解读

垃圾收集器及内存分配_第27张图片

G1垃圾收集器 vs CMS垃圾收集器

  • G1不会产生碎片
  • G1可以精准控制停顿,它把整堆划分为多个固定大小的区域,每次根据停顿时间去收集垃圾最多的区域

G1垃圾收集器优化建议

  • 年轻代大小

    • 避免使用 -Xmn 选项或 -XX:NewRatio 等其他相关选项显式设置年轻代大小
    • 固定年轻代的大小会覆盖暂停时间目标
  • 暂停时间目标不要太过严苛

    • G1 GC 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间
    • 评估 G1 GC 的吞吐量时,暂停时间目标不要太严苛。目标太过严苛表示您愿意承受更多的垃圾回收开销,而这会直接影响到吞吐量

可视化GC日志分析工具

1、GC日志输出参数

前面通过-XX:+PrintGCDetails可以对GC日志进行打印,我们就可以在控制台查看,这样虽然可以查看GC的信息,但是并不直观,可以借助于第三方的GC日志分析工具进行查看。 在日志打印输出涉及到的参数如下:

‐XX:+PrintGC 输出GC日志

‐XX:+PrintGCDetails 输出GC的详细日志

‐XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)

‐XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013‐05‐04T21:53:59.234+0800)

‐XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息

‐Xloggc:F://test//gc.log 日志文件的输出路径

测试:

最后生成gc.log,我们利用下面的可视化工具进行分析。

2、GC Easy可视化工具

GC Easy是一款在线的可视化工具,易用、功能强大, GCEasy官网地址:Universal JVM GC analyzer - Java Garbage collection log analysis made easy

打开官网上传gc.log,点击分析即可。分析完之后它会给我们出相关的分析报告,那查看指标如何解读呢?

GC Easy查看gc报告

垃圾收集器及内存分配_第28张图片

垃圾收集器及内存分配_第29张图片

垃圾收集器及内存分配_第30张图片

垃圾收集器及内存分配_第31张图片

垃圾收集器及内存分配_第32张图片

你可能感兴趣的:(Java,java,jvm,jdk)