More comments in addition to what I replied earlier....
On 4/23/2013 4:43 PM, Mandy Chung wrote:
Each ClassLoader maintains explicit hard-references to all Class
objects for classes defined by the loader. So proxy Class object can
not be GC-ed until the ClassLoader is GC-ed.
AFAIU, a class loader will be GC'ed as long as there is no reference to
any of its loaded classes. The ClassLoader's internal vector of keeping
the loaded classes is to prevent the classes from being GC'ed until the
class loader is being GC'ed which will unload the classes.
So we should make the class loader and the proxy classes weak referenced
so that they will be GC'ed properly.
So we need not register the CacheValue objects in WeakCache with a
refQueue. The expunging of reverseMap entries is already performed
with CacheKey when it is cleared and equeued. There's no harm as it
is, since the clean-up is performed with all the checks and is
idempotent, but it need not be done for ClassValue objects holding
weak references to proxy Class objects.
I actually think we don't need to make CacheKey as a weak reference but
the CacheValue object should still be registered in the refQueue. The
proxy class in the CacheValue implementing the given interfaces always
reference the interfaces in the CacheKey and it means that the classes
in the CacheKey will never be GC'ed before the proxy class. When there
is no reference to the proxy class, it will be added to the reference
queue. Once the entry with the CacheValue holding the proxy class is
expunged, the interfaces will not be referenced in the cache.
Does this make sense to you?
Mandy
As explained above, for the per-loader proxy class cache, both the key
(interfaces) and the proxy class should be wrapped with weak reference.
In your revisions, you optimize for 0-interface and 1-interface proxy
class. What I hacked up earlier was just to use Class<?>[] as the key
(need to make a copy of the array to prevent that being mutated during
runtime) that is a simpler and straightforward implementation. I
didn't measure the footprint and compare the performance of your
versions. Have you seen any performance difference which led you to
make the recent changes?
Mandy
[1]
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.3