本文目录导读:

我来提供一个完整的Java JVM监控实现案例,包含内存、线程、GC等多个维度的监控。
核心监控类
JVMMonitor.java
import java.lang.management.*;
import java.util.*;
import javax.management.*;
import com.sun.management.OperatingSystemMXBean;
public class JVMMonitor {
// 内存监控
public static Map<String, Object> getMemoryInfo() {
Map<String, Object> memoryInfo = new HashMap<>();
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
// 堆内存
MemoryUsage heapMemory = memoryMXBean.getHeapMemoryUsage();
memoryInfo.put("heapInit", heapMemory.getInit());
memoryInfo.put("heapMax", heapMemory.getMax());
memoryInfo.put("heapUsed", heapMemory.getUsed());
memoryInfo.put("heapCommitted", heapMemory.getCommitted());
// 非堆内存
MemoryUsage nonHeapMemory = memoryMXBean.getNonHeapMemoryUsage();
memoryInfo.put("nonHeapInit", nonHeapMemory.getInit());
memoryInfo.put("nonHeapMax", nonHeapMemory.getMax());
memoryInfo.put("nonHeapUsed", nonHeapMemory.getUsed());
memoryInfo.put("nonHeapCommitted", nonHeapMemory.getCommitted());
// 内存池详情
List<Map<String, Object>> memoryPools = new ArrayList<>();
for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
Map<String, Object> poolInfo = new HashMap<>();
poolInfo.put("name", pool.getName());
poolInfo.put("type", pool.getType().toString());
poolInfo.put("usage", pool.getUsage());
poolInfo.put("peakUsage", pool.getPeakUsage());
memoryPools.add(poolInfo);
}
memoryInfo.put("memoryPools", memoryPools);
return memoryInfo;
}
// 线程监控
public static Map<String, Object> getThreadInfo() {
Map<String, Object> threadInfo = new HashMap<>();
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
threadInfo.put("threadCount", threadMXBean.getThreadCount());
threadInfo.put("peakThreadCount", threadMXBean.getPeakThreadCount());
threadInfo.put("totalStartedThreadCount", threadMXBean.getTotalStartedThreadCount());
threadInfo.put("daemonThreadCount", threadMXBean.getDaemonThreadCount());
// 死锁检测
long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
threadInfo.put("deadlockedThreads", deadlockedThreads != null ? deadlockedThreads.length : 0);
// 线程详情
List<Map<String, Object>> threads = new ArrayList<>();
for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
Map<String, Object> thread = new HashMap<>();
thread.put("threadId", info.getThreadId());
thread.put("threadName", info.getThreadName());
thread.put("threadState", info.getThreadState().toString());
thread.put("blockedCount", info.getBlockedCount());
thread.put("blockedTime", info.getBlockedTime());
thread.put("waitedCount", info.getWaitedCount());
thread.put("waitedTime", info.getWaitedTime());
// 堆栈信息
StackTraceElement[] stackTrace = info.getStackTrace();
thread.put("stackTraceLength", stackTrace.length);
threads.add(thread);
}
threadInfo.put("threads", threads);
return threadInfo;
}
// GC监控
public static Map<String, Object> getGCInfo() {
Map<String, Object> gcInfo = new HashMap<>();
List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
long totalGcCount = 0;
long totalGcTime = 0;
List<Map<String, Object>> gcDetails = new ArrayList<>();
for (GarbageCollectorMXBean gc : gcBeans) {
Map<String, Object> gcDetail = new HashMap<>();
long count = gc.getCollectionCount();
long time = gc.getCollectionTime();
gcDetail.put("name", gc.getName());
gcDetail.put("collectionCount", count);
gcDetail.put("collectionTime", time);
// GC内存池
String[] poolNames = gc.getMemoryPoolNames();
gcDetail.put("memoryPools", Arrays.toString(poolNames));
gcDetails.add(gcDetail);
totalGcCount += count;
totalGcTime += time;
}
gcInfo.put("totalGcCount", totalGcCount);
gcInfo.put("totalGcTime", totalGcTime);
gcInfo.put("gcDetails", gcDetails);
return gcInfo;
}
// 类加载监控
public static Map<String, Object> getClassLoadingInfo() {
Map<String, Object> classInfo = new HashMap<>();
ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
classInfo.put("loadedClassCount", classLoadingMXBean.getLoadedClassCount());
classInfo.put("totalLoadedClassCount", classLoadingMXBean.getTotalLoadedClassCount());
classInfo.put("unloadedClassCount", classLoadingMXBean.getUnloadedClassCount());
return classInfo;
}
// 系统信息
public static Map<String, Object> getSystemInfo() {
Map<String, Object> systemInfo = new HashMap<>();
OperatingSystemMXBean osMXBean =
(OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
systemInfo.put("osName", System.getProperty("os.name"));
systemInfo.put("osVersion", System.getProperty("os.version"));
systemInfo.put("osArch", System.getProperty("os.arch"));
systemInfo.put("availableProcessors", osMXBean.getAvailableProcessors());
systemInfo.put("systemLoadAverage", osMXBean.getSystemLoadAverage());
systemInfo.put("cpuUsage", osMXBean.getSystemCpuLoad() * 100);
systemInfo.put("processCpuUsage", osMXBean.getProcessCpuLoad() * 100);
systemInfo.put("totalPhysicalMemory", osMXBean.getTotalPhysicalMemorySize());
systemInfo.put("freePhysicalMemory", osMXBean.getFreePhysicalMemorySize());
systemInfo.put("totalSwapSpace", osMXBean.getTotalSwapSpaceSize());
systemInfo.put("freeSwapSpace", osMXBean.getFreeSwapSpaceSize());
return systemInfo;
}
// 编译监控
public static Map<String, Object> getCompilationInfo() {
Map<String, Object> compileInfo = new HashMap<>();
if (ManagementFactory.getCompilationMXBean() != null) {
CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();
compileInfo.put("compilationTime", compilationMXBean.getTotalCompilationTime());
compileInfo.put("compilerName", compilationMXBean.getName());
}
return compileInfo;
}
// 获取所有监控数据
public static Map<String, Object> getAllMonitorInfo() {
Map<String, Object> allInfo = new HashMap<>();
allInfo.put("timestamp", System.currentTimeMillis());
allInfo.put("memory", getMemoryInfo());
allInfo.put("thread", getThreadInfo());
allInfo.put("gc", getGCInfo());
allInfo.put("classLoading", getClassLoadingInfo());
allInfo.put("system", getSystemInfo());
allInfo.put("compilation", getCompilationInfo());
allInfo.put("runtime", getRuntimeInfo());
return allInfo;
}
// JVM运行时信息
public static Map<String, Object> getRuntimeInfo() {
Map<String, Object> runtimeInfo = new HashMap<>();
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
runtimeInfo.put("name", runtimeMXBean.getName());
runtimeInfo.put("vmName", runtimeMXBean.getVmName());
runtimeInfo.put("vmVersion", runtimeMXBean.getVmVersion());
runtimeInfo.put("vmVendor", runtimeMXBean.getVmVendor());
runtimeInfo.put("uptime", runtimeMXBean.getUptime());
runtimeInfo.put("startTime", runtimeMXBean.getStartTime());
// JVM参数
List<String> inputArguments = runtimeMXBean.getInputArguments();
runtimeInfo.put("jvmArguments", inputArguments);
// Classpath
runtimeInfo.put("classPath", runtimeMXBean.getClassPath());
// 系统属性
Map<String, String> systemProperties = runtimeMXBean.getSystemProperties();
runtimeInfo.put("systemProperties", systemProperties);
return runtimeInfo;
}
}
监控数据格式化输出
JVMInfoFormatter.java
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class JVMInfoFormatter {
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化字节大小为可读格式
public static String formatBytes(long bytes) {
if (bytes == 0) return "0 B";
final String[] units = {"B", "KB", "MB", "GB", "TB"};
int unitIndex = (int) (Math.log10(Math.abs(bytes)) / Math.log10(1024));
if (unitIndex >= units.length) {
unitIndex = units.length - 1;
}
double value = bytes / Math.pow(1024, unitIndex);
return String.format("%.2f %s", value, units[unitIndex]);
}
// 格式化内存信息
public static String formatMemoryInfo(Map<String, Object> memoryInfo) {
StringBuilder sb = new StringBuilder();
sb.append("========== 内存监控 ==========\n");
long heapMax = (Long) memoryInfo.get("heapMax");
long heapUsed = (Long) memoryInfo.get("heapUsed");
long heapCommitted = (Long) memoryInfo.get("heapCommitted");
sb.append("堆内存:");
sb.append("\n 最大: ").append(formatBytes(heapMax));
sb.append("\n 已用: ").append(formatBytes(heapUsed));
sb.append("\n 已分配: ").append(formatBytes(heapCommitted));
sb.append("\n 使用率: ").append(String.format("%.2f%%",
heapMax > 0 ? (double) heapUsed / heapMax * 100 : 0));
sb.append("\n\n非堆内存:");
sb.append("\n 已用: ").append(formatBytes((Long) memoryInfo.get("nonHeapUsed")));
sb.append("\n 已分配: ").append(formatBytes((Long) memoryInfo.get("nonHeapCommitted")));
// 内存池详情
@SuppressWarnings("unchecked")
List<Map<String, Object>> pools = (List<Map<String, Object>>) memoryInfo.get("memoryPools");
if (pools != null) {
sb.append("\n\n内存池详情:");
for (Map<String, Object> pool : pools) {
sb.append("\n ").append(pool.get("name"))
.append(" (").append(pool.get("type")).append("):");
MemoryUsage usage = (MemoryUsage) pool.get("usage");
if (usage != null) {
sb.append(" used=").append(formatBytes(usage.getUsed()))
.append(", max=").append(formatBytes(usage.getMax()))
.append(", committed=").append(formatBytes(usage.getCommitted()));
}
}
}
return sb.toString();
}
// 格式化线程信息
public static String formatThreadInfo(Map<String, Object> threadInfo) {
StringBuilder sb = new StringBuilder();
sb.append("\n========== 线程监控 ==========\n");
sb.append("当前线程数: ").append(threadInfo.get("threadCount"));
sb.append("\n峰值线程数: ").append(threadInfo.get("peakThreadCount"));
sb.append("\n守护线程数: ").append(threadInfo.get("daemonThreadCount"));
sb.append("\n总启动线程数: ").append(threadInfo.get("totalStartedThreadCount"));
sb.append("\n死锁线程数: ").append(threadInfo.get("deadlockedThreads"));
@SuppressWarnings("unchecked")
List<Map<String, Object>> threads = (List<Map<String, Object>>) threadInfo.get("threads");
if (threads != null) {
sb.append("\n\n线程状态统计:");
Map<String, Integer> stateCount = new HashMap<>();
for (Map<String, Object> thread : threads) {
String state = (String) thread.get("threadState");
stateCount.merge(state, 1, Integer::sum);
}
stateCount.forEach((state, count) ->
sb.append("\n ").append(state).append(": ").append(count));
}
return sb.toString();
}
// 格式化GC信息
public static String formatGCInfo(Map<String, Object> gcInfo) {
StringBuilder sb = new StringBuilder();
sb.append("\n========== GC监控 ==========\n");
sb.append("总GC次数: ").append(gcInfo.get("totalGcCount"));
sb.append("\n总GC时间: ").append(gcInfo.get("totalGcTime")).append(" ms");
@SuppressWarnings("unchecked")
List<Map<String, Object>> gcDetails = (List<Map<String, Object>>) gcInfo.get("gcDetails");
if (gcDetails != null) {
sb.append("\n\nGC详情:");
for (Map<String, Object> gc : gcDetails) {
sb.append("\n ").append(gc.get("name"))
.append(": 次数=").append(gc.get("collectionCount"))
.append(", 时间=").append(gc.get("collectionTime")).append("ms");
}
}
return sb.toString();
}
// 格式化系统信息
public static String formatSystemInfo(Map<String, Object> systemInfo) {
StringBuilder sb = new StringBuilder();
sb.append("\n========== 系统信息 ==========\n");
sb.append("操作系统: ").append(systemInfo.get("osName"))
.append(" ").append(systemInfo.get("osVersion"));
sb.append("\nCPU核心数: ").append(systemInfo.get("availableProcessors"));
sb.append("\n系统负载: ").append(systemInfo.get("systemLoadAverage"));
sb.append("\nCPU使用率: ").append(String.format("%.2f%%",
(Double) systemInfo.get("cpuUsage") * 100));
sb.append("\n进程CPU使用率: ").append(String.format("%.2f%%",
(Double) systemInfo.get("processCpuUsage") * 100));
sb.append("\n物理内存: 总=").append(formatBytes((Long) systemInfo.get("totalPhysicalMemory")))
.append(", 可用=").append(formatBytes((Long) systemInfo.get("freePhysicalMemory")));
return sb.toString();
}
// 格式化所有信息
public static String formatAllInfo(Map<String, Object> allInfo) {
StringBuilder sb = new StringBuilder();
long timestamp = (Long) allInfo.get("timestamp");
sb.append("===== JVM监控信息 ").append(SDF.format(new Date(timestamp))).append(" =====\n");
// 内存
@SuppressWarnings("unchecked")
Map<String, Object> memoryInfo = (Map<String, Object>) allInfo.get("memory");
sb.append(formatMemoryInfo(memoryInfo));
// 线程
@SuppressWarnings("unchecked")
Map<String, Object> threadInfo = (Map<String, Object>) allInfo.get("thread");
sb.append(formatThreadInfo(threadInfo));
// GC
@SuppressWarnings("unchecked")
Map<String, Object> gcInfo = (Map<String, Object>) allInfo.get("gc");
sb.append(formatGCInfo(gcInfo));
// 系统
@SuppressWarnings("unchecked")
Map<String, Object> systemInfo = (Map<String, Object>) allInfo.get("system");
sb.append(formatSystemInfo(systemInfo));
// 类加载
@SuppressWarnings("unchecked")
Map<String, Object> classInfo = (Map<String, Object>) allInfo.get("classLoading");
sb.append("\n========== 类加载监控 ==========\n");
sb.append("已加载类: ").append(classInfo.get("loadedClassCount"));
sb.append("\n总加载类: ").append(classInfo.get("totalLoadedClassCount"));
sb.append("\n卸载类数量: ").append(classInfo.get("unloadedClassCount"));
// JVM运行时
@SuppressWarnings("unchecked")
Map<String, Object> runtimeInfo = (Map<String, Object>) allInfo.get("runtime");
sb.append("\n========== JVM运行时 ==========\n");
sb.append("JVM名称: ").append(runtimeInfo.get("vmName"));
sb.append("\nJVM版本: ").append(runtimeInfo.get("vmVersion"));
sb.append("\n运行时间: ").append(formatUptime((Long) runtimeInfo.get("uptime")));
return sb.toString();
}
private static String formatUptime(long uptimeMillis) {
long days = uptimeMillis / (24 * 3600 * 1000);
long hours = (uptimeMillis % (24 * 3600 * 1000)) / (3600 * 1000);
long minutes = (uptimeMillis % (3600 * 1000)) / (60 * 1000);
long seconds = (uptimeMillis % (60 * 1000)) / 1000;
return String.format("%d天 %02d:%02d:%02d", days, hours, minutes, seconds);
}
}
监控服务类
MonitorService.java
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MonitorService implements AutoCloseable {
private final ScheduledExecutorService scheduler;
private final long intervalSeconds;
private PrintWriter logWriter;
private boolean logToFile;
public MonitorService(long intervalSeconds) {
this.intervalSeconds = intervalSeconds;
this.scheduler = Executors.newScheduledThreadPool(1);
}
public MonitorService(long intervalSeconds, String logFilePath) {
this(intervalSeconds);
this.logToFile = true;
try {
this.logWriter = new PrintWriter(new FileWriter(logFilePath, true), true);
} catch (IOException e) {
System.err.println("无法创建日志文件: " + e.getMessage());
this.logToFile = false;
}
}
public void start() {
System.out.println("JVM监控服务启动,每 " + intervalSeconds + " 秒采集一次");
scheduler.scheduleAtFixedRate(() -> {
try {
collectAndDisplay();
} catch (Exception e) {
System.err.println("监控采集失败: " + e.getMessage());
}
}, 0, intervalSeconds, TimeUnit.SECONDS);
}
private void collectAndDisplay() {
Map<String, Object> allInfo = JVMMonitor.getAllMonitorInfo();
String formattedInfo = JVMInfoFormatter.formatAllInfo(allInfo);
// 控制台输出
System.out.println(formattedInfo);
System.out.println("========================================");
// 文件输出
if (logToFile && logWriter != null) {
logWriter.println(formattedInfo);
logWriter.println("========================================");
}
}
@Override
public void close() {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
}
if (logWriter != null) {
logWriter.close();
}
System.out.println("JVM监控服务已停止");
}
}
主程序入口
Main.java
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("=== JVM监控工具 ===");
System.out.println("1. 单次采集监控信息");
System.out.println("2. 定时监控(默认5秒间隔)");
System.out.println("3. 定时监控并保存日志");
System.out.print("请选择 (1/2/3): ");
int choice = scanner.nextInt();
scanner.nextLine();
switch (choice) {
case 1:
// 单次采集
collectOnce();
break;
case 2:
System.out.print("请输入监控间隔(秒): ");
long interval = scanner.nextLong();
scanner.nextLine();
try (MonitorService service = new MonitorService(interval)) {
service.start();
System.out.println("按回车键停止监控...");
scanner.nextLine();
}
break;
case 3:
System.out.print("请输入监控间隔(秒): ");
interval = scanner.nextLong();
scanner.nextLine();
System.out.print("请输入日志文件路径(如: jvm_monitor.log): ");
String logPath = scanner.nextLine();
try (MonitorService service = new MonitorService(interval, logPath)) {
service.start();
System.out.println("按回车键停止监控...");
scanner.nextLine();
}
break;
default:
System.out.println("无效选择");
}
scanner.close();
}
private static void collectOnce() {
System.out.println("正在采集JVM监控信息...\n");
Map<String, Object> allInfo = JVMMonitor.getAllMonitorInfo();
String formattedInfo = JVMInfoFormatter.formatAllInfo(allInfo);
System.out.println(formattedInfo);
// 显示JVM参数
System.out.println("\n========== JVM启动参数 ==========");
@SuppressWarnings("unchecked")
Map<String, Object> runtimeInfo = (Map<String, Object>) allInfo.get("runtime");
@SuppressWarnings("unchecked")
java.util.List<String> jvmArgs = (java.util.List<String>) runtimeInfo.get("jvmArguments");
jvmArgs.forEach(arg -> System.out.println(" " + arg));
}
}
运行测试类
MonitorTest.java
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MonitorTest {
// 模拟内存使用
private static List<byte[]> memoryLeak = new ArrayList<>();
private static Random random = new Random();
// 模拟线程创建
private static List<Thread> threads = new ArrayList<>();
public static void main(String[] args) throws Exception {
System.out.println("启动JVM监控测试...");
// 显示初始监控信息
Map<String, Object> initialInfo = JVMMonitor.getAllMonitorInfo();
System.out.println(JVMInfoFormatter.formatAllInfo(initialInfo));
System.out.println("\n开始模拟负载...");
// 模拟内存分配
Thread memoryThread = new Thread(() -> {
try {
for (int i = 0; i < 100; i++) {
// 分配5MB内存
memoryLeak.add(new byte[5 * 1024 * 1024]);
System.out.println("分配内存: " + ((i + 1) * 5) + "MB");
Thread.sleep(500);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
memoryThread.start();
// 模拟线程创建
Thread threadThread = new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
Thread t = new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
t.start();
threads.add(t);
System.out.println("创建线程: " + t.getName());
Thread.sleep(300);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
threadThread.start();
// 运行10秒后显示监控信息
Thread.sleep(10000);
System.out.println("\n=== 运行10秒后的监控信息 ===");
Map<String, Object> afterInfo = JVMMonitor.getAllMonitorInfo();
System.out.println(JVMInfoFormatter.formatAllInfo(afterInfo));
// 清理
memoryLeak.clear();
for (Thread t : threads) {
t.interrupt();
}
// 触发GC
System.gc();
Thread.sleep(1000);
System.out.println("\n=== GC后的监控信息 ===");
Map<String, Object> gcAfterInfo = JVMMonitor.getAllMonitorInfo();
System.out.println(JVMInfoFormatter.formatAllInfo(gcAfterInfo));
System.out.println("\n测试完成");
}
}
运行说明
编译和运行:
# 编译 javac -d . *.java # 运行主程序 java Main # 运行测试程序 java MonitorTest # 使用JVM参数运行(推荐,便于观察) java -Xms256m -Xmx1024m -XX:+UseG1GC -XX:+PrintGCDetails Main
输出示例:
========== 内存监控 ==========
堆内存:
最大: 1.00 GB
已用: 256.00 MB
已分配: 512.00 MB
使用率: 25.00%
========== 线程监控 ==========
当前线程数: 5
峰值线程数: 12
守护线程数: 3
========== GC监控 ==========
总GC次数: 3
总GC时间: 150 ms
========== 系统信息 ==========
操作系统: Windows 10
CPU核心数: 8
CPU使用率: 15.00%
功能特点
- 全面监控:内存、线程、GC、类加载、系统、编译、运行时信息
- 实时采集:可配置采集频率
- 多种输出:控制台显示、文件日志
- 性能分析:支持死锁检测、内存池分析
- 易于扩展:模块化设计,方便添加新监控项
这个监控工具可以用于:
- JVM性能调优
- 内存泄漏排查
- 线程问题分析
- GC性能优化
- 生产环境监控