The version with a WeakHashMap and first getting ClassInfo without synchronization (which would could not be used in the end anyway) appeared in some quick (probably not representative) tests with concurrent access to be about 10-20% slower than the current implementation. Similar result also when I split up into 4096 WeakHashMap instances in an array of clazz.hashCode()%4096 and always synchronizing on get().

I looked into the source of ClassValue. I had naively expected it to contain some native code or otherwise interact more directly with the VM, but there is only a new field in the Class class that it uses. So there is a hard link from the class via that field to ClassInfo in the case of Groovy, which I guess prevents "on-the-fly" garbage collection because ClassInfo contains lots of stuff with hard references to the class. And with the pre Java 7 implementation I presume the situation is similar. (With a WeakHashMap that is different because the value does not count, the entry can be collected independently of the value and it could be argued that ClassValue should have been implemented in a way that would have had the same behavior, if I my reasoning is correct.)

So maybe refactoring to always using WeakReference<Class> in all objects stored in ClassInfo (meta classes, caches, ...) would be sufficient to get "on-the-fly" garbage collection (i.e. before the maximum on Metaspace or Heap is reached)? And would the additional weakRef.get() calls maybe have again a noticeable effect on performance? I won't try this refactoring myself, but if someone else wants to try this?

Well, at least I think I might start to understand the problem... ;)

Alain

Reply via email to