Uploaded image for project: 'Application Server 3  4  5 and 6'
  1. Application Server 3 4 5 and 6
  2. JBAS-3041

ClassNotFoundException for dynamic classes will cause memory leak



    • Documentation (Ref Guide, User Guide, etc.)


      Basically, there is an optimization attempt in RepositoryClassLoader (in 3.2.x was UnifiedClassLoader) to blacklist any names that throw a ClassNotFoundException (the same problem with resource attempts).

      What will happen is that you will add an entry to the black list which will grow string and HashMap$Entry objects.

      This was exposed when we switched to using Java objects within Rhino (which isn't too unpopular so I'm surprised how long it took us to find it – try we've been searching for this bug for 4 weeks, 2 full time people and many profiler's later).

      When using Rhino, if you attempt to use the Java Importer and then surround your evaluations with code like

      with (importname)

      Rhino will attempt to call

      Class.forName(importname + "." + variablename)

      to attempt to first see if the variable is a pre-defined Java class and if it throws a CNFE, it will then assume that (a) it's defined in the ECMAScript scope or (b) doesn't exist.

      If you attempt to then reference a variable that's defined in your local scope (not a java class), and you define either dynamic variables (for example, in the case of an interpreter that uses javascript like we do), you will eventually and mysteriously run out of memory.

      A very simple example of how to reproduce this w/o having to go through the agony above:

      Build a very simple JSP and then do the following:

      for (int c=0;c<10000;c++)

      { Class.forName("com.foo.bar."+c); }

      catch (ClassNotFoundException ex) {}

      Re-load the page a bunch of times as you watch you Heap grow... and then grow. Eventually, out pops a friendly OutofMemoryException.

      TIP: we found this after many many weeks of profiling and removing various code components by hacking the Java runtime jar and making a hooked HashMap which keep track of all the hashmaps. We knew the problem was in String and HashMap$Entry growth but couldn't find out why (there were just so many growing). We then build a JSP page which would then access the hashtable of HashMaps and would print out hashmaps in a table and their age and # of objects. Once we did this, we found the bug within a few hours.

      I would suggest that you remove the blacklist code - I don't think that the small cost savings of the cache is worth this type of behavior. Luckily, we were able to patch this ourselves, but it would be impossible to workaround if you leave it in.




            starksm64 Scott Stark (Inactive)
            jhaynie_jira Jeff Haynie (Inactive)
            0 Vote for this issue
            1 Start watching this issue