JVM 故障调查教程

#JVM 故障调查教程

##java 程序 cpu100%原因排查
模拟cpu占用100%代码

public class App {
    public static void main(String[] args) throws InterruptedException {
        int num = 20;
        Thread[] threads = new Thread[num];
        for (int i = 0; i < num; i++) {
            threads[i] = new Thread(new PressureRunner());
            threads[i].start();

        }


    }

    public static class PressureRunner implements Runnable {
        @Override
        public void run() {
            while (true) {

            }
        }
    }

}

编译:javac App.java

执行:java App.java

第一步:确认cpu占用情况及进程ID

​ top

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RzrvIHOd-1623727209982)(C:\Users\27381\Pictures\Camera Roll\1623122537062.png)]

第二步: 显示进程下的线程占用CPU情况

top -H -p pid

找到占用CPU最高的线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LUJ0MiqS-1623727209984)(C:\Users\27381\AppData\Local\Temp\1623123012135.png)]

​ echo “obase=16;9758” | bc

​ 线程id结果是

​ 261E

###第三步: 导出java进程的线程栈

jstack pid > pid.tdump

执行

jstack 9745 > 9745.tdump

#查看tdump
cat 9745.tdump 

代码定位

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cEmuQ6cE-1623727209985)(C:\Users\27381\Documents\1623123988844.png)]

###小结
本例子是针对业务程序引用的CPU100%的分析方法,还可能会有,并发io读写或网络读取而引起的内存资源用完引起的CPU占用100%的情况。也适用此方法来定位问题代码。一般这种情况如果计算任务释放或io读写或网络资源释放,cpu占用情况自动会下降,不会导致jvm奔溃。
还有另外一种引起的CPU占用100%情况,就是JVM空间不够引起的GC频繁回收。GC是使用多线程回收的。导致大量线程疯狂回收最终CPU资源占满。而且是不会释放的,CPU一直100%。解决办法就要调整jvm的增加内存配置。请看下节。

jvm 内存空间不足引起的CPU100% 原因排除

代码

package com.hdk.demofullgc;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * VM参数: -XX:+PrintGC -Xms50M -Xmx50M
 *  GC调优---生产服务器推荐开启(默认是关闭的)
 *  -XX:+HeapDumpOnOutOfMemoryError
 */

public class FullGCProblem {
    //线程池
    private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50,
            new ThreadPoolExecutor.DiscardOldestPolicy());

    public static void main(String[] args) throws Exception {
        //50个线程
        executor.setMaximumPoolSize(50);
        while (true){
            calc();
            Thread.sleep(100);
        }
    }

    /**
     * 多线程执行任务计算
     */
    private static void calc(){
        List<UserInfo> taskList = getAllCardInfo();
        taskList.forEach(userInfo -> {
            executor.scheduleWithFixedDelay(() -> {
                userInfo.user();
            }, 2, 3, TimeUnit.SECONDS);
        });
    }

    /**
     * 模拟从数据库读取数据,返回
     * @return
     */
    private static List<UserInfo> getAllCardInfo(){
        List<UserInfo> taskList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            UserInfo userInfo = new UserInfo();
            taskList.add(userInfo);
        }
        return taskList;
    }
    private static class UserInfo {
        String name = "hdk";
        int age = 18;
        BigDecimal money = new BigDecimal(999999.99);

        public void user() {
            //
        }
    }
}

###运行代码:
java -cp demofullgc.jar -XX:+PrintGC -Xms50M -Xmx50M com.hdk.demofullgc.FullGCProblem
结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XN37JJ7G-1623727209987)(C:\Users\27381\Documents\1623231867792.png)]

GC 日志详解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ang5IQI-1623727209988)(C:\Users\27381\Documents\1623295085337.png)]

GC 常用参数
-Xmn -Xms -Xmx –Xss 年轻代 最小堆 最大堆 栈空间
-XX:+UseTLAB 使用 TLAB,默认打开
-XX:+PrintTLAB 打印 TLAB 的使用情况
-XX:TLABSize 设置 TLAB 大小
-XX:+DisableExplicitGC 启用用于禁用对的调用处理的选项 System.gc()
-XX:+PrintGC 查看 GC 基本信息
-XX:+PrintGCDetails 查看 GC 详细信息
-XX:+PrintHeapAtGC 每次一次 GC 后,都打印堆信息
-XX:+PrintGCTimeStamps启用在每个 GC 上打印时间戳的功能
-XX:+PrintGCApplicationConcurrentTime

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值