OutOfMemory error in one classloader

I thought this was interesting. If an OutOfMemory error (not exception, there is a difference) is thrown in one classloader when multiple class loaders are in use, it won’t cause the entire JVM to abort as it will when it is thrown in the system class loader.

Our source code below causes an error to be thrown. Depending on whether you ask it to run the offending class method in the same class loader as the caller, or a different one, is what we will show the effects.

import java.util.*;
import java.lang.reflect.*;

public class oom {
  public static void doIt() {
    try {
      System.out.println("started");
      int[] a = new int[Integer.MAX_VALUE];
    }
    catch(Exception e ) {
      e.printStackTrace();
    }
    String s = "";
    try {
      Thread.sleep(5000);
    }
    catch( Exception e ) {
      e.printStackTrace();
    }
    for (int i = 1; i <= 1000; i++) {
          s = s + "x";
        }
        ArrayList al = new ArrayList();
        for (int i = 1; i <= 10; i++) {
          al.add(new String(s));
          System.out.println(al.size());
        }
  }
  public static void main(String args[]) {
    oom o = new oom();
    System.out.println("main() method call completed");
  }
}

class oomTest extends ClassLoader {
  public oomTest() {
    super(oomTest.class.getClassLoader());
  }
  public static void main (String args[]) {
    try {
          if (args[0].equals("diff")) {
            oomTest c = new oomTest();
        Class t = Class.forName("oom");
        Object main = c.loadClass("oom").newInstance();
        Method method = t.getDeclaredMethod("doIt");
            method.invoke(main);
          }
          else if(args[0].equals("same")) {
        oom o = new oom();
        o.doIt();
          }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("--------------------------------------------");
    System.out.println("JVM still running after OOM error");
    System.out.println("--------------------------------------------");
  }
}

When we cause an out of memory condition in the same classloader, we see our line that suggests we made it past the OOM error is never reached...

c:\java>java oomTest same
started
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at oom.doIt(oom.java:8)
        at oomTest.main(oom.java:50)

...and in a different class loader than the caller, we see it is reached...

c:\java>java oomTest diff
started
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at oomTest.main(oom.java:46)
Caused by: java.lang.OutOfMemoryError: Java heap space
        at oom.doIt(oom.java:8)
        ... 5 more
--------------------------------------------
JVM still running after OOM error
--------------------------------------------

c:\java>

1 comment for “OutOfMemory error in one classloader

  1. Anonymous
    June 17, 2015 at 2:39 AM

    sas

Leave a Reply

Your email address will not be published. Required fields are marked *

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