早期搞过java的人应该都接触过jdb,那时候写个java程序用的都是记事本,调试用得是jdb,现在有了eclipse,已经很少人会用记事本和jdb来开发java程序了,从我接触到的搞Java开发的人,说起框架啥的都是很清楚,但的确很少有人熟悉JDB,更别说java是如何进行调试的了。
现在负责系统的运维,大多使用的都是weblogic,一出问题就头大,开发商写的程序太烂,日志也不全,自己写了一个GUI程序来显示运行时的线程,变量信息,工作量还是挺大的,最近没忙那个程序,回想起了这个JDB,这里记下来常用的操作,生产系统使用jdb来调试程序还是会有很多好处的,比如说线程卡了,是卡在什么地方,参数是什么。
首先要在java程序启动的时候加上参数-Xrunjdwp:transport=dt_socket,address=localhost:9191,server=y,suspend=n -Dcom.sun.management.jmxremote.port=9001 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
然后运行jdb -connect com.sun.jdi.SocketAttach:"port=9191,hostname=localhost"连接上
为什么这个地方要加上localhost:9191,呢,不直接写address=9191呢,这个是防止外部的地址连接调试端口,只能在本地连接9191端口,这样在生产系统上开启的话风险要小很多
./jdb -connect可以显示所有的选项
后面是具体的命令事例
//查询出当前所有的线程
> threads
组 system:
(java.lang.Thread)0x405 RMI TCP Accept-0 正在运行
组 main:
(java.lang.Thread)0x408 Main Thread 正在休眠
>
//选定0x408的线程
> thread 0x408
Main Thread[1]
//暂停当前线程
Main Thread[1] suspend 0x408
Main Thread[1]
//显示线程堆栈
Main Thread[1] where
[1] java.lang.Thread.sleep (本机方法)
[2] TestCase.testOutMemory (TestCase.java:33)
[3] TestCase.main (TestCase.java:99)
Main Thread[1]
//通过向上命令转移到关注的方法上
Main Thread[1] up
Main Thread[2] where
[2] TestCase.testOutMemory (TestCase.java:33)
[3] TestCase.main (TestCase.java:99)
Main Thread[2]
//显示局部变量
Main Thread[2] locals
方法参数:
局部变量:
i = 1
j = 164
Main Thread[2]
//显示全局变量
Main Thread[2] dump this
this = {
data: instance of java.util.ArrayList(id=1034)
}
//Dump支持的参数如下:
"false" ...
"new" ...
"null" ...
"super" ...
"this" ...
"true" ...
<INTEGER_LITERAL> ...
<FLOATING_POINT_LITERAL> ...
<CHARACTER_LITERAL> ...
<STRING_LITERAL> ...
<IDENTIFIER> ...
"(" ...
"!" ...
"~" ...
"++" ...
"--" ...
"+" ...
"-" ...
//Dump类下面的对象
Main Thread[2] dump this.data
this.data = {
serialVersionUID: 8683452581122892189
elementData: instance of java.lang.Object[88256] (id=1035)
size: 63796
java.util.AbstractList.modCount: 63796
}
Main ThreaMain Thread[2] dump this.data.elementData
//设置断点
Main Thread[2] stop at TestCase:33
设置 断点 TestCase:33
Main Thread[2] resume
所有线程已恢复。
>
断点命中: "thread=Main Thread", TestCase.testOutMemory(), line=33 bci=35
Main Thread[1] resume
所有线程已恢复。
>