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

Reply via email to