Ignatenko vs Gagnon proposal checklist follows. :)
In accordance with Section 2.17.8 of the JVM spec, class unloading (and its related native resource cleanup) can only happen when the class loader instance becomes unreachable. For this to happen, we put in place the following things:
1- Each class loader is represented by some VM internal structure.
[We'll call it the "class loader structure"].
This is true.
2- Each class loader internal structure, except (optionally) the bootstrap class loader, maintains a weak reference to an object instance of class ClassLoader (or some subclass). The Java instance has some opaque pointer back to the internal VM structure. The Java instance is usually created before the internal VM structure. The instance constructor is usually in charge of creating the internal VM structure. [We'll call it the "class loader instance"]
This is true.
3- Each class loader instance maintains a collection of loaded classes. A class/interface is never removed from this collection. This collection maintains "hard" (i.e. "not weak") references to classes/interfaces.
This is true.
4- [Informative] A class loader instance is also most likely to maintain a collection of classes for which it has "initiated" class loading. This collection should use hard references (as weak references won't lead to earlier class loading).
This is not true. Look for the thread "[drlvm] Non-bug difference HARMONY-1688?", where Eugene Ostrovsky desribed initiating loaders in details with links to specification.
5- Each class loader instance maintains a hard reference to its parent class loader. This reference is (optionally) null if the parent is the bootstrap class loader.
This is true. This is actually a part of delegation framework.
6- Each j.l.Class instance maintains a hard reference to the class loader instance of the class loader that has loaded it. [This is not the "initiating" loaders, but really the "loading" loader].
This is true. AFAIU, this class loader is called "defining" loader for a class.
7- Each class loader structure maintains a set of boolean flags, one flag per "non-nursery" garbage collected area (even when thread-local heaps are used). The flag is set when an instance of a class loaded by this class leader is moved into the related GC-area. The flag is unset when the GC-area is emptied, or (optionally) when it can be determined that no instance of a class loaded by this class loader remains in the GC-area. This is best implemented as follows: a) use an unconditional write of "true" in the flag every time an object is moved into the GC-area by the garbage collector, b) unset the related flag in "all" class loader structures just before collecting a GC-area, then setting the flag back when an object survives in the area.
Requires identification of object' class type during GC. Will most probably degrade GC performance.
8- Each method invocation frame maintains a hard reference to either its surrounding instance (in case of instance methods, i.e. (invokevirtual, invokeinterface, and invokespecial) or its surrounding class (invokestatic). This is already required for synchronized methods (it's not a good idea to allow the instance to be collected before the end of a synchronized instance method call; yep, learned the hard way in SableVM...) So, the "overhead" is quite minimal. The importance of this is in the correctness of not letting a class loader to die while a static/instance method of a class loaded by it is still active, leading to premature release of native resources (such as jitted code, etc.).
Not generally true for optimizing JITs. "This" (or "class") can be omitted from enumeration if it is not used anywhere in the code. Generally, this technique reduces number of registers used in the code ("register pressure" they call it :)).
9- A little magic is required to prevent premature collection of a class loader instance and its loaded j.l.Class instances (see [3-] above), as object instances do not maintain a hard reference to their j.l.Class instance, yet we want to preserve the correctness of Object.getClass(). So, the simplest approach is to maintain a hard reference in a class loader structure to its class loader instance (in addition to the weak reference in [2-] above). This reference is kept always set (thus preventing collection of the class loader instance), except when *all* the following conditions are met: a) All nurseries are empty. b) All GC-area flags are unset.
This requires more involvment of a GC in unloading process and affects GC code more. In DRLVM, GC is designed to be a replaceable component. Moreover, we already have 3 different working GCs and MMTk on the way. So, including GC into the design is not a good idea for DRLVM. <SNIP> In addition,I highly recommend using the approach proposed in Chapter 3
of http://sablevm.org/people/egagnon/gagnon-phd.pdf for managing class-loader related memory. It has many advantages:
It is also true. Per class loader memory allocation is already used for part of data allocated for this class loader. Look in HARMONY-2000 which brings per-class loader pools to the extent. <SNIP> -- Pavel Pervov, Intel Enterprise Solutions Software Division