Now it's clear why RI doesn't call parent's loadClass() directly but
uses internal chain instead. It does so to distinguish between
initiating class loader and other loaders. Don't you think so?
Hmm...such behaviour doesn't seem to be strictly alligned with the
spec but RI does so.....should we do the same? I think yes.
Thanks
Evgueni
On 10/25/07, Sergey Dmitriev <[EMAIL PROTECTED]> wrote:
> Evgueni
>
> as for the:
>
> > 2) Every class loader in the calling chain is marked as initiated
> > class loader for class hi since findLoadedClass() returns non null
> > value.
>
> I just have checked on RI: after we'have called Class.forName("hi",
> CL3), if we do not explicitly call Class.forName("hi", CL2) the
> CL2.findLoadedClass() returns false. So not every class loader from
> the chain becomes the "initiated" one. Here is the output of slightly
> modified classloadertest2.java (commented out the explicit loading of
> "hi" via CL2):
>
> mycl1.parent = [EMAIL PROTECTED]
> mycl2.parent = [MyClassLoader [dir:my]]
> mycl3.parent = [MyClassLoader [dir:X2]]
> [MyClassLoader [dir:X3]].loadClass(hi) enter...
> [MyClassLoader [dir:my]].findClass(hi) enter...
> [MyClassLoader [dir:my]].loadClassData(hi) enter...
> [MyClassLoader [dir:my]].loadClassData(hi) exit. out = [EMAIL PROTECTED]
> [MyClassLoader [dir:my]].findClass(hi) exit. out = [EMAIL PROTECTED]
> [MyClassLoader [dir:my]].loadClass(java.lang.Object) enter...
> [MyClassLoader [dir:my]].loadClass(java.lang.Object) exit. out = class
> java.lang.Object
> [MyClassLoader [dir:X3]].loadClass(hi) exit. out = class hi
> Class.forName("hi", true, mycl3) = [class hi]
> mycl1.findLoadedClass(hi) = [class hi]
> mycl2.findLoadedClass(hi) = [null]
> mycl3.findLoadedClass(hi) = [class hi]
>
> Next thing I would note, I just looked to "The JavaTM Virtual Machine
> Specification" and realized that [CL3.findLoadedClass(hi) != hi.class]
> behaviour is what we have to fix because CL3 is the "initiating one";
> but the behaviour of [Class.forName("hi", CL3); Class.forName("hi",
> CL2) -> CL2.findLoadedClass("hi") == hi.class] is optional thing I
> would say, this is not specified clearly. And actually the last thing
> is desired, meaning consequent calls of CL.loadClass("class") should
> not run though the whole chain every time even if the "class" was
> loaded before but by the different classloader.
>
>
> Thanks
> Sergey
>
>
> On 10/25/07, Evgueni Brevnov <[EMAIL PROTECTED]> wrote:
> > This test shows two things:
> >
> > 1) SUN doesn't strictly follow the spec since it doesn't call
> > loadClass() method of the parent class loader but uses alternative
> > call chain instead.
> >
> > 2) Every class loader in the calling chain is marked as initiated
> > class loader for class hi since findLoadedClass() returns non null
> > value.
> >
> > I believe if you change class loader's parent on the fly it will not
> > have any effect on already loaded classes. So it should be legal (and
> > compatible with SUN) to cache classes.
> >
> > Thanks
> > Evgueni
> >
> >
> >
> > On 10/24/07, Sergey Dmitriev <[EMAIL PROTECTED]> wrote:
> > > Hello
> > >
> > > sorry for such a delay. Here what I've got with my experiments. Please
> > > refer to classloadertest2.java attached to JIRA.
> > >
> > > Talking about the Pavel's case: CL1 <- CL2 <- CL3, loading via CL3
> > > then loading via CL2.
> > >
> > > SUN JDK 6:
> > > mycl1.parent = [EMAIL PROTECTED]
> > > mycl2.parent = [MyClassLoader [dir:my]]
> > > mycl3.parent = [MyClassLoader [dir:X2]]
> > > [MyClassLoader [dir:X3]].loadClass(hi) enter...
> > > [MyClassLoader [dir:my]].findClass(hi) enter...
> > > [MyClassLoader [dir:my]].loadClassData(hi) enter...
> > > [MyClassLoader [dir:my]].loadClassData(hi) exit. out = [EMAIL PROTECTED]
> > > [MyClassLoader [dir:my]].findClass(hi) exit. out = [EMAIL PROTECTED]
> > > [MyClassLoader [dir:my]].loadClass(java.lang.Object) enter...
> > > [MyClassLoader [dir:my]].loadClass(java.lang.Object) exit. out = class
> > > java.lang.Object
> > > [MyClassLoader [dir:X3]].loadClass(hi) exit. out = class hi
> > > Class.forName("hi", true, mycl3) = [class hi]
> > > [MyClassLoader [dir:X2]].loadClass(hi) enter...
> > > [MyClassLoader [dir:X2]].loadClass(hi) exit. out = class hi
> > > Class.forName("hi", true, mycl2) = [class hi]
> > > mycl1.findLoadedClass(hi) = [class hi]
> > > mycl2.findLoadedClass(hi) = [class hi]
> > > mycl3.findLoadedClass(hi) = [class hi]
> > >
> > > HARMONY:
> > > mycl1.parent = [EMAIL PROTECTED]
> > > mycl2.parent = [MyClassLoader [dir:my]]
> > > mycl3.parent = [MyClassLoader [dir:X2]]
> > > [MyClassLoader [dir:X3]].loadClass(hi) enter...
> > > [MyClassLoader [dir:X2]].loadClass(hi) enter...
> > > [MyClassLoader [dir:my]].loadClass(hi) enter...
> > > [MyClassLoader [dir:my]].findClass(hi) enter...
> > > [MyClassLoader [dir:my]].loadClassData(hi) enter...
> > > [MyClassLoader [dir:my]].loadClassData(hi) exit. out = [EMAIL PROTECTED]
> > > [MyClassLoader [dir:my]].findClass(hi) exit. out = [EMAIL PROTECTED]
> > > [MyClassLoader [dir:my]].loadClass(java.lang.Object) enter...
> > > [MyClassLoader [dir:my]].loadClass(java.lang.Object) exit. out = class
> > > java.lang.Object
> > > [MyClassLoader [dir:my]].loadClass(hi) exit. out = class hi
> > > [MyClassLoader [dir:X2]].loadClass(hi) exit. out = class hi
> > > [MyClassLoader [dir:X3]].loadClass(hi) exit. out = class hi
> > > Class.forName("hi", true, mycl3) = [class hi]
> > > [MyClassLoader [dir:X2]].loadClass(hi) enter...
> > > [MyClassLoader [dir:my]].loadClass(hi) enter...
> > > [MyClassLoader [dir:my]].loadClass(hi) exit. out = class hi
> > > [MyClassLoader [dir:X2]].loadClass(hi) exit. out = class hi
> > > Class.forName("hi", true, mycl2) = [class hi]
> > > mycl1.findLoadedClass(hi) = [class hi]
> > > mycl2.findLoadedClass(hi) = [null]
> > > mycl3.findLoadedClass(hi) = [null]
> > >
> > > First thing that one can catch: in case of SUN we don't touch the CL2
> > > at all during the loading via CL3. Interesting.
> > >
> > > And during the loading via CL2 SUN does not touch the CL1.
> > >
> > >
> > > Thanks
> > > Sergey
> > >
> > > On 10/23/07, Evgueni Brevnov <[EMAIL PROTECTED]> wrote:
> > > > Pavel,
> > > >
> > > > I don't know exact answer to you question :-(, sorry, I hope Dmitry
> > > > will provide such information soon :-)
> > > >
> > > > I have two notes:
> > > >
> > > > 1) I believe the spec requires to return the same class each time
> > > > since a pair <ClassLoader, ClassName> must uniquely identify java
> > > > class. So in you example from the first letter CL2 should always
> > > > return the same class.
> > > >
> > > > 2) Regarding "initiating" class loader notion. My understanding is
> > > > that each class loader in the hierarhy chain up to defining one should
> > > > be marked as initiating class loader. At least this is written in [1]
> > > >
> > > > [1] "Inside the Jva2 Virtual Machine" by Bill Venners.
> > > >
> > > > Thanks
> > > > Evgueni
> > > > On 10/23/07, Pavel Pervov <[EMAIL PROTECTED]> wrote:
> > > > > Evgueni,
> > > > >
> > > > > 1) Our own URLClassLoader overrides ClassLoader.loadClass method, so
> > > > > the
> > > > > idea of adding such registry to base class will not work from the
> > > > > start.
> > > > >
> > > > > 2) The question in my previous letter is not answered. If the answer
> > > > > is
> > > > > positive, then adding the registry of "initiated" classes to
> > > > > URLClassLoader
> > > > > (which AFAIU will cover the issue described by Sergey) still requires
> > > > > solid
> > > > > algorithm to distinguish the class loader which was initially asked
> > > > > to load
> > > > > a class from the one, which resides in the middle of delegation chain.
> > > > >
> > > > > I'm not against caching, I just see problems I do not know how to
> > > > > solve.
> > > > >
> > > > > WBR,
> > > > > Pavel.
> > > > >
> > > > > P.S. BTW, we have the registry of "initiated" classes but it is only
> > > > > appended on class resolutions.
> > > > > On 10/23/07, Evgueni Brevnov <[EMAIL PROTECTED]> wrote:
> > > > > >
> > > > > > Pavel,
> > > > > >
> > > > > > As you pointed out to change delegation model user must override
> > > > > > ClassLoader.loadClass() method. By doing so user can specify any
> > > > > > search order he only want and doesn't depend on caching capabilities
> > > > > > provided by java.lang.ClassLoader. If user uses default
> > > > > > implementation
> > > > > > of ClassLoader.loadClass() method then it should be safe to use
> > > > > > cache.
> > > > > > What do you think?
> > > > > >
> > > > > > Thanks
> > > > > > Evgueni
> > > > > >
> > > > > > On 10/23/07, Pavel Pervov <[EMAIL PROTECTED]> wrote:
> > > > > > > Evgueni,
> > > > > > >
> > > > > > > ClassLoader.loadClass is not final. One can overload this and
> > > > > > > build any
> > > > > > > delegation model his or her application requires. So, -1 here.
> > > > > > >
> > > > > > > It would be good to answer the following case before considering
> > > > > > > class
> > > > > > > caching.
> > > > > > >
> > > > > > > Assume, we have delegation of three class loaders: CL1<-CL2<-CL3.
> > > > > > > Assume, class Foo is only available from CL1.
> > > > > > >
> > > > > > > We call to CL3.loadClass("Foo"). The call chain will look like
> > > > > > > CL3.loadClass->CL2.loadClass->CL1.loadClass. As far as we know,
> > > > > > > the
> > > > > > second
> > > > > > > and subsequent calls to CL3.loadClass("Foo") will not call to
> > > > > > > CL2.loadClass("Foo")
> > > > > > > but return "cached" copy from CL3 on RI (as described by Sergey).
> > > > > > >
> > > > > > > But it would be really interesting to know if the call to
> > > > > > > CL2.loadClasswill
> > > > > > > result in call chain CL2.loadClass->CL1.loadClass.
> > > > > > >
> > > > > > > If this is true, my initial idea that it is only allowed to
> > > > > > > register the
> > > > > > > class in "initiating" and "defining" loaders is also true. And I
> > > > > > > have no
> > > > > > > solid solution to determining "initiating" class loader.
> > > > > > >
> > > > > > > Otherwise, it is ok to create the cache in URLClassLoader as
> > > > > > > Sergey
> > > > > > > initially suggested.
> > > > > > >
> > > > > > > Pavel.
> > > > > > >
> > > > > > > On 10/23/07, Evgueni Brevnov <[EMAIL PROTECTED]> wrote:
> > > > > > > >
> > > > > > > > Pavel,
> > > > > > > >
> > > > > > > > I think its not common situation when parent class loader is
> > > > > > > > changed
> > > > > > > > at runtime. To be honest I don't know how it's possible since
> > > > > > > > parent
> > > > > > > > class loader is kept in private field. Anyway, can we somehow
> > > > > > > > detect
> > > > > > > > such situation and switch to normal scheme or discard cached
> > > > > > > > classes
> > > > > > > > upon switching parent class loader.
> > > > > > > >
> > > > > > > > Thanks
> > > > > > > > Evgueni
> > > > > > > >
> > > > > > > > On 10/22/07, Pavel Pervov <[EMAIL PROTECTED]> wrote:
> > > > > > > > > Looking at the Java Virtual Machine Specification there are
> > > > > > > > > two
> > > > > > terms:
> > > > > > > > > initiating loader and defining loader.
> > > > > > > > >
> > > > > > > > > Initiating loader is the class loader which was first asked
> > > > > > > > > to load
> > > > > > > > class in
> > > > > > > > > delegation chain (CL2 in your example).
> > > > > > > > >
> > > > > > > > > Defining loader is the class loader which has found bytes for
> > > > > > > > > class
> > > > > > > > > definition and called to JNI->DefineClass.
> > > > > > > > >
> > > > > > > > > Lets review the following delegation model.
> > > > > > > > >
> > > > > > > > > CL1<-CL2<-CL3
> > > > > > > > >
> > > > > > > > > CL4<-CL2<-CL5
> > > > > > > > >
> > > > > > > > > There is nothing wrong with CL2: its delegation model simply
> > > > > > > > > assumes
> > > > > > > > > switching delegation parent depending on some external
> > > > > > > > > property.
> > > > > > > > >
> > > > > > > > > Different versions of class Foo are available from CL1 and
> > > > > > > > > CL4. Now,
> > > > > > we
> > > > > > > > do
> > > > > > > > > something like CL3.loadClass("Foo") and CL5.loadClass("Foo").
> > > > > > > > > If CL2 will cache the class Foo, then the call to CL5 will
> > > > > > > > > return
> > > > > > wrong
> > > > > > > > > result.
> > > > > > > > >
> > > > > > > > > So the caching is possible, but it is only allowed to
> > > > > > > > > register class
> > > > > > in
> > > > > > > > > initiating loader and in defining loader. Otherwise, you may
> > > > > > > > > have
> > > > > > wrong
> > > > > > > > > classes returned to your application.
> > > > > > > > >
> > > > > > > > > Determining defining loader is simple. Can you suggest some
> > > > > > > > > working
> > > > > > idea
> > > > > > > > on
> > > > > > > > > how to determine initiating loader for a class?
> > > > > > > > >
> > > > > > > > > WBR,
> > > > > > > > > Pavel.
> > > > > > > > >
> > > > > > > > > On 10/22/07, Sergey Dmitriev <[EMAIL PROTECTED]> wrote:
> > > > > > > > > >
> > > > > > > > > > Hello
> > > > > > > > > >
> > > > > > > > > > This letter is actually about HARMONY-4965, I just changed a
> > > > > > little
> > > > > > > > > > bit a subject. :)
> > > > > > > > > >
> > > > > > > > > > During my play with SPECjAppServer2004 on OC4J I've found
> > > > > > > > > > out that
> > > > > > we
> > > > > > > > > > have a way to optimize the class loader. Or in other words
> > > > > > currently
> > > > > > > > > >
> > > > > > > > > > Lets say we have class loaders CL1 and CL2, and
> > > > > > > > > > CL2.getParent() ==
> > > > > > > > > > CL1. And lets say we have a class C which is loaded by the
> > > > > > > > > > CL1
> > > > > > (the
> > > > > > > > > > parent one). And then we try to load class via the class
> > > > > > > > > > loader
> > > > > > CL2:
> > > > > > > > > > of course CL2 first of all tries to load it via its parent
> > > > > > > > > > CL1 and
> > > > > > > > > > succeed in it. When we try to load class C via CL2 again we
> > > > > > > > > > will
> > > > > > have
> > > > > > > > > > the same chain of calls: CL2 -> CL1. But if CL2 have
> > > > > > > > > > support of
> > > > > > > > > > caching of classes loaded by not itself - the chain can
> > > > > > > > > > become
> > > > > > much
> > > > > > > > > > shorter - it could end at CL2.findFinishedClass().
> > > > > > > > > >
> > > > > > > > > > For example RI behaves like this. See JIRA's demo.
> > > > > > > > > >
> > > > > > > > > > Back to the SPECjAppServer2004 @ OC4J. In this case we have
> > > > > > > > > > a
> > > > > > deeper
> > > > > > > > > > chain: we have a concrete class which is been searched so
> > > > > > > > > > deep
> > > > > > that we
> > > > > > > > > > looking for this class in boot strap class path. And this
> > > > > > > > > > is what
> > > > > > we
> > > > > > > > > > have in steady state of the benchmark. Don't you think it is
> > > > > > useless?
> > > > > > > > > > :)
> > > > > > > > > >
> > > > > > > > > > Talking about numbers: my measurements show that we can
> > > > > > > > > > take up to
> > > > > > 20%
> > > > > > > > > > of burst having this bug fixed. Could some competent guy
> > > > > > > > > > take a
> > > > > > look
> > > > > > > > > > into this?
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > Thanks
> > > > > > > > > > Sergey
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > --
> > > > > > > > > Pavel Pervov,
> > > > > > > > > Intel Enterprise Solutions Software Division
> > > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > --
> > > > > > > Pavel Pervov,
> > > > > > > Intel Enterprise Solutions Software Division
> > > > > > >
> > > > > >
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Pavel Pervov,
> > > > > Intel Enterprise Solutions Software Division
> > > > >
> > > >
> > >
> >
>