GC导致线上CPU超100%

运维同学告知报警,一个java进程占用CPU 100%以上。下面进行排查步骤。
1.top -c ,效果如下图(这个截图是另一个节点的效果,实际进程号为17817,后续的截图将都会以进程号17817为准)。
在这里插入图片描述
2.top -pH 17817,获取17817进程中,CPU消耗大的两个线程。
在这里插入图片描述
3.printf “%x\n” 17819 ,获取16进制的线程号,因为在jstack的报告中,线程号都是以16进制表示的。
在这里插入图片描述
4.jstack 17817 > 17817.jstack,将jstack的报告输出到17817.jstack文件中。
4.1.然后less 17817.jstack,搜索上面的16进制的线程号,结果如下。发现,是两个gc线程在疯狂占用CPU,由此可知,jvm内存不够,或者,java代码写得有漏洞导致对象无法回收。
在这里插入图片描述
5.jmap -heap 17817 > 17817.heap ,查看jvm堆快照,发现jvm堆内存一共500M,新生代和老年代各250M,且新生代的eden区一直处于100%利用状态,老年代也一直处于99.87%被利用的状态。之所以From和To两个区域的used为0%,是因为它们的空间(15M)根本无法容纳eden区回收之后剩余的对象,所以直接都去了老年代(个人猜测而已)。
在这里插入图片描述
6.jmap -dump:format=b,file=17817.dump 17817,导出内存dump,输出到17817.dump文件中。628M大小。
在这里插入图片描述
7.利用jdk自带工具jvisualvm分析内存dump文件。在mac下,可以直接在终端窗口输入命令jvisualvm,即可打开jvisualvm图形界面窗口,在windows下可以直接双击jvisualvm.exe。
打开jvisualvm图形界面窗口之后,点击文件->装入,在文件类型那一栏选择堆,选择要分析的17817.dump文件,打开。
在这里插入图片描述
效果如下:
在这里插入图片描述
发现char[]占用内存达到了276733352,应该是263M(新生代一共才250M,总堆内存一共才500M)。然后查看其实例情况,如下图,有大量的字符串对象(包括各种json、大量的SELECT/UPDATE的sql语句,还有一些类似token字符串的东西,等等):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
综上,cpu飙高的原因已经找到,即为gc导致,而gc的原因表象也已经找到,是存在大量字符串对象。但是,为什么会存在这么多字符串对象,需要业务开发人员去看自己的代码,这些字符串是怎么产生的,为什么会产生这么多,却gc不掉。

个人建议:
这个项目的启动参数是-Xms500m -Xmx500m -Xmn250m,而实际运行时的堆内存参数,如上面的截图:
在这里插入图片描述
由此可知,在启动参数中设置了新生代大小为250m(-Xmn250m),就会覆盖默认的-XX:NewRatio=2(即新生代:老年代=1:2),导致现在的新生代和老年代都是250m,即1:1。
所以,应该去掉-Xmn250m这个参数,而根据比例来设置其与老年代的占比。

其他参考如下:
来自:https://blog.csdn.net/yrwan95/article/details/82826519

Xmn、Xms、Xmx、Xss都是JVM对内存的配置参数,我们可以根据不同需要区修改这些参数,以达到运行程序的最好效果。
-Xms 堆内存的最小大小,默认为物理内存的1/64
-Xmx 堆内存的最大大小,默认为物理内存的1/4
-Xmn 堆内新生代的大小。通过这个值也可以得到老生代的大小:-Xmx减去-Xmn
-Xss 设置每个线程可使用的内存大小,即栈的大小。在相同物理内存下,减小这个值能生成更多的线程,当然操作系统对一个进程内的线程数还是有限制的,不能无限生成。线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时出现溢出的可能性更大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会出现内存溢出的错误。
除了这些配置,JVM还有非常多的配置,常用的如下:
堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-Xmn:新生代大小
-XX:NewRatio:设置新生代和老年代的比值。如:为3,表示年轻代与老年代比值为1:3
-XX:SurvivorRatio:新生代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:为3,表示Eden:Survivor=3:2,一个Survivor区占整个新生代的1/5
-XX:MaxTenuringThreshold:设置转入老年代的存活次数。如果是0,则直接跳过新生代进入老年代
-XX:PermSize、-XX:MaxPermSize:分别设置永久代最小大小与最大大小(Java8以前)
-XX:MetaspaceSize、-XX:MaxMetaspaceSize:分别设置元空间最小大小与最大大小(Java8以后)
收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行老年代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n:设置并发收集器新生代收集方式为并行收集时,使用的CPU数。并行收集线程数。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这句话大概意思是系统有很多个GC(Garbage Collection)任务的线程,每个线程都占用 CPU 的 20%。 GC 是一种自动内存管理机制,用于回收不再使用的对象。在 Java 等高级编程语言中,GC 是由系统的垃圾回收器来执行的。在执行 GC 时,系统会启动一个或多个线程来处理垃圾回收的工作。 根据您提供的信息,似乎系统中有很多个 GC 线程在同时运行。每个线程都占用 CPU 的 20%,这意味着这些线程在 CPU 上的使用率很高。如果系统的 CPU 不够强大,这些线程可能会导致系统的响应速度变慢,甚至可能导致系统崩溃。因此,需要根据具体情况对系统进行优化,例如调整 GC 线程的数量和优先级,或者升级系统硬件等。 ### 回答2: GC(垃圾回收)任务线程是负责执行垃圾回收操作的线程。垃圾回收是指在程序运行过程中,自动释放不再使用的内存空间,以便为新的对象分配内存。一个线程占用CPU 20%意味着该线程在CPU资源上占用的时间为总时间的20%。 假设有许多GC任务线程,每个线程都占用CPU的20%,那么总的CPU占用率将取决于总线程数量和CPU的总资源。假设总共有10个GC任务线程,并且CPU资源能够完全满足这些线程的需求,那么总的CPU占用率将达到10个线程*20% = 200%。这意味着这些GC任务线程实际上会占用过一个CPU的资源。 但是,实际情况可能没有这么简单。首先,该系统可能有其他任务线程同时运行,而不仅仅是垃圾回收。其次,CPU本身可能还在执行其他系统和进程的任务。这将导致CPU的总资源被其他任务占用,从而影响GC任务线程的CPU占用率。 在实践中,GC任务线程通常会根据系统的需求和可用资源进行调整。例如,可以通过调整GC算法、调整垃圾回收频率或者调整GC任务线程的数量来优化系统的性能和资源利用率。通过合理的调整和配置,可以使GC任务线程的CPU占用率在一个可接受的范围内,以提高系统的整体性能和稳定性。 ### 回答3: 有很多GC task thread,每个线程占用CPU的20%。 这意味着有多个垃圾回收任务线程在运行,每个线程使用CPU的20%的资源。假设有10个GC任务线程,则每个线程使用CPU的20%的资源。 当系统中有多个垃圾回收任务需要同时进行时,这些任务会在不同的线程中同时执行。每个线程在执行任务时,会使用CPU的20%的资源。这样可以提高垃圾回收的效率,加快系统的整体运行速度。 GC任务的目的是回收不再使用的内存资源,以便系统可以重新利用这些资源。GC任务通常在后台运行,以不影响系统的正常操作。通过将GC任务分配给多个线程并将其占用的CPU资源限制在20%,可以确保这些任务不会占用过多的系统资源,从而保证系统的响应性和稳定性。 然而,需要注意的是,在分配给GC任务的线程中,20%的CPU资源可能会对其他正在运行的任务产生一定的影响。如果系统中同时运行其他需要大量CPU资源的任务,这些任务可能会受到GC任务的影响而运行缓慢。 总而言之,通过将GC任务分配给多个线程并限制其占用的CPU资源在20%,可以提高垃圾回收的效率,同时保证系统的响应性和稳定性。然而,需要根据具体情况进行调整,以便平衡系统中不同任务之间的资源分配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值