On 04/26/2013 09:59 AM, Jochen Theodorou wrote: > Hi all, > > basically ClassValue is there so that my runtime/framework or whatever > can store information and bind it to a class. The information is then > available as long as the class exists. In Groovy3 I am going to use this > for meta classes. > > Some time ago a user came up with a special need, he wanted to be able > to replace the groovy runtime at runtime but could not do so because of > classes being referenced that keep classloaders alive, which then lock > the jar on the file system on windows. > > This did let me to the thought, that as soon as I start storing meta > classes using ClassValue, my Groovy runtime will never unload again as > soon as I store for the example a meta class on ArrayList (which is > likely to happen) or Object, or any other java core class for that > matter. This makes me think that I should not directly use ClassValue to > enable unloading... but I also do not want unloading to happen when I > still need the value. > > Does anyone have any idea on now to solve this problem? > > bye blackdrag >
Hi Jochen, It seems you have similar issues that for example j.l.r.Proxy has. It spins a class implementing given interfaces, defines it with a given ClassLoader and then caches it for future-use. The situation with j.l.r.Proxy is simpler than your's, I assume. Could you describe in some more detail, what are "meta classes" in groovy runtime in terms of how they are generated (lazily at runtime or ahead of runtime?), what dependencies they can have and who is dependent on them. I assume they are generated at runtime, since if they were accessible as class files on the classpath of some loader, you would not have to design your own caching/loading/defining layer (Class.forName() would do). That's still an option if you create your own ClassLoader subclass that would use a naming convention (say groovymeta.some.pkg.ClassName would be the name of meta class "belonging" to some.pkg.ClassName main class) and use that ClassLoader as the class loader for groovy apps. But that's hard to enforce in various environments... So dynamic generation then. You typically would want to define a class with the ClassLoader that also "sees" all the dependencies of the class. But there could be several ClassLoaders in a runtime that are suitable in a given situation. You would choose the right one depending on the lifetime of the generated class and the possible users of that class. And you would want the Class object of the "meta class" to be cached via a WeakReference<Class>, so that when all the users of the class are gone the class itself becomes one step to eligible to GC. It will not be GC-ed until the ClassLoader that defined it becomes eligible to GC (since the ClassLoader maintains explicit hard-references to all the Class objects for classes that it has defined). And each class maintains an implicit reference to the ClassLoader that defined it. So when all the users of all classes defined by a single ClassLoader are gone and the ClassLoader is not reachable any more, the whole graph of ClassLoader with all it's Class objects is GC-ed. It's that simple. The question is how to most effectively design the structure so that you can quickly obtain the cached Class object and use the class represented by it. One part of the lookup "key" seems to be the "main class" that the "meta class" belongs to. So ClassValue is one option. But I can imagine you would want to support groovy runtime in environments such as app servers where the groovy runtime is deployed at the system level and the contents of a metaclass belonging to some system class (say ArrayList) is supplied by the deployed application and there could be several deployed applications, each contributing it's own different "meta class" for ArrayList. So the main class is not the only "key" for lookup. I would imagine the ClassLoader of the deployed application is the other part of the "key" and you would want to define a separate meta class with each application ClassLoader for the same main class. So the most general approach would be the structure similar to the following: Map<WeakReference<ClassLoader>, ClassValue<WeakReference<Class>>> ^ ^ | meta class the defining class loader of the meta class which is equivalent to: Map<WeakReference<ClassLoader>, Map<WeakReference<Class>, WeakReference<Class>>> ^ ^ ^ | | meta class | main class the defining class loader of the meta class ... with the hashCode/equals of the WeakReferences suitably overriden of course. Regards, Peter _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev