首页 > 系统相关 >jvm 内存变化监控测试,观察Eden 内存增长到最大,触发GC、堆内存越来越高,触发FullGC,直到最后内存溢出。打印GC日志 -XX:+PrintGC -XX:+PrintGCDetails -

jvm 内存变化监控测试,观察Eden 内存增长到最大,触发GC、堆内存越来越高,触发FullGC,直到最后内存溢出。打印GC日志 -XX:+PrintGC -XX:+PrintGCDetails -

时间:2025-01-23 23:43:08浏览次数:1  
标签:0.00 XX secs GC 内存 15872K

1 测试准备

1)写一个程序,创建一个二维的直接数组,长度为10000,用于存放生成的数据;

2)写一个while 循环,每秒向二维数组中放入1个 1M 的字节数组;

package com.spqin.jvm;

/**
 * @author Spqin
 * @version 1.0
 * @Date 2022-09-11 19:52
 */
public class JvmTest {
    public static void main(String[] args) {
        byte[][] byteArray = new byte[10000][];
        int n = 0;
        while(true){
            try {
                //每秒50M 数据,放入到字节数组的数组中
                byteArray[n] = new byte[1024 * 1024 * 1];
                n++;
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3)运行时设置最大堆内存和最小堆内存为 4G,运行程序。

-Xms4G -Xmx4G -XX:+PrintGC

 2 监测过程

2.1 查看内存结构

通过jmap 查看内存非配信息,5296 是jvm的进程Id,可以通过 jpsjconsole 查看

jmap -heap 5296

可以查看默认jvm 默认的配置信息  

NewRatio = 2,默认 年轻代和老年代比率是1:2,通过NewRatio设置,默认值是2,代表1:2 的意思

由于最大堆内存 4G = 4096M,年轻代占 1/3 ,4096 ÷ 3 = 1365.333 ≈ 1365.0M,老年代 占 2/3,4096 × 2 ÷ 3 = 2730.667 ≈ 2731.0M

SurvivorRatio = 8 ,这个值是幸存者区在整个新生代中的占比,即新生代分成个8份,两个幸存者区各占1份,Eden 区占6份,Eden:From:To = 6:1:1

由于年轻代已知是1365M,所以Eden 区是 1365 M 的 0.75,1365 × 0.75 = 1023.75 ≈ 1024.0M,2个生存者区都是 (1365 - 1024)÷ 2 =  170.5M

通过下面的信息得以验证

2.2 查看堆内存使用情况

通过jstat 监测查看堆内存使用过程

jstat -gcutil pid 毫秒数 # 周期性查看堆内存各组成的使用率
jstat -gcnew pid 毫秒数 # 周期性查看堆内存中 年轻代使用情况
jstat -gcold pid 毫秒数 # 周期性查看堆内存中 老年代使用情况

1)刚开始查看结果,幸存者区使用都是0,使用率肯定也是0,Eden 区每秒增加1M数据,使用率按每秒 1%~2% 增长

 2)当Eden 区内存增长到(或超过)了最大值 1024M 时,就触发GC

日志查看及分析(这里是我查看到一个代时间片段的资料,主要看有的信息就行,带日期的是另外一个命令打印的)

 通过GC 日志分析,该区域总容量 = 4091712K = 3925.5M,是整个清理区域的内存,大于年轻代总内存,小于年轻代+老年代总内存,说明这是一次并发收集,即收集了 Eden + From(或者To)+Old = 4096 - 170.5 = 3925.5 ,刚好验证了我们的结论。

 清理前只有Eden 区有数据,是1047809k,清理后Eden 区还有796163K ,即清理了1047809k - 796163K = 251646k ≈245.748M,清理后剩余的数据796163K,放入到幸存者1区,放不下,只放了174561.7k(占用了幸存者区的174561.7k ÷ 174592 = 0.99982 ≈ 99.98%),剩下的数据放到了老年代 621601.5k(占用了老年代的621601.5Kk÷ 2796544k = 0.222274 ≈ 22.23%)

和上文的截图一致。

 3)GC后,Eden 区内存继续增长,再次增长到(或超过)了最大值 1024M 时,就再次触发GC,如下如所示

GC 前的数据1843950k ,这一部分数据应该有上次清理后剩余的数据 796163k ,Eden 区的数据是 1843950k - 796163k = 1047787k 和 上次清理前Eden 区的数据 1047809k 接近(相差22k),清理之后的内存是1738265k,其中174561.8k 放入到幸存者2区,剩余1563703.9 放到了,老年代,清空幸存者1区和Eden 区。

幸存者区 占比 还是99.98%,老年代占比上升到 1563703.9 ÷ 2796544 = 0.559155 ≈ 55.92%

 4)GC后,Eden 区内存继续增长,再次增长到(或超过)了最大值 1024M 时,就第3次触发GC,如下如所示

GC 前的数据2786841k = 2.65G ,这一部分数据应该有上次清理后剩余的数据 796163k ,Eden 区的数据是 2786841k - 1738265 k = 1048576 k 和 上次清理前Eden 区的数据 1047787k 接近(相差789k),清理之后的内存是2711072 k ≈ 2.59G,清理后的数据都放进了老年代,清空幸存者1区、2区和Eden 区。

幸存者区 占比 变成0,老年代占比上升到 2710908.7 ÷ 2796544 = 0.969377 ≈ 96.94%

  5)GC后,Eden 区内存继续增长,再次增长到(或超过)了最大值 1024M 时,开始触发Full GC,如下如所示

GC 前,由于老年代已经达到了96.94%,Eden 区又产生了1024M 的数据,老年代放不下新生成的数据了,触发了Full GC,但是内存是清理不掉多少,清理后Eden 区的数据有一部分被转移到了了老年代,老年代内存上升到了99.96%,Eden 区内存占用也达到了 88.39%,此时程序还在继续产生数据,每秒1M,很快又达到了1024M

 

接下来就是频繁的Full GC,但是能清理掉的数据也是越来越少,清空越来越严重,连续出现Full GC ,内存溢出了,Eden 直接到了 100%,老年代也到了99.96%,清理越来越赶不上增长,最后挽救不了了,最后爆炸了。

 

 3 更详细的日志打印

3.1 -verbose:gc 参数和-XX:+PrintGC 效果一样

打印效果都是

[GC (Allocation Failure) 3203K->1767K(15872K), 0.0013214 secs]
[GC (Allocation Failure) 4917K->4855K(15872K), 0.0008501 secs]
[GC (Allocation Failure) 7997K->7975K(15872K), 0.0010062 secs]
[Full GC (Ergonomics) 7975K->7842K(15872K), 0.0062387 secs]
[GC (Allocation Failure) 11070K->10914K(15872K), 0.0009302 secs]
[Full GC (Ergonomics) 10914K->10899K(15872K), 0.0068005 secs]

3.2 -XX:+PrintGCDetails 参数,打印的更详细

想看详细的信息用 -XX:+PrintGCDetails,想看简单的信息 用 -XX:+PrintGC

打印效果如下

[GC (Allocation Failure) [PSYoungGen: 3972K->495K(4608K)] 3972K->2195K(15872K), 0.0007601 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 3634K->503K(4608K)] 5335K->5291K(15872K), 0.0008066 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 3638K->471K(4608K)] 8426K->8331K(15872K), 0.0010018 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 471K->0K(4608K)] [ParOldGen: 7860K->8234K(11264K)] 8331K->8234K(15872K), [Metaspace: 3744K->3744K(1056768K)], 0.0096754 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 3141K->0K(4608K)] [ParOldGen: 8234K->11219K(11264K)] 11375K->11219K(15872K), [Metaspace: 3745K->3745K(1056768K)], 0.0087364 secs] [Times: user=0.13 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 3217K->3072K(4608K)] [ParOldGen: 11219K->11219K(11264K)] 14437K->14291K(15872K), [Metaspace: 3745K->3745K(1056768K)], 0.0080702 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 3072K->3072K(4608K)] [ParOldGen: 11219K->11219K(11264K)] 14291K->14291K(15872K), [Metaspace: 3745K->3745K(1056768K)], 0.0023664 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 4608K, used 3182K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
  eden space 4096K, 77% used [0x00000000ffb00000,0x00000000ffe1b880,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 11264K, used 11219K [0x00000000ff000000, 0x00000000ffb00000, 0x00000000ffb00000)
  object space 11264K, 99% used [0x00000000ff000000,0x00000000ffaf4e00,0x00000000ffb00000)
 Metaspace       used 3776K, capacity 4536K, committed 4864K, reserved 1056768K
  class space    used 415K, capacity 428K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.spqin.jvm.gclog.JvmGcPrintTest.main(JvmGcPrintTest.java:15)

3.3 -XX:+PrintGCTimeStamps 可以打印出GC 时间戳

-XX:+PrintGCTimeStamps 打印时间戳,此时间戳为打印GC 日志时,JVM 启动的时间。

1.124: [GC (Allocation Failure) [PSYoungGen: 3972K->495K(4608K)] 3972K->2235K(15872K), 0.0011614 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
4.147: [GC (Allocation Failure) [PSYoungGen: 3634K->479K(4608K)] 5375K->5291K(15872K), 0.0010732 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
7.163: [GC (Allocation Failure) [PSYoungGen: 3614K->511K(4608K)] 8426K->8411K(15872K), 0.0014633 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
7.164: [Full GC (Ergonomics) [PSYoungGen: 511K->0K(4608K)] [ParOldGen: 7900K->8234K(11264K)] 8411K->8234K(15872K), [Metaspace: 3745K->3745K(1056768K)], 0.0101831 secs] [Times: user=0.13 sys=0.00, real=0.01 secs] 
10.190: [Full GC (Ergonomics) [PSYoungGen: 3141K->0K(4608K)] [ParOldGen: 8234K->11219K(11264K)] 11375K->11219K(15872K), [Metaspace: 3745K->3745K(1056768K)], 0.0081231 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
13.222: [Full GC (Ergonomics) [PSYoungGen: 3217K->3072K(4608K)] [ParOldGen: 11219K->11219K(11264K)] 14437K->14291K(15872K), [Metaspace: 3745K->3745K(1056768K)], 0.0097859 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
13.232: [Full GC (Allocation Failure) [PSYoungGen: 3072K->3072K(4608K)] [ParOldGen: 11219K->11219K(11264K)] 14291K->14291K(15872K), [Metaspace: 3745K->3745K(1056768K)], 0.0027274 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 4608K, used 3182K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
  eden space 4096K, 77% used [0x00000000ffb00000,0x00000000ffe1b880,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 11264K, used 11219K [0x00000000ff000000, 0x00000000ffb00000, 0x00000000ffb00000)
  object space 11264K, 99% used [0x00000000ff000000,0x00000000ffaf4e30,0x00000000ffb00000)
 Metaspace       used 3777K, capacity 4536K, committed 4864K, reserved 1056768K
  class space    used 415K, capacity 428K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.spqin.jvm.gclog.JvmGcPrintTest.main(JvmGcPrintTest.java:15)

3.4 -XX:+PrintGCDateStamps 打印日期戳

-XX:+PrintGCDateStamps 打印日期戳,这里日期戳打印的当前系统时间,具体到

2025-01-23T23:07:47.360+0800: 1.120: [GC (Allocation Failure) [PSYoungGen: 3934K->503K(4608K)] 3934K->2203K(15872K), 0.0009505 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2025-01-23T23:07:50.378+0800: 4.137: [GC (Allocation Failure) [PSYoungGen: 3642K->487K(4608K)] 5342K->5331K(15872K), 0.0012393 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2025-01-23T23:07:53.400+0800: 7.159: [GC (Allocation Failure) [PSYoungGen: 3622K->487K(4608K)] 8466K->8419K(15872K), 0.0013130 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2025-01-23T23:07:53.401+0800: 7.160: [Full GC (Ergonomics) [PSYoungGen: 487K->0K(4608K)] [ParOldGen: 7932K->8235K(11264K)] 8419K->8235K(15872K), [Metaspace: 3746K->3746K(1056768K)], 0.0089178 secs] [Times: user=0.13 sys=0.00, real=0.01 secs] 
2025-01-23T23:07:56.425+0800: 10.184: [Full GC (Ergonomics) [PSYoungGen: 3141K->0K(4608K)] [ParOldGen: 8235K->11219K(11264K)] 11376K->11219K(15872K), [Metaspace: 3746K->3746K(1056768K)], 0.0084256 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2025-01-23T23:07:59.467+0800: 13.226: [Full GC (Ergonomics) [PSYoungGen: 3217K->3072K(4608K)] [ParOldGen: 11219K->11219K(11264K)] 14437K->14291K(15872K), [Metaspace: 3746K->3746K(1056768K)], 0.0078200 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2025-01-23T23:07:59.475+0800: 13.234: [Full GC (Allocation Failure) [PSYoungGen: 3072K->3072K(4608K)] [ParOldGen: 11219K->11219K(11264K)] 14291K->14291K(15872K), [Metaspace: 3746K->3746K(1056768K)], 0.0023979 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 4608K, used 3182K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
  eden space 4096K, 77% used [0x00000000ffb00000,0x00000000ffe1b8d0,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 11264K, used 11219K [0x00000000ff000000, 0x00000000ffb00000, 0x00000000ffb00000)
  object space 11264K, 99% used [0x00000000ff000000,0x00000000ffaf4e60,0x00000000ffb00000)
 Metaspace       used 3778K, capacity 4536K, committed 4864K, reserved 1056768K
  class space    used 415K, capacity 428K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.spqin.jvm.gclog.JvmGcPrintTest.main(JvmGcPrintTest.java:15)

3.5 -Xloggc:path/gc.log 

上述都是把日志打印到控制台,把日志打印到当前目录下的path 目录下的gc.log 文件中,打印之前要确保 文件出在,不然会报错。

-Xloggc:E:\study\javase-demo\gclogs/gc.log

查看日志文件

3.6 GC 日志查看

3.6.1 Minor GC 年轻代GC

 

3.6.2 Full GC 年轻代GC

 

 

 

3.5 上述文件的代码

源码在 javase-demo 下的jvm 文件夹中。

package com.spqin.jvm.gclog;

/**
 * -Xms16m -Xmx16m -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps
 * 解释
 * -XX:+PrintGC 参数和 -verbose 参数效果一样
 * -XX:+PrintGCDetails 替代 -XX:+PrintGC,打印的更详细
 * -XX:+PrintGCTimeStamps 记录打印日志时 JVM 启动了多久,单位S,例如 1.120秒
 * -XX:+PrintGCDateStamps 记录打印日志时 当前系统的时间,例如 2025-01-23T23:07:47.360+0800:
 * @author Spqin
 * @version 1.0
 * @Date 2022-09-11 19:52
 */
public class JvmGcPrintTest {
    public static void main(String[] args) {
        byte[][] byteArray = new byte[10000][];
        int n = 0;
        while(true){
            try {
                //每秒50M 数据,放入到字节数组的数组中
                byteArray[n] = new byte[1024 * 1024 * 1];
                n++;
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

标签:0.00,XX,secs,GC,内存,15872K
From: https://www.cnblogs.com/spqin/p/18687563

相关文章

  • 9. SpringCloud Alibaba Sentinel 流量控制、熔断降级、系统负载,热点规则的部署设置讲
    9.SpringCloudAlibabaSentinel流量控制、熔断降级、系统负载,热点规则的部署设置讲解@目录9.SpringCloudAlibabaSentinel流量控制、熔断降级、系统负载,热点规则的部署设置讲解1.Sentinel是什么?2.Sentinel控制台3.Sentinel下载&安装&运行4.Sentinel监控微服务5.Se......
  • 一篇文章,从源码深入详解ThreadLocal内存泄漏问题
    目录一、造成内存泄漏的原因?二、已经做出了哪些改进?三、threadLocal最佳实践一、造成内存泄漏的原因?threadLocal是为了解决对象不能被多线程共享访问的问题,通过threadLocal.set方法将对象实例保存在每个线程自己所拥有的threadLocalMap中,这样每个线程使用自己的对象......
  • 【LLM应用开发】 langchain框架的 4大组件
    在人工智能的浪潮中,大型语言模型(LLM)逐渐成为推动科技进步的重要力量。而LangChain,作为一个专为LLM应用开发设计的框架,凭借其模块化和高效性,受到了广泛关注。本文将深入浅出地讲解LangChain中的四个基础组件:PromptTemplate、LLMs、Chain和OutputParser,帮助入门者快速上手。一、Pro......
  • Springcloud在线问诊平台-毕业设计源码24037
    基于springcloud技术的在线问诊平台的设计与实现摘 要在当今社会,医疗资源分配的不均衡和医疗卫生资源的匮乏成为了制约医疗服务质量提升的关键因素。特别是在广大农村地区和偏远地区,优质的医疗资源更是稀缺。因此,打破地域限制,实现医疗资源的优化配置和高效利用,成为了医疗......
  • 2025春招 SpringCloud 面试题汇总
    大家好,我是V哥。SpringCloud在面试中属于重灾区,不仅是基础概念、组件细节,还有高级特性、性能优化,关键是项目实践经验的解决方案,都是需要掌握的内容,正所谓打有准备的仗,秒杀面试官,如果你正在准备这一块内容,V哥整理的以下面试题及答案,可能在2025年SpringCloud面试中出现,......
  • 在Rust中大范围使用引用会导致生命周期泛滥, 但是使用结构体clone也会导致内存的频繁分
    eeeeeeeeeeeeeeeeeeeeee在Rust中,引用和克隆各有优缺点,你的选择需要基于实际应用场景的需求进行权衡。以下是一些分析和建议:使用引用的优缺点优点:性能更优:避免了内存的分配和拷贝操作。更适合读密集场景:如果数据只需要被读取而不需要修改,引用非常高效。显式的生命周期管......
  • 为嵌入式板卡交叉编译gcc
    需要提前准备什么?交叉编译器(以及相应的sysroot,可以通过xxx-gcc--print-sysroot来查看路径)gcc源码,这里我用的是7.5.0版本的,也可以尝试别的下载地址binutils源码,光有gcc是不行的,还需要as才可以完成整个编译过程下载地址编译器路径其实一般情况下我是比较建议直接使用交叉......
  • 实数域上的DP?——[AGC020F] Arcs on a Circle
    #实数域上的DP?——[AGC020F]ArcsonaCircle有点没搞懂。---注意到线段长度为整数,即li和ri的小数部分一定相同而判断两个线段是否相交只会用到l和r的相对大小关系,所以可以对小数部分离散化然后就可以dp了。先断环为链,$n!$暴力枚举小数部分相对大小,离散化以后一共......
  • Hugging Face全面拥抱LangChain:全新官方合作包
    最近HuggingFace官宣发布langchain_huggingface,这是一个由HuggingFace和LangChain共同维护的LangChain合作伙伴包。这个新的Python包旨在将HuggingFace最新功能引入LangChain并保持同步。本系列合集,点击链接查看通过官方包的加持,开发小伙伴们通过简单的api调用......
  • spring-boot-starter-data-redis OutOfDirectMemoryError 堆外内存泄漏
    一、现象  起因:应用经常重启,JVM内存是比较稳定,查看错误日志发现是堆外内存泄漏,而且观看相关的trace,只有这个用户会导致OutOfDirectMemoryError继续排查现象查看redis出口流量远没有这么大查看对应堆栈的数据的key,也木有这么大。900KB左右(这个很大,也是促成现象的原......