如何无需重启应用实现Java应用在线调试?
无需重启调试运行中Java应用的方案
一、用jdb连接运行中的进程(无需提前配置远程调试参数)
从Java 5开始,HotSpot虚拟机支持动态加载调试代理,不用重启进程就能开启调试端口,步骤如下:
- 找到目标Java进程的PID,执行:
或者用jpsps aux | grep java(Linux)/任务管理器(Windows)查看。 - 动态加载JDWP代理到目标进程,执行:
(如果需要远程连接,把jcmd <PID> VM.agentlib jdwp=transport=dt_socket,server=y,address=localhost:8000,suspend=nlocalhost改成0.0.0.0,但生产环境要做好端口安全限制) - 用jdb连接调试端口:
连接成功后就能像常规调试一样设置断点、查看变量、跟踪代码执行了。jdb -attach localhost:8000
注意:操作需要和目标进程相同的用户权限,且仅支持HotSpot系JVM(OpenJDK、Oracle JDK等主流版本都符合)。
二、无调试场景下的在线排查方案
如果环境不允许开启调试端口,或者想更高效定位问题,这些工具/方法可以直接用:
1. 线程栈分析(jstack)
导出目标进程的线程栈,快速定位线程阻塞、死锁或异常执行路径:
jstack <PID> > thread_stack.log
查看日志里的线程状态,比如BLOCKED状态的线程,找到它等待的锁,或者异常线程的调用栈,定位到具体方法。
2. 堆内存分析(jmap)
导出堆转储文件,分析内存泄漏、对象异常堆积的情况:
jmap -dump:format=b,file=heap_dump.hprof <PID>
可以用jhat heap_dump.hprof启动本地分析服务,或者用VisualVM、MAT(Memory Analyzer Tool)打开堆文件,查看对象实例数量、引用链,找到内存问题根源。
3. JVM性能监控(jstat)
实时监控GC情况、内存区域使用率,判断是否是GC停顿导致功能异常:
jstat -gcutil <PID> 1000 10
(每1秒输出一次,共10次)查看E(Eden区使用率)、O(老年代使用率)、YGC(年轻代GC次数)、FGC(Full GC次数),如果Full GC频繁触发,可能是内存不足或内存泄漏。
4. 动态调整日志(无需重启)
如果异常功能没有日志输出,可以动态调高指定类的日志级别:
- 若用Logback,可通过JMX控制台修改日志级别;
- 用Arthas的
logger命令直接修改:
这样就能输出该类的调试日志,不用重启应用。logger -n com.yourpackage.YourClass -l DEBUG
5. Arthas诊断工具(强力推荐)
阿里开源的Java诊断工具,功能覆盖几乎所有在线排查场景,无需修改应用代码或重启:
- 查看线程状态:
thread,直接找出阻塞/死锁线程; - 跟踪方法调用:
trace com.yourpackage.YourClass yourMethod,查看方法的执行耗时、调用链; - 监控方法入参出参:
watch com.yourpackage.YourClass yourMethod "{params,returnObj}" -x 2,实时查看方法的参数和返回值; - 查看方法调用栈:
stack com.yourpackage.YourClass yourMethod; - 热替换代码:
redefine /path/to/modified/YourClass.class(生产环境谨慎使用)。
6. VisualVM图形化工具
JDK自带的图形化监控工具,直接连接本地/远程Java进程,整合了jstack、jmap、jstat的功能,还能查看方法执行时间、内存快照,操作直观,适合快速排查问题。
内容的提问来源于stack exchange,提问作者WesAtWork
相关产品推荐
相关产品推荐

