一、前言
严格来说,JDB 是 Java 调试工具。但是为了文章好分类,所以我加了“性能工具”几个字。其实才是仅为性能工具呢,这个是不好分类的。仅有一些专门的性能测试和性能监控工具,但是对性能分析、性能调试来说,用的工具几乎都不是专门为性能而设计的。
我们知道 windows 上面有 windebug,Linux 上面有 GDB,在 Java 的层面呢就有 JDB 可以用。
它可以实现对 Java 进程和线程进行各种动态控制操作。命令参数可以在网上查查或者直接 help 一下。由于太长,我就不列在这里了。直接把我的操作列在这里供参考。
二、服务端
在要运行的 Java 程序中的 JAVA_OPTIONS
里加入:
-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y
看需要,suspend 可以为 n,也就是不等待连上来就直接运行程序。这个和 jprofiler 连接中的参数是一个意思。
三、客户端
localhost:~Zee$ jdb-attach 192.168.1.105:8000 -sourcepath
/Users/Zee/Documents/workspace/testProj/src/ #连接远程JVM,带源代码
Setuncaught java.lang.Throwable
Setdeferred uncaught java.lang.Throwable
Initializingjdb ...
>
VMStarted: No frames on the current call stack
main[1]threads #查看线程
Groupsystem:
(java.lang.ref.Reference$ReferenceHandler)0x153 Reference Handler cond.waiting
(java.lang.ref.Finalizer$FinalizerThread)0x152 Finalizer cond. waiting
(java.lang.Thread)0x151 Signal Dispatcherrunning
Groupmain:
(java.lang.Thread)0x1 main running
> stop atZee.MemoryTest.OOM.MEMTestDemo:42 #设置断点
Setbreakpoint Zee.MemoryTest.OOM.MEMTestDemo:42
> #断点命中
Breakpoint hit: "thread=main",Zee.MemoryTest.OOM.MEMTestDemo.main(), line=42 bci=6
42if(args[0].equals("HeapOOM")) {
> thread0x1 #进入线程
main[1]where #查看位置
[1] Zee.MemoryTest.OOM.MEMTestDemo.main(MEMTestDemo.java:42)
Localvariables:
main[1]clear #查看断点
Breakpointsset:
breakpoint Zee.MemoryTest.OOM.MEMTestDemo:42
main[1]cont #继续执行
>where
Nothread specified.
>thread 0x1
>
main[1]suspend #暂停线程
Allthreads suspended.
main[1]where #查看位置
[1] Zee.MemoryTest.OOM.MEMTestDemo.main(MEMTestDemo.java:46)
main[1]tracemethods 0x1 #跟踪方法调用
main[1]
main[1]cont
>
Methodentered:
Methodentered: "thread=main", Zee.MemoryTest.OOM.OOMObject.<init>(),line=3 bci=0
3 public class OOMObject {
main[1]untracemethods 0x1 #取消跟踪
main[1]step #单步调试
>
Stepcompleted: "thread=main", Zee.MemoryTest.OOM.MEMTestDemo.main(),line=46 bci=33
46 list.add(newOOMObject());
main[1]next #执行一行(stepOVERCalls)
>
Stepcompleted: "thread=main", Zee.MemoryTest.OOM.MEMTestDemo.main(),line=45 bci=39
45while (true) {
main[1]locals #查看变量
Methodarguments:
args= instance of java.lang.String[1] (id=439)
Localvariables:
list= instance of java.util.ArrayList(id=441)
main[1]list #查看源码
42 if(args[0].equals("HeapOOM")) {
43 List<OOMObject>list = new ArrayList<OOMObject>();
44
45 while(true) {
46=> list.add(new OOMObject());
47 }
48 }
49
50 if(args[0].equals("StackSOF")) {
51 MEMTestDemo memtestdemo = newMEMTestDemo();●
main[1]dumplist #dump变量
list = {
serialVersionUID: 8683452581122892189
DEFAULT_CAPACITY: 10
EMPTY_ELEMENTDATA: instance ofjava.lang.Object[0] (id=442)
DEFAULTCAPACITY_EMPTY_ELEMENTDATA: instanceof java.lang.Object[0] (id=443)
elementData: instance ofjava.lang.Object[2734845] (id=444)
size: 1964611
MAX_ARRAY_SIZE: 2147483639
java.util.AbstractList.modCount: 1964611
java.util.AbstractCollection.MAX_ARRAY_SIZE: 2147483639
}
其实 JDB 还可以做更多的事情,比如说修改 JVM 中的变量值、监控某个变量的修改记录等等。
四、总结
不用特定死板的界定工具是用来干什么的,要看你想达到的目的是什么。包括它在什么时候用,怎么用,都没有统一的标准,就看适合不适合。