title: Classloader held by weak references?
body: <p>I've been battling some memory leaks, and I'm currently baffled by this issue. There's a web application classloader that was supposed to be garbage collected, but it isn't (even after I fixed several leaks). I dumped the heap with jmap and browsed it with jhat, found the classloader and checked the rootset references.</p>
  
  <p>If I exclude weak refs, the list is empty! How is that possible, since an object held only by weak references should get garbage collected? (I performed GC many times in jconsole)</p>
  
  <p>If I include weak refs, I get a list of references, all of which come from one of the following fields:</p>
  
  <ul>
  <li>java.lang.reflect.Proxy.loaderToCache</li>
  <li>java.lang.reflect.Proxy.proxyClasses</li>
  <li>java.io.ObjectStreamClass$Caches.localDescs</li>
  <li>java.io.ObjectStreamClass$Caches.reflectors</li>
  <li>java.lang.ref.Finalizer.unfinalized</li>
  </ul>
  
  <p>I couldn't find any reason why any of those references should prevent garbage collecting the classloader. Is it a gc bug? Special undocumented case? jmap/jhat bug? Or what?</p>
  
  <p>And the weirdest thing... after sitting idle and gc-ing from time to time for about 40 min, without changing anything, it finally decided to unload classes and collect the classloader.</p>
  
  <p><strong>Note:</strong></p>
  
  <p>If you make a claim about delayed collection of classloaders or weak references, then please specify the circumstances in which it happens, and ideally:</p>
  
  <ul>
  <li>provide a link to an authoritative article that supports your claim</li>
  <li>provide a sample program that demonstrates the behavior</li>
  </ul>
  
  <p>If you think the behavior is implementation-dependent, then please focus on what happens in the oracle or icedtea jvm, version 6 or 7 (pick any one of them and be specific).</p>
  
  <p>I'd really like to get to the bottom of this. I actually put some effort into reproducing the issue in a test program, and I failed - the classloader was instantly collected on System.gc() every time unless there was a strong reference to it.</p>