一、常见Java 系统线上性能问题
中心的Java Web项目基本上都是使用 Tomcat 容器来部署的,在系统的日常运行过程中,我们可能会遇到各种性能问题,如:
● OutOfMemoryError可用内存不足
● OutOfMemory内存溢出
● 线程死锁
● 线程消耗大量 CPU资源
● ......
这些性能问题的发生有特定的触发条件,在开发测试过程中不会经常或一定出现,容易被开发和测试人员忽视。但是这些问题基本上又是程序代码原因导致的,不是重启服务器或者提高资源的配置就能彻底解决的。所以,当线上系统出现这些性能问题时,就需要根据系统当前上下文环境定位到问题原因,排查出问题代码。
二、线上 Java 系统性能问题排查思路
这里使用一个简单的Java 死循环程序为例进行说明,如何排查性能问题代码。新建 Java 程序 JvmTes.java,定义方法 jvm(),方法内容为一个 while(true)死循环,当程序执行到 jvm 方法内后,会不停执行 while 语句块中的内容进行计数, 结果就是占用大量CPU资源。示例代码如下:
![469d5ee5af091e946396b737c8457e01.png](https://img-blog.csdnimg.cn/img_convert/469d5ee5af091e946396b737c8457e01.png)
►第一步:找出应用系统对应的Java 进程
可以使用 ps 或者jps 命令,根据Tomcat 或者自己的应用名称进行搜索。这里使用 jps 命令进行查找Tomcat 容器进程,对应命令格式如下:
jps -v | grep [程序名称]
执行jps命令后得到应用程序的进程 id为 28528。
![2f7e87292a300dd50744d637063a906e.png](https://img-blog.csdnimg.cn/img_convert/2f7e87292a300dd50744d637063a906e.png)
►第二步:找出应用系统Java进程内的问题线程
使用top 命令,根据消耗性能的高低进行排序,找到占用 CPU 资源最多、时间最长的线程,并记录对应的线程 id:这个线程一般就是导致 CPU 使用率高、内存使用不足,或者线程死锁的原因。top 命令对应格式如下,其中 pid 为进程 id:
top -Hp pid
这里得到进程 id 为 28570。
![d3947fcf15f079e1d991a2962ff688dc.png](https://img-blog.csdnimg.cn/img_convert/d3947fcf15f079e1d991a2962ff688dc.png)
►第三步:将问题线程 id 转换为十六进制
top 命令输出的线程 ID 为十进制,需要使用 printf 命令将将其转换为十六进制表示,命令格式如下:
printf "%x\n" 28570
![36483bdb70a60ddecdb2facb73cabf4e.png](https://img-blog.csdnimg.cn/img_convert/36483bdb70a60ddecdb2facb73cabf4e.png)
printf 命令执行后得到输出结果为620f。
►第四步:根据线程堆栈信息找出问题代码
使用 jstack 命令,根据问题进程ID和十六进制的问题线程 ID 进行grep,输出具体的堆栈信息。命令如下,其中 pid 为进程 id,tid 为线程 id:
jstack pid | grep tid
![466f8d8e20e85233c4496a4494320941.png](https://img-blog.csdnimg.cn/img_convert/466f8d8e20e85233c4496a4494320941.png)
从线程堆栈信息中即可以看出问题代码的具体位置。
jstack 是 JDK 提供的开发工具包中的命令,可用于查看 Java 进程内的线程堆栈信息。这里也可以使用 jstack 命令将线程堆栈信息 dump 到指定文件中,在线下使用其他工具载入 dump 文件进行分析,命令格式如下,其中 pid 为进程 id:
jstack -l pid > jstack.log
除此之外,还可以配置
-XX:+HeapDumpOnOutOfMemoryError 参数,在Java程序内存溢出时自动将线程堆栈信息输出 dump 文件。
三、Java性能排查相关工具
除了 jstack 工具外,这里再简单介绍几种常见的 Java性能分析工具:
➭jinfo 命令,用来查看和调整 JVM 设置的各项参数。
➭jmap命令,用于生成堆转储快照,可以使用该命令查看进程堆内存的使用情况,包括JVM 使用的 GC 算法、堆配置参数和各代中堆内存的使用情况。此外,也可以使用 jmap 工具把进程内存导出到文件中,再结合其他工具进行分析查看。
➭jhat 工具,和 jmap 搭配使用,使用 jhat 工具分析jmap 导出来的堆快照文件。
➭jconsole图形界化工具,可以用在本地开发环境排查性能问题。
➭jvisualvm图形界化工具:图形化显示线程信息、内存区块和 GC使用情况,可用在开发环境排查性能问题。
➭jstat:JVM 统计信息监测工具,可以使用该工具查看分析各区内存使用和 GC 情况。