内存爆炸、CPU100%问题定位

编程入门 行业动态 更新时间:2024-10-15 02:26:40

<a href=https://www.elefans.com/category/jswz/34/1771154.html style=内存爆炸、CPU100%问题定位"/>

内存爆炸、CPU100%问题定位

目录

  • 一、内存爆炸相关
    • 1、关于-Xms(最小堆内存)和-Xmx(最大堆内存)
    • 2、JVM初始化时申请实际物理内存
    • 3、OutOfMemory问题排查
      • (1) 堆内存溢出排查
      • (2) 堆外内存溢出排查
  • 二、CPU 100及死锁问题定位
    • 1、CPU 100问题排查
      • (1) 找到程序对应进程号
      • (2) 查找进程对应的线程编号
      • (3)查看线程堆栈信息
    • 2、死锁问题排查

一、内存爆炸相关

1、关于-Xms(最小堆内存)和-Xmx(最大堆内存)

最大堆内存为JVM能向操作系统申请的最大内存。最小堆内存并不是程序一启动就申请这么多内存,而是当前进程如果申请的内存已超过最小堆内存,内存回收时,大于最小堆内存的部分会返回给操作系统,其它申请的内存不会。

2、JVM初始化时申请实际物理内存

默认没有配置-XX:+AlwaysPreTouch参数时,JVM进程申请的内存只是虚拟内存,程序运行时根据虚拟内存地址映射到实际的物理内存,缺页时才将数据加载到物理内存,分配实际的物理空间。加上-XX:+AlwaysPreTouch参数后,程序将直接分配到实际的物理内存,而不是根据需要在缺页时才申请物理内存。

简单来说就是没有开启预热时,JVM只是向操作系统做了登记,告诉操作系统我需要多少内存,但实际上并没有进行物理分配,加上该参数后在程序启动时就会分配物理内存。

注意:加上该参数可能会导致程序启动变慢。

3、OutOfMemory问题排查

(1) 堆内存溢出排查

内存溢出示例如下:

/*** -Xmx512m -server -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\Users\Administrator\Desktop\java_heapdump.hprof*/
public class OutOfMemoryExample1 {private static List<Object> space = new ArrayList<>();public static void main(String[] args) throws Exception {// 内存泄漏 最终会导致 = 内存溢出for (int i = 0; i < 1000; i++) {space.add(new byte[1024 * 1024 * 128]);Thread.sleep(3000L);}}
}

通过MAT(Eclipse Memory Analyzer)工具查找leak suspect即可排查:

(2) 堆外内存溢出排查

直接内存溢出示例:

/*** 堆外内存溢出* 控制堆外内存大小:-XX:MaxDirectMemorySize=128m -XX:+HeapDumpOnOutOfMemoryError*/
public class OutOfMemoryExample2 {private static List<Object> space = new ArrayList<>();public static void main(String[] args) throws Exception {// 内存泄漏 最终会导致  内存溢出for (int i = 0; i < 1000; i++) {ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 * 1024 * 64);byteBuffer.put(new byte[1024 * 1024 * 5]);space.add(byteBuffer);Thread.sleep(2000L);}}
}

对于堆外内存溢出的情况,通过jvisualvm中的btrace插件分析调用情况,如下:


二、CPU 100及死锁问题定位

1、CPU 100问题排查

CPU占用率过高通常是因为死循环或者递归调用导致的,通过jstack基本能定位到具体是哪些线程在执行CPU高度密集型操作。示例代码如下:

public class Cpu100Example {public static void main(String[] args) {System.out.println("Starting executing the programme");// 如果有多核,开启与逻辑cpu相等的线程数执行计算型任务即可,不要有阻塞或者I/O操作while (true) {new Random().nextInt();}}
}

问题解决思路如下:

(1) 找到程序对应进程号

通过jps或者jcmd命令可查到程序进程号,如下:

[universe@VM_0_13_centos ~]$ jps -l
2792 org.apache.zookeeper.server.quorum.QuorumPeerMain
2745 org.apache.zookeeper.server.quorum.QuorumPeerMain
30858 comease.issue.cpu.Cpu100Example
2716 org.apache.zookeeper.server.quorum.QuorumPeerMain
31822 sun.tools.jps.Jps

(2) 查找进程对应的线程编号

top -H -p 30858

结果如下:

从上图可以看到,pid为30859的线程几乎占用了全部CPU。

(3)查看线程堆栈信息

jstack命令内容中的nid为上一步我们获取到的线程pid的16进制形式,因此先把线程pid转换为16进制,再对jstack内容进行查找。


现在可以看到该线程的方法调用栈,进而找到相应的代码。

2、死锁问题排查

示例代码如下:

public class DeadLockExample {private static Object monitor1 = new Object();private static Object monitor2 = new Object();public static void main(String[] args) {new Thread(new ObtainLockTask1()).start();new Thread(new ObtainLockTask2()).start();}private static class ObtainLockTask1 implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " starts to obtain lock from monitor1");try {while (true) {synchronized (monitor1) {System.out.println(Thread.currentThread().getName() + " has obtained lock from monitor1");Thread.sleep(3000);synchronized (monitor2) {System.out.println(Thread.currentThread().getName() + " starts to obtain lock from monitor2");}}}} catch (InterruptedException e) {e.printStackTrace();}}}private static class ObtainLockTask2 implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " starts to obtain lock from monitor2");try {while (true) {synchronized (monitor2) {System.out.println(Thread.currentThread().getName() + " has obtained lock from monitor2");Thread.sleep(3000);synchronized (monitor1) {System.out.println(Thread.currentThread().getName() + " starts to obtain lock from monitor1");}}}} catch (InterruptedException e) {e.printStackTrace();}}}
}

依然通过jstack命令查看线程堆栈信息可以定位,如下图:

注意:通过synchronized关键字导致的Java平台级死锁通过jstack命令可以直接分析出来,而使用ReentrantLock导致的死锁则不能。

更多推荐

内存爆炸、CPU100%问题定位

本文发布于:2023-12-06 08:28:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1667015.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:内存

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!