跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
内存泄漏排查
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{Note|本条目适用于Java开发者及需要理解JVM内存管理的程序员。内容涵盖基础概念到高级排查技巧。}} = 内存泄漏排查 = '''内存泄漏(Memory Leak)'''是指程序中已动态分配的堆内存由于某种原因未能被正确释放,导致系统内存被无效占用,最终可能引发内存溢出(OOM)或性能下降。在JVM中,内存泄漏通常表现为对象不再被使用但仍被GC Roots引用,无法被垃圾回收器回收。 == 核心原理 == 内存泄漏的本质是'''可达性分析失效'''。根据JVM规范,对象被判定为可回收需满足: <math>Object_{unreachable} \iff \nexists\ Path\ from\ GC\ Roots\ to\ Object</math> 典型泄漏场景包括: * 静态集合长期持有对象引用 * 未关闭的资源(如数据库连接、文件流) * 监听器未注销 * 线程池未清理 <mermaid> graph LR A[GC Roots] --> B[静态变量] A --> C[活动线程栈帧] A --> D[JNI引用] B --> E[泄漏对象] C --> F[泄漏对象] </mermaid> == 排查工具 == {| class="wikitable" |+ 常用JVM内存分析工具 ! 工具 !! 作用 !! 适用场景 |- | jmap || 生成堆转储快照 || 离线分析 |- | jvisualvm || 可视化内存监控 || 实时观察 |- | Eclipse MAT || 内存分析 || 深度诊断 |- | Arthas || 在线诊断 || 生产环境 |} === 基础排查步骤 === 1. 使用<code>jps</code>获取目标进程ID 2. 生成堆转储文件: <syntaxhighlight lang="bash"> jmap -dump:format=b,file=heap.hprof [pid] </syntaxhighlight> 3. 使用MAT分析<code>.hprof</code>文件 == 代码示例 == 典型静态集合泄漏案例: <syntaxhighlight lang="java"> public class LeakExample { private static List<byte[]> cache = new ArrayList<>(); public void addToCache() { // 每次添加1MB数据且永不释放 cache.add(new byte[1024 * 1024]); } } </syntaxhighlight> '''输出表现''': <pre> java.lang.OutOfMemoryError: Java heap space at LeakExample.addToCache(LeakExample.java:6) </pre> == 高级分析技巧 == === 支配树分析 === 在Eclipse MAT中使用Dominator Tree视图: 1. 查找占用内存最大的对象 2. 检查其引用链 3. 定位非必要引用 === 引用链追踪 === 关键引用类型: * '''强引用''':直接导致泄漏 * '''软/弱引用''':通常合规 * '''虚引用''':不影响回收 <mermaid> pie title 内存泄漏引用类型占比 "强引用" : 78 "软引用" : 12 "弱引用" : 8 "虚引用" : 2 </mermaid> == 生产环境案例 == '''案例背景''':某电商系统每日凌晨出现OOM,重启后恢复。 '''排查过程''': 1. 添加JVM参数收集OOM时的堆转储: <syntaxhighlight lang="bash"> -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp </syntaxhighlight> 2. MAT分析显示<code>OrderProcessor</code>类中的<code>ConcurrentHashMap</code>持续增长 3. 最终发现是未清理已完成订单的引用 '''修复方案''': <syntaxhighlight lang="java"> // 原错误代码 completedOrders.put(orderId, order); // 修正后 completedOrders.remove(orderId); // 处理完成后立即移除 </syntaxhighlight> == 预防措施 == * 定期进行代码审查,重点关注: ** 集合使用情况 ** 资源关闭操作 ** 监听器注销 * 使用工具自动化检测: ** FindBugs/SpotBugs静态分析 ** JaCoCo覆盖率检查资源释放路径 {{Warning|生产环境建议设置内存使用阈值告警,如通过JMX监控<code>MemoryUsage.getUsed()</code>}} == 参见 == * [[垃圾回收机制]] * [[JVM内存模型]] * [[性能调优基础]] [[Category:计算机科学]] [[Category:面试技巧]] [[Category:JVM相关]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
该页面使用的模板:
模板:Mbox
(
编辑
)
模板:Note
(
编辑
)
模板:Warning
(
编辑
)
模块:Arguments
(
编辑
)
模块:Message box
(
编辑
)
模块:Message box/ambox.css
(
编辑
)
模块:Message box/configuration
(
编辑
)
模块:Yesno
(
编辑
)