OpenJDK 11 是在 OpenJDK 8 之后的第一个长期支持版本,这一版本在JVM日志配置有了很大改动,主要是规范化,统一化了。在 OpenJDK 8 中,日志配置有很多状态位,让人摸不着头脑,并且比较难以维护与进一步迭代。在 OpenJDK 11终于将JVM日志相关的配置规范起来,统一配置。这篇文章会对于这些配置做一个基本的说明和解析。
一、JVM日志标签
JVM 日志和我们 java 代码中的日志,其实是类似。在 Java 代码中,我们一般使用 slf4j 记录日志,例如:
Logger logger = LogFactory.getLooger("core-logger"); logger.info("this is core logger log");
然后日志中就会输出类似于:
2020-02-05 10:50:52.670 INFO [core-logger] [22] [pool-13-thread-1]: this is core logger log
包括时间戳,日志级别,日志标签(core-logger),日志内容这些信息。JVM 日志也是包括这些元素。举个例子:
[0.182s][debug][jit,compilation] 1 3 java.lang.StringLatin1::hashCode (42 bytes) [0.183s][debug][jit,compilation] 2 3 java.lang.Object::<init> (1 bytes) [0.183s][debug][jit,compilation] 3 3 java.lang.String::hashCode (49 bytes)
可以看出,默认的 JVM 日志包括:
[启动经过时间][日志级别][日志标签,可能包含多个] 日志内容
其中一行日志,可能包含多个标签,之后关于JVM日志相关的配置,也是围绕着这些标签进行配置。大部分的标签是给JVM开发者用的,其中某些标签供我们使用 JVM 的人进行 JVM 参数调优以及代码调优。那么我们需要关心哪些标签呢?我个人按照功能,把我们需要关心的标签分为如下几大类
1. gc相关
gc日志有很多标签与组合,大部分以 gc 标签为开始,混合搭配其他一些标签。一般,有如下几个标签我们会经常用到:
标签gc
gc总体描述日志,一般设置info级别查看gc的发生时间,消耗时间还有内存大小。例如:Pause Young (Normal) (g1 Evacuation Pause) 3480M->1565M(5120M) 15.968ms
包含了gc类型,gc原因,收集内存大小,持续时间等信息
标签gc,age
gc 中 age 相关信息,age比较高的对象会进入老年代。如果是 trace 级别,会输出每一个 age 的所有对象占用总大小,以及比这个 age 低的所有 age 的大小,debug 级别只会输出最高级别的 age 以及期望大小,不是当前总大小,例如:
[2020-02-26T08:34:12.823+0000][debug][gc,age ] gc(1661) Desired survivor size 167772160 bytes, new threshold 6 (max threshold 6) [2020-02-26T08:34:12.823+0000][trace][gc,age ] age 1: 16125960 bytes, 16125960 total [2020-02-26T08:34:12.823+0000][trace][gc,age ] age 2: 16259512 bytes, 32385472 total [2020-02-26T08:34:12.823+0000][trace][gc,age ] age 3: 2435240 bytes, 34820712 total [2020-02-26T08:34:12.823+0000][trace][gc,age ] age 4: 17179320 bytes, 52000032 total [2020-02-26T08:34:12.823+0000][trace][gc,age ] age 5: 43986952 bytes, 95986984 total [2020-02-26T08:34:12.823+0000][trace][gc,age ] age 6: 20858328 bytes, 116845312 total
标签gc,alloc
,gc,alloc,region
这两个参数仅对 g1 gc 有效 gc,alloc
在 gc 完成的时候,打印 trace 级别日志记录触发 gc 的线程是哪一个以及返回的 gc 结果地址;这个一般是在调试 gc 的时候才需要看这个日志。 gc,alloc,region
统计每次 gc 的 Regions 信息,打印 debug 级别日志。
[2020-02-28T02:14:02.694+0000][trace][gc,alloc ] sdk-27692-2-amqp-t-4: Successfully scheduled collection returning 0x00000007ffc00000 [2020-02-28T02:16:00.372+0000][debug][gc,alloc,region ] gc(7848) Mutator Allocation stats, regions: 677, wasted size: 63832B ( 0.0%)
标签gc,cpu
这个是大多数 gc 问题定位需要查看的日志, info 级别打印每次gc真正耗时:
[2020-02-28T01:59:46.406+0000][info ][gc,cpu ] gc(7841) User=0.10s Sys=0.00s Real=0.04s [2020-02-28T02:01:20.148+0000][info ][gc,cpu ] gc(7842) User=0.04s Sys=0.06s Real=0.04s
注意这个和 JFR 的统计可能会有差异,JFR 统计的 gc 时间是从开始 schedule gc 就认为开始 gc ,而这里的时间是从开始标记开始。
标签gc,ergo
,gc,ergo,cset
,gc,ergo,ihop
,gc,ergo,refine
这是 Adaptive Size Policy 相关的日志,如果想详细学习算法,可以用 trace 级别,一般的 debug 级别信息就够了
[2020-02-28T01:59:46.367+0000][trace][gc,ergo,cset ] gc(7841) Start choosing CSet. pending cards: 26996 predicted base time: 13.34ms remaining time: 186.66ms target pause time: 200.00ms [2020-02-28T01:59:46.367+0000][trace][gc,ergo,cset ] gc(7841) Add young regions to CSet. eden: 676 regions, survivors: 6 regions, predicted young region time: 19.02ms, target pause time: 200.00ms [2020-02-28T01:59:46.367+0000][debug][gc,ergo,cset ] gc(7841) Finish choosing CSet. old: 0 regions, predicted old region time: 0.00ms, time remaining: 167.64 [2020-02-28T01:59:46.389+0000][debug][gc,ergo ] gc(7841) Running g1 Clear Card Table Task using 4 workers for 7 units of work for 895 regions. [2020-02-28T01:59:46.391+0000][debug][gc,ergo ] gc(7841) Running g1 Free Collection Set using 4 workers for collection set length 682 [2020-02-28T01:59:46.391+0000][trace][gc,ergo,refine ] gc(7841) Updating Refinement Zones: update_rs time: 6.800ms, update_rs buffers: 397, update_rs goal time: 19.998ms [2020-02-28T01:59:46.391+0000][debug][gc,ergo,refine ] gc(7841) Updated Refinement Zones: green: 572, yellow: 1716, red: 2860 [2020-02-28T02:01:20.108+0000][trace][gc,ergo,cset ] gc(7842) Start choosing CSet. pending cards: 25786 predicted base time: 12.87ms remaining time: 187.13ms target pause time: 200.00ms [2020-02-28T02:01:20.108+0000][trace][gc,ergo,cset ] gc(7842) Add young regions to CSet. eden: 677 regions, survivors: 5 regions, predicted young region time: 14.43ms, target pause time: 200.00ms [2020-02-28T02:01:20.108+0000][debug][gc,ergo,cset ] gc(7842) Finish choosing CSet. old: 0 regions, predicted old region time: 0.00ms, time remaining: 172.70 [2020-02-28T02:01:20.132+0000][debug][gc,ergo ] gc(7842) Running g1 Clear Card Table Task using 4 workers for 8 units of work for 903 regions. [2020-02-28T02:01:20.133+0000][debug][gc,ergo ] gc(7842) Running g1 Free Collection Set using 4 workers for collection set length 682 [2020-02-28T02:01:20.133+0000][trace][gc,ergo,refine ] gc(7842) Updating Refinement Zones: update_rs time: 6.303ms, update_rs buffers: 305, update_rs goal time: 19.997ms [2020-02-28T02:01:20.133+0000][debug][gc,ergo,refine ] gc(7842) Updated Refinement Zones: green: 572, yellow: 1716, red: 2860 [2020-02-28T02:04:36.095+0000][trace][gc,ergo,cset ] gc(7843) Start choosing CSet. pending cards: 26115 predicted base time: 12.85ms remaining time: 187.15ms target pause time: 200.00ms [2020-02-28T02:04:36.095+0000][trace][gc,ergo,cset ] gc(7843) Add young regions to CSet. eden: 676 regions, survivors: 6 regions, predicted young region time: 69.11ms, target pause time: 200.00ms [2020-02-28T02:04:36.095+0000][debug][gc,ergo,cset ] gc(7843) Finish choosing CSet. old: 0 regions, predicted old region time: 0.00ms, time remaining: 118.04 [2020-02-28T02:04:36.118+0000][debug][gc,ergo ] gc(7843) Running g1 Clear Card Table Task using 4 workers for 7 units of work for 894 regions. [2020-02-28T02:04:36.120+0000][debug][gc,ergo ] gc(7843) Running g1 Free Collection Set using 4 workers for collection set length 682 [2020-02-28T02:04:36.121+0000][trace][gc,ergo,refine ] gc(7843) Updating Refinement Zones: update_rs time: 6.929ms, update_rs buffers: 364, update_rs goal time: 19.997ms [2020-02-28T02:04:36.121+0000][debug][gc,ergo,refine ] gc(7843) Updated Refinement Zones: green: 572, yellow: 1716, red: 2860
标签gc,heap
,gc,heap,region
gc,heap
的 debug 级别会显示 gc 的时候堆的概况,对于 g1 gc gc,heap,region
的 trace 级别,会打印每一个 region 的详细情况,这个一般供 gc 调试使用。
我们一般只需要关心gc,heap
的日志就行了
这些标签是在
[2020-02-28T06:01:20.787+0000][debug][gc,heap ] gc(7922) Heap before gc invocations=7922 (full 0): garbage-first heap total 8388608K, used 4076387K [0x0000000600000000, 0x0000000800000000) [2020-02-28T06:01:20.787+0000][debug][gc,heap ] gc(7922) region size 4096K, 682 young (2793472K), 5 survivors (20480K) [2020-02-28T06:01:20.787+0000][debug][gc,heap ] gc(7922) Metaspace used 163068K, capacity 166731K, committed 169728K, reserved 1198080K[2020-02-28T06:01:20.787+0000][debug][gc,heap ] gc(7922) class space used 18180K, capacity 19580K, committed 20480K, reserved 1048576K [2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) Heap Regions: E=young(eden), S=young(survivor), O=old, HS=humongous(starts), HC=humongous(continues), CS=collection set, F=free, A=archive, TAMS=top-at-mark-start (previous, next)[2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) | 0|0x0000000600000000, 0x0000000600400000, 0x0000000600400000|100%| O| |TAMS 0x0000000600400000, 0x0000000600000000| Untracked [2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) | 1|0x0000000600400000, 0x0000000600800000, 0x0000000600800000|100%| O| |TAMS 0x0000000600800000, 0x0000000600400000| Untracked [2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) | 2|0x0000000600800000, 0x0000000600c00000, 0x0000000600c00000|100%| O| |TAMS 0x0000000600c00000, 0x0000000600800000| Untracked [2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) | 3|0x0000000600c00000, 0x0000000601000000, 0x0000000601000000|100%| O| |TAMS 0x0000000601000000, 0x0000000600c00000| Untracked [2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) | 4|0x0000000601000000, 0x0000000601400000, 0x0000000601400000|100%| O| |TAMS 0x0000000601400000, 0x0000000601000000| Untracked [2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) | 5|0x0000000601400000, 0x0000000601800000, 0x0000000601800000|100%| O| |TAMS 0x0000000601800000, 0x0000000601400000| Untracked [2020-02-28T06:01:20.787+0000][trace][gc,heap,region ] gc(7922) | 6|0x0000000601800000, 0x0000000601c00000, 0x0000000601c00000|100%| O| |TAMS 0x0000000601c00000, 0x0000000601800000| Untracked
标签gc,humongous
如果你使用的是g1 gc,并且经常出现 Evacuation Failure 或者 Humongous Allocation ,并且不知道是什么原因的话,可以考虑看看这个标签相关的日志:
[2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 219 object size 2160888 start 0x0000000636c00000 with remset 1 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 412 object size 2160888 start 0x0000000667000000 with remset 1 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 443 object size 3241320 start 0x000000066ec00000 with remset 1 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 489 object size 2160888 start 0x000000067a400000 with remset 2 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 490 object size 2160888 start 0x000000067a800000 with remset 1 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 499 object size 7292936 start 0x000000067cc00000 with remset 2 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 536 object size 2160888 start 0x0000000686000000 with remset 2 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 656 object size 2160888 start 0x00000006a4000000 with remset 1 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 768 object size 2160888 start 0x00000006c0000000 with remset 1 code roots 0 is marked 0 reclaim candidate 0 type array 0 [2020-02-28T06:01:20.831+0000][debug][gc,humongous ] gc(7922) Live humongous region 786 object size 2160888 start 0x00000006c4800000 with remset 1 code roots 0 is marked 0 reclaim candidate 0 type array 0
标签gc,metaspace
,gc,metaspace,freelist
,gc,metaspace,freelist,blocks
查看 metaspace 相关的 gc 日志,gc,metaspace
的 info 级别会输出每次 gc 涉及的 metaspace 内存变化,如果有变化,详细变化会通过gc,metaspace,freelist
,gc,metaspace,freelist,blocks
的 trace 级别输出。
[2020-02-28T04:32:13.123+0000][info ][gc,metaspace ] gc(7896) Metaspace: 163062K->163062K(1198080K) [2020-02-28T04:35:44.956+0000][trace][gc,metaspace,freelist ] SpaceManager::grow_and_allocate for 49 words 109 words used 19 words left [2020-02-28T04:35:44.956+0000][trace][gc,metaspace,freelist ] ChunkManager::free_chunks_get: free_list: 0x00007fddccb89770 chunks left: 433. [2020-02-28T04:35:44.956+0000][trace][gc,metaspace,freelist ] ChunkManager::chunk_freelist_allocate: 0x00007fddccb89770 chunk 0x00007fdc74221000 size 128 count 433 Free chunk total 255616 count 824 [2020-02-28T04:35:44.956+0000][trace][gc,metaspace,freelist,blocks] returning block at 0x00007fdd95575b68 size = 19 [2020-02-28T04:35:44.956+0000][trace][gc,metaspace,freelist ] SpaceManager::added chunk: [2020-02-28T04:35:44.956+0000][trace][gc,metaspace,freelist ] Metachunk: bottom 0x00007fdc74221000 top 0x00007fdc74221040 end 0x00007fdc74221400 size 128 (specialized) [2020-02-28T04:35:44.956+0000][trace][gc,metaspace,freelist ] Free chunk total 255616 count 824 [2020-02-28T04:36:35.367+0000][info ][gc,metaspace ] gc(7897) Metaspace: 163065K->163065K(1198080K)
标签gc,phases
,gc,phases,ref
,gc,phases,task
,gc,ref
,gc,start
,gc,ref,start
这些标签与 gc 步骤相关,如果想学习 gc 算法,可以查看这些标签的日志,来了解 gc 的步骤以及原理
标签safepoint
我们知道只有到达 safepoint,我们才可以进行 gc,如果我们对这些 safepoint 感兴趣,可以查看这个标签的 debug 级别的日志
2. 类加载与运行时编译相关
标签class,preorder
,class,init
,class,load
,class,unload
顾名思义,这是类初始化,类加载与类卸载的日志,info 级别的信息就以足够。 如果你想学习 JVM 类加载过程,可以查看 class 标签的 trace 级别日志。
[8.931s][debug][class,preorder ] com.fasterxml.jackson.core.PrettyPrinter source: file:/D:/Repositories/maven/com/fasterxml/jackson/core/jackson-core/2.10.0/jackson-core-2.10.0.jar [8.931s][info][class,init ] 2740 Initializing 'com/fasterxml/jackson/core/PrettyPrinter' (0x0000000801399220) [8.934s][info][class,load ] com.fasterxml.jackson.core.PrettyPrinter source: file:/D:/Repositories/maven/com/fasterxml/jackson/core/jackson-core/2.10.0/jackson-core-2.10.0.jar
标签jit,compilation
一般我们对于即时编译优化,只用看 jit 编译日志即可,对应的标签是jit,compilation
,日志级别是 debug
[2020-02-28T03:01:51.619+0000][debug][jit,compilation] 153756 ! 4 jdk.internal.reflect.GeneratedConstructorAccessor161::newInstance (49 bytes) made zombie [2020-02-28T03:01:51.620+0000][debug][jit,compilation] 153219 4 io.lettuce.core.protocol.CommandArgs$IntegerArgument::encode (12 bytes) made zombie [2020-02-28T03:01:51.623+0000][debug][jit,compilation] 153192 4 io.lettuce.core.protocol.CommandArgs$StringArgument::writeString (60 bytes) made zombie [2020-02-28T03:01:54.911+0000][debug][jit,compilation] 157252 ! 4 jdk.internal.reflect.GeneratedConstructorAccessor161::newInstance (49 bytes)
3. 其他运行时相关
标签monitorinflation
同步锁相关日志, 一般查看 debug 级别的,可以用于定位死锁
[5.033s][debug][monitorinflation] Deflating object 0x0000000708310378 , mark 0x0000021cef446002 , type java.lang.ref.ReferenceQueue$Lock [5.033s][debug][monitorinflation] Inflating object 0x0000000708310378 , mark 0x0000021cf085c002 , type java.lang.ref.ReferenceQueue$Lock [5.035s][debug][monitorinflation] Deflating object 0x0000000708310378 , mark 0x0000021cf085c002 , type java.lang.ref.ReferenceQueue$Lock [5.035s][debug][monitorinflation] Inflating object 0x0000000708310378 , mark 0x0000021cef445e02 , type java.lang.ref.ReferenceQueue$Lock
标签biasedlocking
偏向锁相关日志,一般查看 info 级别即可,trace 级别显示更详细的偏向锁争用细节,可以用于学习偏向锁实现原理
[7.273s][info ][biasedlocking] Revoking bias by walking my own stack: [7.273s][info ][biasedlocking] Revoking bias of object 0x0000000711b1ca40, mark 0x000001c6d0acc905, type sun.net.www.protocol.jar.URLJarFile, prototype header 0x0000000000000105, allow rebias 0, requesting thread 0x000001c6d0acc800 [7.273s][info ][biasedlocking] Revoked bias of object biased toward live thread (0x000001c6d0acc800) [7.273s][trace][biasedlocking] mon_info->owner (0x00000007022634d8) != obj (0x0000000711b1ca40) [7.273s][trace][biasedlocking] mon_info->owner (0x0000000711b200d8) != obj (0x0000000711b1ca40) [7.273s][trace][biasedlocking] mon_info->owner (0x0000000711b200d8) != obj (0x0000000711b1ca40) [7.273s][trace][biasedlocking] mon_info->owner (0x0000000702970260) != obj (0x0000000711b1ca40) [7.273s][info ][biasedlocking] Revoked bias of currently-unlocked object
二、JVM日志配置
配置格式:
-Xlog[:[what][:[output][:[decorators][:output-options[,...]]]]]
如果不配置,默认的是:
-Xlog:all=warning:stdout:uptime,level,tags
这是一个冒号分割的配置,第一个冒号后面的就是what
,第二个是output
,第三个是decorators
,第四个是逗号分割的output-options
.没有配置的部分就是上面默认值的对应部分,例如下面的几组配置就是等价的:
-Xlog:all=warning
与-Xlog::stdout
与-Xlog::::uptime,level,tags
与-Xlog:all=warning:stdout
与-Xlog::stdout:uptime,level,tags
与-Xlog:all=warning:stdout:uptime,level,tags
-Xlog:gc*=info
与-Xlog:gc*=info:stdout:uptime,level,tags
-Xlog::file=/project/log/app.log::filecount=50,filesize=100M
与-Xlog:all=warning:file=/project/log/app.log:uptime,level,tags:filecount=50,filesize=100M