Skip to content

Java 代码获取 JVM 参数

运行时诊断:代码中读取 JVM 状态

除了命令行工具,Java 代码本身也提供了丰富的 API 来获取 JVM 和运行时信息。这一节介绍如何在代码中诊断和获取 JVM 参数。

ManagementFactory:获取管理 MXBean

java.lang.management.ManagementFactory 是获取 JVM 运行时信息的入口:

java
import java.lang.management.*;

public class JvmDiagnostics {
    public static void main(String[] args) {
        // 获取内存管理 MXBean
        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
        System.out.println("堆内存使用:" + memoryMXBean.getHeapMemoryUsage());
        System.out.println("非堆内存使用:" + memoryMXBean.getNonHeapMemoryUsage());

        // 获取类加载 MXBean
        ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
        System.out.println("已加载类数量:" + classLoadingMXBean.getLoadedClassCount());
        System.out.println("总加载类数量:" + classLoadingMXBean.getTotalLoadedClassCount());

        // 获取运行时 MXBean
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        System.out.println("JVM 名称:" + runtimeMXBean.getVmName());
        System.out.println("JVM 版本:" + runtimeMXBean.getVmVersion());
        System.out.println("启动时间:" + new Date(runtimeMXBean.getStartTime()));
        System.out.println("运行时间:" + runtimeMXBean.getUptime() + " ms");
    }
}

内存信息:MemoryMXBean

堆内存使用

java
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ManagementFactory;

public class MemoryInfo {
    public static void main(String[] args) {
        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();

        // 堆内存使用
        MemoryUsage heapUsage = memoryMXBean.getHeapMemoryUsage();
        System.out.println("=== 堆内存 ===");
        System.out.println("初始大小:" + bytesToMB(heapUsage.getInit()) + " MB");
        System.out.println("已使用:" + bytesToMB(heapUsage.getUsed()) + " MB");
        System.out.println("最大限制:" + bytesToMB(heapUsage.getMax()) + " MB");
        System.out.println("已提交:" + bytesToMB(heapUsage.getCommitted()) + " MB");
        System.out.println("使用率:" + String.format("%.2f%%",
            (double) heapUsage.getUsed() / heapUsage.getMax() * 100));

        // 非堆内存(元空间)
        MemoryUsage nonHeapUsage = memoryMXBean.getNonHeapMemoryUsage();
        System.out.println("\n=== 非堆内存 ===");
        System.out.println("已使用:" + bytesToMB(nonHeapUsage.getUsed()) + " MB");
        System.out.println("最大限制:" + (nonHeapUsage.getMax() == -1 ? "无限制" :
            bytesToMB(nonHeapUsage.getMax()) + " MB"));
    }

    private static long bytesToMB(long bytes) {
        return bytes / 1024 / 1024;
    }
}

获取各内存池使用

java
import java.lang.management.*;
import java.util.*;

public class MemoryPools {
    public static void main(String[] args) {
        List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();

        for (MemoryPoolMXBean pool : pools) {
            String name = pool.getName();
            MemoryType type = pool.getType();
            MemoryUsage usage = pool.getUsage();

            System.out.println("=== " + name + " (" + type + ") ===");
            System.out.println("已使用:" + usage.getUsed() / 1024 / 1024 + " MB");
            System.out.println("最大:" + (usage.getMax() == -1 ? "无限制" :
                usage.getMax() / 1024 / 1024 + " MB"));
        }
    }
}

GC 信息:GarbageCollectorMXBean

java
import java.lang.management.*;
import java.util.*;

public class GcInfo {
    public static void main(String[] args) {
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();

        System.out.println("=== GC 信息 ===");
        for (GarbageCollectorMXBean gc : gcBeans) {
            System.out.println("GC 名称:" + gc.getName());
            System.out.println("收集次数:" + gc.getCollectionCount());
            System.out.println("总耗时:" + gc.getCollectionTime() + " ms");

            // 内存池名称
            String[] poolNames = gc.getMemoryPoolNames();
            System.out.println("管理的内存池:" + Arrays.toString(poolNames));
        }
    }
}

线程信息:ThreadMXBean

java
import java.lang.management.*;
import java.util.*;

public class ThreadInfo {
    public static void main(String[] args) {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

        System.out.println("=== 线程信息 ===");
        System.out.println("活动线程数:" + threadMXBean.getThreadCount());
        System.out.println("峰值线程数:" + threadMXBean.getPeakThreadCount());
        System.out.println("总启动线程数:" + threadMXBean.getTotalStartedThreadCount());
        System.out.println("守护线程数:" + threadMXBean.getDaemonThreadCount());

        // 获取所有线程信息
        long[] threadIds = threadMXBean.getAllThreadIds();
        System.out.println("\n=== 所有线程 ===");
        for (long tid : threadIds) {
            ThreadInfo info = threadMXBean.getThreadInfo(tid);
            if (info != null) {
                System.out.println("线程: " + info.getThreadName() +
                    " | 状态: " + info.getThreadState() +
                    " | CPU: " + threadMXBean.getThreadCpuTime(tid) / 1_000_000 + " ms");
            }
        }
    }
}

运行时信息:RuntimeMXBean

java
import java.lang.management.*;
import java.util.*;

public class RuntimeInfo {
    public static void main(String[] args) {
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();

        System.out.println("=== JVM 信息 ===");
        System.out.println("JVM 名称:" + runtimeMXBean.getVmName());
        System.out.println("JVM 供应商:" + runtimeMXBean.getVmVendor());
        System.out.println("JVM 版本:" + runtimeMXBean.getVmVersion());
        System.out.println("Java 版本:" + System.getProperty("java.version"));
        System.out.println("Java 主页:" + System.getProperty("java.home"));

        System.out.println("\n=== 启动信息 ===");
        System.out.println("启动时间:" + new Date(runtimeMXBean.getStartTime()));
        System.out.println("运行时间:" + runtimeMXBean.getUptime() / 1000 + " 秒");

        System.out.println("\n=== 系统属性 ===");
        Map<String, String> props = runtimeMXBean.getSystemProperties();
        props.forEach((k, v) -> System.out.println(k + "=" + v));
    }
}

编译信息:CompilationMXBean

java
import java.lang.management.*;

public class CompilerInfo {
    public static void main(String[] args) {
        CompilationMXBean compilerMXBean = ManagementFactory.getCompilationMXBean();

        if (compilerMXBean != null) {
            System.out.println("=== 编译信息 ===");
            System.out.println("编译器名称:" + compilerMXBean.getName());
            System.out.println("编译耗时:" + compilerMXBean.getTotalCompilationTime() + " ms");

            // 获取 JIT 编译器名称
            String compilerName = compilerMXBean.getName();
            System.out.println("JIT 编译器:" + compilerName);
        } else {
            System.out.println("JIT 编译器信息不可用");
        }
    }
}

类加载信息:ClassLoadingMXBean

java
import java.lang.management.*;

public class ClassLoadingInfo {
    public static void main(String[] args) {
        ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();

        System.out.println("=== 类加载信息 ===");
        System.out.println("当前加载类数:" + classLoadingMXBean.getLoadedClassCount());
        System.out.println("总加载类数:" + classLoadingMXBean.getTotalLoadedClassCount());
        System.out.println("已卸载类数:" + classLoadingMXBean.getUnloadedClassCount());
        System.out.println("类加载是否启用:" + classLoadingMXBean.isVerbose());
    }
}

操作系统信息:OperatingSystemMXBean

java
import java.lang.management.*;
import java.lang.reflect.*;

public class OsInfo {
    public static void main(String[] args) throws Exception {
        OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();

        System.out.println("=== 操作系统信息 ===");
        System.out.println("系统名称:" + osMXBean.getName());
        System.out.println("系统架构:" + osMXBean.getArch());
        System.out.println("CPU 数量:" + osMXBean.getAvailableProcessors());

        // 获取系统负载(需要使用底层方法)
        System.out.println("系统负载:" + osMXBean.getSystemLoadAverage());

        // 通过反射获取更详细的信息
        for (Method method : osMXBean.getClass().getDeclaredMethods()) {
            method.setAccessible(true);
            if (method.getName().startsWith("get") &&
                method.getParameterCount() == 0) {
                Object value = method.invoke(osMXBean);
                if (value instanceof Number) {
                    System.out.println(method.getName().replace("get", "") + ": " + value);
                }
            }
        }
    }
}

监控接口:MonitoringMXBean

通过 JMX 暴露监控数据

java
import java.lang.management.*;
import javax.management.*;

public class JmxExporter {
    public static void main(String[] args) throws Exception {
        // 获取 MBean Server
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

        // 注册一个自定义 MBean
        ObjectName name = new ObjectName("com.example:type=AppMonitor");
        AppMonitorMBean mbean = new AppMonitor();
        mbs.registerMBean(mbean, name);

        System.out.println("AppMonitor MBean 已注册,JMX 端口:"
            + ManagementFactory.getPlatformMBeanServer());

        // 等待
        Thread.sleep(Long.MAX_VALUE);
    }
}

public interface AppMonitorMBean {
    long getRequestCount();
    void incrementRequestCount();
}

public class AppMonitor implements AppMonitorMBean {
    private long requestCount = 0;

    @Override
    public long getRequestCount() {
        return requestCount;
    }

    @Override
    public void incrementRequestCount() {
        requestCount++;
    }
}

完整示例:健康检查端点

java
import org.springframework.web.bind.annotation.*;
import java.lang.management.*;
import java.util.*;

@RestController
@RequestMapping("/api/health")
public class HealthController {

    @GetMapping("/jvm")
    public Map&lt;String, Object&gt; getJvmHealth() {
        Map&lt;String, Object&gt; health = new HashMap&lt;&gt;();

        // 内存
        MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
        MemoryUsage heap = memory.getHeapMemoryUsage();
        health.put("heapUsed", heap.getUsed());
        health.put("heapMax", heap.getMax());
        health.put("heapUsedPercent",
            String.format("%.2f%%", (double) heap.getUsed() / heap.getMax() * 100));

        // GC
        List&lt;GarbageCollectorMXBean&gt; gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        long totalGcCount = 0;
        long totalGcTime = 0;
        for (GarbageCollectorMXBean gc : gcBeans) {
            totalGcCount += gc.getCollectionCount();
            totalGcTime += gc.getCollectionTime();
        }
        health.put("gcCount", totalGcCount);
        health.put("gcTimeMs", totalGcTime);

        // 线程
        ThreadMXBean threads = ManagementFactory.getThreadMXBean();
        health.put("threadCount", threads.getThreadCount());
        health.put("peakThreadCount", threads.getPeakThreadCount());
        health.put("daemonThreadCount", threads.getDaemonThreadCount());

        // 类加载
        ClassLoadingMXBean classes = ManagementFactory.getClassLoadingMXBean();
        health.put("loadedClassCount", classes.getLoadedClassCount());

        // 运行时
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        health.put("uptimeMs", runtime.getUptime());
        health.put("vmName", runtime.getVmName());
        health.put("vmVersion", runtime.getVmVersion());

        return health;
    }
}

常用 API 速查

API作用关键方法
ManagementFactory.getMemoryMXBean()内存信息getHeapMemoryUsage()
ManagementFactory.getGarbageCollectorMXBeans()GC 信息getCollectionCount()
ManagementFactory.getThreadMXBean()线程信息getThreadCount()
ManagementFactory.getRuntimeMXBean()JVM 信息getVmName()
ManagementFactory.getClassLoadingMXBean()类加载信息getLoadedClassCount()
ManagementFactory.getOperatingSystemMXBean()OS 信息getAvailableProcessors()
ManagementFactory.getCompilationMXBean()编译信息getTotalCompilationTime()
ManagementFactory.getPlatformMBeanServer()MBean ServerJMX 暴露

本节小结

Java 代码获取 JVM 参数的核心 API 是 ManagementFactory,它提供了访问所有 MXBean 的入口:

ManagementFactory 核心 MXBean:
MemoryMXBean         → 堆/非堆内存使用
GarbageCollectorMXBean → GC 次数和耗时
ThreadMXBean          → 线程数量和状态
RuntimeMXBean         → JVM 版本、启动时间
ClassLoadingMXBean   → 类加载数量
OperatingSystemMXBean → OS 信息
CompilationMXBean     → JIT 编译信息

实际应用:在 Spring Boot Actuator、Dropsonde 等框架中,这些 API 被广泛用于暴露 /actuator/metrics 端点。

下一节,我们来看 OOM 及性能优化案例与解决方案

基于 VitePress 构建