Stacktraces are telling the truth. But not the whole truth.

Our company is all about making the cause of software errors transparent to developers and operations. As opposed to alternative solutions, we surface the location of the problem pointing you towards the malicious line in source code. Even though we are currently best known by our capabilities in detecting memory leaks, we are expanding into other areas as well. To give you a hint about our research directions, we decided to share it via three examples.

The examples boil down to the JVM capabilities to give meaningful stacktraces. In many occasions the stacktrace does contain all the information required to fix the problem. In other situations it only surfaces the symptoms without a clue to what could be causing the underlying the problem. Let me illustrate this with three examples triggering the following infamous error messages:

  • java.lang.OutOfMemoryError: unable to create new native thread
  • java.io.IOException: Too many open files in system
  • java.lang.OutOfMemoryError: Java heap space

All the examples are illustrated with simple code snippets making the underlying problem easier to understand.

Too Many Threads

static void createTooManyThreads() {
	try {
		for (int i = 0; i < TOO_MANY; i++) {
			Thread t = new Thread(new Runnable() {

				public void run() {
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
			t.start();
		}
	} catch (OutOfMemoryError e) {
		e.printStackTrace();
	}
}

In the code above, we keep launching threads until we hit the system limit and encounter the “java.lang.OutOfMemoryError: unable to create new native thread” message. What is wrong with understanding that the problem is related to the thread limit being exhausted? Lets take a closer look to the stacktrace:

java.lang.OutOfMemoryError: unable to create new native thread
	at java.lang.Thread.start0(Native Method)
	at java.lang.Thread.start(Thread.java:693)
	at eu.plumbr.demo.MisleadingStacktrace.createTooManyThreads(MisleadingStacktrace.java:34)
	at eu.plumbr.demo.MisleadingStacktrace.main(MisleadingStacktrace.java:16)

The problem is staring right into our face – we are being told where the camel back was broken by adding the last straw. At the same time we do not have a clue whose fault is that the camel is already loaded to the full extent. If the error message contained also a way to see the different traces about which call stacks were consuming the threads before our last attempt to launch the last one resulted in the stacktrace above, it would make lives of developers a lot easier.

But lets look at the same problem – resource consumption from another point:

Too many open files

Again, lets start with the sample code:

static void createTooManyFiles() {
	try {
		for (int i = 0; i < TOO_MANY; i++) {
			File f = new File(PATH_TO_FILE + i + ".txt");
			f.createNewFile();
			OutputStream s = new FileOutputStream(f);
			s.write(1);
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

The sample tries to create many files and write just one integer into each of the files without closing the previous ones. And again, running the code above results in a not-too-helpful stacktrace:

java.io.IOException: Too many open files in system
	at java.io.UnixFileSystem.createFileExclusively(Native Method)
	at java.io.File.createNewFile(File.java:947)
	at eu.plumbr.demo.MisleadingStacktrace.createTooManyFiles(MisleadingStacktrace.java:45)
	at eu.plumbr.demo.MisleadingStacktrace.main(MisleadingStacktrace.java:17)

The same problem is now disguised differently – we do get the message that I now tried to open one file too much, but – who has opened the other files to stress the JVM to the extent where it cannot complete the run?

If you are still not convinced – take a look at the third example, our current bread and butter:

Too much memory consumed

The code sample is simple again – we take a data structure and keep increasing it until the available heap is exhausted:

static void createTooLargeDataStructure() {
	try {
		List l = new ArrayList();
		for (int i = 0; i < TOO_MANY; i++) {
			l.add(i);
		}
	} catch (OutOfMemoryError e) {
		e.printStackTrace();
	}
}

Running the code gives you the infamous java.lang.OutOfMemoryError: Java heap space message. Which again is difficult to interpret if the data structure in question was populated via different possible locations in the source code.

I know that all the fellow C – developers now shrug helplessly because in their world all of the above would just take the form of a segfault, but – if we have come so far, why couldn’t we do better? I am sure we can and thats what we are about to do – find the performance bottlenecks for you.

If you are interested in the full code sample, it can be downloaded here. The code was ran on my Macbook Pro with OS X 10.9 on JDK 7u25. After this, make sure you are not going to miss future updates on interesting content, and subscribe to our Twitter feed.
 

Reference: Stacktraces are telling the truth. But not the whole truth. from our JCG partner Nikita Salnikov Tarnovski at the Plumbr Blog blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

One Response to "Stacktraces are telling the truth. But not the whole truth."

Leave a Reply


eight − 4 =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close