当前位置: 首页 > 工具软件 > mojito-debug > 使用案例 >

Debug Java Application

臧曜瑞
2023-12-01

Debugger Java Application

总结一些关于Java Debug的经验,一般来说Java开发者调试Java程序是通过IDE,比如Eclipse,以Debug方式启动之后,可以在任意行加入断点,待程序运行到这一行的时候会被断点阻塞。众所周知Java程序是以class文件中的字节码方式来运行,JVM负责解读字节码转换成JVM内部指令,如果查阅JVM Specification的文档,即使是手工都能翻译出每个字节码的含义,就像古老的汇编指令一样,0~255每个byte代表一个指令,不同的指令又需要不同数量的参数,由此来依次读入恰当数量的字节码,翻译成真正的机器指令运行。

 

其实,除了程序员编写的程序对应的字节码之外,class文件中还包含有大量的调试信息,这些信息是用于记录每一个JVM指令对应着怎样的代码,每个变量的声明位置,以及每个函数调用、数值计算对应的源代码中的行号……所有这些调试信息都可以被JVM用于运行时提供反馈,对断点和调试操作的响应。

 

所以,如果没有特别的编译指令来处理掉这些调试信息,也没有混淆器来混乱这些调试信息,即使只得到了class文件,也可以对其反编译或者进行运行时调试。动态调试可以使用开发者喜好的任何EditorIDE或者JDK自带的工具。

 

JVM之所以会接受动态调试发出的一系列指令,是因为JVM自身就有一套完整的Debug框架,每当Java程序在JVM中运行,只要打开了调试开关,JVM调试框架就可以正确即时的反馈调试命令。(完全不依赖于源代码)

 

JVM Debug框架规范:http://download.oracle.com/javase/1.3/docs/guide/jpda/index.html

JVM主要可以提供了三种协议来支持Runtime调试:

l   JVMDI: Java Virtual Machine Debug Interface

l   JDWP: Java Debug Wire Protocol

l   JDI: Java Debug Interface

 

如果要打开JVMDebug开关,需要加入某些启动参数,一个典型的例子是:

-Xdebug -Xrunjdwp:transport=dt_socket, server=y, address=8000

官方解释是:Listen for a socket connection on port 8000. Suspend this VM before main class loads (suspend=y by default). Once the debugger application connects, it can send a JDWP command to resume the VM.

 

更多参数说明见官方文档:http://download.oracle.com/javase/1.3/docs/guide/jpda/conninv.html

 

至于调试所用的工具,我试验了EclipseIntelliJ IDE 以及JDK自带的Debugger Tool: JDB

当使用Eclipse或者IntelliJ IDE这种大型的IDE时,不外乎在Debug Configuration中添加新的Remote Java Application,设置hostport便可开始debug,用户可以在界面上关联ApplicationSource code,以便断点更好的反馈到Source code上。

 

当使用JDB的时候,主要是通过命令行交互的方式,显示起来没有那么给力,但是作为了解原理的练习方式是非常值得推荐的。进入JDK_HOME/bin目录下,输入jdb即可运行,一般来说提供hostport就可以连接上Local或者Remote的开启了Debug开关的JVM,例如:

jdb –attach 192.168.1.101:8000

 

有时候笔者碰到一些Java程序并无Main方法,是通过JNI本地调用驱动起来的,这个时候JDBattach参数似乎连接不上,于是采用了另外一种建立Connection的方式:

jdb -connect com.sun.jdi.SocketAttach:hostname=192.168.1.101,port=8000

 

这是因为JDB连接JVM主要通过两种方式:shared memorysockets,暂时没有研究者两种方式的细节,留作将来再谈起这个话题的时候分享吧!见谅~~:)

 类似资料:

相关阅读

相关文章

相关问答