On 04/24/2013 07:33 AM, Mandy Chung wrote:
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.
That's right.
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.
But! If the interface in the sub-key (the CacheKey in WeakCache is the
1st-level key and is a WeakReference<ClassLoader>, the sub-key holds
interfaces or interface names) happens to be loaded by the same
ClassLoader as the proxy class, the ClassLoader will never be GC-ed and
consequently the ClassValue will never be cleared and the entry will
never be expunged... We have to wrap with a WeakReference:
- the ClassLoader
- each individual interface Class object
- proxy Class object
All 3 types of objects can have implicit or explicit strong references
among them.
Regards, Peter
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