三、内存管理(排查 OOM、内存泄漏必备)
⭐⭐⭐⭐⭐ Java 后端、Linux 运维、操作系统、校招面试高频内容
本章重点:
- 逻辑地址与物理地址
- 分页机制
- 页表、TLB(快表)
- 虚拟内存
- Swap(交换分区)
- 缺页中断
- 页面置换算法
- 内存抖动(Thrashing)
- OOM 与内存泄漏
一、为什么需要内存管理?
CPU运行程序时:
所有代码和数据都必须先加载到内存(RAM)。
例如:
打开: QQChromeIDEA微信
这些程序都会占用内存。
如果没有内存管理:
- 程序会互相覆盖
- 数据会混乱
- 系统容易崩溃
因此:
操作系统负责统一管理内存资源。
二、内存管理的作用
主要作用有:
① 分配内存
程序A ↓ 100MB
程序B:
500MB
② 回收内存
程序退出后:
释放RAM
否则:
内存越来越少。
③ 地址转换
程序看到:
0x0010
真正:
对应:
物理内存: 0x8A2F0010
④ 内存保护
程序A:
不能访问:
程序B的数据。
否则:
系统不安全。
三、逻辑地址(Logical Address)
也叫:
虚拟地址(Virtual Address)
程序运行时:
看到的地址。
例如:
cint a=10;
变量:
0x1000
其实:
不是实际内存地址。
而是:
逻辑地址。
程序:
永远不知道真实物理地址。
为什么?
如果程序直接操作物理地址:
例如:
程序A 1000
程序B:
1000
数据马上冲突。
所以:
每个进程:
都有自己的逻辑地址空间。
互不影响。
四、物理地址(Physical Address)
真正:
RAM上的地址。
例如:
内存: 8GB
真实地址:
0x7FF01234
CPU最终访问:
就是物理地址。
五、逻辑地址与物理地址关系(★★★★★)
程序:
逻辑地址 ↓ MMU(内存管理单元) ↓ 物理地址 ↓ RAM
即:
程序 ↓ 逻辑地址 ↓ 页表 ↓ 物理地址
所以:
程序无需关心真实内存位置。
对比
| 逻辑地址 | 物理地址 |
|---|---|
| 程序看到 | 内存真实地址 |
| 每个进程独立 | 系统唯一 |
| CPU不能直接访问 | CPU最终访问 |
口诀:
程序使用逻辑地址,硬件访问物理地址。
六、分页(Paging)(★★★★★)
早期:
内存连续分配。
容易:
产生碎片。
因此:
现代操作系统:
使用:
分页。
什么是页(Page)?
把内存:
切成:
固定大小。
例如:
4KB
一页。
程序:
也切成:
很多页。
例如:
程序 ↓ 第一页 第二页 第三页
什么是页框(Frame)?
物理内存:
也切成:
同样大小。
Frame1 Frame2 Frame3
然后:
程序页面:
映射:
物理页框。
分页优势
例如:
程序:
Page1 ↓ Frame5
Page2 ↓ Frame18
Page3 ↓ Frame99
可以:
离散存放。
不用连续。
因此:
提高内存利用率。
七、页表(Page Table)
程序:
只有:
逻辑地址。
如何找到:
物理地址?
答案:
页表。
例如:
| 页号 | 页框 |
|---|---|
| 0 | 15 |
| 1 | 20 |
| 2 | 31 |
| 3 | 45 |
CPU:
查:
页表。
得到:
真正地址。
八、TLB(快表)(★★★★★)
问题:
每次:
都查页表。
速度慢。
于是:
CPU增加:
TLB(Translation Lookaside Buffer)
中文:
快表。
工作流程
CPU ↓ TLB ↓ 没有 ↓ 页表 ↓ 内存
如果:
TLB命中:
速度:
极快。
如果:
TLB未命中:
才访问页表。
为什么快?
TLB:
本质:
高速缓存。
里面:
保存:
最近访问的:
页表项。
类似:
CPU Cache。
总结
| TLB命中 | 快 |
|---|---|
| TLB未命中 | 查页表 |
口诀:
先查TLB,再查页表。
九、虚拟内存(Virtual Memory)(★★★★★)
假设:
电脑:
8GB内存
程序:
需要:
16GB
还能运行吗?
答案:
可以。
因为:
有:
虚拟内存。
什么是虚拟内存?
操作系统:
让程序觉得:
自己拥有:
很大的内存。
实际上:
只有部分:
在RAM。
剩下:
放磁盘。
例如:
RAM ↓ 8GB
磁盘:
Swap ↓ 8GB
程序:
感觉:
16GB。
为什么需要?
优势:
- 程序可以更大
- 多程序同时运行
- 提高内存利用率
十、Swap(交换分区)
Swap:
就是:
磁盘上的:
备用内存。
例如:
Linux:
swap
Windows:
pagefile.sys
工作过程
内存:
快满了。
操作系统:
把:
暂时不用的数据:
移到:
Swap。
RAM ↓ Swap
需要时:
再换回来。
Swap特点
优点:
节省内存。
缺点:
速度:
远低于RAM。
例如:
RAM 几十GB/s
SSD:
几百MB/s
因此:
Swap:
只是:
应急。
十一、缺页(Page Fault)(★★★★★)
程序:
访问:
某一页。
结果:
RAM没有。
怎么办?
CPU:
产生:
缺页中断(Page Fault)。
处理流程
访问页面 ↓ RAM没有 ↓ 缺页中断 ↓ OS处理 ↓ 从磁盘加载 ↓ 更新页表 ↓ 继续执行
为什么叫缺页?
因为:
访问:
这一页。
发现:
缺失。
所以:
叫:
缺页。
十二、页面置换(Page Replacement)
RAM:
满了。
新页面:
进不来。
怎么办?
必须:
淘汰一页。
这就是:
页面置换。
常见算法(★★★★★)
① FIFO(先进先出)
最早进入:
最早出去。
例如:
1 2 3 4
淘汰:
1
简单。
但:
效果一般。
② LRU(最近最少使用)
最近:
很久没访问。
就淘汰。
例如:
最近访问: 5 2 8 1
最久没访问:
淘汰。
优点:
实际效果最好。
Java缓存:
Redis:
都采用:
类似思想。
③ LFU(最少使用)
访问次数:
最少。
先淘汰。
例如:
A 100次
B 2次
淘汰:
B。
对比
| 算法 | 特点 |
|---|---|
| FIFO | 最简单 |
| LRU | 最常用 |
| LFU | 按访问次数 |
十三、抖动(Thrashing)(★★★★★)
什么是抖动?
程序:
一直:
缺页。
一直:
换页。
CPU:
几乎不执行程序。
一直:
读磁盘。
例如:
缺页 ↓ 加载 ↓ 换页 ↓ 再缺页 ↓ 再加载
不断循环。
这就是:
抖动(Thrashing)。
为什么发生?
原因:
内存:
太小。
程序:
太多。
或者:
页面分配:
太少。
后果
CPU:
利用率:
下降。
磁盘:
疯狂读写。
程序:
越来越慢。
如何解决?
方法:
① 增加内存
② 减少程序
③ 优化分页
④ 减少Swap
十四、OOM(Out Of Memory)
OOM:
内存不足。
例如:
Java:
java.lang.OutOfMemoryError
常见原因
① 内存泄漏
对象:
一直存在。
GC:
无法回收。
② 内存不足
程序:
需要:
8GB。
电脑:
只有:
4GB。
③ 创建对象过多
例如:
javawhile(true){ list.add(new User());}
最终:
OOM。
十五、内存泄漏(Memory Leak)
什么是内存泄漏?
对象:
已经不用了。
但是:
还有引用。
GC:
不能回收。
例如:
javaList<User> list=new ArrayList<>(); while(true){ list.add(new User());}
list:
一直引用。
对象:
越来越多。
最终:
OOM。
常见原因
- 集合一直保存对象
- 静态变量引用对象
- ThreadLocal 未清理
- 数据库连接未关闭
- IO流未关闭
- 监听器未注销
如何避免?
- 对象及时释放
- 使用 try-with-resources
- 清理 ThreadLocal
- 不缓存无用对象
- 使用内存分析工具(MAT、VisualVM、JProfiler)
十六、本章知识关系图(★★★★★)
程序 ↓ 逻辑地址 ↓ TLB(快表) ↓ 页表 ↓ 物理地址 ↓ RAM
如果:
RAM没有:
↓ 缺页中断 ↓ Swap ↓ 加载回来
RAM满:
↓ 页面置换 ↓ FIFO LRU LFU
不停换页:
↓ 抖动
内存耗尽:
↓ OOM
十七、本章重点总结(必背)
地址
| 类型 | 含义 |
|---|---|
| 逻辑地址 | 程序看到的地址(虚拟地址) |
| 物理地址 | RAM中的真实地址 |
分页
- Page(页)
- Frame(页框)
- 页表
- TLB(快表)
口诀:
先查TLB,再查页表。
虚拟内存
作用:
- 扩大可用内存
- 支持大程序运行
- 提高资源利用率
Swap
Linux:
Swap
Windows:
pagefile.sys
作用:
RAM不足时,
临时存放页面。
缺页
流程:
访问 ↓ RAM没有 ↓ 缺页中断 ↓ 磁盘读取 ↓ 继续运行
页面置换
| 算法 | 特点 |
|---|---|
| FIFO | 先进先出 |
| LRU | 最近最少使用(最常见) |
| LFU | 最少访问次数 |
抖动
原因:
大量缺页。
不断换页。
CPU几乎都在等待磁盘。
OOM 与内存泄漏
| 问题 | 含义 |
|---|---|
| OOM | 内存耗尽,无法继续分配内存 |
| 内存泄漏 | 无用对象仍被引用,无法释放,最终可能导致 OOM |
面试/考试高频问题
Q1:逻辑地址和物理地址有什么区别?
答: 逻辑地址(虚拟地址)是程序看到和使用的地址,每个进程拥有独立的逻辑地址空间;物理地址是内存中的真实地址。CPU 通过 MMU、页表和 TLB 将逻辑地址转换为物理地址后访问内存。
Q2:TLB(快表)的作用是什么?
答: TLB 是页表项的高速缓存,CPU 在地址转换时优先查询 TLB,命中即可快速得到物理地址;未命中再访问页表,从而减少地址转换时间,提高内存访问效率。
Q3:什么是虚拟内存?Swap 有什么作用?
答: 虚拟内存利用磁盘空间扩展内存容量,使程序认为拥有更大的可用内存。Swap 是磁盘上的交换空间,当 RAM 不足时,操作系统会把暂时不用的页面换出到 Swap,需要时再换回。
Q4:什么是缺页中断?
答: 当程序访问的页面不在物理内存中时,CPU 会触发缺页中断,由操作系统将页面从磁盘加载到 RAM,并更新页表后继续执行程序。
Q5:什么是抖动(Thrashing)?
答: 抖动是系统频繁发生缺页和页面置换,CPU 大部分时间用于等待磁盘读写而不是执行程序,导致系统性能急剧下降。
Q6:OOM 与内存泄漏有什么关系?
答: 内存泄漏是指无用对象仍被引用,无法被垃圾回收器释放;随着泄漏对象不断累积,可用内存越来越少,最终可能触发 OOM(Out OfMemoryError)。

