Why does this throw a ClassCastException?

R

Robert Paris

I have installed my ClassLoader as the System classloader (using
-Djava.system.class.loader). My ClassLoader extends URLClassLoader. In
the constructor (the only one called by the bootclasspath loader is:
YourClassLoader(ClassLoader parent) ) I call super(URL[] urls,
ClassLoader parent) by passing it like so:
Code:
MyClassLoader(ClassLoader parent)
{
super( classPathURLS, parent );
}
When I do the above, I get a class cast exception when I try to cast a
class that a class loader instance (in the program below) created to
an interface that my class loader defined.
Code:
public Doable load()
{
URLClassLoader uc = new URLClassLoader( someURLNotOnClassPath
);
Class c = uc.loadClass( "com.something.Test" );

/*
* This cast only throws an exception if my system classloader
* passes "parent" to the constructor of "super." If I instead
* do the following: "super( classPathURLS, null );" then I
* never get a ClassCastException. Does anyone know why this
is?
*/
return ( Doable ) c.newInstance();
}
Just to give some more information on the problem: in both cases
(passing "parent" to "super()" and passing "null" to "super()"), the
ClassLoader of the "Doable" class is always MyClassLoader. Also, I
have logging in every method called (when an attempt is made to load
or find a class) and it is called for Doable only once - whereupon I
define and load the class.

I'm sure I am doing something wrong, but I'm not sure what. Does
anyone have any idea what it might be?
 
A

Anton Spaans

Robert Paris said:
I have installed my ClassLoader as the System classloader (using
-Djava.system.class.loader). My ClassLoader extends URLClassLoader. In
the constructor (the only one called by the bootclasspath loader is:
YourClassLoader(ClassLoader parent) ) I call super(URL[] urls,
ClassLoader parent) by passing it like so:
Code:
MyClassLoader(ClassLoader parent)
{
super( classPathURLS, parent );
}
When I do the above, I get a class cast exception when I try to cast a
class that a class loader instance (in the program below) created to
an interface that my class loader defined.
Code:
public Doable load()
{
URLClassLoader uc = new URLClassLoader( someURLNotOnClassPath
);
Class c = uc.loadClass( "com.something.Test" );

/*
* This cast only throws an exception if my system classloader
* passes "parent" to the constructor of "super." If I instead
* do the following: "super( classPathURLS, null );" then I
* never get a ClassCastException. Does anyone know why this
is?
*/
return ( Doable ) c.newInstance();
}
Just to give some more information on the problem: in both cases
(passing "parent" to "super()" and passing "null" to "super()"), the
ClassLoader of the "Doable" class is always MyClassLoader. Also, I
have logging in every method called (when an attempt is made to load
or find a class) and it is called for Doable only once - whereupon I
define and load the class.

I'm sure I am doing something wrong, but I'm not sure what. Does
anyone have any idea what it might be?

Which class loader loaded the class Double() in your example? I assume it
is the system's classloader?

Two classes having the same name (fully qualified) but that are loaded by
two different classloaders can be different. I.e. a class-cast exception may
be thrown. E.g:

ClassLoader cl1 = ...;
ClassLoader cl2 = ...;

Class klass1 = cl1.loadClass("com.something.Test");
Class klass2 = cl2.loadClass("com.something.Test");

Object obj1 = cl1.newInstance();
Object obj2 = cl1.newInstance();

Now: obj1 and obj1 are of different types: klass1.equals(klass2) will return
false.

In your case, the Double class is probably loaded by the system classloader.
The instance returned by your call 'c.newInstance()' may *look* as a
subclass of Double, but it is not, because 'c' is not loaded by the system
classloader.

-- Anton Spaans.
 
A

Anton Spaans

Anton Spaans said:
Robert Paris said:
I have installed my ClassLoader as the System classloader (using
-Djava.system.class.loader). My ClassLoader extends URLClassLoader. In
the constructor (the only one called by the bootclasspath loader is:
YourClassLoader(ClassLoader parent) ) I call super(URL[] urls,
ClassLoader parent) by passing it like so:
Code:
MyClassLoader(ClassLoader parent)
{
super( classPathURLS, parent );
}
When I do the above, I get a class cast exception when I try to cast a
class that a class loader instance (in the program below) created to
an interface that my class loader defined.
Code:
public Doable load()
{
URLClassLoader uc = new URLClassLoader( someURLNotOnClassPath
);
Class c = uc.loadClass( "com.something.Test" );

/*
* This cast only throws an exception if my system classloader
* passes "parent" to the constructor of "super." If I instead
* do the following: "super( classPathURLS, null );" then I
* never get a ClassCastException. Does anyone know why this
is?
*/
return ( Doable ) c.newInstance();
}
Just to give some more information on the problem: in both cases
(passing "parent" to "super()" and passing "null" to "super()"), the
ClassLoader of the "Doable" class is always MyClassLoader. Also, I
have logging in every method called (when an attempt is made to load
or find a class) and it is called for Doable only once - whereupon I
define and load the class.

I'm sure I am doing something wrong, but I'm not sure what. Does
anyone have any idea what it might be?

Which class loader loaded the class Double() in your example? I assume it
is the system's classloader?

Two classes having the same name (fully qualified) but that are loaded by
two different classloaders can be different. I.e. a class-cast exception may
be thrown. E.g:

ClassLoader cl1 = ...;
ClassLoader cl2 = ...;

Class klass1 = cl1.loadClass("com.something.Test");
Class klass2 = cl2.loadClass("com.something.Test");

Object obj1 = cl1.newInstance();
Object obj2 = cl1.newInstance();

Now: obj1 and obj1 are of different types: klass1.equals(klass2) will return
false.

In your case, the Double class is probably loaded by the system classloader.
The instance returned by your call 'c.newInstance()' may *look* as a
subclass of Double, but it is not, because 'c' is not loaded by the system
classloader.

-- Anton Spaans.

Oops.. did not read the last part of your question too well.
But the idea of my response remains the same:

MyClassLoader != URLClassLoader

Try to construct a URLClassLoader whose parent is MyClassLoader.

URLClassLoader uc = new URLClassLoader( someURLNotOnClassPath,
myClassLoaderInstance);

-- Anton.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top