jvm虚拟机调优实战

  1. 使用命令 jps查看进程
  2. 使用jstat gc -1 5000查看内存占用和回收情况




正式测试 是否跑job区别。大量的job,部分用户点击的热数据 ,不同时刻在跑 600-700对比 200 多了400-500m,代码原数据(不占用堆区)占了300m,所以 堆空间=老年代(900)+700+7 约等于 1500-1600m。加上本地区(主要是栈内存(堆的对象引用指针) gc root+程序及计数器等小空间)

-server -XX:+PrintGCDetails -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Xms1600m -Xmx1600m -Xverify:none -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/log/plan01.hprof

full gc 过程: 15次=》old =>old大=》young变小=》young持续小=》young gc 频繁=>full gc

heap out of range: full gc =>old 不能变大(young 足够小)=》full gc后不能增大old的空间 容不下新来的数据。

  1. 使用visal vm 和mat图形化分析







排查出问题:DruidDataSource比例最高 在线程池的destroy线程中,排查可能是druid的数据源异常配置问题:

  1. remove-abandoned: false=>remove-abandoned: true。

    相关的其他配置 正常

    time-between-eviction-runs-millis: 60000 # 1 minute

    min-evictable-idle-time-millis: 300000 # 5 minutes

    useGlobalDataSourceStat: false

    druid配置导致堆溢出 (https://blog.csdn.net/lypeng13/article/details/121911981)

    改动后观察启动后的 E O区的占用变化和之前趋势对比情况。和FullGc在相同时间的变化趋势

    增大heap大小观察full gc

  2. 导出dump文件的方式 1. 命令 2. 工具 3. 代码

(1)docker file 文件启动文件,堆溢出自动导出

​-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/log/plan01.hprof

(2)

public class FullGCHeapDump {

private static HotSpotDiagnosticMXBean hotspotMBean;

private static long lastFullGCTime = -1; // To store the time of the last Full GC

private static final long THRESHOLD = 15000; // 2 seconds in milliseconds

复制代码
// Method to trigger a heap dump
public static void dumpHeap(String filePath) {
    if (hotspotMBean == null) {
        try {
            hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(
                    ManagementFactory.getPlatformMBeanServer(),
                    "com.sun.management:type=HotSpotDiagnostic",
                    HotSpotDiagnosticMXBean.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    try {
        // Dump the heap to the specified file
        hotspotMBean.dumpHeap(filePath, true);
        System.out.println("Heap dump created at: " + filePath);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@PostConstruct
public void postConstruct(){
    // Keep the application running so we can monitor GC events
    System.out.println("Monitoring for Full GC events...");
    // Register GC notification listener
    for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
        NotificationEmitter emitter = (NotificationEmitter) gcBean;
        emitter.addNotificationListener(new NotificationListener() {
            @Override
            public void handleNotification(Notification notification, Object handback) {
                String notificationType = notification.getType();
                if (notificationType.equals("com.sun.management.gc.notification")) {
                    com.sun.management.GarbageCollectionNotificationInfo info =
                            com.sun.management.GarbageCollectionNotificationInfo.from((javax.management.openmbean.CompositeData) notification.getUserData());

                    // Check if the GC type is "end of major GC" or "Full GC"
                    String gcAction = info.getGcAction();
                    System.out.println(gcAction);
                    if (gcAction.contains("end of major GC") || gcAction.contains("end of Full GC")) {
                        System.out.println("Full GC detected.");
                        long currentTime = System.currentTimeMillis();  // Get the current time

                        if (lastFullGCTime != -1 && (currentTime - lastFullGCTime) <= THRESHOLD) {
                            // If two Full GCs occurred within 2 seconds, trigger the heap dump
                            System.out.println("Two Full GCs detected within 2 seconds. Triggering heap dump...");
                            FullGCHeapDump.dumpHeap("heapdump.hprof");
                        }

                        // Update the time of the last Full GC
                        lastFullGCTime = currentTime;
                    }
                }
            }
        }, null, null);
    }
}

}

  1. mat实例分析查找追踪堆栈和可能得内存泄漏点

模拟堆栈溢出

@PostMapping("post")

public void post(){

// simulate full gc

int maxValue = Integer.MAX_VALUE;

List list = new ArrayList<>();

while (true){

for (int i = 0; i < maxValue; i++) {

list.add(new AchResult());

}

}

相关推荐
松仔log1 小时前
JetPack——Paging3+Room
android·java·zoom
biter down5 小时前
14:pytest-order 插件 顺序控制案例
开发语言·python·pytest
郝学胜-神的一滴6 小时前
Qt 高级开发 009: C++ Lambda 表达式
开发语言·c++·qt·软件构建
星栈独行6 小时前
我在 Rust 全栈项目里用 JWT 做无状态认证
开发语言·后端·rust·前端框架·开源·github·web
Lei活在当下6 小时前
先用起来,再理解,关于协程Coroutine应该知道的事
android·java·jvm
石山代码6 小时前
C++ 轻量级日志系统
开发语言·c++
Java爱好狂.6 小时前
Java程序员体系化学习路线(2026最新版)
java·后端·java面试·java架构师·java程序员·java八股文·java学习路线
tongluowan0077 小时前
以ReentrantLock为例解释AQS的工作流程
java·模板方法模式·aqs·reentrantlock
小技与小术7 小时前
玩转Flask
开发语言·python·flask
SilentSamsara7 小时前
Python 性能优化:tracemalloc、profiling 与 C 扩展加速
开发语言·python·青少年编程·性能优化