JVM实战中5个核心概念

  1. 堆内存:你的Java对象住在哪?

简单比喻:堆就像公司的办公区

· 新生代:新员工的工位(频繁进出)

· 老年代:老员工的固定工位(比较稳定)

· 元空间:公司规章制度(方法、类信息)

常见问题:对象怎么从新生代到老年代?

java 复制代码
public class Employee {
    private String name;
    
    public static void main(String[] args) {
        Employee emp = new Employee(); // 对象出生在新生代
        
        // 经过15次GC还存活(默认阈值)
        // 或者新生代放不下大对象
        byte[] bigData = new byte[10 * 1024 * 1024]; // 10MB,直接进老年代
    }
}
  1. GC垃圾回收:保洁阿姨什么时候来?

保洁规则(GC算法):

· 年轻代:Minor GC - 频繁打扫新员工区域

· 老年代:Major GC/Full GC - 全公司大扫除(业务暂停!)

常见问题:什么时候会发生Full GC?

回答:"老年代空间不足、System.gc()调用、或者CMS/G1的并发失败时"

  1. 类加载:Java程序如何启动?

三步加载过程:

java 复制代码
// 1. 加载(Load):从磁盘找到class文件
// 2. 链接(Link):验证格式,准备内存
// 3. 初始化(Init):执行静态代码块

public class HelloWorld {
    static {
        System.out.println("我在初始化阶段执行");
    }
}

双亲委派机制(就像公司汇报流程):

员工(自定义类加载器) → 经理(扩展类加载器) → 总监(应用类加载器) → CEO(启动类加载器)

· 好处:防止核心API被篡改

  1. 常见内存问题与排查

问题1:内存泄漏(东西只进不出)

java 复制代码
// ❌ 错误示范:静态Map无限增长
public class Cache {
    private static Map<String, Object> cache = new HashMap<>();
    
    public void addData(String key, Object value) {
        cache.put(key, value); // 永远不remove,导致内存泄漏
    }
}

问题2:OOM内存溢出(仓库爆满)

java 复制代码
// 堆内存溢出
List<byte[]> list = new ArrayList<>();
while(true) {
    list.add(new byte[1024 * 1024]); // 不停申请1MB数组
}

// 栈溢出(递归太深)
public void recursive() {
    recursive(); // 无限递归
}
  1. 实战场景

场景1:线上CPU飙高怎么办?

复制代码
1. top命令找到Java进程
2. top -Hp [pid] 找到高CPU线程
3. printf "%x\n" [线程id] 转16进制
4. jstack [pid] | grep -A 10 [16进制id]

场景2:内存占用高怎么分析?

bash 复制代码
# 1. 查看堆内存概览
jmap -heap [pid]

# 2. 生成堆转储文件
jmap -dump:format=b,file=heap.hprof [pid]

# 3. 用MAT或JVisualVM分析
  1. JVM参数调优(记住这几个就够了)
bash 复制代码
# 启动参数示例
java -Xms512m      # 初始堆大小(公司初始办公区)
     -Xmx2048m     # 最大堆大小(最大可扩张办公区)
     -Xmn256m      # 新生代大小(新员工区)
     -XX:+HeapDumpOnOutOfMemoryError  # OOM时自动dump
     -XX:HeapDumpPath=./              # dump文件路径
     -jar your-app.jar
  1. 简单诊断工具箱

快速检查命令:

bash 复制代码
# 查看JVM进程
jps -l

# 查看GC情况
jstat -gc [pid] 1000 5  # 每秒1次,共5次

# 线程快照
jstack [pid] > thread.txt
  1. 避免常见误区

✅ 正确认知:

· 不是-Xmx越大越好,太大会延长GC时间

· 频繁GC不一定是问题,要看停顿时间

· 不同的业务场景需要不同的GC算法

❌ 常见误解:

· "我的程序从不GC,性能很好"(可能内存泄漏!)

· "Full GC是正常的"(应该尽量避免!)

· "OOM一定是代码bug"(可能是配置问题)

记住三句话:

  1. 对象有生有死 - 大部分对象活不过一次GC
  2. 垃圾回收是成本 - GC时业务会暂停
  3. 监控比调优重要 - 先知道问题在哪
相关推荐
风筝在晴天搁浅2 小时前
hot100 146.LRU缓存
java·缓存
liliangcsdn2 小时前
MySQL存储字节类数据的方案示例
java·前端·数据库
lbb 小魔仙2 小时前
【Java】Spring Cloud 核心组件详解:Eureka、Ribbon、Feign 与 Hystrix
java·spring cloud·eureka
予枫的编程笔记2 小时前
从入门到精通:RabbitMQ全面解析与实战指南
java·开发语言·后端·rabbitmq·ruby
大爱编程♡2 小时前
JAVAEE-前端三剑客
java·前端·java-ee
csdnZCjava2 小时前
Spring MVC工作原理 及注解说明
java·后端·spring·mvc
__万波__2 小时前
二十三种设计模式(十八)--中介者模式
java·设计模式·中介者模式