Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ClassLoader

0 views
Skip to first unread message

Come Raczy

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
Hi,

I'm trying to write my own class loader (jdk1.2rc1). Particularly,
I'd like to force the class loader to reload a class even if it was
already loaded. I've writen something like that:

public static class MyClassLoader extends URLClassLoader {
public MyClassLoader(java.net.URL[] urls, ClassLoader father) {
super(urls, father);
}
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class theClass = findClass(name);
if (resolve) {
resolveClass(theClass);
}
return theClass;
}
}

Then I build a new class loader and load a class:

MyClassLoader classLoader = new MyClassLoader(urls, father);
Class newClass = classLoader.loadClass("ClassToLoad", true);

I get the following exception:

java.lang.LinkageError: wrong Throwable class linked with ClassToLoad
at java.lang.ClassLoader.resolveClass0(Native Method)
at java.lang.ClassLoader.resolveClass(ClassLoader.java:429)
at test.LoadClass$MyClassLoader.loadClass(LoadClass.java:20)
at test.LoadClass.main(Compiled Code)
Exception in thread "main"
Process test.LoadClass exited abnormally with code 1

If I don't ask for the resolveClass, I get the same erros, as soon
as I try to use theClass. What does it mean? What should I to avoid
the problem?

Come

Mathias Waack

unread,
Nov 16, 1998, 3:00:00 AM11/16/98
to
In article <364c7d00....@news.belnet.be>,

ra...@fucam.ac.be (Come Raczy) writes:
> I'm trying to write my own class loader (jdk1.2rc1). Particularly,
> I'd like to force the class loader to reload a class even if it was
> already loaded. I've writen something like that:
>
> public static class MyClassLoader extends URLClassLoader {
> public Class loadClass(String name, boolean resolve)
> throws ClassNotFoundException {
> [code snipped]

> }
> }
>
> Then I build a new class loader and load a class:
>
> MyClassLoader classLoader = new MyClassLoader(urls, father);
> Class newClass = classLoader.loadClass("ClassToLoad", true);
>
> I get the following exception:
>
> java.lang.LinkageError: wrong Throwable class linked with ClassToLoad
> at java.lang.ClassLoader.resolveClass0(Native Method)
> at java.lang.ClassLoader.resolveClass(ClassLoader.java:429)
> at test.LoadClass$MyClassLoader.loadClass(LoadClass.java:20)
> at test.LoadClass.main(Compiled Code)
> Exception in thread "main"
> Process test.LoadClass exited abnormally with code 1
>
> If I don't ask for the resolveClass, I get the same erros, as soon
> as I try to use theClass. What does it mean? What should I to avoid
> the problem?
I've got the same proble. The common solution is to overwrite the
findClass() method instead of the loadClass() methods.
But the findClass() methods first look for the class in a kind of
cache, so they will call your findClass() method only for classes which
are not loaded at this time (and which are not System-classes!).
So you must unload a class before you can reload it. This can be
done by calling the gc if there are no references to instances of
your class.
Another solution is to create a new classloader for each class which
should be reloaded. I would choose this method.

Hope that helps
Mathias

Come Raczy

unread,
Nov 17, 1998, 3:00:00 AM11/17/98
to
On 16 Nov 1998 09:07:45 GMT, mat...@mufasa.informatik.uni-mannheim.de
(Mathias Waack) wrote:

>In article <364c7d00....@news.belnet.be>,
> ra...@fucam.ac.be (Come Raczy) writes:
>> I'm trying to write my own class loader (jdk1.2rc1). Particularly,
>> I'd like to force the class loader to reload a class even if it was
>> already loaded.

>> [snip, snip, snip...]

>I've got the same proble. The common solution is to overwrite the
>findClass() method instead of the loadClass() methods.
>But the findClass() methods first look for the class in a kind of
>cache, so they will call your findClass() method only for classes which
>are not loaded at this time (and which are not System-classes!).
>So you must unload a class before you can reload it. This can be
>done by calling the gc if there are no references to instances of
>your class.

That seems a good starting point, but I can't really force the
invocation of the gc. I've seen something like a finalize method
for classes, which could be used to synchronize the findClass()
and the unloading of the class. Actually, there are too many things
that I don't really understand in this pocess (is there something
easy to understand about that topic?)

>Another solution is to create a new classloader for each class which
>should be reloaded. I would choose this method.

That seems to be a hard work. Do you have any pointer, doc or book
reference about this topic?

Come


Mathias Waack

unread,
Nov 17, 1998, 3:00:00 AM11/17/98
to
In article <365136cd...@news.belnet.be>,
Where's the problem? To run a Java-App XXX you must simply:
1. create an instance of your classloader
2. load the class XXX
3. invoke the main()-method of the class XXX
That's all.

Regards
Mathias

--
Mathias Waack | mat...@mufasa.informatik.uni-mannheim.de
Tel.: +49 621 292 1620 Fax.: +49 621 292 5597

Come Raczy

unread,
Nov 17, 1998, 3:00:00 AM11/17/98
to
On 17 Nov 1998 11:02:46 GMT, mat...@mufasa.informatik.uni-mannheim.de
(Mathias Waack) wrote:

>In article <365136cd...@news.belnet.be>,
> ra...@fucam.ac.be (Come Raczy) writes:
>> On 16 Nov 1998 09:07:45 GMT, mat...@mufasa.informatik.uni-mannheim.de
>> (Mathias Waack) wrote:
>>>Another solution is to create a new classloader for each class which
>>>should be reloaded. I would choose this method.
>>
>> That seems to be a hard work. Do you have any pointer, doc or book
>> reference about this topic?
>Where's the problem? To run a Java-App XXX you must simply:
> 1. create an instance of your classloader
> 2. load the class XXX
> 3. invoke the main()-method of the class XXX
>That's all.

The problem is that if I use SecureClassLoader or URLClassLoader,
they do a call to the findLoadedClass(String) method to know if
the loaded class must actually be loaded. So I have to write my
own class loader. In this case, I have to link the class and I
have no idea about the way to do that. Did I miss out something
important?

Come

David Smiley

unread,
Nov 17, 1998, 3:00:00 AM11/17/98
to

Mathias Waack wrote:
>
> In article <364c7d00....@news.belnet.be>,


> ra...@fucam.ac.be (Come Raczy) writes:
> > I'm trying to write my own class loader (jdk1.2rc1). Particularly,
> > I'd like to force the class loader to reload a class even if it was

> > already loaded. I've writen something like that:

[snip]


> I've got the same proble. The common solution is to overwrite the
> findClass() method instead of the loadClass() methods.
> But the findClass() methods first look for the class in a kind of
> cache, so they will call your findClass() method only for classes which
> are not loaded at this time (and which are not System-classes!).
> So you must unload a class before you can reload it. This can be
> done by calling the gc if there are no references to instances of
> your class.

> Another solution is to create a new classloader for each class which
> should be reloaded. I would choose this method.

From my understanding the ONLY way to re-load a class is to have a
seperate ClassLoader instance for each set of classes that you want
re-loaded. You null out the classes, AND the ClassLoader that loaded
them... then create a new ClassLoader and start over. If anybody knows
otherwise (because they actually know somehow, not from conjecturing on
javadocs), please tell me.

Cheers,
David Smiley

Mathias Waack

unread,
Nov 18, 1998, 3:00:00 AM11/18/98
to
In article <3651bc96...@news.belnet.be>,

ra...@fucam.ac.be (Come Raczy) writes:
> The problem is that if I use SecureClassLoader or URLClassLoader,
> they do a call to the findLoadedClass(String) method to know if
> the loaded class must actually be loaded. So I have to write my
> own class loader. In this case, I have to link the class and I
> have no idea about the way to do that. Did I miss out something
> important?
The javadoc-docu says about findLoadedClass:

Finds the class with the given name if it had been previously
loaded through this(!!!) class loader.

So I'm still didn't understand your problem. Create a new
URLClassLoader without parent, load your class and all things
will be right. No matter it this class was loaded by another
ClassLoader, the classes are not the same (two classes are the
same in Java, if they have the same name _and_ the same
ClassLoader).

Regards
Mathias

Come Raczy

unread,
Nov 18, 1998, 3:00:00 AM11/18/98
to
On 18 Nov 1998 12:45:06 GMT, mat...@mufasa.informatik.uni-mannheim.de
(Mathias Waack) wrote:

The fact is that if I create a new URLClassLoader without
parent and use its loadClass method for a class already loaded,
the class is *not* loaded again. I tried this with jdk1.2 RC1.

According to the doc (and the source) of jdk1.2 RC1, the default
implementation of the method loadClass does the following:

- findLoadedClass(String) to check if the class has already been
loaded.
- Call the loadClass method on the parent class loader. If the
parent is null the class loader built-in to the virtual machine is
used, instead.
- Call the findClass(String) method to find the class.

Although you're absolutely right about the result of the
findLoadedClass, this delegation model prohibits reloading of classes.
I've tried to call directly the findClass method, and there I got
LinkageErrors, which was the topic of my first post. Basically,
my problem is to reload a class without restarting the VM.

Best regards

Come

>
>Regards
> Mathias


Mathias Waack

unread,
Nov 18, 1998, 3:00:00 AM11/18/98
to
In article <3652c8a5....@news.belnet.be>,

ra...@fucam.ac.be (Come Raczy) writes:
> The fact is that if I create a new URLClassLoader without
> parent and use its loadClass method for a class already loaded,
> the class is *not* loaded again. I tried this with jdk1.2 RC1.
I've tried this with jdk1.2 RC1 (under Solaris) too and I've got
what I've expected...

>
> According to the doc (and the source) of jdk1.2 RC1, the default
> implementation of the method loadClass does the following:
>
> - findLoadedClass(String) to check if the class has already been
> loaded.
> - Call the loadClass method on the parent class loader. If the
> parent is null the class loader built-in to the virtual machine is
> used, instead.
> - Call the findClass(String) method to find the class.
Yeah, that's all right, but if one instance of a ClassLoader calls
findLoadedClass(String) it can't see the classes allready loaded
by another ClassLoader (did you understand the difference between
a class and an instance?)

>
> Although you're absolutely right about the result of the
> findLoadedClass, this delegation model prohibits reloading of classes.
Yeah, you _didn't_ understand the difference:(

> I've tried to call directly the findClass method, and there I got
> LinkageErrors, which was the topic of my first post. Basically,
> my problem is to reload a class without restarting the VM.
That's ok, you must not call the findClass() methods directly.

Okay, I give you an example for better understanding:
Let's load a class XXX.java:

public class XXX {
public int k;
}

For loading we're using a class Test (very good name, isn't it:) )

import java.net.*;
import java.io.*;
import java.lang.reflect.*;

public class Test {
public Class c = null;
public Test() {
try {
URLClassLoader cl = new URLClassLoader(
new URL[] { new URL("file://<the path to the XXX.class file>") }, null);
c = cl.loadClass("XXX");
} catch (ClassNotFoundException e1) {
//System.out.println(e1);
e1.printStackTrace();
} catch (MalformedURLException e) {
System.out.println(e);
}
}
public static void main(String args[]) {
Test t1 = new Test();
try {
System.out.println("Press Enter to continue");
System.in.read();
} catch (IOException e) {
}
Test t2 = new Test();
Field f1[] = t1.c.getFields();
System.out.println(t1.c);
System.out.println(f1[0]);
Field f2[] = t2.c.getFields();
System.out.println(t2.c);
System.out.println(f2[0]);
}
}

Now I call "java Test" and get the prompt "Press Enter to continue"
I'm editing XXX.java and changing the name "k" to "i", and compile the
class again.
Now I press enter and the result is (all output):

Press Enter to continue

class XXX
public int XXX.k
class XXX
public int XXX.i

No magic things, no own ClassLoader - and all works as expect. Now tell
me how you did the test and why you've got another results.

David Smiley

unread,
Nov 18, 1998, 3:00:00 AM11/18/98
to
Come Raczy wrote:
[snip]

> The fact is that if I create a new URLClassLoader without
> parent and use its loadClass method for a class already loaded,
> the class is *not* loaded again. I tried this with jdk1.2 RC1.

What you have not told us is *what* loaded the other class. If that
was the primordial built-in system ClassLoader, then I don't think it is
re-loadable at all (especially in jdk1.2). If that class was loaded by
a ClassLoader that you have control of, then you can remove all
references to the Class, instances of it, *and* the instance of the
ClassLoader that loaded it... then you can re-load the class with any
ClassLoader you want.

> According to the doc (and the source) of jdk1.2 RC1, the default
> implementation of the method loadClass does the following:
>
> - findLoadedClass(String) to check if the class has already been
> loaded.
> - Call the loadClass method on the parent class loader. If the
> parent is null the class loader built-in to the virtual machine is
> used, instead.
> - Call the findClass(String) method to find the class.
>

> Although you're absolutely right about the result of the
> findLoadedClass, this delegation model prohibits reloading of classes.

Mmmm. If you think about it, this is not surprising. Since you don't
really have control of what the system ClassLoader is up to, you
shouldn't be able to load its classes. It is a special, unique
ClassLoader. Don't put classes you want unloadable on the classpath.

> I've tried to call directly the findClass method, and there I got
> LinkageErrors, which was the topic of my first post. Basically,
> my problem is to reload a class without restarting the VM.

Cheers,
David Smiley

Dario Scopesi

unread,
Nov 19, 1998, 3:00:00 AM11/19/98
to
On Tue, 17 Nov 1998 17:50:52 -0500, David Smiley <dsm...@mitre.org>
wrote:

>
>
>Mathias Waack wrote:
>>
>> In article <364c7d00....@news.belnet.be>,

Well, I'm working on a servlet application right now, and encountered
the same problem.
I solved it in this way: when I want to reload a service class (I have
one only servlet, and it launches different services), I just get rid
of every reference to its object (I have only one instance per class)
and then I call System.gc();
It works. Without using classloaders.

Dario

____________________________________________________________
Dario Scopesi
Software engineering student at
Politecnico di Milano - ITALY
Java, C++ and MSAccess developer

mailto:dario....@usa.net.NOSPAM (remove '.NOSPAM')
http://dscopesi.freeweb.org
____________________________________________________________

David Smiley

unread,
Nov 19, 1998, 3:00:00 AM11/19/98
to
Dario Scopesi wrote:
[snip]

> Well, I'm working on a servlet application right now, and encountered
> the same problem.
> I solved it in this way: when I want to reload a service class (I have
> one only servlet, and it launches different services), I just get rid
> of every reference to its object (I have only one instance per class)
> and then I call System.gc();
> It works. Without using classloaders.

Well, it may work, but I don't think it is "correct". I am almost
certain that somewhere in the specs, there is info that would prove
this. I am wondering if you could get it to work without calling
System.gc(). Your way may not work on other VMs. If I every see a call
to System.gc() in code, I get suspiscious... only use it for
optimization. Regardless, you could grab a public-domain classloader
and get up and running in no time with "correct" code.

Cheers,
David Smiley

0 new messages