如何判断对象是否被GC标记为垃圾?有哪些工具可可视化特定对象GC状态?
判断对象是否被GC标记为垃圾的常见途径
- 利用引用特性实现简易判断:将目标对象用
WeakReference或者PhantomReference包裹,绑定到自定义的ReferenceQueue。当GC完成标记后,如果目标对象被判定为可回收,对应的引用实例会被加入引用队列,只要监听队列是否有对应引用入队,就能判断对象是否被GC标记为垃圾。注意这种方式必须等GC触发后才能得到结果,无法实时查询当前标记状态。 - 通过堆快照导出分析:执行
jmap -dump:format=b,file=heap.hprof <进程PID>命令导出当前JVM进程的堆快照,后续分析快照时,如果对象没有和GC Roots之间的可达引用链,就说明已经被GC标记为待回收垃圾。 - 基于JVMTI自定义Agent实现:开发自定义JVM Agent,注册GC事件回调,在GC的标记阶段直接获取对象的标记状态,这种方式可以做到相对实时的观测,但需要修改JVM启动参数加载Agent,有一定开发成本,且会对进程性能产生明显影响,仅适合调试场景使用。
可查看对象GC状态的可视化工具
- JDK自带VisualVM:JDK8及以前版本默认内置,更高版本可单独下载。安装堆分析插件后导入堆快照,搜索目标对象即可直接查看其可达性状态,无额外成本,适合日常调试使用。
- Eclipse MAT:专业开源堆内存分析工具,加载堆快照后支持通过OQL语句检索指定对象,会直接标识对象是否为不可达垃圾,还可以一键查看对象的完整引用链,分析内存泄漏的效率远高于基础工具。
- JProfiler/YourKit等商业性能分析工具:支持运行时实时查看对象的GC状态,不需要手动导出堆快照,还可以追踪对象从创建到被回收的完整生命周期,可视化能力更强,适合复杂线上问题定位,但需要付费授权。
注意:所有需要观测GC标记状态的操作,要么会触发STW暂停,要么会显著增加JVM运行开销,除非必要不要在生产环境高频执行这类操作。
内容的提问来源于stack exchange,提问作者Koko
相关产品推荐
相关产品推荐

