一般情况下,我们可以通过Java虚拟机(Java Virtual Machine,JVM)生成的如下三个关键文件来进行产品的性能优化,或者是解决一些生产问题。
- 垃圾收集(Garbage collection,GC)日志
- 线程转储(Thread dump)
- 堆转储(Heap dump)
那么这三个文件都是什么呢?别傻傻分不清楚了,下面就来对比一下这三个文件都是干啥的。
介些都是些啥东东
GC日志
GC日志包含了垃圾收集事件的相关信息,比如:“发生了多少次GC事件”,“这些各自是什么类型的GC事件(比如,年轻代GC或完整GC)”,“每个GC事件将应用暂停了多长时间”,“每个GC事件回收了多少对象”。
线程转储
线程转储是一个运行中的应用在某一个时刻的所有线程的快照,它包含了应用中的每一个线程的所有信息。比如:线程状态,线程ID,原生ID,线程名称,线程栈信息,线程优先级。
堆转储
堆转储是一个运行中的应用在某一个时刻的内存快照,它同样也包含了很多信息。比如:内存中都有那些对象,这些对象的当前值,对象的大小,对象的引用关系。
来!出来亮个相
是骡子是马拉出来遛遛!下面各举个例子先让大家看看这几个东东都长什么样子,消除一下神秘感。
GC日志
1 | 2021-04-01T12:32:24.398+0800: 0.356: [GC pause (G1 Evacuation Pause) (young), 0.0215287 secs] |
线程转储
1 | "HeavyThread" #11 prio=5 os_prio=0 tid=0x000001885e78f000 nid=0x2e3c runnable [0x0000001b443fe000] |
堆转储
堆转储文件为二进制格式,并且通常较大,这里就不举例子了。 除此之外,堆转储格式相关文档少的可怜。 因此,我们必须借助堆转储分析工具来分析和理解这玩意。
这些文件都用在什么场景
GC日志
垃圾收集日志用于优化GC暂停时间,用于确定应用程序的最佳内存大小,还用于解决与内存相关的问题。
线程转储
线程转储主要用于解决生产问题,例如CPU尖峰,应用程序无响应,响应时间差,线程挂起,内存消耗高。
内存转储
堆转储主要用于解决与内存相关的OutOfMemoryError
问题。
我怎么获取这些文件呢
GC日志
使用如下的JVM参数可以生成垃圾收集日志:
- java 8及以前版本
1 | -XX:+PrintGCDetails |
- java 9及以后版本
1 | -Xlog:gc*:file=<file-path> |
注:<file-path>为垃圾收集日志的生成文件路径
线程转储
线程转储捕获的方法比较多,后面有时间了再展开说说,这里说个一般方法。通常情况下,我们使用 jstack
工具来获取线程转储, jstack
在 JDK_HOME\bin
目录下。线程转储文件可以用如下方式获取:
1 | jstack -l <pid> > <file-path> |
注:<pid>为应用进程号;<file-path>为线程转储文件生成的文件路径
堆转储
同样,堆转储获取的方法也比较多,后面有空再细说。通常情况下,我们使用 jmap
工具来获取堆转储, jmap
在 JDK_HOME/bin
目录下。获取堆转储文件用以下方法即可:
1 | jmap -dump:format=b,file=<file-path> <pid> |
注:<pid>为应用进程号;<file-path>为堆转储文件生成的文件路径
分析工具
GC日志
线程转储
堆转储
最后
本篇主要是一个偏科普性质的文章,从几个不同的出发点比较了GC日志、线程转储文件、堆转储文件。平时在性能优化和问题处理的过程中必然少不了会用到这些。当然在分析的过程中的除过使用上面列出来的工具之外,还是需要您具备一定程度的JVM知识,要不然工具跑完之后也看不出来个所以然。
最好的办法是自己动手实践一下,从上面列出来的工具中找一个自己最顺手的出来,后面就会事半功倍!
欢迎关注我的公众号 须弥零一,跟我一起学习IT知识。
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !