Mantis - Resin
Viewing Issue Advanced Details
4628 minor always 06-20-11 09:34 06-20-11 09:59
ferg  
ferg  
normal  
closed 4.0.19  
fixed  
none    
none 4.0.20  
0004628: classloader leak for JPA
(rep by Patric Rufflar)

I think that resin (at least version 3.1, but most probably 4.0 too) suffers
from a critical classloader leak which may cause that the memory occupied
by an application will not get released when destroying its servlet context
(stopping/redeploying the application).
As an result, further restarts/redeployments will sooner or later
result in an OutOfMemoryError.

Please have a look at
resin-3.1.10\modules\jpa\src\javax\persistence\Persistence.java

On line 51 there's a WeakHashMap defined, which maps the classloader
to the corresponding PersistenceProvider instances:

   private static WeakHashMap<ClassLoader,PersistenceProvider[]>
     _providerMap = new WeakHashMap<ClassLoader,PersistenceProvider[]>();


The problem is that a PersistenceProvider instance may reference the
key indirectly
(which is at least true when not using Amber, e.g. EclipseLink)
The loaded class will of course reference its classloader, which is
the web application's classloader.
However according to the javadocs this will prevent the removal of the entry:

"Thus care should be taken to ensure that value objects do not
strongly refer to their own keys,
either directly or indirectly, since that will prevent the keys from
being discarded."

With the consequence that the EnvironmentClassLoader cannot be garbage
collected.

When looking at the GC roots (for a classloader from a stopped application)
this can be seen easily:

Class Name
             | Shallow Heap | Retained Heap
------------------------------------------------------------------------------------------------------------------
com.caucho.loader.EnvironmentClassLoader @ 0xe68362d0
             | 376 | 131.077.664
'- <classloader> class org.eclipse.persistence.jpa.PersistenceProvider
@ 0xd3bda6d8| 0 | 0
    '- <class> org.eclipse.persistence.jpa.PersistenceProvider @
0xe7bb2010 | 24 | 40
       '- [3] javax.persistence.spi.PersistenceProvider[4] @
0xe7bb2020 | 56 | 144
          '- value java.util.WeakHashMap$Entry @ 0xe7c72ca8
              | 72 | 432
             '- [11] java.util.WeakHashMap$Entry[16] @ 0xe118fc18
              | 152 | 800
                '- table java.util.WeakHashMap @ 0xe118fbe8
              | 72 | 928
                   '- _providerMap class javax.persistence.Persistence
@ 0xd1fc55a8 | 32 | 960
                      '- [1152] java.lang.Object[1280] @ 0xe0b40378
              | 10.264 | 1.774.424
------------------------------------------------------------------------------------------------------------------

As you can see, the second last line (_providerMap class
javax.persistence.Persistence @ 0xd1fc55a8) which is actually
a caucho class, references the old EnvironmentClassLoader.
So in my case, 131 MB will not get released.

If I am right - is there a workaround available?
(Is it possible to configure the EnvironmentClassLoader that it will not load
the PersistenceProvider/Persistence class from Amber but from the JPA
implementation which my application provides?)


There are no notes attached to this issue.