user1160931
user1160931

Reputation: 238

Dumping state of variables on Exception

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

Answers (6)

Sanjiv Jivan
Sanjiv Jivan

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

Wei Hao
Wei Hao

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

boto
boto

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

Perception
Perception

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

Brian
Brian

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

Michael Shopsin
Michael Shopsin

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

Related Questions