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. 监控比调优重要 - 先知道问题在哪
相关推荐
亦暖筑序1 小时前
Java 8老系统AI Workflow实战:把一次性AI对话升级成可恢复工作流
java·后端
敲代码的彭于晏2 小时前
Bean 生命周期完全图解:前端同学也能看懂的 Spring 核心机制
java·前端·后端
plainGeekDev3 小时前
ButterKnife → ViewBinding
android·java·kotlin
像我这样帅的人丶你还19 小时前
Java 后端详解(四):分页与搜索
java·javascript·后端
她的男孩19 小时前
数据权限为什么不能只靠注解?Forge 的 Mapper 层 SQL 改写源码拆解
java·后端·架构
tntxia20 小时前
Mybatis的日志输入
java
亦暖筑序21 小时前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
用户298698530141 天前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao1 天前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿1 天前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试