一、死循环,超大循环
可以多次做CPU usage分析, 比如每次都是1s的interval 内所有线程消耗CPU的百分比, 因为CPU 已经100%, 所以很容易可以看到是哪些线程在大量消耗CPU, 然后去分析这些stacktrace, 基本上死循环的代码之外的stack每次都一样, 死循环以内的某些时候的stack有些差别. 可以通过结合 heap dump 里面的局部变量, 参数同时阅读stack里面的方法的调用关系, 去查看死循环的位置所在. 对于HashMap这种, 基本在几次tread dump中就能确定, 然后去 heap dump 去找到那个循环.
二、耗时操作
和第一种差不多
先观察下stack里面有没有看上去就是特耗CPU的操作, 如果有继续看源代码去查看. 最后结合heap dump里面的数据去验证.
三、IO操作(文件IO、网络IO)
频繁的IO操作:如果代码中频繁进行磁盘或网络IO操作,会导致CPU等待IO操作完成,从而造成CPU占用率过高。
四、线程超多、或者线程池中的线程超多,cpu用于调度了
线程超多有一个情况是频繁创建对象触发Yang GC eg:不分页获取大量数据在内存中转换javabean
五、cpu密集性操作
1、使用正则表达式去判断是不是符合某个规则, 可是有些时候输入参数是一个几十K或更长的数据, 该正则写又不好, 导致CPU遇到这种输入, 就爆掉了.
2、超大对象的序列化、反序列化
六、GC overhead
1、为什么会产生GC overhead limit exceeded问题
OutOfMemoryError是java.lang.VirtualMachineError的子类;JVM遇到与资源利用有关的问题时,会抛出该错误。更具体地说,当JVM花太多时间执行垃圾回收并且只能回收很少的堆空间时,就会发生该错误。
根据Java文档,默认情况下,如果Java进程花费其时间的98%以上用于GC,并且每次运行中仅回收不到2%的堆,则JVM配置为抛出此错误。换句话说,这意味着我们的应用程序几乎耗尽了所有可用的内存,而垃圾回收器花费了太多时间尝试清理它,并反复失败。
在这种情况下,用户会遇到应用程序极慢的情况。某些操作通常会在几毫秒内完成,因此需要花费更多时间才能完成。这是因为CPU将其全部容量用于垃圾回收,因此无法执行任何其他任务。
2、有什么表现
具体现象一般来说,有以下几点:
程序中大量的死循环或有使用大内存的代码;
程序中的递归栈的层数太深了,导致内存不足;
给服务器的堆内存设置的太小,没有足够的内存可以使用;
数据库中的数据表数据太大,由于没有判断带有条件,导致查询全表数据,查询出来的数据量太大,内存溢出;
GC overhead limit exceeded问题-CSDN博客
七、工具
top
命令:用于监控系统的各个进程的资源占用情况,其中包括CPU占用率。
jstack
命令:用于打印Java应用程序中的线程堆栈信息,可以通过分析线程堆栈信息来确定CPU占用率过高的原因。
jprofiler
:一款商业化的Java性能分析工具,它可以提供更详细的性能分析信息,帮助我们找出CPU占用率过高的原因。