使用java 做開發,大部分的朋友都是利用DIE 來做debug 工作,因為這樣可視化效果好。
但是在真實的工作中,很多使用遇到問題,手頭或者環境是不允許你利用DIE 來對源碼做debug 工作,開發者只能夠利用僅有的jdk 環境和shell 環境,對出現問題的程序進行debug。
本篇文章主要是向大家介紹,如何利用jdk 自帶的 jdb 和jstack 來定位問題。
- jdb
首先jdb 是一款類似gdb 的工具,它可以幫助用戶在運行程序時,直接打對應斷點,然后進行debug 工作。
jdb 和IDE debug 的區別在於,整個debug 過程都是命令行交互的。
用戶使用jdb 進行debug ,有兩種方式
- 直接利用jdb 啟動程序
- 在啟動程序時,加入特殊參數,使得用戶可以通過 jdb attach 進去
我們先來看看直接使用jdb 如何debug 程序。
jdb 運行程序,其實和java 直接運行程序差不多,但是有一些小細節需要大家注意的,就是jdb 不支持-cp 命令,也不支持以下方式添加classpath
-Djava.ext.dirs="/root/monitor_collect/lib"
在使用jdb 運行程序時,如果有以來jar 包,用戶必須要使用 -classpath 參數,將相關的jar 全部填寫進去,例如一個完整的啟動命令
jdb -Dlog4j.configuration="file:/root/monitor_collect/log4j.properties" \ -classpath /root/monitor_collect/lib/args4j-2.33.jar:/root/monitor_collect/lib/sequoiadb-driver-3.0.jar:/root/monitor_collect/lib/slf4j-api-1.7.12.jar:/root/monitor_collect/lib/log4j-1.2.14.jar:/root/monitor_collect/SdbMonitor.jar \ com.sequoiadb.monitor.MonitorAlarm
進入jdb后,會顯示以下信息
Initializing jdb ...
然后用戶就可以開始debug 了,先打一個斷點。
打斷點有兩種方式
- 對某個類的方法打上斷點
- 對某個類的行號打上斷點
如果是對某個類的方法打斷點,命令是
stop in com.sequoiadb.monitor.alarm.util.AlarmObject.analy_transaction
如果是對某個類的行號打斷點,命令是
stop at com.sequoiadb.monitor.alarm.util.AlarmObject:944
注意:類名一定要寫全,包括package 名字也要寫好。
運行的命令為:run
查看當前運行的堆棧信息為:where
執行下一步為:next
打印某個變量為:print
進入該行的函數為:step
從函數中跳出來為:step up
讓程序從斷點中繼續執行為:cont
后面讓我們再來看看,如果利用java 程序啟動后,用戶通過jdb 連接並且調試的。
用戶在執行java 程序時,需要添加以下額外的參數,suspend=y 表示不加載主類,只有用戶通過 jdb connect 后,再加載主類。
-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y
例如一個完整的命令:
java \ -Dlog4j.configuration="file:/root/monitor_collect/log4j.properties" \ -cp /root/monitor_collect/lib/args4j-2.33.jar:/root/monitor_collect/lib/sequoiadb-driver-3.0.jar:/root/monitor_collect/lib/slf4j-log4j12-1.7.25.jar:/root/monitor_collect/lib/slf4j-api-1.7.12.jar:/root/monitor_collect/lib/log4j-1.2.14.jar:/root/monitor_collect/SdbMonitor.jar \ -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y \ com.sequoiadb.monitor.MonitorAlarm
用戶執行該命令后,窗口會掛起,用戶可以在另外一個窗口中,繼續操作(支持遠程連接),如果需要遠程連接,添加hostname 參數即可,如果hostname 參數不填寫,默認為本地
jdb -connect com.sun.jdi.SocketAttach:port=8787,hostname=sdb1
用戶通過 jdb connect 到遠程的jave 程序后,操作方式和直接使用 jdb 啟動程序的方式一致。
- jstack
jstack 是jdk 又一個好用的debug 工具。它和jdb 不同,不是交互式地查看java 程序的相關調用和變量值,而是當用戶的java 程序在運行過程中,突然出現 handle 的情況,而且該情況無法 100% 復現時,用戶可以利用 jstack 工具將java 程序當前的堆棧信息全部打印出來。
這樣用戶可以通過堆棧信息分析程序到底是 handle 在什么地方。
jstack 打印java 程序當前的堆棧信息
jstack -l PID > java.jstack.out
參考博客:
http://blog.csdn.net/arkblue/article/details/39718947
https://www.ibm.com/developerworks/cn/java/joy-jdb/index.html
介紹jave 程序在啟動 jdwp 時,各種參數的含義:http://chainhou.iteye.com/blog/1837059