JVM 入门学习笔记(内存模型 / GC / 类加载机制)

整理一下基本概念,因为遇到了本地线程无法创建的问题,回顾一下基本JVM的,有利于解决所需要的理论知识


一、JVM 内存模型

1. 什么是 JVM

JVM(Java Virtual Machine)本质上是:

text 复制代码
Java代码的运行环境

Java代码不会直接运行在操作系统上。

而是:

text 复制代码
Java代码
   ↓
编译成.class字节码
   ↓
JVM解释执行

所以 JVM 本质上是:

text 复制代码
Java程序和操作系统之间的一层中间层

二、堆和栈到底是什么

这是 JVM 最核心概念。


1. 栈(Stack)

栈是:

text 复制代码
线程私有的运行空间

每个线程:

text 复制代码
都有自己的栈

例如:

  • main线程
  • Tomcat工作线程
  • GC线程

都有自己的栈。


2. 栈里存什么

栈主要存:

  • 方法调用
  • 局部变量
  • 基本类型
  • 对象引用地址

例如:

java 复制代码
User user = new User();
int age = 18;

运行时:

text 复制代码
栈:
user = 对象地址
age = 18

3. 堆(Heap)

堆是:

text 复制代码
所有线程共享的对象存储区

真正对象:

text 复制代码
放在堆里

例如:

java 复制代码
new User()

会进入:

text 复制代码
Heap(堆)

4. 栈和堆的关系

text 复制代码
栈(Stack)                  堆(Heap)

user  ───────────────→   User对象
                           name
                           age
                           phone

核心:

text 复制代码
栈保存地址
堆保存真正对象

三、为什么对象不直接放栈里

因为:

text 复制代码
对象可能很大
生命周期不确定

例如:

  • List
  • Map
  • JSON
  • Redis缓存对象
  • Spring Bean

如果都放栈里:

text 复制代码
线程内存会瞬间爆炸

所以 JVM 设计成:

区域 作用
快速执行方法
管理大量对象

四、线程、HTTP请求、栈之间关系

很多人误会:

text 复制代码
HTTP请求来了才创建栈

其实不是。

真正是:

text 复制代码
线程创建时
栈就已经存在

核心:

text 复制代码
一个线程 = 一个虚拟机栈

SpringBoot 启动时

JVM 会创建很多线程:

  • main线程
  • GC线程
  • Tomcat线程
  • 定时任务线程

每个线程:

text 复制代码
都有自己的栈

五、虚拟机栈 vs 本地方法栈


1. Java虚拟机栈

负责:

text 复制代码
Java方法运行

例如:

  • Controller
  • Service
  • DAO

2. 本地方法栈

负责:

text 复制代码
Native方法运行

例如:

  • 文件IO
  • 网络IO
  • 操作系统调用
  • 创建线程

很多 JVM 底层能力:

text 复制代码
实际上是C/C++实现

六、GC(垃圾回收)到底是什么

GC:

text 复制代码
Garbage Collection

即:

text 复制代码
垃圾回收

负责:

text 复制代码
回收堆中的无用对象

七、OOM(内存溢出)是什么

最经典:

text 复制代码
java.lang.OutOfMemoryError: Java heap space

表示:

text 复制代码
堆满了

OOM 本质

不是简单:

text 复制代码
GC太慢

真正本质:

text 复制代码
对象创建速度
>
对象释放速度

或者:

text 复制代码
对象一直被引用
无法回收

八、GC Roots 与可达性分析

这是 JVM GC 核心。

GC 并不会判断:

text 复制代码
对象有没有业务价值

而是判断:

text 复制代码
还能不能找到对象

1. 什么是 GC Roots

GC Roots:

text 复制代码
GC扫描的起点

常见 GC Roots:

类型 示例
栈引用 方法里的变量
static变量 静态缓存
正在运行线程 Thread
常量引用 String常量池

2. GC 扫描逻辑

text 复制代码
GC Roots
   │
   ├──── 能找到对象
   │         │
   │         └──── 对象存活
   │
   └──── 找不到对象
             │
             └──── 对象死亡

3. 为什么 static 容易OOM

例如:

java 复制代码
static Map cache = new HashMap();

因为:

text 复制代码
static属于GC Roots

所以:

text 复制代码
cache中的对象长期可达
GC不敢删

4. 为什么 ThreadLocal 容易泄漏

因为:

text 复制代码
线程本身是GC Roots

Tomcat线程池长期存在。

所以:

text 复制代码
ThreadLocalMap中的对象
长期无法回收

九、分代垃圾回收机制

JVM发现:

text 复制代码
大部分对象生命周期很短

所以:

text 复制代码
把不同生命周期对象分开管理

1. 堆结构

text 复制代码
堆
├── 新生代
└── 老年代

十、新生代

新对象:

text 复制代码
先进入新生代

结构:

text 复制代码
新生代
├── Eden
├── Survivor From
└── Survivor To

对象流转

text 复制代码
new对象
   │
   ▼
Eden
   │
   ▼
Minor GC
   │
   ├── 死亡 → 回收
   └── 存活 → Survivor
                    │
                    ▼
              多次存活
                    │
                    ▼
                 老年代

十一、Minor GC 和 Full GC


1. Minor GC

触发时机:

text 复制代码
Eden区满了

特点:

  • 频繁
  • 回收年轻对象

2. Full GC

触发时机:

text 复制代码
老年代空间不足

特点:

  • 很慢
  • Stop The World
  • 扫描整个堆

十二、GC 什么时候执行

GC 并不是:

text 复制代码
方法结束立即执行

而是:

text 复制代码
内存不够时触发

正确流程

text 复制代码
方法结束
   │
   ▼
对象失去引用
   │
   ▼
变成"可回收对象"
   │
   ▼
等待GC触发
   │
   ▼
GC扫描
   │
   ▼
真正回收

十三、类加载机制

Java类不会自动进入JVM。

必须:

text 复制代码
ClassLoader加载

JVM默认三层类加载器

text 复制代码
Application ClassLoader
            ↑
Extension ClassLoader
            ↑
Bootstrap ClassLoader

各自职责

类加载器 负责内容
Bootstrap JDK核心类
Extension 扩展类库
Application 业务代码

十四、双亲委派机制

核心思想:

text 复制代码
加载类时
先问父加载器
父加载不了
自己再加载

加载流程

text 复制代码
Application收到请求
   │
   ▼
先问Extension
   │
   ▼
Extension问Bootstrap
   │
   ▼
Bootstrap能加载?
   │
 ┌─┴───────┐
 │          │
能         不能
 │          │
Bootstrap   返回下层
加载         │
             ▼
       最终Application加载

十五、双亲委派为什么重要

1. 防止核心类被篡改

例如:

java 复制代码
java.lang.String

只能由:

text 复制代码
Bootstrap加载

业务代码无法替换。


2. 防止类重复加载

JVM 中:

text 复制代码
类名 + ClassLoader
=
唯一类

3. 保证安全隔离

Tomcat 能同时运行多个项目:

text 复制代码
因为每个项目有自己的ClassLoader

十六、今天最核心的理解


JVM 内存

text 复制代码
栈:线程私有
堆:对象存储

GC

text 复制代码
GC判断对象是否死亡
看的是:
还能不能从GC Roots找到

分代GC

text 复制代码
不同生命周期对象
采用不同回收策略

双亲委派

text 复制代码
本质是:
优先级 + 安全机制

防止:

  • 核心类被覆盖
  • 类重复加载
  • 恶意注入


十八、现实世界类比总结(帮助真正理解)


1. JVM 像什么?

JVM 可以理解成:

text 复制代码
Java程序的"操作系统"

它负责:

  • 管理内存
  • 管理线程
  • 管理对象
  • 管理类加载
  • 管理垃圾回收

就像:

text 复制代码
一个大型公司的总管理系统

2. 栈(Stack)像什么?

栈像:

text 复制代码
每个员工自己的办公桌

特点:

  • 私有
  • 快速
  • 临时
  • 方法结束立刻清理

所以:

text 复制代码
一个线程 = 一张办公桌

3. 堆(Heap)像什么?

堆像:

text 复制代码
公司公共仓库

所有线程:

text 复制代码
共享这个仓库

真正的大对象:

  • List
  • Map
  • Bean
  • DTO
  • JSON

都放在这里。


4. 对象引用像什么?

代码:

java 复制代码
User user = new User();

本质像:

text 复制代码
办公桌上放着"仓库货架编号"

即:

text 复制代码
栈里放地址
堆里放真正对象

5. GC 像什么?

GC 像:

text 复制代码
公司保洁 + 仓库管理员

负责:

text 复制代码
清理没人使用的物品

6. GC Roots 像什么?

GC Roots 像:

text 复制代码
公司总台登记系统

GC 会从"总台记录"开始查:

text 复制代码
这个东西还有没有人能找到

如果:

text 复制代码
还能找到

说明:

text 复制代码
对象还活着

否则:

text 复制代码
对象死亡

7. Minor GC 像什么?

Minor GC 像:

text 复制代码
快递临时区清理

因为:

text 复制代码
大部分快递当天就会拿走

所以:

text 复制代码
清理特别快

8. 老年代像什么?

老年代像:

text 复制代码
公司长期仓库

放:

  • 核心设备
  • 长期资产
  • 大型机器

特点:

text 复制代码
东西多
清理慢

9. Full GC 像什么?

Full GC 像:

text 复制代码
整个公司停工大扫除

所以:

text 复制代码
会暂停业务

即:

text 复制代码
Stop The World

10. 双亲委派像什么?

双亲委派像:

text 复制代码
公司逐级审批制度

基层:

text 复制代码
不能直接覆盖总部规定

必须:

text 复制代码
先问上级

这就是:

text 复制代码
先委派父加载器

11. Bootstrap ClassLoader 像什么?

Bootstrap 类加载器像:

text 复制代码
公司董事长 / 国家中央系统

负责:

text 复制代码
最核心最重要的类

例如:

  • String
  • Object
  • Thread
  • Class

这些:

text 复制代码
绝对不能被业务代码替换

12. ThreadLocal 为什么容易泄漏?

ThreadLocal 像:

text 复制代码
员工工位抽屉

如果:

text 复制代码
员工一直不离职

抽屉里的东西:

text 复制代码
永远不会被清理

Tomcat线程池就是这样。


13. OOM 像什么?

OOM 像:

text 复制代码
仓库塞满了

可能因为:

  • 东西产生太快
  • 垃圾清理太慢
  • 有人一直占着不丢

最终:

text 复制代码
仓库彻底放不下

十九、最终一句总结

JVM 最核心其实只有一句话:

text 复制代码
对象如何创建
对象如何存活
对象如何死亡

而:

  • 内存模型
  • GC
  • 类加载

本质上都是围绕:

text 复制代码
对象生命周期管理

展开的。

相关推荐
什么半岛铁盒1 小时前
LangChain常用组件学习
学习·microsoft·langchain
happymaker06261 小时前
SpringBoot学习日记——DAY04(整合junit,myBatis)
spring boot·学习·junit
Restart-AHTCM1 小时前
LangChain学习之模型 I/O 与输出解析器 (Output Parsers)(3/8)
前端·学习·langchain
windawdaysss1 小时前
离线学习SQL和数据库的工具及其部署
数据库·sql·学习
yoona10201 小时前
AI × Web3 项目拆解笔记
人工智能·笔记·web3
二哈赛车手9 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
吃好睡好便好10 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
nashane10 小时前
HarmonyOS 6学习:CapsLock键失效诊断与长截图完整实现指南
学习·华为·harmonyos
AI人工智能+电脑小能手12 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm