Java应用CPU使用率飙升的原因

标签: 问题集锦 JStack JVM Java | 发表时间:2021-03-11 12:00 | 作者:
出处:http://www.arccode.net/

背景

1、无限循环的while会导致CPU使用率飙升吗?
2、经常使用Young GC会导致CPU占用率飙升吗?
3、具有大量线程的应用程序的CPU使用率是否较高?
4、CPU使用率高的应用程序的线程数是多少?
5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?
6、分时操作系统中的CPU是消耗 us还是 sy

思路

如何计算CPU使用率?

CPU%= 1 - idleTime / sysTime * 100

idleTime:CPU空闲的时间

sysTime:CPU处于用户模式和内核模式的时间总和

与CPU使用率有关的是什么?

人们常说,计算密集型程序的CPU密集程度更高。

那么,JAVA应用程序中的哪些操作更加CPU密集?

以下列出了常见的CPU密集型操作:

1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。
2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。
3、序列化和反序列化;
4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。
5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。
6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。

CPU是否与进程和线程相关?

现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。

答案

while的无限循环会导致CPU使用率飙升吗?

是。

首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?

除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。

stackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?

https://stackoverflow.com/questions/2846165/why-does-an-infinite-loop-of-the-unintended-kind-increase-the-cpu-use

频繁的Young GC会导致CPU占用率飙升吗?

是。

Young GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。

让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。

具有大量线程的应用程序的CPU使用率是否较高?

不是。

如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。

我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。

但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。

对于CPU占用率高的应用程序,线程数是否较大?

不是。

高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。

处于BLOCKED状态的线程是否会导致CPU占用率飙升?

不会。

CPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。

如果分时操作系统中CPU的值 ussy值很高,这意味着什么?

您可以使用命令查找CPU的值 ussytop,如以下示例所示:

图片

us:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。

sy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。

经验

如何找出CPU使用率高的原因?下面简要描述分析过程。

如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。

以下是一个真实案例:

一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。 图片

进一步检查日志:

1     
2
3
4
5
6
7
8
9
10
11
12
onsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE     
stackTrace:
java.lang.Thread.State:RUNNABLE
at java.lang.Object.hashCode(NativeMethod)
at java.util.HashMap.hash(HashMap.java:362)
at java.util.HashMap.getEntry(HashMap.java:462)
at java.util.HashMap.containsKey(HashMap.java:449)
at com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)
at com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)
at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)

现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升。

参考

声明

本文属于转载: 原文(这六种原因,真能让 Java 应用 CPU 使用率飙升至 100% 吗?)

相关 [java 应用 cpu] 推荐:

Java应用CPU使用率飙升的原因

- - arccode
1、无限循环的while会导致CPU使用率飙升吗. 2、经常使用Young GC会导致CPU占用率飙升吗. 3、具有大量线程的应用程序的CPU使用率是否较高. 4、CPU使用率高的应用程序的线程数是多少. 5、处于BLOCKED状态的线程会导致CPU使用率飙升吗. 6、分时操作系统中的CPU是消耗 us还是 sy.

从Java视角理解CPU缓存(CPU Cache)

- - 淘宝网通用产品团队博客
从Java视角理解系统结构连载, 关注我的微博( 链接)了解最新动态众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多. 其实在30年前, CPU的频率和内存总线的频率在同一个级别, 访问内存只比访问CPU寄存器慢一点儿.

一个Java应用频繁抛异常导致cpu us诡异现象的案例

- - BlueDavy之技术Blog
某Java应用在生产环境运行时cpu us呈现了非常诡异的现象,在qps(每秒请求数)基本稳定的情况下,cpu us会进入一个上涨–迅速下降然后又上涨的循环中,我第一眼看到这cpu us的图的时候都以为是java gc的图,于是着手排查是什么原因造成的. 1、用perf看看是什么地方在耗cpu,跟踪了一段时间后,看到主要是StringTable::intern在消耗cpu,幸运的是淘宝JVM团队之前在做一个应用的优化的时候,也碰到了StringTable::intern是cpu us消耗的主要因素的现象,当时排查的原因是应用里抛异常比较多造成的,于是同样按照这个思路继续;.

Java定位CPU使用100%的方法

- cong - 龙浩的blog
流程:把线程dump出来,然后分析. 1:Threaddump的方法:. jvisualvm中来thread dump.  对应的线程id是十进制的,需要转换为十六进制的在threaddump文件中才可以看到. 找到对应的线程,把相关的方法找出来,可以精确到代码的行号,自己修改相关源码来fix bug.

写Java也得了解CPU缓存

- - 忘我的追寻
CPU,一般认为写C/C++的才需要了解,写高级语言的(Java/C#/pathon…)并不需要了解那么底层的东西. 我一开始也是这么想的,但直到碰到LMAX的 Disruptor,以及 马丁的博文,才发现写Java的,更加不能忽视CPU. 经过一段时间的阅读,希望总结一下自己的阅读后的感悟. 本文主要谈谈CPU缓存对Java编程的影响,不涉及具体CPU缓存的机制和实现.

java在CPU中的一些个破事

- - ImportNew
还是那句话,貌似java和CPU没有多少关系,我们现在来聊聊有啥关系;. 这三个步骤来完成,从这点你也能看出i++为什么能实现先做其他的事情再自我加1,因为它讲值赋予给了另一个变量. 2、我们要用到多线程并发一致性,就需要用到锁的机制,目前类似Atomic*的东西基本可以满足这些要求,内部提供了很多unsafe类的方法,通过不断对比绝对可见性的数据来保证获取的数据是最新的;接下来我们继续来说一些CPU其他的事情.

从Java视角理解CPU上下文切换(Context Switch)

- - 淘宝网通用产品团队博客
从Java视角理解系统结构连载, 关注我的微博( 链接)了解最新动态在高性能编程时,经常接触到多线程. 起初我们的理解是, 多个线程并行地执行总比单个线程要快, 就像多个人一起干活总比一个人干要快. 然而实际情况是, 多线程之间需要竞争IO设备, 或者竞争锁资源,导致往往执行速度还不如单个线程. 在这里有一个经常提及的概念就是: 上下文切换(Context Switch).

JAVA获取计算机CPU、硬盘、主板、网络等信息

- - 编程语言 - ITeye博客
l转[ http://www.cnblogs.com/jifeng/archive/2012/05/16/2503519.html]. 通过使用第三方开源jar包sigar.jar我们可以获得本地的信息. 1.下载sigar.jar. 2.按照主页上的说明解压包后将相应的文件copy到java路径.

Linux下java进程CPU占用率高-分析方法

- - Linux - 操作系统 - ITeye博客
今天登陆同事的一台gateway 开始以为hive环境登陆不了了,仔细一看看了下是因为机器很卡,我每次等几秒没登陆就ctrl+c了,看了下是有个java进程cpu:340.4%  mem:14.6%. 一般解决方法是通过top命令找出消耗资源高的线程id,利用strace命令查看该线程所有系统调用.

快速定位消耗CPU的Java线程

- - BlogJava_首页
1.通过快递定位消耗CPU的线程.     工具: Window 平台 通过 Processor  explorer 获得线程ID .     Linux 通过 top -H 获得. 然后通过Thread dump 获得java 所有线程 搜索到相应的线程ID 定位该线程.     可以通过 Java 内置的jvisualvm  或者Jstack.