JDB | Using Java Command Line Debugging Tool
Hello Friends, Welcome to my blog. Today in this blog we will be learning one of the tools provided by Java for the application debugging & inspection known as JDB. It is the command line tool which allows debugging local or remote java application. many developments tools like Eclipse, NetBeans uses JDB internally to debug remote or local the application.
Connect Command
Executing URL which will hit above the breakpoint
You will be notified with information, whenever the breakpoint got hit.
You can notice here, the previously prompt sign was > and now it is replaced with the thread name when the breakpoint got hits. This means now whatever operation you are going to perform that will be on executing on that particular thread and execution flow.
Expression Evaluation
Using the eval function, you can evaluate all the expression inside the context of the thread.
Assigning Values
You can use the set command to assign new values to the variable while runtime.
Execute the current line and move to the next line
This function will execute the current line and move the cursor to next line, if your current line has another function, call, it will go inside the function call. if you want to step over the line you can use next command.
http-nio-8080-exec-1[1] step
Step Up and move to the caller of the function
Continue the execution by release hold thread by the debugger
This command will release the thread holder by the debugger, and continue its remaining execution.
Clear will be used to release the breakpoint
This command will list all the breakpoints marked when executed without parameters. You can pass breakpoint location as a parameter to this command, this will clear the breakpoint being triggered in subsequent flows.
Exit to the debugger console
So that's all for this tutorials friends, I hope you like these tutorials. Please provide your feedback, suggestion & queries in below comment box.
Till then goodbye
Happy Coding & have a wonderful day
- JDB is a java command line debugging tool
- It can debug local as well as the remote java application
- It ships by default with JDK in the bin directory
- You can use this tool if the debugging is enabled on a remote java application server, but the debugging port is not opened over internet/intranet due to security constraints and you have ssh access to the server or the jump host.
- This tool has a rich set of commands which is enough to troubleshoot your problem.
So let's get our hand dirty and connect to already running application on the local server. I have added the Java debugging parameter before running my application. My spring boot application is running on localhost:8080 and debug port is 8001.
Since my application is local, am using the only port to connect. if you have a remote application, you can provide IP: Port from the jump box/bastion server.
Connect Command
[root@localhost anilsable]# jdb -attach 8001 Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... >
Help Command, You will get Complete List of Supportable operations in JDB
> 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-- set default thread suspend [thread id(s)] -- suspend threads (default: all) resume [thread id(s)] -- resume threads (default: all) where [ | all] -- dump a thread's stack wherei [ | 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 -- kill a thread with the given exception object . . . . Startup commands can be placed in either "jdb.ini" or ".jdbrc" in user.home or user.dir
List all threads in the system
> threads Group system: (java.lang.ref.Reference$ReferenceHandler)0x153 Reference Handler cond. waiting (java.lang.ref.Finalizer$FinalizerThread)0x152 Finalizer cond. waiting (java.lang.Thread)0x151 Signal Dispatcher running Group main: (java.lang.Thread)0x1236 ContainerBackgroundProcessor[StandardEngine[Tomcat]] sleeping (org.springframework.boot.web.embedded.tomcat.TomcatWebServer$1)0x1241 container-0 sleeping (org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller)0x13e7 NioBlockingSelector.BlockPoller-1 running (org.apache.tomcat.util.threads.TaskThread)0x13f1 http-nio-8080-exec-1 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13f8 http-nio-8080-exec-2 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13f7 http-nio-8080-exec-3 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13f6 http-nio-8080-exec-4 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13f5 http-nio-8080-exec-5 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13f4 http-nio-8080-exec-6 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13f3 http-nio-8080-exec-7 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13f2 http-nio-8080-exec-8 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13fb http-nio-8080-exec-9 cond. waiting (org.apache.tomcat.util.threads.TaskThread)0x13fc http-nio-8080-exec-10 cond. waiting (java.lang.Thread)0x13fd http-nio-8080-ClientPoller-0 running (java.lang.Thread)0x13ff http-nio-8080-Acceptor-0 running (java.lang.Thread)0x1402 http-nio-8080-AsyncTimeout sleeping (java.lang.Thread)0x141b DestroyJavaVM running >
Adding Breakpoint to the method
> stop at org.javahotfix.threading.controller.SomeController:21 Set breakpoint org.javahotfix.threading.controller.SomeController:21 >
Executing URL which will hit above the breakpoint
curl -G http://localhost:8080/somecontroller?operationCode=A
You will be notified with information, whenever the breakpoint got hit.
You can notice here, the previously prompt sign was > and now it is replaced with the thread name when the breakpoint got hits. This means now whatever operation you are going to perform that will be on executing on that particular thread and execution flow.
> Breakpoint hit: "thread=http-nio-8080-exec-1", org.javahotfix.threading.controller.SomeController.performOperation(), line=21 bci=0 http-nio-8080-exec-1[1]
Printing Objects, Local Variables
You can print the instance variable, objects, local objects, local variable using dump and print command. You can print all local variable using locals command.
You can print the instance variable, objects, local objects, local variable using dump and print command. You can print all local variable using locals command.
http-nio-8080-exec-1[1] dump requestCode requestCode = "A"
http-nio-8080-exec-1[1] http-nio-8080-exec-1[1] print requestCode requestCode = "A" http-nio-8080-exec-1[1] http-nio-8080-exec-1[1] locals Method arguments: requestCode = "A" Local variables: http-nio-8080-exec-1[1]
Know the location where are you currently
This command will print the stack trace of the current thread. using this you can identify where are you right now.
This command will print the stack trace of the current thread. using this you can identify where are you right now.
http-nio-8080-exec-1[1] where [1] org.javahotfix.threading.controller.SomeController.performOperation (SomeController.java:21) [2] sun.reflect.NativeMethodAccessorImpl.invoke0 (native method) [3] sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) [4] sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) [5] java.lang.reflect.Method.invoke (Method.java:498) [6] org.springframework.web.method.support.InvocableHandlerMethod.doInvoke (InvocableHandlerMethod.java:209) [7] org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest (InvocableHandlerMethod.java:136) [8] org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle (ServletInvocableHandlerMethod.java:102) [9] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod (RequestMappingHandlerAdapter.java:891) [10] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal (RequestMappingHandlerAdapter.java:797) [11] org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle (AbstractHandlerMethodAdapter.java:87) [47] org.apache.coyote.http11.Http11Processor.service (Http11Processor.java:800) [48] org.apache.coyote.AbstractProcessorLight.process (AbstractProcessorLight.java:66) [49] org.apache.coyote.AbstractProtocol$ConnectionHandler.process (AbstractProtocol.java:806) [50] org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun (NioEndpoint.java:1,498) [51] org.apache.tomcat.util.net.SocketProcessorBase.run (SocketProcessorBase.java:49) [52] java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1,142) [53] java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:617) [54] org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run (TaskThread.java:61) [55] java.lang.Thread.run (Thread.java:745)
Expression Evaluation
Using the eval function, you can evaluate all the expression inside the context of the thread.
http-nio-8080-exec-1[1] eval requestCode == "A" requestCode == "A" = false http-nio-8080-exec-1[1] eval requestCode.equals("A"); requestCode.equals("A"); = true http-nio-8080-exec-1[1]
Assigning Values
You can use the set command to assign new values to the variable while runtime.
http-nio-8080-exec-1[1] dump requestCode requestCode = "A" http-nio-8080-exec-1[1] set requestCode = "B" requestCode = "B" = "B" http-nio-8080-exec-1[1] dump requestCode requestCode = "B" http-nio-8080-exec-1[1]
Execute the current line and move to the next line
This function will execute the current line and move the cursor to next line, if your current line has another function, call, it will go inside the function call. if you want to step over the line you can use next command.
http-nio-8080-exec-1[1] step
Step completed: "thread=http-nio-8080-exec-1", org.javahotfix.threading.controller.SomeController.performOperation(), line=24 bci=2 http-nio-8080-exec-1[1] http-nio-8080-exec-1[1] locals Method arguments: requestCode = "B" Local variables: timeDuration = 0 http-nio-8080-exec-1[1] http-nio-8080-exec-1[1] step > Step completed: "thread=http-nio-8080-exec-1", org.javahotfix.threading.controller.SomeController.getSomeServiceBean(), line=54 bci=0 http-nio-8080-exec-1[1] locals No local variables http-nio-8080-exec-1[1]
Step Up and move to the caller of the function
This command will step up the execution to 1 level up so as it will reach to the caller of the function.
http-nio-8080-exec-1[1] step up > Step completed: "thread=http-nio-8080-exec-1", org.javahotfix.threading.controller.SomeController.performOperation(), line=30 bci=158 http-nio-8080-exec-1[1]
Continue the execution by release hold thread by the debugger
This command will release the thread holder by the debugger, and continue its remaining execution.
http-nio-8080-exec-1[1] cont >
Clear will be used to release the breakpoint
This command will list all the breakpoints marked when executed without parameters. You can pass breakpoint location as a parameter to this command, this will clear the breakpoint being triggered in subsequent flows.
> clear Breakpoints set: breakpoint org.javahotfix.threading.controller.SomeController:21 > clear org.javahotfix.threading.controller.SomeController:21 Removed: breakpoint org.javahotfix.threading.controller.SomeController:21 >
Exit to the debugger console
This command will exit the debugger console, and detach the debugger to the remote application.
> exit [root@localhost anilsable]#
So that's all for this tutorials friends, I hope you like these tutorials. Please provide your feedback, suggestion & queries in below comment box.
Till then goodbye
Happy Coding & have a wonderful day
Hello, i read you post and successfully debugged my application on command line.
ReplyDeleteThank you for this post. It's awesome!
Hello, I've read this post, and solved my problem. Thank you very much.
ReplyDeleteDid you have some detail bog to show how to load source java file when run 'list' in jdb?
You need to have source jar on your classpath. that will resolve your problem.
Delete