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<String, Object> getJvmHealth() {
Map<String, Object> health = new HashMap<>();
// 内存
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<GarbageCollectorMXBean> 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 Server | JMX 暴露 |
本节小结
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 及性能优化案例与解决方案。
