Proxy.isProxyClass scalability (original) (raw)
Peter Levart peter.levart at gmail.com
Wed Apr 24 07:13:31 UTC 2013
- Previous message: Proxy.isProxyClass scalability
- Next message: Proxy.isProxyClass scalability
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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, 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
- Previous message: Proxy.isProxyClass scalability
- Next message: Proxy.isProxyClass scalability
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]