Y 说
最近杭州的花都陆陆续续开了。原本打算去太子湾看看郁金香,但到了中央才发现太子湾人满为患,无预约不能进。于是就在西湖边逛了逛,拍了点花花草草的照片。
当然,为了可能拍到难看的照片,我翻出了吃灰已久的索尼微单相机,也顺便学了一波摄影根底,偏入门的摄影常识,整顿成了思维导图,蕴含摄影的实践根底和索尼相机的次要应用办法。感兴趣的敌人能够关注我的微信公众号“编了个程 ”,回复“ 摄影根底”就能够获取这份思维导图链接哦。
为什么写这篇文章
作为一个 Java 程序员,或多或少都理解过 JVM 和 GC 算法。但工作中不肯定有机会遇到和亲手解决 GC 问题。
JVM 的基础理论、GC 排查问题的思路和工具,这部分常识就是平时可能很久都不会用到,但须要用到的时候又十分重要。
而入职面试的时候,常常会有面试官问:有没有排查 GC 问题的教训?如果这个时候不论你有没有理论排查过 GC 问题,但能聊一聊排查 GC 问题的思路,那必然是十分加分的。
最近排查了一个 GC 问题,于是想整顿总结一下与 GC 无关的知识点,造成零碎的常识体系和思维。打算写几篇对于 GC 的文章。那就从介绍一些 GC 排查问题的工具说起吧。
在我的集体网站 yasinshaw.com 上,之前写过一些对于 JVM 根底的文章。感兴趣的同学能够在“文章”页面搜寻“jvm”浏览。
日志和监控
能够在 Java 程序启动的时候加上一些命令参数,来把程序运行中的 GC 日志打印进去。
-XX:+PrintGC 输入 GC 日志
-XX:+PrintGCDetails 输入 GC 的具体日志
-XX:+PrintGCTimeStamps 输入 GC 的工夫戳(以基准工夫的模式)-XX:+PrintGCDateStamps 输入 GC 的工夫戳(以日期的模式,如 2013-05-04T21:53:59.234+0800)-XX:+PrintHeapAtGC 在进行 GC 的前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的输入门路
有些命令可能在不同的 Java 版本实用。比方在 Java 11 中,就会提醒你:-XX:+PrintGC is deprecated. Will use -Xlog:gc instead。
而输入的日志格局,也会依据不同的 Java 版本和 GC 有一些轻微的差异,这个能够具体依据本人我的项目上的 Java 版本和 GC 去对应具体的格局。
举荐 GC 日志与 logback 集成,这样能够利用 logback 的日志切割性能。
再配上可视化的监控工具和告警工具,就可能及时晓得 JVM 的状态和趋势数据。开源的解决方案举荐的是 Prometheus(应用 jmx_exporter)+ Grafana。
命令行工具
日志和监控更多的是反馈历史的数据和监控告警的作用。而光靠历史的数据有时候并不能很好地定位问题。应用一些命令行工具,能够失去实时的 JVM 数据。
JDK 自带的命令行工具
jps
jps 能够查看机器正在运行的 Java 过程 id,尽管用 ps -ef | grep java
也能达到相似的成果,但用 jps 更不便一点。
拿到 Java 过程 id 后,能够不便地用上面的命令去获取更多的信息。
jstat
应用 jps 取得的过程号,能够用 jstat 实时获取 JVM 中各区域的信息。
下图是一个 Java 8 的程序应用 jstat 打印进去的后果。图中最初两个参数,1000 是指的距离多久采集一次,单位是毫秒。5 指的是总共采集次数。
每列的含意:
S0C、S1C、S0U、S1U:Survivor 0/ 1 区容量(Capacity)和使用量(Used)EC、EU:Eden 区容量和使用量
OC、OU:年轻代容量和使用量
PC、PU:永恒代容量和使用量
YGC、YGT:年老代 GC 次数和 GC 耗时
FGC、FGCT:Full GC 次数和 Full GC 耗时
GCT:GC 总耗时
jmap
jmap 性能比拟弱小。它能够生成 dump 文件,也能够查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列,甚至能够近程诊断。
要看 JVM 的信息很简略,应用 jmap -heap 过程号
就能够了。应用 jmap 也比 jstat 要更直观一些。
这里有一点坑,就是机器上必须装置了 debug 包,且版本要与 JDK 的版本统一(包含小版本),不然会报错。
Arthas
Arthas 是一个阿里出品的开源的 Java 诊断工具,深受开发者青睐。
应用上面两行命令即可开启 Arthas:
curl -O https://arthas.aliyun.com/arthas-demo.jar
java -jar arthas-boot.jar
Arthas 有两个次要的命令能够查看 JVM 信息。一个是dashboard
,另一个是jvm
。
dashboard 命令能够查看程序和机器的整体信息。包含次要的线程信息、JVM 各区的内存占用状况、Java 和操作系统的版本信息等。而且 dashboard 还能够实时刷新,动静监控。
这里有一个小彩蛋,咱们本人创立线程的时候,优先级只能设置为 1~10,但 JVM 本人启动的几个线程(比方编译线程等,优先级能够为 -1)。
// Thread 类的 setPriority 办法源码
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {if (newPriority > g.getMaxPriority()) {newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
而应用 jvm
命令,则能够获取更加具体的 JVM 信息。包含类加载、编译器、GC、内存治理、操作系统、线程等等。
总的来说,我集体感觉 arthas 比 JDK 自带的命令行工具好用。信息比拟全,而且排版也看起来更不便一些。
dump 剖析
dump
dump 指的是生成快照。在 Java 中,dump 次要要 heap dump 和 thread dump。
Java heap dump 能够将过后的 JVM 信息 dump 到一个二进制文件,用于前面缓缓剖析。能够在 Java 程序启动的时候,应用参数让程序在指定的机会 dump,比方:
-XX:+HeapDumpBeforeFullGC:实现在 Full GC 前 dump。-XX:+HeapDumpAfterFullGC:实现在 Full GC 后 dump。-XX:+HeapDumpOnOutOfMemoryError 产生 OOM 时 dump
-XX:+HeapDumpPath:设置 Dump 保留的门路
也能够应用下面提到的 jmap 工具来手动 dump 以后的信息:
jmap -dump:live,file=heap.bin PID
Tips:应用 jstack 能够进行 thread dump,但不在本文范畴内,所以不做介绍。
Java 自带的 Jconsole 也有 dump 性能,能够监控本地或近程的 Java 过程。它具备图形化的操作界面,还能够实时查看 JVM 的内存、线程等信息。
剖析
JDK 自带了一些 dump 文件剖析工具,比方jhat,能够剖析 dump 文件并启动一个 http 服务器。但 jhat 曾经在 Java 9 被移除掉。举荐应用 Visual VM 来剖析 dump 文件,应用 Visual VM 能够图形化地看到 dump 时候的对象信息和线程信息。
总结
这些工具都是用来排查 GC 问题的。在产生 GC 问题事先,能够通过打日志 + 监控告警的形式,尽快晓得最近一段时间 JVM 的状况。
在事中,如果不紧急(比方 GC 变频繁但不影响业务)的状况下,能够应用 arthas 等命令行工具剖析以后的 JVM 状况。而如果比拟紧急(比方 Full GC 耗时长,影响业务)的状况下,能够应用 dump 工具把过后的数据 dump 下来,回滚或限流应用程序,在预先找工夫去剖析 dump 文件。
求个反对
我是 Yasin,一个保持技术原创的博主,我的微信公众号是:编了个程
都看到这儿了,如果感觉我的文章写得还行,无妨反对一下。
文章会首发到公众号,浏览体验最佳,欢送大家关注。
你的每一个转发、关注、点赞、评论都是对我最大的反对!
还有学习资源、和一线互联网公司内推哦