← 返回首页
🏎️

JVM架构:内存模型与GC算法

📂 architecture ⏱ 3 min 523 words

JVM架构:内存模型与GC算法

JVM内存模型

JVM内存分为堆、栈、方法区、程序计数器等区域,理解内存模型是性能调优的基础。

// JVM内存监控
@Component
public class JVMMemoryMonitor {
    
    private final MemoryMXBean memoryBean;
    private final List<GarbageCollectorMXBean> gcBeans;
    private final MetricsExporter metrics;
    
    @Scheduled(fixedRate = 5000)
    public void monitorMemory() {
        // 堆内存
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
        metrics.gauge("jvm.heap.used", heapUsage.getUsed());
        metrics.gauge("jvm.heap.committed", heapUsage.getCommitted());
        metrics.gauge("jvm.heap.max", heapUsage.getMax());
        metrics.gauge("jvm.heap.usage", 
            (double) heapUsage.getUsed() / heapUsage.getMax() * 100);
        
        // 非堆内存
        MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
        metrics.gauge("jvm.nonheap.used", nonHeapUsage.getUsed());
        metrics.gauge("jvm.nonheap.committed", nonHeapUsage.getCommitted());
        
        // 各内存池
        MemoryPoolMXBean[] memoryPools = ManagementFactory.getMemoryPoolMXBeans();
        for (MemoryPoolMXBean pool : memoryPools) {
            String name = pool.getName().toLowerCase().replace(" ", "_");
            MemoryUsage usage = pool.getUsage();
            
            metrics.gauge("jvm.memory_pool." + name + ".used", usage.getUsed());
            metrics.gauge("jvm.memory_pool." + name + ".max", usage.getMax());
        }
        
        // GC统计
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            String name = gcBean.getName().toLowerCase().replace(" ", "_");
            metrics.counter("jvm.gc." + name + ".count", gcBean.getCollectionCount());
            metrics.counter("jvm.gc." + name + ".time", gcBean.getCollectionTime());
        }
    }
}

// 内存泄漏检测
@Component
public class MemoryLeakDetector {
    
    public void detect() {
        // 获取内存池信息
        MemoryPoolMXBean[] pools = ManagementFactory.getMemoryPoolMXBeans();
        
        for (MemoryPoolMXBean pool : pools) {
            if (pool.isUsageThresholdSupported()) {
                MemoryUsage usage = pool.getUsage();
                long used = usage.getUsed();
                long max = usage.getMax();
                
                // 检查内存使用率
                if (max > 0 && (double) used / max > 0.9) {
                    alertService.send(new Alert(
                        "内存使用率过高",
                        String.format("内存池 %s 使用率: %.2f%%", 
                            pool.getName(), (double) used / max * 100)
                    ));
                }
                
                // 检查是否有内存池已满
                if (pool.isCollectionUsageThresholdSupported()) {
                    MemoryUsage collectionUsage = pool.getCollectionUsage();
                    if (collectionUsage != null && 
                        collectionUsage.getUsed() > collectionUsage.getMax() * 0.9) {
                        alertService.send(new Alert(
                            "GC后内存仍高",
                            String.format("内存池 %s GC后使用率仍高", pool.getName())
                        ));
                    }
                }
            }
        }
    }
}

GC算法详解

// GC配置与监控
@Component
public class GCConfigAndMonitor {
    
    // G1 GC配置建议
    public String getG1GCConfig() {
        return """
            -XX:+UseG1GC
            -XX:MaxGCPauseMillis=200
            -XX:G1HeapRegionSize=16m
            -XX:InitiatingHeapOccupancyPercent=45
            -XX:G1ReservePercent=10
            -XX:G1NewSizePercent=5
            -XX:G1MaxNewSizePercent=60
            -XX:+ParallelRefProcEnabled
            -XX:ParallelGCThreads=8
            -XX:ConcGCThreads=4
            """;
    }
    
    // ZGC配置建议
    public String getZGCConfig() {
        return """
            -XX:+UseZGC
            -XX:+ZGenerational
            -XX:SoftMaxHeapSize=8G
            -XX:ZUncommitDelay=300
            -XX:+UnlockExperimentalVMOptions
            """;
    }
    
    // Shenandoah配置建议
    public String getShenandoahConfig() {
        return """
            -XX:+UseShenandoahGC
            -XX:ShenandoahGCHeuristics=compact
            -XX:ShenandoahMinFreeThreshold=10
            -XX:ShenandoahGuaranteedGCInterval=300000
            """;
    }
}

// GC日志分析
@Component
public class GCLogAnalyzer {
    
    public GCAnalysis analyze(String logFilePath) throws IOException {
        List<GCEvent> events = new ArrayList<>();
        
        try (BufferedReader reader = Files.newBufferedReader(
                Path.of(logFilePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.contains("GC")) {
                    GCEvent event = parseGCEvent(line);
                    if (event != null) {
                        events.add(event);
                    }
                }
            }
        }
        
        // 分析GC模式
        return analyzePattern(events);
    }
    
    private GCAnalysis analyzePattern(List<GCEvent> events) {
        GCAnalysis analysis = new GCAnalysis();
        
        // 计算GC频率
        long totalTime = events.stream()
            .mapToLong(GCEvent::getDuration)
            .sum();
        
        double avgPause = events.stream()
            .mapToLong(GCEvent::getPauseTime)
            .average()
            .orElse(0);
        
        long maxPause = events.stream()
            .mapToLong(GCEvent::getPauseTime)
            .max()
            .orElse(0);
        
        analysis.setTotalGCTime(totalTime);
        analysis.setAvgPause(avgPause);
        analysis.setMaxPause(maxPause);
        analysis.setGCFrequency(events.size());
        
        // 检测问题
        if (maxPause > 200) {
            analysis.addIssue("最大GC暂停时间过长: " + maxPause + "ms");
        }
        
        if (events.size() > 100) {
            analysis.addIssue("GC频率过高,可能存在内存压力");
        }
        
        return analysis;
    }
}

JIT编译优化

// JIT监控与优化
@Component
public class JITOptimizer {
    
    private final CompilationMXBean compilationBean;
    
    public JITStats getJITStats() {
        return JITStats.builder()
            .totalCompilationTime(compilationBean.getTotalCompilationTime())
            .totalCompiledMethods(compilationBean.getTotalCompilationTime())
            .build();
    }
    
    // 常用JIT优化参数
    public String getOptimizationFlags() {
        return """
            -XX:+TieredCompilation
            -XX:TieredStopAtLevel=4
            -XX:CompileThreshold=10000
            -XX:OnStackReplacePercentage=140
            -XX:InterpreterProfilePercentage=33
            -XX:+UseCodeCacheExpansion
            -XX:ReservedCodeCacheSize=256m
            -XX:InitialCodeCacheSize=128m
            """;
    }
    
    // 内联优化
    public String getInliningFlags() {
        return """
            -XX:+UnlockDiagnosticVMOptions
            -XX:+PrintInlining
            -XX:MaxInlineSize=35
            -XX:FreqInlineSize=325
            -XX:MaxInlineLevel=9
            -XX:MaxRecursiveInlineLevel=3
            """;
    }
}

JVM性能调优实战

# JVM调优配置
jvm:
  memory:
    # 堆内存配置
    heap:
      min: "4g"
      max: "8g"
      young_gen: "2g"
      old_gen: "6g"
    
    # 非堆内存
    non_heap:
      metaspace: "256m"
      code_cache: "256m"
    
    # 线程栈
    thread_stack: "512k"
    
    # 直接内存
    direct_memory: "1g"
  
  gc:
    # G1 GC配置
    g1:
      enabled: true
      max_pause_millis: 200
      heap_region_size: "16m"
      initiating_occupancy_percent: 45
      parallel_gc_threads: 8
      conc_gc_threads: 4
    
    # ZGC配置
    zgc:
      enabled: false
      max_heap_size: "16g"
      soft_max_heap_size: "8g"
  
  jit:
    tiered_compilation: true
    compile_threshold: 10000
    code_cache_size: "256m"
  
  diagnostics:
    heap_dump_on_oome: true
    heap_dump_path: "/tmp/heapdump.hprof"
    gc_log: true
    gc_log_path: "/var/log/gc.log"
    gc_log_options: "-Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags"

JVM架构优化通过理解内存模型、选择合适的GC算法和JIT调优,显著提升Java应用的性能和稳定性。