JVM的GC过程

既然创建的对象,在不使用后不会立马清除,会在GC时才真正清除,那么,

1.什么时候触发GC?

2.那一部分触发GC?

3.如何进行回收?

首先,我们从对象存储的部分看起,即堆内存。

我们代码在JVM上一直不停的跑,此时就会在堆内存中创建对象,此处假设我们初始的参数配置如下:

-Xms20M -Xmx20M  -Xmn10M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256 -XX:SurvivorRatio=8 
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
 -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/logs

配置详情,请浏览最下方。

然后运行一下测试方法:

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(30000);
        byte[] b=new byte[512*1024];
        for(int i=0;i<50;i++){
            Thread.sleep(1000);
            b=new byte[512*1024];
        }
    }
}

这里,每次new一个0.5M的对象。

先想象一下,当这段代码运行的时候,内存是如何变化的?

由上面配置,我们知道,新生代的内存大小是10M,默认Eden区:from:to的比例是:8:1:1

那么eden区占据了8M的内存,from和to各1M内存空间,启动程序,使用jps查看运行的进程PID。

C:\Users\HBL>jps
8080
12036 RemoteMavenServer
14196 Launcher
16996 Test
9268 Jps

找到我们的Test的进程,然后执行:

jstat -gc 16996 1000 1000

此方法是每隔一秒钟,更新出一条jstat统计语句,共打印1000次,当然程序结束也就不打印了。

这就是运行时实时查看内存变化。

这里截取了第二次和第三次的gc,由于项目启动会有一些配置对象,所以从第二次开始看

1.当上图第一个GC发生的时候,此时Eden区由8M左右的大小,变为0.5M,而s0由s1中的1M变为0.5M,此时可能会发现老年代增加了大约0.5M的数据,这其实是配置对象,所以开始就省略了一次GC截图。

2.当第二次发生GC后,Eden区又从8M左右变为0.5M,而s1由s0的0.5M变为0.5M,此时老年代没有增加数据。

注:

这里肯定存在一个疑问?

不是JVM默认15代后才进入老年代码,那这里为什么实际运行第二次GC就进入了?

这里要注意,当>n代的对象内存大于s1或s0的内存一半的时候,就会将大于n的代的对象直接晋升老年代。

接着你会问,那么为什么第一次都快1M了都没进入老年?

因为第一次GC的时候,即使大于一半也不会直接进入老年代,此处n必须大于1即上面的晋升条件,只是符合n>1的代数才会晋升。

接着我们现在清楚看到了内存在GC后的变化,用图展示如下:

要注意:

1.ParNew垃圾回收器使用的复制算法,同时它是多线程的。

2.ParNew垃圾回收器在执行过程中会造成STW,即它运行时,代码是不能运行的。

那么老年代如何进行垃圾回收,那就是ConcMarkSweep垃圾回收器,简称CMS垃圾回收器。

CMS的工作分四个步骤:

1)初始标记

此阶段,标记出GC Root直接引用的对象,会造成STW,即停止程序运行。

2)并发标记

这个阶段系统可以创建各种对象,继续运行。对老年代所有对象进行GC Root追踪。这个是最耗时的

3)重新标记

由于第二阶段是并行运行,所以会有很多对象创建和对象变为垃圾对象,所以此阶段需要重新标记,它是STW的。

4)并发清理

此阶段跟程序并行执行清理工作。

注:

并发标记和并发清理阶段会有Concurrent Mode Failture错误发生,它是老年代在进行CMS回收时,创建的新对象内存放不下从而报的错误。默认92%进行CMS。

此时,CMS就会停止,转为serial old垃圾回收。

最后,看一下JVM配置:

jps:查看Java进程的PID,

jstat -gc PID:查看进程的虚拟机。

jstat -gc PID 1000 10:每隔一秒,更新出一条jstat统计语句,更新十次。

-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=5

每5次full gc触发一次compaction,也就是压缩

jmap -dump:live,format=b,file=文件名 [服务进程ID]:生成内存快照

-XX:+HeapDumpOnOutOfMemoryError:当内存发生oom自动dump一份内存快照出来

-XX:HeapDumpPath=内存快照存放的地址

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值