visualvm不追踪单个变量变动,而是通过堆内存曲线、对象直方图、支配树、oql查询及visualgc插件,宏观呈现对象创建、引用、晋升与回收的全生命周期轨迹。

VisualVM 本身不直接追踪“堆内存变量”的变动轨迹——它不记录某个具体变量(如 String name)的赋值、修改或生命周期,而是监控堆内存中**对象实例的整体分布、数量、大小及回收行为**。所谓“变量变动轨迹”,在 JVM 层面实际体现为:对象创建 → 引用关系变化 → GC 回收 → 内存占用涨落。VisualVM 通过实时图表和快照,帮你还原这一宏观轨迹。
看懂堆内存动态变化曲线
在“监视”选项卡中,点击“内存(Heap)”图表区域,你会看到一条随时间波动的蓝色曲线:
- 曲线上升:应用持续创建新对象(如循环 new User()、缓存未清理、集合不断 add)
- 周期性下挫:GC(尤其是 Minor GC)成功回收新生代对象,表现为陡降
- 缓慢爬升后平台化:老年代持续增长,可能预示对象晋升过多或内存泄漏
- 突兀断崖式下跌:手动触发了“执行 GC”(右上角按钮),或发生 Full GC
这不是变量级日志,但它是所有堆内对象集体行为的忠实投影——只要某变量指向的对象未被回收,它就贡献着曲线高度。
定位高内存消耗对象类型
切换到“抽样器 → 内存”页,点击“启动”后等待数秒,再点“快照”:
- 表格按“实例数”或“所占字节”排序,一眼看出哪类对象最多(如
byte[]、HashMap$Node、自定义的OrderDetail) - 双击某行,可查看该类所有实例的浅堆(shallow heap)与保留集(retained heap)
- 若发现某业务类实例数持续增加且不下降,就说明其关联的“变量引用链”长期存活——这正是泄漏线索
用堆转储(Heap Dump)回溯对象来源
当曲线异常上涨时,立即点击“堆 Dump”生成快照(.hprof 文件):
- 在新打开的堆转储视图中,使用“类”筛选器输入关键类名(如
CacheEntry) - 右键 → “显示对象列表”,再对任一实例右键 → “引用的传入对象”(Incoming References)
- 逐层向上展开引用链,最终会抵达持有该对象的静态字段、线程局部变量或集合容器——这就是“变量所在位置”
- 配合源码,就能判断是缓存未过期、监听器未注销,还是 ThreadLocal 泄漏
搭配 VisualGC 插件看清分代细节
安装 VisualGC 插件后,界面左侧出现实时分代视图:
- Eden 区快速填满又清空:说明对象朝生暮死,符合正常短生命周期逻辑
- S0/S1 区反复交换但对象不减少:部分对象熬过多次 Minor GC,频繁晋升至 Old
- Old 区单向上涨,GC 后几乎不回落:典型内存泄漏信号,需结合堆转储确认根因
- Metaspace 持续增长:可能是动态类生成(如 CGLIB、Groovy 脚本)未卸载
这些区域的填充节奏,就是堆内存中对象“诞生—流转—消亡”轨迹最直观的图形化表达。










