{"id":2611,"date":"2013-03-07T07:33:51","date_gmt":"2013-03-07T12:33:51","guid":{"rendered":"http:\/\/appcrawler.com\/wordpress\/?p=2611"},"modified":"2013-03-07T07:33:51","modified_gmt":"2013-03-07T12:33:51","slug":"outofmemory-error-in-one-classloader","status":"publish","type":"post","link":"http:\/\/appcrawler.com\/wordpress\/2013\/03\/07\/outofmemory-error-in-one-classloader\/","title":{"rendered":"OutOfMemory error in one classloader"},"content":{"rendered":"<p>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&#8217;t cause the entire JVM to abort as it will when it is thrown in the system class loader.  <\/p>\n<p>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.<\/p>\n<pre lang=\"java\">\r\nimport java.util.*;\r\nimport java.lang.reflect.*;\r\n\r\npublic class oom {\r\n  public static void doIt() {\r\n    try {\r\n      System.out.println(\"started\");\r\n      int[] a = new int[Integer.MAX_VALUE];\r\n    }\r\n    catch(Exception e ) {\r\n      e.printStackTrace();\r\n    }\r\n    String s = \"\";\r\n    try {\r\n      Thread.sleep(5000);\r\n    }\r\n    catch( Exception e ) {\r\n      e.printStackTrace();\r\n    }\r\n    for (int i = 1; i <= 1000; i++) {\r\n          s = s + \"x\";\r\n        }\r\n        ArrayList<String> al = new ArrayList<String>();\r\n        for (int i = 1; i <= 10; i++) {\r\n          al.add(new String(s));\r\n          System.out.println(al.size());\r\n        }\r\n  }\r\n  public static void main(String args[]) {\r\n    oom o = new oom();\r\n    System.out.println(\"main() method call completed\");\r\n  }\r\n}\r\n\r\nclass oomTest extends ClassLoader {\r\n  public oomTest() {\r\n    super(oomTest.class.getClassLoader());\r\n  }\r\n  public static void main (String args[]) {\r\n    try {\r\n          if (args[0].equals(\"diff\")) {\r\n            oomTest c = new oomTest();\r\n        Class t = Class.forName(\"oom\");\r\n        Object main = c.loadClass(\"oom\").newInstance();\r\n        Method method = t.getDeclaredMethod(\"doIt\");\r\n            method.invoke(main);\r\n          }\r\n          else if(args[0].equals(\"same\")) {\r\n        oom o = new oom();\r\n        o.doIt();\r\n          }\r\n    }\r\n    catch (Exception e) {\r\n      e.printStackTrace();\r\n    }\r\n    System.out.println(\"--------------------------------------------\");\r\n    System.out.println(\"JVM still running after OOM error\");\r\n    System.out.println(\"--------------------------------------------\");\r\n  }\r\n}\r\n<\/pre>\n<p>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...<\/p>\n<pre lang=\"text\">\r\nc:\\java>java oomTest same\r\nstarted\r\nException in thread \"main\" java.lang.OutOfMemoryError: Java heap space\r\n        at oom.doIt(oom.java:8)\r\n        at oomTest.main(oom.java:50)\r\n<\/pre>\n<p>...and in a different class loader than the caller, we see it is reached...<\/p>\n<pre lang=\"text\">\r\nc:\\java>java oomTest diff\r\nstarted\r\njava.lang.reflect.InvocationTargetException\r\n        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\r\n        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\r\n        at java.lang.reflect.Method.invoke(Method.java:597)\r\n        at oomTest.main(oom.java:46)\r\nCaused by: java.lang.OutOfMemoryError: Java heap space\r\n        at oom.doIt(oom.java:8)\r\n        ... 5 more\r\n--------------------------------------------\r\nJVM still running after OOM error\r\n--------------------------------------------\r\n\r\nc:\\java>\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;t cause the entire JVM to abort as it will when it&hellip;<\/p>\n<p class=\"more-link-p\"><a class=\"more-link\" href=\"http:\/\/appcrawler.com\/wordpress\/2013\/03\/07\/outofmemory-error-in-one-classloader\/\">Read more &rarr;<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"footnotes":""},"categories":[24,25],"tags":[],"_links":{"self":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts\/2611"}],"collection":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/comments?post=2611"}],"version-history":[{"count":9,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts\/2611\/revisions"}],"predecessor-version":[{"id":2717,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts\/2611\/revisions\/2717"}],"wp:attachment":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/media?parent=2611"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/categories?post=2611"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/tags?post=2611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}