引言:为什么需要理解内存管理?
想象一下你在管理一个大型仓库。如果随意堆放货物,很快就会混乱不堪,找不到需要的物品,甚至可能因为堆放不当导致仓库坍塌。Java内存管理就如同这个仓库的管理系统------它决定了如何分配、使用和回收内存空间。掌握JVM内存管理不仅能让你写出更高效的代码,还能在生产环境中快速定位和解决性能问题。
JVM内存结构深度解析
运行时数据区域
java
public class JVMMemoryLayout {
// 类加载过程演示
public static class ClassLoaderDemo {
// 类变量(存储在方法区)
private static final String CLASS_CONSTANT = "常量";
private static int staticCounter = 0;
// 实例变量(存储在堆内存)
private int instanceId;
private String instanceName;
public ClassLoaderDemo(int id, String name) {
this.instanceId = id;
this.instanceName = name;
staticCounter++;
}
// 方法(字节码存储在方法区)
public void printInfo() {
// 局部变量(存储在栈帧的局部变量表)
String localVar = "局部变量";
System.out.println("实例ID: " + instanceId +
", 名称: " + instanceName +
", 局部: " + localVar);
}
public static void showMemoryInfo() {
// 演示不同内存区域的使用
Runtime runtime = Runtime.getRuntime();
System.out.println("=== 内存信息 ===");
System.out.println("最大内存: " + runtime.maxMemory() / 1024 / 1024 + "MB");
System.out.println("总内存: " + runtime.totalMemory() / 1024 / 1024 + "MB");
System.out.println("空闲内存: " + runtime.freeMemory() / 1024 / 1024 + "MB");
System.out.println("已用内存: " +
(runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024 + "MB");
}
}
// 演示栈内存溢出
public static void causeStackOverflow() {
causeStackOverflow(); // 递归调用,没有终止条件
}
// 演示堆内存溢出
public static void causeHeapOOM() {
List<byte[]> list = new ArrayList<>();
while (true) {
// 每次分配1MB,快速耗尽堆内存
list.add(new byte[1024 * 1024]);
}
}
// 演示方法区(元空间)溢出
public static void causeMetaspaceOOM() {
// 使用动态类加载来填满元空间
// 实际项目中,可以通过CGLIB等动态生成类
}
public static void main(String[] args) throws Exception {
// 展示类加载和内存分配
ClassLoaderDemo obj1 = new ClassLoaderDemo(1, "对象1");
ClassLoaderDemo obj2 = new ClassLoaderDemo(2, "对象2");
obj1.printInfo();
obj2.printInfo();
ClassLoaderDemo.showMemoryInfo();
// 查看对象内存布局(需要JOL库)
// System.out.println(ClassLayout.parseInstance(obj1).toPrintable());
// 小心:以下代码会触发内存溢出,仅用于演示
// causeStackOverflow();
// causeHeapOOM();
}
}
JVM内存结构示意图
java
JVM内存区域:
┌─────────────────────────────────────────────────┐
│ 运行时数据区域 │
├─────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────────────┐ │
│ │ 程序计数器 │ │ Java虚拟机栈 │ │
│ │ (PC Register)│ │ (Java Stack) │ │
│ └─────────────┘ └─────────────────────┘ │
│ │ │ │
│ ┌─────────────┐ ┌─────────────────────┐ │
│ │ 本地方法栈 │ │ Java堆 │ │
│ │ (Native Stack)│ │ (Heap) │ │
│ └─────────────┘ └─────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ 方法区/元空间 │ │
│ │ (Method Area/Metaspace) │ │
│ │ ┌─────────────┐ │ │
│ │ │ 运行时常量池 │ │ │
│ │ └─────────────┘ │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ 直接内存 │ │
│ │ (Direct Memory) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
垃圾回收机制:JVM的自动内存管理
垃圾回收算法
java
public class GarbageCollectionDemo {
// 对象生命周期追踪
static class LifecycleObject {
private final int id;
private byte[] data;
public LifecycleObject(int id) {
this.id = id;
this.data = new byte[1024 * 10]; // 分配10KB
System.out.println("对象 " + id + " 被创建");
}
@Override
protected void finalize() throws Throwable {
System.out.println("对象 " + id + " 即将被垃圾回收");
super.finalize();
}
}
// 引用类型演示
static class ReferenceDemo {
// 强引用 - 最常见的引用类型
public void strongReferenceDemo() {
LifecycleObject obj = new LifecycleObject(1);
obj = null; // 取消强引用,对象可被GC
System.gc(); // 建议JVM进行垃圾回收
}
// 软引用 - 内存不足时才回收
public void softReferenceDemo() {
SoftReference<LifecycleObject> softRef =
new SoftReference<>(new LifecycleObject(2));
System.out.println("软引用对象: " + softRef.get());
// 模拟内存不足
try {
List<byte[]> memoryHog = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
memoryHog.add(new byte[1024 * 1024]); // 每次1MB
}
} catch (OutOfMemoryError e) {
System.out.println("内存不足,软引用对象: " + softRef.get());
}
}
// 弱引用 - GC时立即回收
public void weakReferenceDemo() {
WeakReference<LifecycleObject> weakRef =
new WeakReference<>(new LifecycleObject(3));
System.out.println("弱引用对象: " + weakRef.get());
System.gc();
System.out.println("GC后弱引用对象: " + weakRef.get());
}
// 虚引用 - 用于跟踪对象被回收
public void phantomReferenceDemo() {
ReferenceQueue<LifecycleObject> queue = new ReferenceQueue<>();
PhantomReference<LifecycleObject> phantomRef =
new PhantomReference<>(new LifecycleObject(4), queue);
System.out.println("虚引用对象始终为null: " + phantomRef.get());
System.gc();
// 检查队列中是否有引用
Reference<? extends LifecycleObject> ref = queue.poll();
if (ref != null) {
System.out.println("对象已被回收,进入引用队列");
}
}
// 引用队列示例
public void referenceQueueDemo() {
ReferenceQueue<LifecycleObject> refQueue = new ReferenceQueue<>();
List<WeakReference<LifecycleObject>> refList = new ArrayList<>();
// 创建10个弱引用对象
for (int i = 0; i < 10; i++) {
WeakReference<LifecycleObject> ref =
new WeakReference<>(new LifecycleObject(100 + i), refQueue);
refList.add(ref);
}
// 触发GC
System.gc();
// 处理引用队列
int collectedCount = 0;
while (true) {
Reference<? extends LifecycleObject> ref = refQueue.poll();
if (ref == null) break;
collectedCount++;
System.out.println("回收了第 " + collectedCount + " 个对象");
}
System.out.println("总共回收了 " + collectedCount + " 个对象");
}
}
// 内存泄漏示例
static class MemoryLeakDemo {
private static final List<byte[]> LEAK_LIST = new ArrayList<>();
private static final Map<String, byte[]> LEAK_MAP = new HashMap<>();
// 静态集合引起的内存泄漏
public static void causeStaticLeak() {
for (int i = 0; i < 1000; i++) {
LEAK_LIST.add(new byte[1024 * 100]); // 100KB
LEAK_MAP.put("key" + i, new byte[1024 * 100]);
}
System.out.println("已添加对象到静态集合,即使方法结束也不会释放");
}
// 监听器未移除引起的内存泄漏
public static class LeakyListener {
private byte[] data = new byte[1024 * 1024]; // 1MB
public void onEvent(String event) {
System.out.println("处理事件: " + event);
}
}
// 内部类持有外部类引用引起的内存泄漏
public class OuterClass {
private byte[] outerData = new byte[1024 * 1024]; // 1MB
public Runnable createTask() {
return new Runnable() {
@Override
public void run() {
// 匿名内部类隐式持有OuterClass.this引用
System.out.println("访问外部类数据大小: " + outerData.length);
}
};
}
}
}
public static void main(String[] args) throws Exception {
System.out.println("=== 引用类型演示 ===");
ReferenceDemo refDemo = new ReferenceDemo();
refDemo.strongReferenceDemo();
Thread.sleep(100);
refDemo.softReferenceDemo();
Thread.sleep(100);
refDemo.weakReferenceDemo();
Thread.sleep(100);
refDemo.phantomReferenceDemo();
Thread.sleep(100);
refDemo.referenceQueueDemo();
System.out.println("\n=== 内存泄漏演示 ===");
MemoryLeakDemo.causeStaticLeak();
// 注意:以下代码仅用于演示,实际中应避免内存泄漏
Runtime.getRuntime().gc();
Thread.sleep(1000);
System.out.println("演示完成,建议重启JVM以释放泄漏的内存");
}
}
GC算法详解与比较
java
public class GCAlgorithms {
/**
* 垃圾回收算法比较:
*
* 1. 标记-清除 (Mark-Sweep)
* - 优点:简单,不会移动对象
* - 缺点:产生内存碎片,效率较低
*
* 2. 标记-整理 (Mark-Compact)
* - 优点:没有内存碎片
* - 缺点:需要移动对象,开销较大
*
* 3. 复制算法 (Copying)
* - 优点:没有碎片,实现简单
* - 缺点:内存利用率只有50%
*
* 4. 分代收集 (Generational Collection)
* - 现代JVM主要采用此策略
* - 新生代 (Young Generation):使用复制算法
* - 老年代 (Old Generation):使用标记-清除或标记-整理
*/
// 模拟分代收集策略
static class GenerationalGCSimulation {
// 模拟新生代(Eden + Survivor)
private static final List<Object> youngGen = new ArrayList<>();
// 模拟老年代
private static final List<Object> oldGen = new ArrayList<>();
private static int objectId = 0;
private static int youngGCCount = 0;
private static int fullGCCount = 0;
// 创建新对象(首先分配在新生代)
public static Object allocate() {
Object obj = new Object() {
private final int id = ++objectId;
private final byte[] data = new byte[1024]; // 1KB
private int age = 0; // 对象年龄
@Override
public String toString() {
return "对象#" + id + "(age:" + age + ")";
}
public void incrementAge() {
age++;
}
public int getAge() {
return age;
}
};
youngGen.add(obj);
System.out.println("分配新对象: " + obj + " 到新生代");
return obj;
}
// 模拟新生代GC(Minor GC)
public static void minorGC() {
youngGCCount++;
System.out.println("\n=== 开始第 " + youngGCCount + " 次新生代GC ===");
// 标记阶段(简化版)
List<Object> survivors = new ArrayList<>();
List<Object> promoted = new ArrayList<>();
for (Object obj : youngGen) {
// 模拟可达性分析(这里简化:随机决定对象是否存活)
boolean isAlive = Math.random() > 0.5; // 50%存活率
if (isAlive) {
// 对象年龄增加
try {
java.lang.reflect.Method incrementAge =
obj.getClass().getDeclaredMethod("incrementAge");
incrementAge.invoke(obj);
java.lang.reflect.Method getAge =
obj.getClass().getDeclaredMethod("getAge");
int age = (int) getAge.invoke(obj);
if (age >= 15) { // 年龄阈值,晋升到老年代
promoted.add(obj);
System.out.println("对象 " + obj + " 晋升到老年代");
} else {
survivors.add(obj);
System.out.println("对象 " + obj + " 存活,进入Survivor区");
}
} catch (Exception e) {
survivors.add(obj);
}
} else {
System.out.println("对象 " + obj + " 被回收");
}
}
// 复制存活对象(模拟复制算法)
youngGen.clear();
youngGen.addAll(survivors);
// 晋升到老年代
oldGen.addAll(promoted);
System.out.println("新生代GC完成,存活对象: " + survivors.size() +
", 晋升对象: " + promoted.size());
}
// 模拟Full GC
public static void fullGC() {
fullGCCount++;
System.out.println("\n=== 开始第 " + fullGCCount + " 次Full GC ===");
// 标记阶段(同时处理新生代和老年代)
List<Object> allObjects = new ArrayList<>();
allObjects.addAll(youngGen);
allObjects.addAll(oldGen);
List<Object> survivors = new ArrayList<>();
for (Object obj : allObjects) {
boolean isAlive = Math.random() > 0.3; // 70%存活率
if (isAlive) {
survivors.add(obj);
} else {
System.out.println("对象 " + obj + " 在Full GC中被回收");
}
}
// 整理阶段(简化版)
youngGen.clear();
oldGen.clear();
// 重新分配(实际JVM会移动对象进行内存整理)
for (Object obj : survivors) {
// 简化处理:都放到老年代
oldGen.add(obj);
}
System.out.println("Full GC完成,总存活对象: " + survivors.size());
}
public static void printStats() {
System.out.println("\n=== 内存统计 ===");
System.out.println("新生代对象数: " + youngGen.size());
System.out.println("老年代对象数: " + oldGen.size());
System.out.println("新生代GC次数: " + youngGCCount);
System.out.println("Full GC次数: " + fullGCCount);
}
}
// 现代GC收集器对比
static class GCCollectorsComparison {
/**
* 常用GC收集器:
*
* 1. Serial收集器
* - 单线程,适用于客户端应用
* - 参数:-XX:+UseSerialGC
*
* 2. Parallel收集器 (吞吐量优先)
* - 多线程,适用于后台计算
* - 参数:-XX:+UseParallelGC -XX:ParallelGCThreads=N
*
* 3. CMS收集器 (低延迟优先)
* - 并发标记清除,减少停顿时间
* - 参数:-XX:+UseConcMarkSweepGC
* - 已废弃,不建议使用
*
* 4. G1收集器 (平衡型)
* - 分区收集,可预测停顿时间
* - 参数:-XX:+UseG1GC
*
* 5. ZGC收集器 (超低延迟)
* - 并发,停顿时间不超过10ms
* - 参数:-XX:+UseZGC
*
* 6. Shenandoah收集器 (低延迟)
* - 并发,与ZGC类似
* - 参数:-XX:+UseShenandoahGC
*/
public static void printGCInfo() {
// 获取当前GC信息
List<GarbageCollectorMXBean> gcBeans =
ManagementFactory.getGarbageCollectorMXBeans();
System.out.println("=== GC收集器信息 ===");
for (GarbageCollectorMXBean gcBean : gcBeans) {
System.out.println("收集器名称: " + gcBean.getName());
System.out.println(" 收集次数: " + gcBean.getCollectionCount());
System.out.println(" 收集时间: " + gcBean.getCollectionTime() + "ms");
System.out.println(" 内存池名称: " +
Arrays.toString(gcBean.getMemoryPoolNames()));
System.out.println();
}
}
public static void suggestGCParameters() {
System.out.println("=== GC参数建议 ===");
String appType = System.getProperty("app.type", "web");
switch (appType) {
case "web":
System.out.println("Web应用推荐使用G1GC:");
System.out.println(" -XX:+UseG1GC");
System.out.println(" -XX:MaxGCPauseMillis=200");
System.out.println(" -XX:G1HeapRegionSize=4M");
break;
case "batch":
System.out.println("批处理应用推荐使用ParallelGC:");
System.out.println(" -XX:+UseParallelGC");
System.out.println(" -XX:ParallelGCThreads=CPU核心数");
System.out.println(" -XX:+UseAdaptiveSizePolicy");
break;
case "low-latency":
System.out.println("低延迟应用推荐使用ZGC:");
System.out.println(" -XX:+UseZGC");
System.out.println(" -Xmx<size> -Xms<size> (设置堆大小)");
System.out.println(" -XX:ConcGCThreads=<threads>");
break;
default:
System.out.println("通用建议:");
System.out.println(" -XX:+UseG1GC (JDK 9+默认)");
System.out.println(" -Xmx和-Xms设置为相同值避免堆震荡");
}
}
}
public static void main(String[] args) throws Exception {
System.out.println("=== 分代收集模拟 ===");
// 模拟对象分配和GC
for (int i = 0; i < 20; i++) {
GenerationalGCSimulation.allocate();
if (i % 5 == 0) {
GenerationalGCSimulation.minorGC();
}
if (i % 10 == 0) {
GenerationalGCSimulation.fullGC();
}
Thread.sleep(100);
}
GenerationalGCSimulation.printStats();
System.out.println("\n=== 实际GC信息 ===");
GCCollectorsComparison.printGCInfo();
GCCollectorsComparison.suggestGCParameters();
}
}
JVM监控与故障诊断
1. 命令行监控工具
java
public class JVMMonitoringTools {
// 获取JVM运行时信息
public static void printRuntimeInfo() {
Runtime runtime = Runtime.getRuntime();
System.out.println("=== JVM运行时信息 ===");
System.out.println("可用处理器: " + runtime.availableProcessors());
System.out.println("最大内存: " + formatBytes(runtime.maxMemory()));
System.out.println("总内存: " + formatBytes(runtime.totalMemory()));
System.out.println("空闲内存: " + formatBytes(runtime.freeMemory()));
System.out.println("已用内存: " +
formatBytes(runtime.totalMemory() - runtime.freeMemory()));
}
// 获取内存管理器信息
public static void printMemoryManagerInfo() {
List<MemoryManagerMXBean> memoryManagers =
ManagementFactory.getMemoryManagerMXBeans();
System.out.println("\n=== 内存管理器 ===");
for (MemoryManagerMXBean manager : memoryManagers) {
System.out.println("管理器: " + manager.getName());
System.out.println(" 内存池: " +
Arrays.toString(manager.getMemoryPoolNames()));
}
}
// 获取内存池信息
public static void printMemoryPoolInfo() {
List<MemoryPoolMXBean> memoryPools =
ManagementFactory.getMemoryPoolMXBeans();
System.out.println("\n=== 内存池信息 ===");
for (MemoryPoolMXBean pool : memoryPools) {
MemoryUsage usage = pool.getUsage();
MemoryUsage peakUsage = pool.getPeakUsage();
System.out.println("内存池: " + pool.getName());
System.out.println(" 类型: " + pool.getType());
System.out.println(" 使用量: " + formatBytes(usage.getUsed()) +
" / " + formatBytes(usage.getMax()));
System.out.println(" 提交量: " + formatBytes(usage.getCommitted()));
System.out.println(" 峰值: " + formatBytes(peakUsage.getUsed()));
System.out.println(" 使用率: " +
String.format("%.2f%%", (usage.getUsed() * 100.0 / usage.getMax())));
}
}
// 获取线程信息
public static void printThreadInfo() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
System.out.println("\n=== 线程信息 ===");
System.out.println("活动线程数: " + threadBean.getThreadCount());
System.out.println("峰值线程数: " + threadBean.getPeakThreadCount());
System.out.println("守护线程数: " + threadBean.getDaemonThreadCount());
System.out.println("总启动线程数: " + threadBean.getTotalStartedThreadCount());
// 检测死锁
long[] deadlockedThreads = threadBean.findDeadlockedThreads();
if (deadlockedThreads != null && deadlockedThreads.length > 0) {
System.out.println("检测到死锁线程:");
for (long threadId : deadlockedThreads) {
System.out.println(" 线程ID: " + threadId);
}
}
}
// 获取类加载信息
public static void printClassLoadingInfo() {
ClassLoadingMXBean classBean = ManagementFactory.getClassLoadingMXBean();
System.out.println("\n=== 类加载信息 ===");
System.out.println("已加载类总数: " + classBean.getTotalLoadedClassCount());
System.out.println("当前加载类数: " + classBean.getLoadedClassCount());
System.out.println("已卸载类数: " + classBean.getUnloadedClassCount());
}
// 获取操作系统信息
public static void printOSInfo() {
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
System.out.println("\n=== 操作系统信息 ===");
System.out.println("操作系统: " + osBean.getName() +
" " + osBean.getVersion());
System.out.println("系统架构: " + osBean.getArch());
System.out.println("可用处理器: " + osBean.getAvailableProcessors());
if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
com.sun.management.OperatingSystemMXBean sunOsBean =
(com.sun.management.OperatingSystemMXBean) osBean;
System.out.println("系统负载: " + sunOsBean.getSystemLoadAverage());
System.out.println("进程CPU时间: " +
sunOsBean.getProcessCpuTime() / 1_000_000 + "ms");
System.out.println("进程CPU使用率: " +
String.format("%.2f%%", sunOsBean.getProcessCpuLoad() * 100));
System.out.println("系统CPU使用率: " +
String.format("%.2f%%", sunOsBean.getSystemCpuLoad() * 100));
}
}
// 堆内存转储分析
public static class HeapDumpAnalyzer {
public static void triggerHeapDump(String fileName) {
try {
// 触发堆转储
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
String command = "jcmd " + pid + " GC.heap_dump " + fileName;
System.out.println("执行命令: " + command);
// 实际环境中可以使用以下方法之一:
// 1. 使用jcmd命令
// 2. 使用JMX: HotSpotDiagnosticMXBean.dumpHeap()
// 3. 在启动时添加参数: -XX:+HeapDumpOnOutOfMemoryError
System.out.println("堆转储文件: " + fileName);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void analyzeMemoryLeak() {
System.out.println("\n=== 内存泄漏分析步骤 ===");
System.out.println("1. 使用 jps 命令查找Java进程ID");
System.out.println("2. 使用 jmap 生成堆转储:");
System.out.println(" jmap -dump:live,format=b,file=heap.bin <pid>");
System.out.println("3. 使用分析工具打开堆转储文件:");
System.out.println(" - Eclipse MAT (Memory Analyzer Tool)");
System.out.println(" - VisualVM");
System.out.println(" - YourKit");
System.out.println("4. 查找:");
System.out.println(" - 最大的对象");
System.out.println(" - 重复的字符串");
System.out.println(" - 未关闭的资源");
}
}
// JVM参数优化建议
public static class JVMOptimizer {
public static void analyzeAndSuggest() {
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
List<String> inputArgs = runtimeBean.getInputArguments();
System.out.println("\n=== 当前JVM参数 ===");
for (String arg : inputArgs) {
System.out.println(" " + arg);
}
System.out.println("\n=== 优化建议 ===");
// 检查堆大小设置
boolean hasXmx = inputArgs.stream().anyMatch(arg -> arg.startsWith("-Xmx"));
boolean hasXms = inputArgs.stream().anyMatch(arg -> arg.startsWith("-Xms"));
if (!hasXmx) {
System.out.println("建议设置最大堆大小: -Xmx4g (根据实际内存调整)");
}
if (!hasXms) {
System.out.println("建议设置初始堆大小: -Xms2g (与-Xmx相同以避免堆震荡)");
}
// 检查GC设置
boolean hasGCParam = inputArgs.stream()
.anyMatch(arg -> arg.startsWith("-XX:+Use") && arg.contains("GC"));
if (!hasGCParam) {
System.out.println("建议明确指定GC收集器:");
System.out.println(" G1GC: -XX:+UseG1GC -XX:MaxGCPauseMillis=200");
System.out.println(" ZGC: -XX:+UseZGC (适用于低延迟应用)");
}
// 检查元空间设置
boolean hasMetaspaceParam = inputArgs.stream()
.anyMatch(arg -> arg.contains("MetaspaceSize") || arg.contains("MaxMetaspaceSize"));
if (!hasMetaspaceParam) {
System.out.println("建议设置元空间大小:");
System.out.println(" -XX:MetaspaceSize=256m");
System.out.println(" -XX:MaxMetaspaceSize=512m");
}
}
}
// 格式化字节大小为易读格式
private static String formatBytes(long bytes) {
if (bytes < 1024) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(1024));
char unit = "KMGTPE".charAt(exp - 1);
return String.format("%.2f %sB", bytes / Math.pow(1024, exp), unit);
}
public static void main(String[] args) {
printRuntimeInfo();
printMemoryManagerInfo();
printMemoryPoolInfo();
printThreadInfo();
printClassLoadingInfo();
printOSInfo();
HeapDumpAnalyzer.analyzeMemoryLeak();
JVMOptimizer.analyzeAndSuggest();
}
}
2. 可视化监控工具集成
java
public class VisualMonitoringTools {
// 简易的内存监控仪表盘
static class MemoryMonitorDashboard {
private static final int HISTORY_SIZE = 100;
private final List<Long> heapHistory = new ArrayList<>();
private final List<Long> nonHeapHistory = new ArrayList<>();
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public void startMonitoring(int intervalSeconds) {
System.out.println("启动内存监控,间隔: " + intervalSeconds + "秒");
scheduler.scheduleAtFixedRate(() -> {
try {
updateMetrics();
printDashboard();
} catch (Exception e) {
e.printStackTrace();
}
}, 0, intervalSeconds, TimeUnit.SECONDS);
}
private void updateMetrics() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
// 堆内存使用情况
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
heapHistory.add(heapUsage.getUsed());
if (heapHistory.size() > HISTORY_SIZE) {
heapHistory.remove(0);
}
// 非堆内存使用情况
MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
nonHeapHistory.add(nonHeapUsage.getUsed());
if (nonHeapHistory.size() > HISTORY_SIZE) {
nonHeapHistory.remove(0);
}
}
private void printDashboard() {
System.out.println("\n" + "=".repeat(60));
System.out.println("内存监控仪表盘 - " + new Date());
System.out.println("=".repeat(60));
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
// 堆内存图表
printMemoryChart("堆内存", heapUsage, heapHistory);
// 非堆内存图表
printMemoryChart("非堆内存", nonHeapUsage, nonHeapHistory);
// GC信息
printGCInfo();
}
private void printMemoryChart(String title, MemoryUsage usage,
List<Long> history) {
long used = usage.getUsed();
long committed = usage.getCommitted();
long max = usage.getMax();
System.out.println("\n" + title + ":");
System.out.println(" 使用: " + formatBytes(used));
System.out.println(" 提交: " + formatBytes(committed));
System.out.println(" 最大: " + (max == -1 ? "无限制" : formatBytes(max)));
double usagePercent = (double) used / committed * 100;
System.out.printf(" 使用率: %.2f%%\n", usagePercent);
// 简单图表
if (!history.isEmpty()) {
System.out.print(" 趋势图: ");
long avg = history.stream().mapToLong(Long::longValue).sum() / history.size();
long min = history.stream().mapToLong(Long::longValue).min().orElse(0);
long maxVal = history.stream().mapToLong(Long::longValue).max().orElse(0);
System.out.printf("[最小: %s, 平均: %s, 最大: %s]\n",
formatBytes(min), formatBytes(avg), formatBytes(maxVal));
}
}
private void printGCInfo() {
List<GarbageCollectorMXBean> gcBeans =
ManagementFactory.getGarbageCollectorMXBeans();
System.out.println("\n垃圾回收:");
for (GarbageCollectorMXBean gcBean : gcBeans) {
System.out.printf(" %s: 次数=%d, 时间=%,dms\n",
gcBean.getName(),
gcBean.getCollectionCount(),
gcBean.getCollectionTime());
}
}
private String formatBytes(long bytes) {
if (bytes < 1024) return bytes + "B";
if (bytes < 1024 * 1024) return String.format("%.1fKB", bytes / 1024.0);
if (bytes < 1024 * 1024 * 1024) return String.format("%.1fMB", bytes / (1024.0 * 1024));
return String.format("%.1fGB", bytes / (1024.0 * 1024 * 1024));
}
public void stop() {
scheduler.shutdown();
System.out.println("监控已停止");
}
}
// 性能瓶颈检测
static class PerformanceProfiler {
private final Map<String, MethodStats> methodStats = new ConcurrentHashMap<>();
static class MethodStats {
String methodName;
long invocationCount;
long totalTime;
long maxTime;
long minTime = Long.MAX_VALUE;
synchronized void recordInvocation(long duration) {
invocationCount++;
totalTime += duration;
maxTime = Math.max(maxTime, duration);
minTime = Math.min(minTime, duration);
}
double getAverageTime() {
return invocationCount == 0 ? 0 : (double) totalTime / invocationCount;
}
}
// AOP风格的方法拦截(简化版)
public <T> T profile(Supplier<T> task, String methodName) {
long startTime = System.nanoTime();
try {
return task.get();
} finally {
long duration = System.nanoTime() - startTime;
methodStats.computeIfAbsent(methodName, k -> new MethodStats())
.recordInvocation(duration);
}
}
public void printProfilingReport() {
System.out.println("\n" + "=".repeat(60));
System.out.println("方法性能分析报告");
System.out.println("=".repeat(60));
methodStats.entrySet().stream()
.sorted((a, b) -> Long.compare(b.getValue().totalTime, a.getValue().totalTime))
.limit(10) // 只显示最耗时的10个方法
.forEach(entry -> {
MethodStats stats = entry.getValue();
System.out.printf("\n方法: %s\n", entry.getKey());
System.out.printf(" 调用次数: %,d\n", stats.invocationCount);
System.out.printf(" 总耗时: %,.2fms\n", stats.totalTime / 1_000_000.0);
System.out.printf(" 平均耗时: %,.2fms\n", stats.getAverageTime() / 1_000_000.0);
System.out.printf(" 最长时间: %,.2fms\n", stats.maxTime / 1_000_000.0);
System.out.printf(" 最短时间: %,.2fms\n", stats.minTime / 1_000_000.0);
});
}
}
public static void main(String[] args) throws Exception {
System.out.println("=== 可视化监控工具演示 ===");
// 启动内存监控
MemoryMonitorDashboard dashboard = new MemoryMonitorDashboard();
dashboard.startMonitoring(2); // 每2秒更新一次
// 创建性能分析器
PerformanceProfiler profiler = new PerformanceProfiler();
// 模拟一些方法调用
for (int i = 0; i < 10; i++) {
profiler.profile(() -> {
try {
// 模拟耗时操作
Thread.sleep(100 + (long)(Math.random() * 100));
return "操作完成";
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "simulatedOperation");
// 模拟另一个方法
profiler.profile(() -> {
// 模拟计算密集型操作
long sum = 0;
for (int j = 0; j < 1000000; j++) {
sum += j;
}
return sum;
}, "calculateSum");
Thread.sleep(500);
}
// 打印性能报告
profiler.printProfilingReport();
// 运行一段时间后停止监控
Thread.sleep(10000);
dashboard.stop();
System.out.println("\n监控演示完成");
}
}
实战:JVM调优案例
案例1:电商系统调优
java
public class ECommerceJVMOptimization {
/**
* 电商系统特点:
* 1. 高并发:大量用户同时访问
* 2. 大内存:商品信息、用户会话缓存
* 3. 低延迟:页面加载要快
* 4. 频繁GC:大量短期对象(请求、响应对象)
*/
static class ProductService {
// 商品缓存(大对象)
private final Map<Integer, byte[]> productCache = new ConcurrentHashMap<>();
public ProductService() {
// 初始化缓存(模拟10000个商品,每个商品信息100KB)
for (int i = 0; i < 10000; i++) {
productCache.put(i, new byte[1024 * 100]); // 100KB
}
}
public byte[] getProduct(int id) {
return profile(() -> {
// 模拟业务逻辑
byte[] product = productCache.get(id);
if (product == null) {
// 模拟数据库查询
product = new byte[1024 * 50]; // 50KB
productCache.put(id, product);
}
// 创建响应对象(短期对象)
byte[] response = new byte[product.length + 1024];
System.arraycopy(product, 0, response, 0, product.length);
return response;
}, "getProduct");
}
// 模拟用户请求
public void simulateUserRequests(int requestCount) {
ExecutorService executor = Executors.newFixedThreadPool(50);
for (int i = 0; i < requestCount; i++) {
final int productId = i % 10000;
executor.submit(() -> {
getProduct(productId);
});
}
executor.shutdown();
try {
executor.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private <T> T profile(Supplier<T> task, String methodName) {
long start = System.nanoTime();
try {
return task.get();
} finally {
long duration = System.nanoTime() - start;
// 这里可以记录性能指标
}
}
}
static class OptimizationStrategy {
public static void printOptimizationPlan() {
System.out.println("=== 电商系统JVM调优方案 ===");
System.out.println("\n1. 堆内存设置:");
System.out.println(" -Xms4g -Xmx4g # 固定堆大小,避免堆震荡");
System.out.println(" -XX:NewRatio=2 # 新生代:老年代 = 1:2");
System.out.println(" -XX:SurvivorRatio=8 # Eden:Survivor = 8:1:1");
System.out.println("\n2. GC策略:");
System.out.println(" -XX:+UseG1GC # 使用G1收集器");
System.out.println(" -XX:MaxGCPauseMillis=200 # 目标停顿时间200ms");
System.out.println(" -XX:G1HeapRegionSize=4m # 区域大小4MB");
System.out.println(" -XX:InitiatingHeapOccupancyPercent=45 # IHOP阈值");
System.out.println("\n3. 元空间设置:");
System.out.println(" -XX:MetaspaceSize=256m");
System.out.println(" -XX:MaxMetaspaceSize=512m");
System.out.println("\n4. 代码优化建议:");
System.out.println(" a. 使用对象池复用大对象");
System.out.println(" b. 避免在热点路径中创建大数组");
System.out.println(" c. 使用软引用/弱引用缓存");
System.out.println(" d. 及时清理会话数据");
}
public static void implementObjectPool() {
System.out.println("\n=== 对象池实现示例 ===");
// 简单对象池实现
class ByteArrayPool {
private final Queue<byte[]> pool = new ConcurrentLinkedQueue<>();
private final int arraySize;
public ByteArrayPool(int arraySize, int initialSize) {
this.arraySize = arraySize;
for (int i = 0; i < initialSize; i++) {
pool.offer(new byte[arraySize]);
}
}
public byte[] borrow() {
byte[] array = pool.poll();
if (array == null) {
array = new byte[arraySize];
}
return array;
}
public void returnObject(byte[] array) {
if (array != null && array.length == arraySize) {
// 清空数组内容
Arrays.fill(array, (byte) 0);
pool.offer(array);
}
}
}
// 使用对象池
ByteArrayPool pool = new ByteArrayPool(1024 * 100, 100); // 100KB * 100
// 借用对象
byte[] buffer = pool.borrow();
// 使用对象...
// 归还对象
pool.returnObject(buffer);
System.out.println("对象池实现完成,减少对象创建开销");
}
}
// 压力测试工具
static class StressTester {
private final ProductService productService;
public StressTester(ProductService productService) {
this.productService = productService;
}
public void runTest(int durationSeconds, int threads) {
System.out.println("开始压力测试:");
System.out.println(" 持续时间: " + durationSeconds + "秒");
System.out.println(" 并发线程: " + threads);
ExecutorService executor = Executors.newFixedThreadPool(threads);
AtomicLong requestCount = new AtomicLong();
AtomicBoolean running = new AtomicBoolean(true);
// 监控线程
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
System.out.println("当前QPS: " + requestCount.getAndSet(0) + " 请求/秒");
}, 1, 1, TimeUnit.SECONDS);
// 工作线程
for (int i = 0; i < threads; i++) {
executor.submit(() -> {
Random random = new Random();
while (running.get()) {
try {
productService.getProduct(random.nextInt(10000));
requestCount.incrementAndGet();
Thread.sleep(random.nextInt(10)); // 模拟思考时间
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
// 运行指定时间
try {
Thread.sleep(durationSeconds * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
running.set(false);
// 清理
executor.shutdown();
monitor.shutdown();
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
monitor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("压力测试完成");
}
}
public static void main(String[] args) throws Exception {
System.out.println("=== 电商系统JVM调优实战 ===");
// 显示调优方案
OptimizationStrategy.printOptimizationPlan();
OptimizationStrategy.implementObjectPool();
// 创建服务
ProductService productService = new ProductService();
// 运行压力测试
StressTester tester = new StressTester(productService);
tester.runTest(30, 100); // 30秒,100并发
// 显示GC统计
List<GarbageCollectorMXBean> gcBeans =
ManagementFactory.getGarbageCollectorMXBeans();
System.out.println("\n=== GC统计 ===");
for (GarbageCollectorMXBean gcBean : gcBeans) {
System.out.printf("%s: %d次, %dms\n",
gcBean.getName(),
gcBean.getCollectionCount(),
gcBean.getCollectionTime());
}
// 内存使用统计
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
System.out.printf("\n堆内存使用: %.2fMB / %.2fMB (%.1f%%)\n",
heapUsage.getUsed() / 1024.0 / 1024,
heapUsage.getCommitted() / 1024.0 / 1024,
(heapUsage.getUsed() * 100.0 / heapUsage.getCommitted()));
}
}
案例2:大数据处理系统调优
java
public class BigDataJVMOptimization {
/**
* 大数据处理系统特点:
* 1. 大内存需求:处理大量数据
* 2. 计算密集型:CPU使用率高
* 3. 大量临时对象:中间计算结果
* 4. 需要高吞吐量
*/
static class DataProcessor {
// 处理大数据集
public List<Map<String, Object>> processLargeDataset(List<byte[]> dataset) {
return profile(() -> {
List<Map<String, Object>> results = new ArrayList<>();
for (byte[] data : dataset) {
// 解析数据(创建临时对象)
Map<String, Object> record = parseRecord(data);
// 转换数据(更多临时对象)
Map<String, Object> transformed = transformRecord(record);
// 聚合计算
Map<String, Object> aggregated = aggregateRecord(transformed);
results.add(aggregated);
}
return results;
}, "processLargeDataset");
}
private Map<String, Object> parseRecord(byte[] data) {
// 模拟解析,创建临时对象
Map<String, Object> record = new HashMap<>();
record.put("raw", data);
record.put("timestamp", System.currentTimeMillis());
// 模拟字符串处理(容易产生大量临时对象)
String text = new String(data, 0, Math.min(100, data.length));
record.put("text", text.toUpperCase().trim());
return record;
}
private Map<String, Object> transformRecord(Map<String, Object> record) {
Map<String, Object> transformed = new HashMap<>(record);
// 模拟数据转换
transformed.put("processed", true);
transformed.put("version", 2);
// 模拟计算
double value = Math.random() * 1000;
transformed.put("calculated", value);
return transformed;
}
private Map<String, Object> aggregateRecord(Map<String, Object> record) {
// 模拟聚合,重用部分对象
Map<String, Object> aggregated = new HashMap<>();
// 选择性复制,避免复制整个map
aggregated.put("key", record.get("timestamp"));
aggregated.put("value", record.get("calculated"));
return aggregated;
}
// 优化版本:减少对象创建
public List<Map<String, Object>> processLargeDatasetOptimized(List<byte[]> dataset) {
return profile(() -> {
List<Map<String, Object>> results = new ArrayList<>(dataset.size());
// 重用对象
Map<String, Object> reusableMap = new HashMap<>(4);
for (byte[] data : dataset) {
// 清空重用map
reusableMap.clear();
// 直接填充,避免创建中间对象
reusableMap.put("raw", data);
reusableMap.put("timestamp", System.currentTimeMillis());
// 重用StringBuilder避免创建多个String对象
StringBuilder textBuilder = new StringBuilder(100);
for (int i = 0; i < Math.min(100, data.length); i++) {
textBuilder.append((char) (data[i] & 0xFF));
}
reusableMap.put("text", textBuilder.toString().toUpperCase().trim());
textBuilder.setLength(0); // 重置StringBuilder
reusableMap.put("processed", true);
reusableMap.put("version", 2);
reusableMap.put("calculated", Math.random() * 1000);
// 创建新map保存结果(需要不同的实例)
results.add(new HashMap<>(reusableMap));
}
return results;
}, "processLargeDatasetOptimized");
}
private <T> T profile(Supplier<T> task, String methodName) {
long start = System.nanoTime();
long startMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
try {
return task.get();
} finally {
long duration = System.nanoTime() - start;
long endMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
long memUsed = endMem - startMem;
System.out.printf("%s: 耗时=%,.2fms, 内存使用=%,.2fMB\n",
methodName,
duration / 1_000_000.0,
memUsed / 1024.0 / 1024);
}
}
}
static class BigDataOptimizationStrategy {
public static void printOptimizationPlan() {
System.out.println("=== 大数据处理系统JVM调优方案 ===");
System.out.println("\n1. 内存设置(大内存配置):");
System.out.println(" -Xms16g -Xmx16g # 大堆内存");
System.out.println(" -XX:NewSize=8g -XX:MaxNewSize=8g # 大新生代");
System.out.println(" -XX:SurvivorRatio=6 # 更大的Eden区");
System.out.println("\n2. GC策略(吞吐量优先):");
System.out.println(" -XX:+UseParallelGC # 并行收集器");
System.out.println(" -XX:ParallelGCThreads=8 # GC线程数");
System.out.println(" -XX:+UseAdaptiveSizePolicy # 自适应大小策略");
System.out.println(" -XX:GCTimeRatio=19 # GC时间比率 (1/(1+19)=5%)");
System.out.println("\n3. 字符串优化:");
System.out.println(" -XX:+UseStringDeduplication # 字符串去重");
System.out.println(" -XX:+OptimizeStringConcat # 字符串连接优化");
System.out.println("\n4. 编译优化:");
System.out.println(" -XX:+UseLargePages # 大内存页");
System.out.println(" -XX:+AggressiveOpts # 激进优化");
System.out.println(" -XX:+UseCompressedOops # 压缩指针");
System.out.println("\n5. 代码级优化:");
System.out.println(" a. 使用原始类型集合(fastutil, koloboke)");
System.out.println(" b. 对象池技术");
System.out.println(" c. 堆外内存处理大数组");
System.out.println(" d. 流式处理减少内存占用");
}
// 使用堆外内存处理大数组
public static void demonstrateOffHeapMemory() {
System.out.println("\n=== 堆外内存示例 ===");
int bufferSize = 1024 * 1024 * 100; // 100MB
ByteBuffer offHeapBuffer = ByteBuffer.allocateDirect(bufferSize);
System.out.println("分配了 " + (bufferSize / 1024 / 1024) + "MB 堆外内存");
// 写入数据
for (int i = 0; i < 1000; i++) {
offHeapBuffer.putInt(i);
}
// 读取数据
offHeapBuffer.flip();
while (offHeapBuffer.hasRemaining()) {
int value = offHeapBuffer.getInt();
// 处理数据...
}
System.out.println("堆外内存使用完成,不占用堆空间");
// 注意:堆外内存需要手动管理
// 实际中应该使用try-with-resources或显式清理
}
// 使用原始类型集合
public static void demonstratePrimitiveCollections() {
System.out.println("\n=== 原始类型集合示例 ===");
// 使用第三方库如fastutil(这里用标准API演示思路)
List<Integer> standardList = new ArrayList<>();
IntBuffer primitiveBuffer = IntBuffer.allocate(1000000);
long start = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
standardList.add(i); // 自动装箱,创建Integer对象
}
long standardTime = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
primitiveBuffer.put(i); // 直接存储int
}
long primitiveTime = System.nanoTime() - start;
System.out.printf("标准ArrayList: %,.2fms\n", standardTime / 1_000_000.0);
System.out.printf("原始类型Buffer: %,.2fms\n", primitiveTime / 1_000_000.0);
System.out.println("原始类型集合减少了对象创建和内存占用");
}
}
public static void main(String[] args) {
System.out.println("=== 大数据处理系统调优实战 ===");
// 显示调优方案
BigDataOptimizationStrategy.printOptimizationPlan();
BigDataOptimizationStrategy.demonstrateOffHeapMemory();
BigDataOptimizationStrategy.demonstratePrimitiveCollections();
// 创建测试数据
List<byte[]> testDataset = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
testDataset.add(new byte[1024]); // 每个记录1KB
}
// 创建处理器
DataProcessor processor = new DataProcessor();
System.out.println("\n=== 性能对比测试 ===");
// 测试普通版本
System.out.println("\n1. 普通版本:");
List<Map<String, Object>> result1 = processor.processLargeDataset(testDataset);
System.gc();
// 测试优化版本
System.out.println("\n2. 优化版本:");
List<Map<String, Object>> result2 = processor.processLargeDatasetOptimized(testDataset);
System.gc();
System.out.println("\n处理完成,结果数量: " + result1.size());
// 显示内存状态
Runtime runtime = Runtime.getRuntime();
System.out.printf("\n内存状态:\n");
System.out.printf(" 最大内存: %,.2fMB\n", runtime.maxMemory() / 1024.0 / 1024);
System.out.printf(" 总内存: %,.2fMB\n", runtime.totalMemory() / 1024.0 / 1024);
System.out.printf(" 空闲内存: %,.2fMB\n", runtime.freeMemory() / 1024.0 / 1024);
System.out.printf(" 已用内存: %,.2fMB\n",
(runtime.totalMemory() - runtime.freeMemory()) / 1024.0 / 1024);
}
}
总结:JVM调优最佳实践
调优原则
- 测量先行:不要猜测,使用监控工具收集数据
- 逐步调整:每次只调整一个参数,观察效果
- 关注业务:调优的目标是改善业务指标,不是追求极致参数
- 理解原理:理解GC算法和内存管理原理
常见问题与解决方案
| 问题 | 症状 | 解决方案 |
|---|---|---|
| Full GC频繁 | 应用停顿频繁,响应时间波动 | 增加堆大小,优化对象生命周期 |
| 内存泄漏 | 内存使用持续增长,最终OOM | 使用堆转储分析,修复资源未释放 |
| 高延迟 | 应用响应慢,GC停顿长 | 使用低延迟GC(ZGC/Shenandoah) |
| 低吞吐量 | CPU使用率高但处理量低 | 优化代码,调整GC并行度 |
| 元空间溢出 | 类加载失败,Metaspace满 | 增加MaxMetaspaceSize,检查类加载器泄漏 |
调优检查清单
java
public class JVMTuningChecklist {
public static void printChecklist() {
System.out.println("=== JVM调优检查清单 ===");
System.out.println("\n1. 内存设置检查:");
System.out.println(" ☐ -Xms和-Xmx设置相同值,避免堆震荡");
System.out.println(" ☐ 堆大小设置为物理内存的50-75%");
System.println(" ☐ 年轻代大小合适(通常是堆的1/3到1/2)");
System.out.println(" ☐ 设置了合理的Metaspace大小");
System.out.println("\n2. GC配置检查:");
System.out.println(" ☐ 选择了合适的GC收集器");
System.out.println(" ☐ 设置了合理的GC线程数");
System.out.println(" ☐ 配置了GC日志记录");
System.out.println(" ☐ 考虑了停顿时间目标");
System.out.println("\n3. 监控配置检查:");
System.out.println(" ☐ 启用了JMX监控");
System.out.println(" ☐ 配置了GC日志轮转");
System.out.println(" ☐ 设置了堆转储参数");
System.out.println(" ☐ 配置了性能指标收集");
System.out.println("\n4. 代码优化检查:");
System.out.println(" ☐ 避免大对象直接进入老年代");
System.out.println(" ☐ 合理使用缓存(大小限制、过期策略)");
System.out.println(" ☐ 及时关闭资源(连接、流)");
System.out.println(" ☐ 使用合适的数据结构");
System.out.println("\n5. 部署环境检查:");
System.out.println(" ☐ 容器内存限制设置正确");
System.out.println(" ☐ 系统交换空间足够");
System.out.println(" ☐ 文件描述符限制合适");
System.out.println(" ☐ 网络配置优化");
}
public static void printCommonParameters() {
System.out.println("\n=== 常用JVM参数 ===");
System.out.println("\n内存相关:");
System.out.println(" -Xms4g -Xmx4g # 堆内存");
System.out.println(" -XX:MetaspaceSize=256m # 元空间初始大小");
System.out.println(" -XX:MaxMetaspaceSize=512m # 元空间最大大小");
System.out.println(" -XX:NewRatio=2 # 新生代:老年代比例");
System.out.println(" -XX:SurvivorRatio=8 # Eden:Survivor比例");
System.out.println("\nGC相关:");
System.out.println(" -XX:+UseG1GC # 使用G1收集器");
System.out.println(" -XX:MaxGCPauseMillis=200 # 目标停顿时间");
System.out.println(" -XX:+UseParallelGC # 使用并行收集器");
System.out.println(" -XX:ParallelGCThreads=8 # GC线程数");
System.out.println(" -XX:+UseZGC # 使用ZGC收集器");
System.out.println("\n监控调试:");
System.out.println(" -XX:+PrintGCDetails # 打印GC详情");
System.out.println(" -XX:+PrintGCDateStamps # 打印GC时间戳");
System.out.println(" -Xloggc:/path/to/gc.log # GC日志路径");
System.out.println(" -XX:+HeapDumpOnOutOfMemoryError # OOM时堆转储");
System.out.println(" -XX:HeapDumpPath=/path/to/dump # 堆转储路径");
System.out.println("\n性能优化:");
System.out.println(" -XX:+UseStringDeduplication # 字符串去重");
System.out.println(" -XX:+OptimizeStringConcat # 字符串连接优化");
System.out.println(" -XX:+UseCompressedOops # 压缩指针");
System.out.println(" -XX:+UseLargePages # 使用大内存页");
}
public static void main(String[] args) {
printChecklist();
printCommonParameters();
}
}