Java里提供了非常强大、易用的调试工具和调试接口,可以方便的用来以调试的方式进行java应用,并且可以很容易的连接上这些调试。
这里简单介绍一下如何在指定的端口上以调试的方式启动一个程序,并且在另外一个命令中连接上这个程序进行调试。
整个Java平台调试框架(JavaTM Platform Debugger Architecture (JPDA))由三个部分组件:
- The Java Virtual Machine Tools Interface (JVM TI) defines the services a VM must provide for debugging (JVM TI is a replacement for the Java Virtual Machine Debug Interface (JVMDI) which has been removed). http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/architecture.html#jvmti
- The Java Debug Wire Protocol (JDWP) defines the format of information and requests transferred between the process being debugged and the debugger front end, which implements the Java Debug Interface (JDI). http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/architecture.html#jdwp
- The Java Debug Interface (JDI) defines information and requests at the user code level. http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/architecture.html#jdi
不过我不要是关心这个,我只介绍一下怎么使用Java调试工具:JDB (Java Debugger).
首先需要指定程序以调试的方式启动,命令行如下:
javaw.exe -Xdebug -agentlib:jdwp=transport=dt_socket,server=y,suspend=y|n,address=[host:]<port_number> -Dfile.encoding=<encoding> -classpath <classpath> <main_class>
上面的意思是说:
在端口<port_number>上监听socket连接,并且在main类加载之前挂起虚拟机。一旦调试程序连接上了,再发出一个JDWP的命令唤醒虚拟机
更多的命令行指导,请参考:http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/conninv.html
运行上面的命令,如果成功,会在console上打印一条类似如下消息:
Listening for transport dt_socket at address: 3556
表明程序启动成功。
下面就可以用JDB去尝试连接调试了,命令行为:
jdb -sourcepath <source_dir1:source_dir2:...> -connect com.sun.jdi.SocketAttach:hostname=<host>,port=<port_number>
更多的,请参考:http://docs.oracle.com/javase/1.3/docs/tooldocs/solaris/jdb.html。
如果启动成功,则可以看到类似下面的消息:
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
>
VM Started: No frames on the current call stack
main[1]
程序现在在主线程等待进一步的指示命令。
要查看帮助可以使用命令:help。 例如:
main[1] help
** command list **
connectors -- list available connectors and transports in this VM
run [class [args]] -- start execution of application's main class
threads [threadgroup] -- list threads
thread <thread id> -- set default thread
suspend [thread id(s)] -- suspend threads (default: all)
resume [thread id(s)] -- resume threads (default: all)
where [<thread id> | all] -- dump a thread's stack
wherei [<thread id> | all]-- dump a thread's stack, with pc info
up [n frames] -- move up a thread's stack
down [n frames] -- move down a thread's stack
kill <thread id> <expr> -- kill a thread with the given exception object
interrupt <thread id> -- interrupt a thread
print <expr> -- print value of expression
dump <expr> -- print all object information
eval <expr> -- evaluate expression (same as print)
set <lvalue> = <expr> -- assign new value to field/variable/array element
locals -- print all local variables in current stack frame
classes -- list currently known classes
class <class id> -- show details of named class
methods <class id> -- list a class's methods
fields <class id> -- list a class's fields
threadgroups -- list threadgroups
threadgroup <name> -- set current threadgroup
stop in <class id>.<method>[(argument_type,...)]
-- set a breakpoint in a method
stop at <class id>:<line> -- set a breakpoint at a line
clear <class id>.<method>[(argument_type,...)]
-- clear a breakpoint in a method
clear <class id>:<line> -- clear a breakpoint at a line
clear -- list breakpoints
catch [uncaught|caught|all] <class id>|<class pattern>
-- break when specified exception occurs
ignore [uncaught|caught|all] <class id>|<class pattern>
-- cancel 'catch' for the specified exception
watch [access|all] <class id>.<field name>
-- watch access/modifications to a field
unwatch [access|all] <class id>.<field name>
-- discontinue watching access/modifications to a field
trace [go] methods [thread]
-- trace method entries and exits.
-- All threads are suspended unless 'go' is specified
trace [go] method exit | exits [thread]
-- trace the current method's exit, or all methods' exits
-- All threads are suspended unless 'go' is specified
untrace [methods] -- stop tracing method entrys and/or exits
step -- execute current line
step up -- execute until the current method returns to its caller
stepi -- execute current instruction
next -- step one line (step OVER calls)
cont -- continue execution from breakpoint
list [line number|method] -- print source code
use (or sourcepath) [source file path]
-- display or change the source path
exclude [<class pattern>, ... | "none"]
-- do not report step or method events for specified classes
classpath -- print classpath info from target VM
monitor <command> -- execute command each time the program stops
monitor -- list monitors
unmonitor <monitor#> -- delete a monitor
read <filename> -- read and execute a command file
lock <expr> -- print lock info for an object
threadlocks [thread id] -- print lock info for a thread
pop -- pop the stack through and including the current frame
reenter -- same as pop, but current frame is reentered
redefine <class id> <class file name>
-- redefine the code for a class
disablegc <expr> -- prevent garbage collection of an object
enablegc <expr> -- permit garbage collection of an object
!! -- repeat last command
<n> <command> -- repeat command n times
# <command> -- discard (no-op)
help (or ?) -- list commands
version -- print version information
exit (or quit) -- exit debugger
<class id>: a full class name with package qualifiers
<class pattern>: a class name with a leading or trailing wildcard ('*')
<thread id>: thread number as reported in the 'threads' command
<expr>: a Java(tm) Programming Language expression.
Most common syntax is supported.
Startup commands can be placed in either "jdb.ini" or ".jdbrc"
in user.home or user.dir
main[1]
例如输入:step,程序运行到下一步。