• 深入理解Java虚拟机

    • [JVM]Java内存区域与垃圾收集 - 思维导图
    • [JVM]类加载机制 - 思维导图
    • [JVM]OOM实例分析
    • [JVM]理解Class文件(1):手动解析常量池
    • [JVM]理解GC日志
    • [JVM]理解Class文件(2)

1. 输出GC日志

通过阅读GC日志,我们可以了解Java虚拟机内存分配与回收策略
先来看一个简单的示例,通过设置VM参数"XX:+PrintGCDetails"就可以打印出GC日志


zhanghuamaodeMacBook-Pro:java zhanghuamao$ java -XX:+PrintGCDetails TestClass
hello
HeapPSYoungGen      total 76288K, used 3932K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)eden space 65536K, 6% used [0x000000076ab00000,0x000000076aed7240,0x000000076eb00000)from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)to   space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)ParOldGen       total 175104K, used 0K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000)object space 175104K, 0% used [0x00000006c0000000,0x00000006c0000000,0x00000006cab00000)Metaspace       used 2630K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 286K, capacity 386K, committed 512K, reserved 1048576K
  • PSYoungGen
    PS是Parallel Scavenge收集器的缩写,它配套的新生代称为PSYoungGen,新生代又分化eden space、from space和to space这三部分

  • ** ParOldGen**
    Parallel Scavenge收集器配套的老年代

  • Metaspace
    Parallel Scavenge收集器配套的永久代

  • total & used
    总的空间和用掉的空间

2. GC日志分析

2.1 新生代Minor GC

先来回顾下垃圾回收算法,通常新生代按照8:1:1(eden space + survivor from space + survivor to space)进行内存划分,新生产的对象会被放到eden space,当eden内存不足时,就会将存活对象移动到survivor区域,如果survivor空间也不够时,就需要从老年代中进行分配担保,将存活的对象移动老年代,这就是一次Minor GC的过程。

新生代

1. 示例代码

  • code

/*** VM agrs: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails* -XX:SurvivorRatio=8 -XX:+UseSerialGC*/public class MinorGCTest {private static final int _1MB = 1024 * 1024;public static void testAllocation() {byte[] allocation1, allocation2, allocation3, allocation4;allocation1 = new byte[2 * _1MB];allocation2 = new byte[2 * _1MB];allocation3 = new byte[2 * _1MB];allocation4 = new byte[4 * _1MB];}public static void main(String[] agrs) {testAllocation();}
}
  • VM参数说明
Option Description
-verbose:gc 显示GC的操作内容
-Xms20M -Xmx20M 设置堆大小为20M
-Xmn10M 设置新生代的内存空间大小为10M
-XX:+PrintGCDetails 打印GC中的变化
-XX:SurvivorRatio=8 新生代中Eden区域与Survivor区域的大小比值
-XX:+UseSerialGC 在新生代和老年代中使用串行收集器,由于-verbose:gc参数对Parallel Scavenge收集器不起作用,无法显示显示GC的操作内容,因此采用串行收集器
  • 示例代码说明
  • 该段代码一共创建了4个数组对象,在给allocation4分配空间前的内存空间使用情况如下:

before MinorGC

  • 需要执行一次MinorGC才能给allocation4分配空间,分配成功以后内存空间使用情况如下:

after MinorGC

2. GC日志

Minor GC日志

  • [GC [DefNew ... ...]

  • GC日志开头的信息通过设置-verbose:gc参数后才能输出。

  • "[GC""[Full GC"说明这次垃圾收集的停顿类型,如果这次GC发生了Stop-The-World,则为"[Full GC",否则为"[GC"

  • "[DefNew "表示GC发生的区域为Serial收集器的新生代中,DefNew是"Default New Generation"的缩写。Serial收集器的老年代和永久代分别表示为"Tenured""Perm"

  • ** eden space 8192K, 52% used**

  • 新生代的Eden区总共大小为8MB,使用掉的4MB是用来存放allocation4对象

  • tenured generation total 10240K, used 6144K

  • 老年代大小为10MB,使用掉的6MB是用来存放allocation1、allocation2和allocation3这3个对象

2.2 大对象直接进入老年代

1. 示例代码

  • code

/*** VM agrs: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails* -XX:SurvivorRatio=8 -XX:+UseSerialGC      * -XX:PretenureSizeThreshold=3145728*/public class TestClass2 {private static final int _1MB = 1024 * 1024;public static void testPretenureSizeThreshold() {byte[] allocation;allocation = new byte[4 * _1MB];}/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubtestPretenureSizeThreshold();}}
  • VM参数说明
Option Description
-XX:PretenureSizeThreshold=3145728 所占用内存大于该值的对象直接分配到老年代,3145728为3MB
  • 示例代码说明
    该段代码创建了一个数组对象allocation,大小为4MB,已经超出PretenureSizeThreshold设置的范围,该对象将直接被分配到老年代中。

2. GC日志

大对象直接进入老年代-GC日志

  • tenured generation total 10240K, used 4096K
    老年代大小为10MB,用掉的4MB用来存放allocation对象

2.3 长期存活的对象进入老年代

1. 示例代码

  • code

/*** VM agrs: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails* -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:MaxTenuringThreshold=1*/public class TestClass3 {private static final int _1MB = 1024 * 1024;public static void testTenuringThreshold() {byte[] allocation1, allocation2, allocation3;allocation1 = new byte[_1MB / 4];allocation2 = new byte[4 * _1MB];allocation3 = new byte[4 * _1MB];allocation3 = null;allocation3 = new byte[4 * _1MB];}public static void main(String[] agrs) {testTenuringThreshold();}
}
  • VM参数说明
Option Description
-XX:MaxTenuringThreshold=1 对象晋升为老年代的年龄阀值为1
  • 示例代码说明
    该段代码创建了3个数组对象,当执行到"allocation3 = new byte[4 * _1MB]; "时,Eden已经被占用了256KB + 4MB,而创建allocation3需要4MB,已经超过Eden的大小8MB,需要先发生一次MinorGC,才能保证有空间存放allocation3

2. GC日志

  • 设置参数为MaxTenuringThreshold=1的运行结果

  • 由GC日志开头的两句"[GC [DefNew"可知,该段代码一共发生了2次GC,第一次是"allocation3 = new byte[4 * _1MB]; ",第二次是执行allocation3 = null

  • allocation1在经过第一次GC时,对象年龄变成了1,由于设置的MaxTenuringThreshold=1,当发生第二次GC时,allocation1的年龄已经超出了设置的阀值,allocation1进入到老年代,因此,新生代的from space使用空间为0,对应GC语句为from space 1024K, 0% used

MaxTenuringThreshold=1

  • 设置参数为MaxTenuringThreshold=15的运行结果
    由于设置的MaxTenuringThreshold=15,发生第二次GC时,allocation1的年龄没有超出设置的阀值,因此,新生代的from space使用空间不为0,对应GC语句为from space 1024K, 44% used

MaxTenuringThreshold=15

3. 参考

  • 深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)

JVM:GC日志解读相关推荐

  1. java eden space_《深入理解Java虚拟机》(六)堆内存使用分析,垃圾收集器 GC 日志解读...

    堆内存使用分析,垃圾收集器 GC 日志解读 重要的东东 在Java中,对象实例都是在堆上创建.一些类信息,常量,静态变量等存储在方法区.堆和方法区都是线程共享的. GC机制是由JVM提供,用来清理需要 ...

  2. JVM GC日志详细分析,ParallelGC和G1

    一.默认垃圾回收器:ParallelGC jvm启动参数: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof - ...

  3. GC日志解读,这次别再说看不懂GC日志了

    测试环境:机器内存16G,JDK 8,12核CPU 测试用例,从网上找的示例,视情况修改即可: import java.util.Random; import java.util.concurrent ...

  4. java8 gc配置_基于JDK8的JVM参数设置和GC日志解读

    一.在IDEA中设置程序的运行参数 Run -> Edit Configuration -XX:+PrintGCDetails -Xms30M -Xmx30M -Xmn10M -XX:Survi ...

  5. JVM GC 日志详解

    本文采用的JDK版本: java version "1.8.0_144" Java(TM) SE Runtime Environment (build 1.8.0_144-b01) ...

  6. linux 输出gc日志,Tomcat输出保存JVM GC日志文件

    当系统出现问题时,分析java虚拟机GC日志可以帮助我们定位问题,一般来说, 我们可以通过制定JVM参数使tomcat保存GC日志文件,具体实现如下: Windows下 找到tomcat的解压目录,进 ...

  7. JVM GC日志说明

    本例jvm配置(jdk1.8) -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGCDetails gc日志 [GC (Allocati ...

  8. GC 日志解读与分析:千淘万漉虽辛苦,吹尽狂沙始到金

    本章通过具体示例来演示如何输出 GC 日志,并对输出的日志信息进行解读分析,从中提取有用的信息. 本次演示的示例代码 为了演示需要,我们先来编写一段简单的 Java 代码: package demo. ...

  9. JVM GC日志分析

    常用JVM参数 http://blog.csdn.net/gzh0222/article/details/8223277  分析gc日志后,经常需要调整jvm内存相关参数,常用参数如下 -Xms:初始 ...

最新文章

  1. Luogu P4178 Tree (点分治 + 树状数组)
  2. 下列关于python的说法中、正确的是-以下关于 Python版本的说法中,哪个是正确的?...
  3. Spring创建对象的三种方式以及创建时间
  4. 2.本征矩阵 基本矩阵以及对极几何之间的约束关系
  5. 关于Spring 声明式事务处理时,throws exception不回滚的问题
  6. SSM项目spring配置文件详细步骤(分门别类、灵巧记忆)
  7. 内部类访问局部变量的时候,为什么变量必须加上final修饰
  8. 最大值_285期 博最大值2路,已经箭在弦上!
  9. 2017年中国大功率UPS市场需求、市场需求及市场结构占比分析预测
  10. mysql盲注ascii中文_[翻译]关于通过对8bit的ascii做右位移提高mysql盲注效率
  11. matlab 局部特征检测与提取(问题与特征)
  12. ICMAX解析运行内存发展新趋势 LPDDR4X将会给手机带来哪些改变?
  13. xp计算机怎么共享网络,xp系统手机usb共享网络上网,xp共享上网-
  14. 矢量网络分析仪测量相位是靠什么实现的
  15. 关机时Ubuntu-Unattended upgrade in progress during shutdown
  16. 状态码如何返回Http/1.1 200 OK
  17. Python自动化运维实战:使用Python管理网络设备
  18. App安全软件防护能力检测
  19. activiti 获取审批人员_Activiti审批汇总流程
  20. 快速上手LaTex,书写美观学术论文

热门文章

  1. PHP设计模式——迭代模式
  2. 扩展方法where方法查询不到数据,不会抛异常,也不是返回的null
  3. 自己做站点(二) 20块钱搞定一个企业站:域名amp;空间申请
  4. sscanf函数中类型不匹配警告引发的BUG和思考
  5. 一网打尽深度学习之卷积神经网络的经典网络(LeNet-5、AlexNet、ZFNet、VGG-16、GoogLeNet、ResNet)
  6. GPAC MP4文件写入(支持H264、H265)
  7. mongodb,redis,mysql 简要对比
  8. 高并发的epoll+线程池,epoll在线程池内
  9. vc简易网络服务器、客户端实现
  10. php判断完整数,PHP的几个常用数字判断函数代码