This is the mail archive of the
mailing list for the Mauve project.
RE: ClassLoader.findLoadedClass (was: ServiceFactory)
- From: "David Holmes" <dholmes at dltech dot com dot au>
- To: "Robert Lougher" <robert_lougher at hotmail dot com>, <brawer at dandelis dot ch>, <chris at kiffer dot eunet dot be>, <aph at redhat dot com>
- Cc: <classpath at gnu dot org>, <mauve-discuss at sources dot redhat dot com>
- Date: Tue, 23 Mar 2004 10:41:19 +1000
- Subject: RE: ClassLoader.findLoadedClass (was: ServiceFactory)
- Xantivirus: This e-mail has been scanned for viruses via the Connexus Internet Service
Robert Lougher wrote:
> Interesting -- that's a documentation change between 1.3 and 1.4.
The change to "initiating classloader" was very deliberately done.
> However, as Sascha points out, 1.4's explicitly says it should return
> classes _recorded by the virtual machine_ as initiated by the loader.
> Strictly, this doesn't mean all classes initiated by the loader, just the
> ones recorded by the VM. As I said, if loadClass is called implicitly by
> the VM it's recorded as an initiating loader, but not if
> loadClass is called explicitly by the programmer.
Allow me to take a walk through the spec here :)
Section 5.3.2 of the JVMS states that after invoking loadClass on a loader
the JVM records that the loader is an initiating loader of that class. This
implies that the loaded class cache is maintained by the VM not the loader.
However, if you read the OOPSLA '98 paper by Sheng Liang and Gilda Bracha
"Dynamic Class Loading in the Java Virtual Machine, (which is referred to by
the JLS and JVMS) it states that ClassLoader.findLoadedClass is the method
that performs that lookup in the loaded class cache.
So this supports Robert's position that only classes loaded by the VM get
registered in the loaded class cache in this way. However, we now need to
look at what happens if loadClass is called programmatically. For loadClass
to actually return a Class object it must either successfully use
defineClass - which is a final method and therefore part of the VM - or it
must successfully delegate to a parent loader.
According to JVMS 5.3.5 the final step in a successful defineClass is that
the JVM marks the class as having that loader as its defining loader AND
having that loader as an initiating loader. Hence after a successful
l.defineClass(n) we must have l.findLoadedClass(n) returning true.
If delegation is used then 5.3 defines that the loader is an initiating
loader of the class.
However, there is no explicit rule in 5.3 that states when in the delegation
process the "initiating" loader is marked as an initiating loader. Similarly
there is no obvious rule that states that when A delegates to B which
delegates to C etc that any of the intervening loaders are marked as
initiating loaders, even though by definition they are.
So I conclude that Robert is correct. Although in Sascha's example, the
classloader in question was by definition an initiating loader, it had not
been used in a way that required it to be marked by the VM as an initiating
loader and hence findLoadedClass was not required to return true.
Initially I thought this exposed a hole in the type system but then realized
that it does not. For although a given class could hold two reference to
objects of Class N where N was defined by two different classloaders (L1 and
L2), those references could only be typed as Object. If the class tried to
define a field of type N then it would force marking of the initiating
loader in a way that prevents two different classes for N being returned.
Fun exercise :)