Reputation: 238
I was wondering if there is a way to dump the state of all local variables when there is an exception, to get a better idea of the state of the environment that caused the exception. Below the variable idsToDump
is unknown at run time and I want to find out the state at which value in the collection is causing the NPE.
Example:
public static void main(String[] args) {
HashMap<Integer, String> employees = new HashMap<Integer, String>();
employees.put(1, "James");
Integer[] idsToDump = new Integer[] { 1, 2, 3 };
for (Integer employeeId : idsToDump) {
String name = employees.get(employeeId).toLowerCase();
System.out.println(name + " is employee number: " + employeeId);
}
}
output:
james is employee number: 1
Exception in thread "main" java.lang.NullPointerException
Question: Is there some JVM argument that I can pass to dump information about the current state of the local variables? ie we get
java.lang.NullPointerException
and (this is the part I'm after)
values: employeeId=2
I want to be able to do this on a client site, so no access to Eclipse or debugging tools, looking for just JVM arguments, can't make code changes either. I have looked through them but couldn't really find anything. In the meantime I'll keep searching there too ;)
Upvotes: 17
Views: 4303
Reputation: 1954
I came across a commercial product that does this by simply using a startup -agentlib JVM agent param. I haven't used it yet but intend on giving it a try as it looks very promising.
https://www.takipi.com/product
Anyone have experience with this product?
Upvotes: 4
Reputation: 2856
Like Thomas, I don't know of any current method that can dump variables. However, I believe you want to do so to aid you in your debugging. Here are some simple methods which I use to debug my code using just the console:
1.Learn to read the stacktrace when the exception occurs. It gives you a lot of information on what could be potentially causing the exception. If the particular line that the stacktrace is pointing to doesn't seem to have anything wrong, track back the code and see if it was a prior object that is causing the exception. For example (using some sample code and methods):
Book book = null;
Bookshelf bookshelf = new Bookshelf();
bookshelf.add(book);
bookshelf.getBooks();
Something like that will cause the NPE stacktrace to point to bookshelf
, but actually it is book
that is causing the NPE.
2.Print out the variables that you suspect are causing the NPE.
for (Integer employeeId : idsToDump) {
System.out.println(employeeId);
String name = employees.get(employeeId).toLowerCase();
System.out.println(name + " is employee number: " + employeeId);
}
Your output will be:
1
2
And then you'll know that 2
is causing the NPE.
3.Comment out the suspicious code and systematically uncomment out the code until the exception occurs, or vice-versa.
Although you may find it tedious and frustrating at times, it really does help in your foundation because with enough practice, you'll soon be able to intuitively spot where the error usually occurs (and hence spend less time on future debugging).
Upvotes: 0
Reputation: 455
Although you have mentioned that you are not able to do any code changes, here a hint for the case that code changes are still possible: A handy tool to get some more information about the exception is the method "printStackTrace" of the thrown exception object. You may want to use something like this.
try {
...
}
catch ( Exception e ) {
System.out.println( "Exception occured! Reason: " + e.printStackTrace() );
}
Upvotes: 1
Reputation: 80623
Given all your restrictions, I can't recommend anything else apart from jdb. Fire that bad boy up and start stepping through the client code line by line. I know you said no debugging tools, but unless they are a JRE only environment you should have jdb installed already.
Upvotes: 2
Reputation: 6450
Your best option, afaik, is the old manual way: use some sort of logging (be it Log4J, or just stdout), and to explicitly record the variables you're interested in via a catch
block.
Upvotes: 0
Reputation: 2138
The easiest thing to do is to run this code in a debugger and step through it. If you can't debug the code then you can use a try/catch block and set employeeId outside of this like:
int debugEmployeeId = -1;
try {
Integer[] idsToDump = new Integer[] { 1, 2, 3 };
for (Integer employeeId : idsToDump) {
debugEmployeeId = employeeId;
...
} catch (Exception e) {
throw new Exception("Missing employeeId = " + Integer.toString(debugEmployeeId));
}
Upvotes: 2