Java实践总结:高CPU占用问题
高CPU占用问题
生产环境下的某台Java语言开发的服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高。
针对这一问题,如何定位引起高CPU占用原因?
方法一:逐条命令洞玄机
1.使用top
命令 定位到占用CPU高的进程PID
2.获取线程信息,并找到占用CPU高的线程ps -mp pid -o THREAD,tid,time | sort -rn
3.将需要的线程ID转换为16进制格式printf "%x\n" tid
4.打印线程的堆栈信息,定位到引起CPU高的代码jstack pid |grep tid -A 30
方法二:快捷脚本提效率
通过阿里天猫事业部李鼎贡献的脚本定位CPU问题,事半功倍。访问地址:
☕ Java
相关脚本
-
show-busy-java-threads
用于快速排查Java
的CPU
性能问题(top us
值过高),自动查出运行的Java
进程中消耗CPU
多的线程,并打印出其线程栈,从而确定导致性能问题的方法调用。 -
show-duplicate-java-classes
找出jar
文件和class
目录中的重复类。用于排查Java
类冲突问题。 -
find-in-jars
在目录下所有jar
文件里,查找类或资源文件。
???? Shell
相关脚本
Shell
使用加强:
-
c
原样命令行输出,并拷贝标准输出到系统剪贴板,省去CTRL+C
操作,优化命令行与其它应用之间的操作流。 -
coat
彩色cat
出文件行,方便人眼区分不同的行。 -
a2l
按行彩色输出参数,方便人眼查看。 -
ap and rp
批量转换文件路径为绝对路径/相对路径,会自动跟踪链接并规范化路径。 -
tcp-connection-state-counter
统计各个TCP
连接状态的个数。用于方便排查系统连接负荷问题。 -
xpl and xpf
在命令行中快速完成 在文件浏览器中 打开/选中 指定的文件或文件夹的操作,优化命令行与其它应用之间的操作流。
Shell
开发/测试加强:
-
echo-args
输出脚本收到的参数,在控制台运行时,把参数值括起的括号显示成 红色,方便人眼查看。用于调试脚本参数输入。 -
console-text-color-themes.sh
显示Terminator
的全部文字彩色组合的效果及其打印方式,用于开发Shell
的彩色输出。 -
parseOpts.sh
命令行选项解析库,加强支持选项有多个值(即数组)。
其中,show-busy-java-threads
脚本用于定位java线程中占用CPU最高的TopN线程,并打印堆栈信息,将方法一的过程包装了起来。
使用方法bash show-busy-java-threads.sh -p pid
Java占用CPU很高的可能原因
(1)一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环。死循环肯定要占用一个CPU不放,这是由于操作系统的机制原因造成的,其他原因也一样。
(2)空循环会造成间歇性的CPU高,最常见的场景是信息采集系统中使用while从消息队列(泛指,可以是文件系统、队列、kafka等)循环采集消息,当消息队列中有消息可供处理时,CPU表现正常,当如果消息队列中没有消息,while就会陷入空循环,短时间内CPU会飙升。
(3)由内存泄露引起的CPU狂飙。这类问题最难定位,一般在系统使用一段时间后才会发生,其现象表现为CPU高居不小,系统无法提供正常服务,最明显的标志是使用以上方法定位到的线程中存在大量GC相关的线程。这类问题产生的原因是程序中逻辑处理不当,导致堆内存无法及时回收,产生了大量的垃圾,JVM的GC开始疯狂工作导致其他进程的资源被耗尽。这类问题可从CPU和内存两个方面展开定位分析并予以解决。