I don't know why I never found myself having to use a debugger to step through my program and see what was going on, probably because I'm used to using interpreted languages such as PHP where it becomes very easy to add debugging code (print_r) and see changes live.
However with this new Java project I feel like I must learn the correct ways of debugging.
So this program, that I didn't write, runs on Tomcat and uses basic JSPs. The issue is that when I try to access a specific JSP page it throws an exception and gives me the stacktrace of what happened:
org.apache.jasper.JasperException: java.lang.NullPointerException
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:503)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:363)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:306)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.sgrp.singer.filters.SingerLoginFilter.doFilter(SingerLoginFilter.java:128)
How would I step through my program using a tool such as JDB? I can't really step through a specific class because I need to mimic what my JSP is doing... I would like to do this through the command-line, without using an IDE.
First, java has to be started with certain parameters to plugin a debugger:
-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
are the parameters used for our purpose. Afterwards, you use your IDE and connect the debugger remotely. You set a breakpoint to a piece of code (please make sure that the local files and the remote program are exactly the same revision) and generate the error. You can set breakpoints to uncaught exceptions as well.
As a hint: You can alter your referenced error-catching-JSP (error.jsp for us) to display not only the stacktrace of the caught exception (ex.getStracktrace), but also the causing stacktrace (ex.getCause().getStacktrace()). This might help identify higher level exception causes.
Edit: I'm sorry, without an IDE this is an information overflow that might not be possible for a human to do. Tomcat applications are complex on an architectural level, switching between a number of different classes for the easiest requests.
An alternative solution that may be easier to use than hooking a debugger to Tomcat:
First, take a look at the call stack. At the bottom, you'll see your class named org.sgrp.singer.filters.SingerLoginFilter. The problem lies here, at line 128 of method doFilter.
The first line says org.apache.jasper.JasperException: java.lang.NullPointerException. That means you've used an object whose value is null at line 128 of mentioned class.
Check out that code to find out what could be wrong. Also, add some print/logging statements to your code.
Debugging should be your last resort. You can gather a lot of information just by looking at your stack trace.
JDB could be used, it wouldn't be my first choice though.
Here is a good explanation how to use it:
http://www.javaworld.com/javaworld/javaqa/2000-06/04-qa-0623-jdb.html
You need to remember to include debug information when you compile your files and set up the Tomcat so you are able to connect to it, this is the string, as mentioned by other post:
-Xdebug -Xnoagent -Djava.compiler=NONE-Xrunjdwp:server=y, transport=dt_socket,address=8000,suspend=y
8000 can be replaced by any other numerical value. It basicaly tells jvm to listen on that port for a debugger.
What will happen now, is tomcat will start but suspend itself and wait for a debugger to attach before proceeding.
Start JDB and attach:
jdb -attach localhost:8000
in here, localhost can be replaced by where tomcat is running if it's running on a different machine and 8000 can be replaced with whatever port you set jvm in tomcat.
Now you can debug, you can see the debug instructions if you type help in jdb.
I have always used eclipse debugger, either running tomcat within eclipse or connecting eclipse to a separate, but local to eclipse, jboss server.
Works like a dream, no need to change jvm settings or anything.
Related
I would like to do some debugging on a Java program running on Windows: backtrace, print some variables, set breakpoints, single-step through a critical function.
The first thing I tried was jdb -attach 5312. This failed with "shmemBase_attach failed: The system cannot find the file specified". I found some related questions about that error message but they seem to be talking about a more complex scenario involving debugger and target on separate hosts.
What I'm doing is a local process attach, so I think it should be easier. But there is something making it harder.
The target process isn't run as java -jar foo.jar or anything normal like that. It's an application-specific EXE file wrapping the java code. It identifies itself in a process listing as "Commons Daemon Service Runner" and looking at the strings inside it, it seems to be the prunsrv program from Apache Commons Daemon.
Process Explorer tells me that there are no command line arguments, and the process is a child of services.exe. I have the ability to start and stop it from Windows Services, but I don't know how to do anything else with it.
The jps command doesn't show this process, but I know that it is a Java program... lightly wrapped. Is there any way to debug it?
Try to set _JAVA_OPTIONS variable to something like this:
_JAVA_OPTIONS "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=32887"
This variable should be picked up by JVM while it is started.
Then, you can try to attach to this JVM by calling
jdb -attach 32887
where 32887 is an arbitrary port number used by debugger (numbers have to match).
Update:
You can use different means of connection. It's up to you. What I have given you is just one example of many, different, ways of settings things up. Take a look here for more details:
https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/conninv.html
You can also use VisualVM. In that case you need to have JVM process visible to user that is running VisualVM.
I was watching the livestream at http://www.humblebundle.com, and I saw them running the application, AND making changes to the code in Eclipse. Is this just changes for the next time they compile and run, or was he actually changing the application as it was running somehow?
Sometimes.
In Debug mode, eclipse can compile and change class files in a running JVM, this is called Hot Code Replace.
The idea is that you can start a debugging session on a given runtime
workbench and change a Java file in your development workbench, and
the debugger will replace the code in the receiving VM while it is
running. No restart is required, hence the reference to "hot".
Source: Eclipse Wiki
There are certain circumstances where this won't work, in which case Eclipse will prompt you to restart.
This is called hot code replace:
The idea is that you can start a debugging session on a given runtime workbench and change a Java file in your development workbench, and the debugger will replace the code in the receiving VM while it is running. No restart is required, hence the reference to "hot".
It's not really possible to tell from the stream. Java's capable of both to some extent - you can, with some restrictions, replace classes loaded by a JVM using the debugger. There's also JRebel, which gets rid of a great deal of those restrictions.
Ability to change application code while running is the feature of debugger. In Eclipse and many other popular IDEs it works "out of the box". Feature has several restrictions: can't change method signatures, add/remove class members, etc.
If you are in debug mode you can make certain changes while the application is running. Whether or not it is valid varies based on if the change is to currently loaded code. For example, you could change a sort function while the program isn't sorting and it will use the new code the next time it sorts.
I'm developing a multithreaded webserver applet and have been dealing with system.out.println's for the past week or so as my "debugging" tool. As far as I understand it, the .jar I build is split by a builder and put into .html files and then spit out when I access the web server.
I am wondering if there is some way that I would be able to attach a debugger (plugin?) to Java's virtual machine that would allow me to step through the code as I operate the webserver- there are some critical exceptions that are very frustrating to track down. I believe they're timing issues related to the multithreading which makes them even more unreliable when attempting to locate, and may mean that the debugger won't process appropriately. I don't think it matters, but the IDE I'm building in is Netbeans.
I've taken over a previous developer's hastily-not-quite-finished project and am in well over my head. =/ Thanks in advance for any possible solutions, I appreciate it.
Sure you can.
You need to start the web server JVM with suitable arguments allowing it to be debugged remotely. You can see at http://download.oracle.com/javase/1.3/docs/tooldocs/win32/jdb.html how to do it. jdb is available in the JDK along with javac. You then launch your IDE debugger to connect to your JVM and tell it where the source for your classes is located. Remember to compile with debug information.
As you have it inside Netbeans already then consider just launching it in debug mode as then all the extra work described above will be done automatically for you.
My tomcat (version: 5.5.25) runs an application which I try to profile with VisualVM (ver: 1.3.2).
Everything looks nice but not all classes and methods are shown in visualVM. They ones that are missing run in thread [main]. I know this because this is the thread's name I receive if I a breakpoint has been hit. Classes which run outside main e.g. [worker1] , [worker2], ... are shown correctly.
Any idea what the reasons might be? Or what I could try?
Since the application I run (it is called Assentis Docbase) is closed-source they might have customized the default tomcat configuration. But they allowed me to extend the framework with my own classes and that are the ones I want to profile.
VisualVM I run with the default configuration as downloaded.
You probably need to customize profiling root methods. See Profiling With VisualVM, Part 1 and Profiling With VisualVM, Part 2. You can also use 'Sampler' tab to get high-level picture of what is your Tomcat doing.
Here are a couple of reasons why you may not be able to see the "main" thread:
The thread could have exited.
The thread could have changed its name by calling Thread.setName().
If you want to figure out the real reason, you will probably need to look at the Tomcat source code.
This page tells you where the settings are. Google is your friend.
The reason why VisualVM did not show my method calls in thread [main] is that VisualVM allows only to profile up to 32 threads simoultanously. It is NOT possible to allow more threads to be watched. This has been documented in Profiling With VisualVM, Part 2, section "Comparison With The NetBeans Profiler" they say:
"Profiled threads limit is always 32."
:-(
You've probably badly configured "Start profiling from classes" in the plugin config.
Say you've configured org.acme.competition.* (A) for profiling:
but you've accidentally profiled the class org.acme.reference.ReferenceImpl (B) using a command lie this:
$ cat source.txt | java -Xverify:none \
-agentpath:/usr/share/visualvm/profiler/lib/deployed/jdk16/linux-amd64/libprofilerinterface.so=/usr/share/visualvm/profiler/lib,5140 \
-cp bin/ org.acme.reference.ReferenceImpl
then this would be the wrong result:
When configuring VisualVM's Startup plugin config "Start profiling from classes" with org.acme.reference.* instead, the result is correct:
See the Startup profiler guide too.
I am trying to debug a program running on a remote solaris machine.
I wanted to know path taken by the program during the execution just like stake trace
like
Class A.method1 called method2 in class B
Class B.method2 called method3 in class C
..
...
Control returned from method2 in class B to
method1 in Class A etc
We cannot run the program from eclipse since the environment cannot be reproduced since it is a large enterprise level system having many upstream and downstream systems.
I suspect somewhere in the program there is an exception being thrown and that is not handled properly like a empty catch block/not logging or rethrowing the exception.
What is the best way to debug such programs. Please help me with your solutions.
You can use Eclipse to debug remote applications, all you need to do is add a few startup parameters: http://eclipse.dzone.com/articles/how-debug-remote-java-applicat
You can debug remotely with eclipse, see this
If you want to trace the execution of your Java code you can use a tool called InTrace.
InTrace supports outputting the trace from a Java program to disk or over the network to the InTrace UI. This should be ideal for debugging your Java program on a remote solaris machine.
NOTE: InTrace is a free and open source tool which I have written.
Since, your remote machine runs under Solaris you could use DTrace to dynamically add probes to your running JVMs and the complete system.
You could remote debug, which Eclipse supports, but may not be permitted by the system admin. The only other thing I can think of is lots and lots of logging
in such cases I have used Btrace https://dzone.com/articles/introduction-btrace , it doesn't require you to setup a remote debugger, nor to have the source code of your Java application.
Another way is to run jdb https://docs.oracle.com/javase/7/docs/technotes/tools/windows/jdb.html and attach to the process - but you must enable the process JVM to use jdwp -agentlib:jdwp=transport=dt_shmem,server=y,suspend=n
In general I agree that the JDK is lacking a professional built-in tracing/debugging tool