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

Ok, what's wrong with this ClassLoader ?

1 view
Skip to first unread message

snows...@yahoo.com

unread,
Mar 5, 2000, 3:00:00 AM3/5/00
to
Hi all:

I am having problems with the following ClassLoader.
When I try to use it, I keep getting an exception.
This class loader is intended to load just one local
class file - that class file just happens to be the
class file for the loader itself. (pleasingly ironic
I thought). Can any classloader experts shed any
light on this ? The code, which is very simple, follows below:

import java.io.*;

class FunkyClassLoader extends java.lang.ClassLoader {
String mClassToLoad = "FunkyClassLoader.class";
public synchronized Class loadClass(String name) {
System.out.println("in FunkyClassLoader.loadClass()");
Class c = null;
byte data[] = loadClassData(name);
c = defineClass(data, 0, data.length);
System.out.println("successfully defined class");
return c;
}

private byte[] loadClassData(String name) {
byte[] buf = null;
try {
InputStream in = new BufferedInputStream(
new FileInputStream(mClassToLoad));
buf = new byte[in.available()];
in.read(buf);
}
catch (Exception e) {
e.printStackTrace();
}
return buf;
}

} //~FunkyClassLoader


public class ClassLoaderTest {
public static void main(String args[]) {
try {
FunkyClassLoader testobj = new FunkyClassLoader();
Object obj = testobj.loadClass("foobar(ignored)").newInstance();
}
catch (Exception e) { e.printStackTrace(); }
}
} //~ ClassLoaderTest

And this is the exception I get when I run
java ClassLoaderTest

in FunkyClassLoader.loadClass()
in FunkyClassLoader.loadClass()
Exception in thread "main" java.lang.LinkageError: trying to refine
class FunkyClassLoader (bad class loader?)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:442)
at java.lang.ClassLoader.defineClass(ClassLoader.java:340)
at FunkyClassLoader.loadClass(FunkyClassLoader.java:9)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:442)
at java.lang.ClassLoader.defineClass(ClassLoader.java:340)
at FunkyClassLoader.loadClass(FunkyClassLoader.java:9)
at ClassLoaderTest.main(ClassLoaderTest.java:5)

Any help/comments appreciated. (why does defineClass0 call loadClass
again ?)

snows...@yahoo.com


Sent via Deja.com http://www.deja.com/
Before you buy.

Peter.H...@jyra.com

unread,
Mar 6, 2000, 3:00:00 AM3/6/00
to
I think you've oversimplified your class loader. When your class loader
resolves the class FunkyClassLoader, it tries to load each class that
FunkyClassLoader depends on. But you've decided to ignore the class
name and load FunkyClassLoader every time, so for the subsequent
classes you end up trying to redefine the original class
(FunkyClassLoader). This doesn't work - you can only define a given
class once within a class loader.

In order to be useful, your class loader needs to avoid re-loading
previously loaded classes, and also defer those classes it can't handle
back to the system class loader. For example:

public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = null;
c = (Class)oCache.get(name);
if (c == null)
{
try // have a go with the custom load algorithm
{
byte[] data = loadClassData(name);
c = defineClass(name, data, 0, data.length);
}
catch (ClassNotFoundException e)
{
// fallback - use the system loader to load the class
c = findSystemClass(name);
}
oCache.put(name, c);
}
if (resolve)
{
resolveClass(c);
}
return c;
} // end loadClass()

Hope this helps,
Peter Humphries

In article <89ur4v$mg9$1...@nnrp1.deja.com>,

Narayanan

unread,
Mar 6, 2000, 3:00:00 AM3/6/00
to
In article <89ur4v$mg9$1...@nnrp1.deja.com>, snows...@yahoo.com says...

>
>Hi all:
>
>I am having problems with the following ClassLoader.
>When I try to use it, I keep getting an exception.

Mode pedantic on
Well the first thing you need to understand before going to class
loader is difference between Exception and Error :-).
You are getting a linkage error. Had you used jdk1.1 you would have got
ClassFormatError

Mode pedantic off

>This class loader is intended to load just one local
>class file - that class file just happens to be the
>class file for the loader itself. (pleasingly ironic
>I thought).

You seem to be loading a the Funkyclassloader class under the same
Funkyclassloader. Hmm... very interesting :-).
That is asking for trouble.

The FunkyClassLoader tries to define itself and in an attempt
to do so tries to loadClass of ClassLoader too as it is
being referenced by this class. All classes being
referenced in the class file will get recursively loaded.
Firstly you need to find if the class is already loaded by the class.
You need to do findLoadedClass. If that call fails, try to findSystemClass
with the bytes, if that fails try to do defineClass.
I have modified your class. If you want a new definition of
the class change the order of defineClass and findSystemClass.
If you have loadFromFile ahead of findSystemClass
it is not possible to
do a newInstance from the main method as the main method which is being
executed is loaded by old class loader and you are trying to call
a method of a class loaded by new class loader.

===================================================
import java.io.*;

class FunkyClassLoader extends java.lang.ClassLoader {
String mClassToLoad = "FunkyClassLoader.class";

public synchronized Class loadClass(String name) throws ClassNotFoundException
{
System.out.println(name);


System.out.println("in FunkyClassLoader.loadClass()");
Class c = null;

c = findLoadedClass(name);
if (c!= null)
return c;

byte data[] = loadClassData(name);

try
{


c = defineClass(data, 0, data.length);

resolveClass(c);
}
catch (Throwable e)
{
try
{
c = findSystemClass(name);
if (c != null)
return c;
}
catch(Exception ex){ex.printStackTrace();}

}
if (c == null)
throw new ClassNotFoundException(name);


System.out.println("successfully defined class");

return c;
}

private byte[] loadClassData(String name) throws ClassNotFoundException{
byte[] buf = null;
File f = new File(name);
if ( !f.exists())
{
name = "/usr/jdk1.1.8/classes/"+name.replaceChar('.','/');
//will have to play different trick with windows


}
try {
InputStream in = new BufferedInputStream(

new FileInputStream(name+".class"));


buf = new byte[in.available()];
in.read(buf);
}
catch (Exception e) {
e.printStackTrace();

throw new ClassNotFoundException(name);
}
return buf;
}

} //~FunkyClassLoader

public class ClassLoaderTest {
public static void main(String args[]) {
try {
FunkyClassLoader testobj = new FunkyClassLoader();

Object obj = testobj.loadClass("FunkyClassLoader").newInstance();
//Class c = testobj.loadClass("FunkyClassLoader");


}
catch (Exception e) { e.printStackTrace(); }
}
} //~ ClassLoaderTest

0 new messages