Running out of memory without the OutOfMemoryError

October 24, 2013 by Ivo Mägi

This is actually a reincarnation of a post originally posted in ~2010. The flashback occurred when listening to our engineers cursing at a particularly nasty bug raising its head yesterday. When the cursing stopped, I stepped by to verify my doubts. Lo and behold, I was correct – the mood swing was caused by an app running out of the heap space but dying without the usual OutOfMemoryError symptom.

So let me walk through the case of missing OutOfMemoryError with the same code example I first encountered three years ago. Back then I was using a Windows XP with a mid-2010 JDK 6 installed.

I was playing around with an early release of Plumbr which was supposed to find memory leaks from the application (edit: back then it failed to do pretty much anything besides crashing the JDK). In order to verify this, I wrote a small snippet which I thought would be a good test case for a leak discovery (edit: in reality it is not). I was able to create and launch the following:


class Leak {  
  static List list = new ArrayList();  
  public static void main(String[] args) {  
    for (int i = 0; i >= 0 ;i++) {  
      list.add(i);  
    }  
    System.out.println("I will either reach here or die trying");  
  }  
}

Pretty good for a marketroid, eh? But what do you think running the code displayed to my command prompt:

Option A:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:2760)
        at java.util.Arrays.copyOf(Arrays.java:2734)
        at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
        at java.util.ArrayList.add(ArrayList.java:351)
        at Leak.main(Leak.java:6)

Option B:


I will either reach here or die trying

Well, as I found out, it doesn’t print out anything, so I was pretty much just stuck to staring the empty command prompt.

java outofmemoryerror no stacktrace

As this was two years from my last real Java development experience before being demoted to management, I was out of ammo to troubleshoot the situation. So I took the sample to the hardcore Java hackers who later became known as the founders of Zeroturnaround. For 10 good minutes I managed to have bedazzled look on them as well, before it struck – the memory will be allocated in such a way that there is no room for new OutOfMemoryError() to be created.

If you execute the above with 64MB heap (the default) on Windows XP using a mid 2010 JDK builds, you see a silent failure:


C:\work\snippets\leak java -Xmx64m Leak
C:\work\snippets\leak

But if you increase (well actually modify) the heap size a bit, you will encounter a more familiar situation:

C:\work\snippets\leak java -Xmx65m Leak
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:2760)
        at java.util.Arrays.copyOf(Arrays.java:2734)
        at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
        at java.util.ArrayList.add(ArrayList.java:351)
        at Leak.main(Leak.java:6)
C:\work\snippets\leak

Moral of the story? I can only recommend to upgrade to a more modern release – no matter which configuration I tried, I failed to recreate the situation using the JDK 7 builds I had on my Mac today. But looking at the statistics about popular Java runtime configurations, you see a staggering amount of JDK deployments dating back to pre-2010 releases, meaning that the problem is still out there forcing developers to pull crazy all-nighters trying to figure out the source of the problem without any hints from the stacktrace to support them.

Anyhow, backing the engineering team with my extensive knowledge about JDK 6 internals I went ahead and revived the post from the long-forgotten blog I used to contribute back then. If you enjoyed the content, I can only recommend subscribing to our RSS or Twitter feed.

Can't figure out what causes your OutOfMemoryError? Read more

ADD COMMENT

Can't figure out what causes your OutOfMemoryError? Read more

Latest
Recommended
You cannot predict the way you die
When debugging a situation where systems are failing due to the lack of resources, you can no longer count on anything. Seemingly unrelated changes can trigger completely different messages and control flows within the JVM. Read more
Tuning GC - it does not have to be that hard
Solving GC pauses is a complex task. If you do not believe our words, check out the recent LinkedIn experience in garbage collection optimization. It is a complex and tedious task, so we are glad to report we have a whole lot simpler solution in mind Read more
Building a nirvana
We have invested a lot into our continuous integration / delivery infrastructure. As of now we can say that the Jenkins-orchestrated gang consisting of Ansible, Vagrant, Gradle, LiveRebel and TestNG is something an engineer can call a nirvana. Read more
Creative way to handle OutOfMemoryError
Wish to spend a day troubleshooting? Or make enemies among sysops? Registering pkill java to OutOfMemoryError events is one darn good way to achieve those goals. Read more