JVM中GC日志查看与内存结构

Posted youxin2012

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM中GC日志查看与内存结构相关的知识,希望对你有一定的参考价值。

JVM中GC日志查看

package com.example;

public class TestMinorGC 
    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() 
        testAllocation();
    
vm option: -Xms20M -Xmx20M -Xmn10M -verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio=8

输出:

[GC [PSYoungGen: 7307K->480K(9216K)] 7307K->6624K(19456K), 0.0072860 secs] [Times: user=0.01 sys=0.01, real=0.00 secs]
[Full GC [PSYoungGen: 480K->0K(9216K)] [ParOldGen: 6144K->6476K(10240K)] 6624K->6476K(19456K) [PSPermGen: 2920K->2919K(21504K)], 0.0178620 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
[Full GC [PSYoungGen: 4354K->1024K(9216K)] [ParOldGen: 6476K->9536K(10240K)] 10831K->10560K(19456K) [PSPermGen: 2921K->2921K(21504K)], 0.0139610 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
[Full GC [PSYoungGen: 7339K->0K(9216K)] [ParOldGen: 9536K->4419K(10240K)] 16876K->4419K(19456K) [PSPermGen: 3004K->3004K(21504K)], 0.0120490 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
Heap
 PSYoungGen      total 9216K, used 4190K [0x00000007ff600000, 0x0000000800000000, 0x0000000800000000)
  eden space 8192K, 51% used [0x00000007ff600000,0x00000007ffa17a18,0x00000007ffe00000)
  from space 1024K, 0% used [0x00000007ffe00000,0x00000007ffe00000,0x00000007fff00000)
  to   space 1024K, 0% used [0x00000007fff00000,0x00000007fff00000,0x0000000800000000)
 ParOldGen       total 10240K, used 4419K [0x00000007fec00000, 0x00000007ff600000, 0x00000007ff600000)
  object space 10240K, 43% used [0x00000007fec00000,0x00000007ff050eb0,0x00000007ff600000)
 PSPermGen       total 21504K, used 3010K [0x00000007f9a00000, 0x00000007faf00000, 0x00000007fec00000)
  object space 21504K, 14% used [0x00000007f9a00000,0x00000007f9cf0bf8,0x00000007faf00000)

以一下两条日志为例

[GC [PSYoungGen: 7307K->480K(9216K)] 7307K->6624K(19456K), 0.0072860 secs] [Times: user=0.01 sys=0.01, real=0.00 secs]
[Full GC [PSYoungGen: 480K->0K(9216K)] [ParOldGen: 6144K->6476K(10240K)] 6624K->6476K(19456K) [PSPermGen: 2920K->2919K(21504K)], 0.0178620 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

其中GC, Full GC 说明垃圾收集的停顿类型,full GC表示其他线程均停止工作,仅有垃圾回收线程工作(较长的 停顿时间,会让用户很苦恼--线程莫名其妙停止工作;然而垃圾收集器实现者 确实需要这样的方式,毕竟用户线程一边 产生垃圾,垃圾收集线程要一边收集 也会很痛苦)
其中 PSYoungGen, ParOldGen 表示 GC发生的区域,该区域与 使用的GC收集器密切相关。
例 PSYoungGen 表示 采用 Parallel Scavenge收集器时, 新生代发生的变化
同理 当出现 DefNew 表示 采用 Serial收集器时,新生代发生的变化, default new generation。(收集器类型介绍 见后文)
方括号内数字:7307K->480K(9216K) 表示 GC前该内存区域已使用的容量 -> GC后该内存区域已使用的容量(该内存区域总容量)
方括号外数字:7307K->6624K(19456K) 表示 GC前java 堆已使用容量 -> GC后java堆已使用容量(java堆总容量)
0.0072860 secs 表示 该内存区域GC所占用的时间
[Times: user=0.01 sys=0.01, real=0.00 secs] :分别表示 用户态消耗cpu时间, 内核态消耗cpu时间,操作从开始到结束的墙钟时间。
其中cpu时间与墙钟时间:墙钟时间包括非运算等待耗时,io,线程阻塞等,cpu不包括。当多cpu或多核时 cpu时间为累加。

jvm运行时 内存区域:
大体包含:程序计数器,java虚拟机栈,本地方法栈,java堆,方法区。详见此处
其中:程序计数器,java虚拟机栈,本地方法栈 是线程私有的;
java堆,方法区 为各线程共享。
其中
为了让内存回收更加高效,Sun JDK从1.2开始对堆采用了分代管理的方式,下列引自此处

  1. 新生代(New Generation)
    大多数情况下Java程序中新建的对象都从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space(通常又称为S0和S1或From和To)构成,可通过-Xmn参数来指定新生代的大小,也可通过-XX:SurvivorRatio来调整Eden Space及Survivor Space的大小。不同的GC方式会以不同的方式按此值来划分Eden Space和Survivor Space,有些GC方式还会根据运行状况来动态调整Eden、S0、S1的大小。
  2. 旧生代(Old Generation或Tenuring Generation)
    用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象,新建的对象也有可能在旧生代上直接分配内存。主要有两种状况(由不同的GC实现来决定):一种为大对象,可通过在启动参数上设置-XX:PretenureSizeThreshold=1024(单位为字节,默认值为0)来代表当对象超过多大时就不在新生代分配,而是直接在旧生代分配,此参数在新生代采用Parallel Scavenge GC时无效,Parallel Scavenge GC会根据运行状况决定什么对象直接在旧生代上分配内存;另一种为大的数组对象,且数组中无引用外部对象。
    旧生代所占用的内存大小为-Xmx对应的值减去-Xmn对应的值。

可参考:http://blog.csdn.net/kobejayandy/article/details/8496663

以上是关于JVM中GC日志查看与内存结构的主要内容,如果未能解决你的问题,请参考以下文章

阿里面试100%问到,JVM性能调优篇

JVM之GC日志分析与对象内存分配回收策略

JVM性能调优(2) —— 内存设置和查看GC日志

JVM-GC日志查看分析

JVM GC 日志详解

java gc的日志在哪里看?