调试目标程序:Main.java,为了方便调试,运行以下命令:
C:\Users\Eugene\Desktop\studio\java>javac -g -d bin src\Main.java
最终目录结构如下:
C:\Users\Eugene\Desktop\studio\java>tree /F
Folder PATH listing
Volume serial number is 00000200 7E94:96E4
C:.
├─bin
│ Main.class
│ Test.class
│
└─src
Main.java
C:\Users\Eugene\Desktop\studio\java>java -agentlib:jdwp=transport=dt_socket,serv
er=y,address=8000,suspend=y -cp bin\ Main
Listening for transport dt_socket at address: 8000 //这行内容是虚拟机启动后输出
-agentlib:jdwp=transport=dt_socket 以TCP协议作为连接调试端和被调试断的媒介;
server=y,address=8000 指明java虚拟机以被调试端方式启动,并在8000端口上侦听;
suspend=y java虚拟机启动后并不马上运行程序,而是将它挂起,直到调试器连上。
物理机上运行:
C:\Users\Eugene>jdb -connect com.sun.jdi.SocketAttach:hostname=192.168.80.132,port=8000
设置未捕获的java.lang.Throwable
设置延迟的未捕获的java.lang.Throwable
正在初始化jdb...
>
VM 已启动: 当前调用堆栈上没有帧
main[1] stop at Main:32
正在延迟断点Main:32。
将在加载类后设置。
main[1] use C:\Users\Eugene\Desktop\studio\java\src\main.java
main[1] run
如果目标程序已经在运行中,并且并没有以"-agentlib:jdwp=transport=dt_socket"的形式启动,这时需要以Attach的形式调试程序。(示例中的命令适用于本地调试)
首先模拟正在运行的程序,该进程的PID=1824:
C:\Users\Eugene\Desktop\studio\java>java -cp bin Main
Enter a Char:
启动jsadebugd daemon,并attach到目标程序:
C:\Users\Eugene>jsadebugd 1824
Attaching to process ID 1824 and starting RMI services, please wait...
Debugger attached and RMI services started.
启动jdb连接jsadebugd:
C:\Users\Eugene>jdb -connect sun.jvm.hotspot.jdi.SADebugServerAttachingConnector
:debugServerName=localhost
Initializing jdb ...
> use C:\Users\Eugene\Desktop\studio\java\src\main.java
Command 'stop' is not supported on a read-only VM connection
> where all
Attach Listener:
Signal Dispatcher:
Finalizer:
[1] java.lang.Object.wait (native method)
[2] java.lang.ref.ReferenceQueue.remove (null)
[3] java.lang.ref.ReferenceQueue.remove (null)
[4] java.lang.ref.Finalizer$FinalizerThread.run (null)
Reference Handler:
[1] java.lang.Object.wait (native method)
[2] java.lang.Object.wait (Object.java:503)
[3] java.lang.ref.Reference$ReferenceHandler.run (null)
main:
[1] java.io.FileInputStream.readBytes (native method)
[2] java.io.FileInputStream.read (null)
[3] java.io.BufferedInputStream.fill (null)
[4] java.io.BufferedInputStream.read (null)
[5] Main.main (Main.java:34)
> quit
3.启动HSDB,观察运行中的java程序:
C:\Users\Eugene>java -cp "%JAVA_HOME%\lib\sa-jdi.jar" sun.jvm.hotspot.HSDB
HSDB启动后点击:File-Attach to Hotspot process",并在弹出对话框中输入目标进程的PID。
附注:有部分JDK版本在attach目标进程时会失败,并报错:找不到sawindbg.dll。这时需要将%JAVA_HOME%\jre\bin\sawindbg.dll拷贝到与jdk同一目录的jre\bin下。
参考:
Java Platform Debugger ArchitectureStructure Overview
JPDA Connection and Invocation Details