【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数

时间:2022-12-27 14:01:56
在使用JVM编译java时,都会去设置相关的参数(例如使用eclipse的时候,可以设置eclipse的eclipse.ini文件来对jvm做一些参数配置)。jvm的参数设置主要涉及到三种,分别是Trace跟踪参数、堆的分配参数、栈的分配参数。

本章主要讲解Trace跟踪参数的相关信息。

(1)开启GC日志和打印简要信息
跟踪参数主要对jvm的GC(垃圾回收器)的状况。可以使用以下两种配置方式打开GC的日志:
-verbose:gc
-XX:+printGC
其中“printGC”就是打印GC的简要信息。在程序的运行过程中,如果发生了gc,就会打印出相关的数据,例如下面的日志信息就是一组gc回收的简要数据:
【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数
以第一行举例,GC回收这部分堆内存之前,该部分堆内存占用了4790K的内存,在回收之后占用了374K的内存,而堆内存的总大小是15872K,回收过程使用了0.0001606秒。

(2)打印GC详细信息和时间戳
如果想要打印GC的详细信息,需要以下配置:
-XX:+PrintGCDetails
如果需要GC发生的时间戳,需要配置以下信息:
-XX:+PrintGCTimeStamps
下面是一个配置了上述参数的GC日志详细信息:
5.617: [GC 5.617: [ParNew: 43296K->7006K(47808K), 0.0136826 secs] 44992K->8702K(252608K), 0.0137904 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
上面是一个针对新生代内存的GC操作。新生代内存是堆内存分类的一种,与GC回收有关(在下一篇讲解GC对于堆内存的具体回收算法和堆内存分类时会介绍)。第一个中括号的内容就是GC针对这一块堆内存进行的回收具体大小(43296K),所用时间(0.0136826秒),后面表示该部分堆内存回收前占用44992K的内存,在回收之后占用了8702K的内存,而堆区的总大小是252608K,回收过程使用了0.0001606秒。最后的TImes中的user表示回收这块内存的用户耗时,sys表示回收这块内存的系统耗时,real表示回收这块内存的实际耗时:
5.617(时间戳): [GC(Young GC) 5.617(时间戳): [ParNew(使用ParNew作为年轻代的垃圾回收期): 43296K(年轻代垃圾回收前的大小)->7006K(年轻代垃圾回收以后的大小)(47808K)(年轻代的总大小), 0.0136826 secs(回收时间)] 44992K(堆区垃圾回收前的大小)->8702K(堆区垃圾回收后的大小)(252608K)(堆区总大小), 0.0137904 secs(回收时间)] [Times: user=0.03(Young GC用户耗时) sys=0.00(Young GC系统耗时), real=0.02 secs(Young GC实际耗时)]  

在一个程序执行完毕后,如果配置了“-XX:+PrintGCDetails”,jvm会将整个程序的堆的基本状况打印出来,例如:
【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数
第一行表示“新生代”内存一共有13824K,使用了11223K;
第二行表示“伊甸园”(即对象出生的地方),一共12288K,该处已经使用了91%;
第三行表示from和to(幸存区)的内存总大小和使用率;
第四/五行表示“老年代”内存一共5120K,已经使用的为0K;
第六号表示“永久区”(即方法区)内存一共有12288K,使用了142K,下面的ro(只读)和rw(可读可写)就是共享区间的大小利用率;

我们可以注意到后面的类似“Dx27e80000”的一串字符,一共3或4组,当有三组时分别代表以下信息:
【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数
上图中后面的三串字符,代表了“新生代”类型存储在内存中的位置,以16进制表示。第一个“低边界”代表“新生代”在内存中的起始位置,第二个代表它当前所使用、被分配或所申请到的内存的位置,第三个代表它最多能申请到的内存位置(可以看出上图新生代内存已经申请到极限边界了,内存使用满了,不能够再拓展了)。我们将最高边界的16进制减去低边界的16进制,然后除以两次1024,就得到该类型的内存目前被分配了多少兆(M):
(0x28d80000-0x27e80000)/1024/1024=15M
上述计算得到“新生代”类型内存被分配了15M的空间大小。

(3)重定向GC日志输出位置
一般GC的日志信息是会打印在控制台上的,但是这样我们就无法保留日志信息进行分析,通常我们使用以下参数配置GC日志的输出位置:
-Xloggc:log/gc.log
上面的配置就是将GC日志输出在系统当前目录的log目录下的gc.log文件中:
【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数

(4)每次GC前后打印堆信息
如果我们想要了解每一次垃圾回收的前后堆的存储状况,可以配置以下参数:
-XX:+PrintHeapAtGC
下图就是一个新生代内存在GC回收前后的堆内存情况:
【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数
通过比较这两处的堆内存变化,可以看出eden“伊甸区”由100%变为0%,说明全部被回收;而tenured generation“老年代”回收前是0%,回收后变为了57K,意味着通过这次GC,部分数据从“新生代”移到了“老年代”,还有一部分垃圾被彻底清除了。

“-XX:+PrintHeapAtGC”与“-XX:+PrintGCDetails”的区别就是,前面是程序执行结束之后才会打印堆内存的情况,后面是每一次GC垃圾回收动作发生时,都会打印垃圾回收前后的堆信息。

(4)监控类的加载
有时候我们需要监控系统中哪些类被加载进来,什么样的类加载的比较频繁,什么样的类加载的比较少,可以使用以下配置来打印出程序执行过程中类的加载信息:
-XX:+TraceClassLoading
下面就是一个类加载的例子:
【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数

(5)打印类的直方图
有时候我们需要检测一个类的具体使用情况,可以使用以下配置:
-XX:+PrintClassHistogram
配置了该参数后,在程序执行过程中,按下Ctrl+Break后,就可以打印类的信息,例如:
【Java虚拟机探究】3.常用JVM配置参数-Trace跟踪参数
上图的每一行代表的信息分别是:序号、实例数量、总大小、类型。
所以上图第一行表示一个byte数组实力数量有890617,占用总内存470M左右;后面分别是Map、Long以及Char(C)类型的数据占用内存的情况 。可以推测在上面图所运行的程序中,byte数组和Map类型的类使用的数量比较多,发生内存溢出的情况与这两种类型的数据操作有很大的关系,有助于优化程序。

下一篇讲解堆的分配参数。

转载请注明出处:https://blog.csdn.net/acmman/article/details/80462055