讲下 jvm 调优思路?

2021-10-30  本文已影响0人  技术灭霸

其实工作中,很少有机会能接触到 jvm 调优,大部分时间都是在写 CRUD 代码,但如果万一线上真的出问题了,那么再去想 jvm 调优就有点晚了,所以我们需要先把这部分知识储备起来。

面试官思路:主要是想看下你对造成 JVM 性能问题有没有思考总结过。

可以从三个方面说:
1. 工作中引起 JVM 性能问题的原因到底是代码问题还是 JVM 参数问题?
2. JVM 性能问题如何监控和排查?
3. 如何根据性能问题进行参数调优?

代码排查

首先第一个方面,其实大部分 JVM 性能问题,并不是我们设置的参数问题,一般情况下,都是用默认参数就搞定了,而真正出问题的情况多是自己写的代码有问题,如频繁创建大对象,然后又引用它们不释放,然后这些大对象进入了老年代后,垃圾收集器有回收不了它们,老年代内存不足,造成频繁 Full GC,每次 Full GC 都会触发 STW,也就是造成卡顿现象,这样性能不就很差了吗?

如何监控

这个就是为了记录日志用的,我们可以利用日志来快速定位性能问题。

记录日志就是这个命令了:

-XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:gc.log

然后还可以设置内存溢出后自动导出Dump文件:

-XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\jvm.dump

另外如果想立即导出 dump 文件,用这个命令就可以了:

jmap -dump:format=b,file=D:/demo.hprof pid

当然,我们最好是能把 dump 文件获取到,然后放到本地的工具中分析就好办了。

如何分析 dump 文件

第二个方面中,拿到 dunp 文件后,就是分析:

说到常用的分析工具,当然是少不了 jvisualvm 可视化工具了,可以通过输入命令 jvisualvm 打开,然后载入之前的 dump 文件就可以了。这个工具会显示现在有哪些大对象占用着内存在。另外也可以通过 JProfiler 可视化工具来排查。

整体思路就是拿到 dump 文件,放到可视化工具中分析一把,大部分情况都是大对象造成的,然后再结合自己的代码,看看哪个地方造成了对象创建后没有被回收,然后优化代码就好了。

如何排查 Full GC

有时候,我们只能在线上的服务器上通过命令排查,那么就只能使用命令行工具来排查了,其实思路也很常规:

  1. jps -l 找到当前进程的pid
  2. ps -mp-o THREAD,tid,time 定位到具体线程。
  3. printf “%x\n”,把线程 pid 转为16进制,比如 0xf58
  4. jstack pid | g rep -A 10 0xf58 查看线程的堆栈日志,还找不到问题继续。
  5. 实在没办法了,只能 dump 出内存文件用可视化工具进行分析了,然后 定位到代码后修复。

分析 YGC

大多数情况下,新创建的对象都会在新生代的 Eden 区中分配,当 Eden 区没有足够的空间分配时,虚拟机将会发生一次 Minor GC,也就是 YGC。频繁发生 YGC 也是会对性能造成影响的。

分析年轻代对象增长速率。

每5秒执行一次,执行10次,然后观察这50秒内 eden 区增加的趋势,即可知道年轻代对象增长的速率。

jstat -gc pid 5000 10

思路:如果 eden 区增长很快,那么发生 YGC 的频率也会很高,说明 Eden 区太小了,可以调大 Eden 区(调整 -Xmn 参数),然后再次进行测试,看小是否减少了 YGC 回收频率。

另外如果 YGC 后,存活的对象超过了 Survivor 的 50%,则会进入老年代。

我们的调优思路是尽量减少对象进入老年代,以减少发生 FGC 的频率。所以通过调整 Eden 区的大小,减少了对象进入老年代的频率。

参数调优

第三个方面,如何进行参数调优。一般情况下,参数用默认的就好了,但是某些场景还是要进行参数调优的。

调优思路如下:

上一篇 下一篇

猜你喜欢

热点阅读