Core Java

On a quest for missing stacktraces

One comment to our recent blog post brought back some memories about a specific experience. The type of experience I wish I had not experienced. Long time before we founded Plumbr I was debugging an application that gave me an exception every once in a blue moon. The level of detail was astounding:
 
 
 
 
 
 
 

java.lang.NullPointerException

That was it – no stacktrace to work with. And the application was guarded by a truly evil sysadmin who would not let me within 100 yards from the deployment. So the stage was set for numerous all-nighters trying to understand what was causing the error. I bet most of our readers know what I am talking about here. The first suspect was obvious. The summer intern who never really got exception handling and who could have easily swallowed the exception instead of rethrowing or proper logging. So I was expecting to find something like this in the code somewhere:

System.out.println(e);

But no matter how thoroughly I grep’ed through my source code I could not find anything resembling such carelessness. I do not recall much from the following day besides answering a phone call every few hours and giving the “progress report”. Unfortunately the progress was nowhere in sight. Unless I would count in the numerous updates done to production in a desperate attempt of getting something a bit more meaningful about the possible causes. But I do remember my faith in Java being tested when I started suspecting something I had always thought being impossible. Namely that Java is capable of literally eating your Exception stacktraces. And indeed the JIT can and will do it. Need proof? Run the following code:

for (int i = 0; i < 100_000; i++) {
	try {
		args[0].toString();
	} catch (Exception e) {
		if (e.getStackTrace().length == 0) {
			System.out.format("Java ate my stacktrace after iteration #%d %n", i);
			break;
		}
	}
}

In my MB Pro equipped with the latest stable JDK 7 hotspot the exception stacktrace gets eaten at the iteration #12,288. But why on earth is this happening and how could one avoid it? The simple answer is that it is one of the JIT optimizations applied during runtime. As one of our recent posts described, creating Exceptions is darn expensive. So, for performance purposes, when the JIT discovers that an exception is being thrown several times, the code may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. Hopefully the vast majority of you will hopefully never have to deal with a situation like this. After all, when exceptions are created at the pace triggering JIT to switch to preallocated exceptions, you must be doing something else wrong. After all, exceptions should occur only on exceptional situations. But for those who do, the solution is simple. You can disable the use of preallocated exceptions by adding -XX:-OmitStackTraceInFastThrow to your JVM startup parameters. So did I and found the culprit after the next JVM restart.
 

Reference: On a quest for missing stacktraces from our JCG partner Nikita Salnikov Tarnovski at the Plumbr Blog blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Vikas Shukla
10 years ago

Thanks admin you very much for providing such informational material….
Please visit also core java concepts

Mike Hayes
Mike Hayes
10 years ago

The Java Specialist Newsletter has a great article on this (http://www.javaspecialists.eu/archive/Issue187.html).

Chances are that if you see some gnarly behaviour in Java the The Java Specialist Newsletter will be able to explain it and provide a workaround.

Back to top button