Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > ClassCastException and ClassLoaders

Reply
Thread Tools

ClassCastException and ClassLoaders

 
 
Luther Baker
Guest
Posts: n/a
 
      09-08-2003
Hi,

I've been walking through Stuart Halloway and Ted Newards' books on
Java component development - and can't seem to figure out how to
correctly cast a custom loaded class to a common interface.

Here is my dir structure:

classes/subdir/PointImpl.class
classes/IPoint.class
classes/PointClient.class
classes/PointServer.class

Here is my classpath:

CLASSPATH=/classes


Everything is explicitly in the classpath, except the Point
Implementation class. If I use this line:

URL[] serverURLs = new URL[] { new URL
("file:classes/subdir/") };

I get the following runtime exception:

java.lang.NoClassDefFoundError: Point

Whereas, if I use this line:

URL[] serverURLs = new URL[] { new URL
("file:classes/subdir/"), new URL ("file:classes/") };

I get the following runtime exception:

Exception: java.lang.ClassCastException

I would guess that the URLClassLoader needs to see the IPoint.class
interface, so it makes sense to include the additional path (although
Stuart's example does not), but when I add the the classes directory
to the URLClassLoader classpath, it correctly instantiates PointImpl,
but cannot cast it since the primordial and custom class loaders see
two unique IPoint interfaces.

Looking for suggestions on how to correctly cast to a common
interface, when using different class loaders ... or at least, some
insight into what Stuart implies can be done.

Thanks,

-Luther


import java.net.*;

public class PointServer
{
static ClassLoader cl_;
static Class ptClass_;

public static synchronized Point
createPoint (Point template)
throws Exception
{
if (ptClass_ == null) {
PointServer.reloadImpl ();
}


//// CLASS CAST EXCEPTION OCCURS HERE
Point newPt = (Point) ptClass_.newInstance ();



if (template != null) {
newPt.move (template.getX(), template.getY());
}
return newPt;
}

public static synchronized
void reloadImpl ()
throws Exception
{
URL[] serverURLs = new URL[] { new URL
("file:classes/subdir/"), new URL ("file:classes/") };
Class localClass = PointServer.class.getClass ();
ClassLoader localClassLoader = localClass.getClassLoader ();
cl_ = new URLClassLoader (serverURLs, localClassLoader);
ptClass_ = cl_.loadClass ("PointImpl");
}
}
 
Reply With Quote
 
 
 
 
Dave Glasser
Guest
Posts: n/a
 
      09-09-2003
http://www.velocityreviews.com/forums/(E-Mail Removed) (Luther Baker) wrote on 8 Sep 2003 16:42:52
-0700 in comp.lang.java.programmer:

>Hi,
>
>I've been walking through Stuart Halloway and Ted Newards' books on
>Java component development - and can't seem to figure out how to
>correctly cast a custom loaded class to a common interface.
>
>Here is my dir structure:
>
> classes/subdir/PointImpl.class
> classes/IPoint.class
> classes/PointClient.class
> classes/PointServer.class
>
>Here is my classpath:
>
> CLASSPATH=/classes
>
>
>Everything is explicitly in the classpath, except the Point
>Implementation class. If I use this line:
>
> URL[] serverURLs = new URL[] { new URL
>("file:classes/subdir/") };
>
>I get the following runtime exception:
>
> java.lang.NoClassDefFoundError: Point
>
>Whereas, if I use this line:
>
> URL[] serverURLs = new URL[] { new URL
>("file:classes/subdir/"), new URL ("file:classes/") };
>
>I get the following runtime exception:
>
> Exception: java.lang.ClassCastException
>
>I would guess that the URLClassLoader needs to see the IPoint.class
>interface, so it makes sense to include the additional path (although
>Stuart's example does not), but when I add the the classes directory
>to the URLClassLoader classpath, it correctly instantiates PointImpl,
>but cannot cast it since the primordial and custom class loaders see
>two unique IPoint interfaces.
>
>Looking for suggestions on how to correctly cast to a common
>interface, when using different class loaders ... or at least, some
>insight into what Stuart implies can be done.
>
>Thanks,
>
>-Luther
>
>
>import java.net.*;
>
>public class PointServer
>{
> static ClassLoader cl_;
> static Class ptClass_;
>
> public static synchronized Point
> createPoint (Point template)
> throws Exception
> {
> if (ptClass_ == null) {
> PointServer.reloadImpl ();
> }
>
>
> //// CLASS CAST EXCEPTION OCCURS HERE
> Point newPt = (Point) ptClass_.newInstance ();
>
>
>
> if (template != null) {
> newPt.move (template.getX(), template.getY());
> }
> return newPt;
> }
>
> public static synchronized
> void reloadImpl ()
> throws Exception
> {
> URL[] serverURLs = new URL[] { new URL
>("file:classes/subdir/"), new URL ("file:classes/") };
> Class localClass = PointServer.class.getClass ();
> ClassLoader localClassLoader = localClass.getClassLoader ();
> cl_ = new URLClassLoader (serverURLs, localClassLoader);
> ptClass_ = cl_.loadClass ("PointImpl");
> }
>}



Does PointImpl implement Point, or IPoint? Where is the Point
class/interface, anyway? You're not really giving enough information
here to diagnose the cause of the ClassCastException.



----
Check out QueryForm, a free, open source, Java/Swing-based
front end for relational databases.

http://qform.sourceforge.net
 
Reply With Quote
 
 
 
 
A. Bolmarcich
Guest
Posts: n/a
 
      09-09-2003
In article <(E-Mail Removed) >, Luther Baker wrote:
> Hi,
>
> I've been walking through Stuart Halloway and Ted Newards' books on
> Java component development - and can't seem to figure out how to
> correctly cast a custom loaded class to a common interface.
>
> Here is my dir structure:
>
> classes/subdir/PointImpl.class
> classes/IPoint.class
> classes/PointClient.class
> classes/PointServer.class
>
> Here is my classpath:
>
> CLASSPATH=/classes
>
>
> Everything is explicitly in the classpath, except the Point
> Implementation class. If I use this line:
>
> URL[] serverURLs = new URL[] { new URL
> ("file:classes/subdir/") };
>
> I get the following runtime exception:
>
> java.lang.NoClassDefFoundError: Point


What is the Point class? Previously, you listed an IPoint class, but not
a Point class.

>
> Whereas, if I use this line:
>
> URL[] serverURLs = new URL[] { new URL
> ("file:classes/subdir/"), new URL ("file:classes/") };
>
> I get the following runtime exception:
>
> Exception: java.lang.ClassCastException
>
> I would guess that the URLClassLoader needs to see the IPoint.class
> interface, so it makes sense to include the additional path (although
> Stuart's example does not), but when I add the the classes directory
> to the URLClassLoader classpath, it correctly instantiates PointImpl,
> but cannot cast it since the primordial and custom class loaders see
> two unique IPoint interfaces.
>
> Looking for suggestions on how to correctly cast to a common
> interface, when using different class loaders ... or at least, some
> insight into what Stuart implies can be done.
>
> Thanks,
>
> -Luther
>
>
> import java.net.*;
>
> public class PointServer
> {
> static ClassLoader cl_;
> static Class ptClass_;
>


Based on your description, all the following occurences of "Point" as
a Java type should be "IPoint".

> public static synchronized Point
> createPoint (Point template)
> throws Exception
> {
> if (ptClass_ == null) {
> PointServer.reloadImpl ();
> }
>
>
> //// CLASS CAST EXCEPTION OCCURS HERE
> Point newPt = (Point) ptClass_.newInstance ();
>
>
>
> if (template != null) {
> newPt.move (template.getX(), template.getY());
> }
> return newPt;
> }
>
> public static synchronized
> void reloadImpl ()
> throws Exception
> {
> URL[] serverURLs = new URL[] { new URL
> ("file:classes/subdir/"), new URL ("file:classes/") };


You should only use the subdir URL. Using the second URL will have the
URL class loader load the IPoint interface, which, as you described, is
a different class than the one loaded the the class loader of PointServer.
You want the URL class loader to delegate the loading of IPoint to
the class loader that loaded PointServer.

> Class localClass = PointServer.class.getClass ();
> ClassLoader localClassLoader = localClass.getClassLoader ();
> cl_ = new URLClassLoader (serverURLs, localClassLoader);


The getClassLoader() method may return null to indicate that the class
was loaded by the bootstrap class loader. When that happens, the
URLClassLoader(serverURLs, localClassLoader) will not delegate the
loading of classes not in subdir to the bootstrap class loader. For
this example, you can use

cl_ = new URLClassLoader (serverURLs);

More generally, you can use

if (localClassLoader == null) {
cl_ = new URLClassLoader (serverURLs);
else
cl_ = new URLClassLoader (serverURLs, localClassLoader);
}

> ptClass_ = cl_.loadClass ("PointImpl");
> }
> }

 
Reply With Quote
 
Luther Baker
Guest
Posts: n/a
 
      09-10-2003
http://www.velocityreviews.com/forums/(E-Mail Removed)9.net (A. Bolmarcich) wrote in message news:<(E-Mail Removed)9.net>...
>
> Based on your description, all the following occurences of "Point" as
> a Java type should be "IPoint".
>


Yes. I was remembering the original example, and forget that I didn't
do that.

> > URL[] serverURLs = new URL[] { new URL
> > ("file:classes/subdir/"), new URL ("file:classes/") };

>
> You should only use the subdir URL. Using the second URL will have the
> URL class loader load the IPoint interface, which, as you described, is
> a different class than the one loaded the the class loader of PointServer.
> You want the URL class loader to delegate the loading of IPoint to
> the class loader that loaded PointServer.


Thank you very much for the clarification.

>
> More generally, you can use
>
> if (localClassLoader == null) {
> cl_ = new URLClassLoader (serverURLs);
> else
> cl_ = new URLClassLoader (serverURLs, localClassLoader);
> }
>


Ah. Good point. I actually added the longer version in when I couldn't
get the single argument to work. I thought that by providing the
parent, the URLClassLoader would somehow talk to the parent and find
the interface. As you point out, though, the parent is most likely
null.

So, after your mail I decided that the only unknown was Ant. I
immediately put javac and java in my path and did everything manually
.... ant it works.

So back to ant and I include fork="true" and all is well. I should've
thought of that. I guess that ant's classloader is somehow interfering
here ... Stuart implies tomcat, ant and junit do not write delegating
classloaders ... I wonder if that's causing this ...

http://staff.develop.com/halloway/we...02/14.html#a24

For those of you lost since I've provided so little code, here is a
version of the example I was trying to create:

http://developer.java.sun.com/develo...00/tt1027.html

Many thanks to both of you for your help. This opens quite a few doors
for me.

-Luther
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Plug-in classloaders and class path rexguo@h.o.t.m.a.i.l.c.o.m Java 2 06-22-2005 08:31 AM
Generics and ClassLoaders Josef Garvi Java 4 04-30-2005 06:59 AM
plugins, api and classloaders ittay.dror@gmail.com Java 3 02-07-2005 04:44 PM
Tomcat and classloaders Erik Berglund Java 7 09-18-2004 09:48 PM
RMI, singletons and multiple classloaders in Weblogic Michael Brown Java 3 08-09-2004 08:49 PM



Advertisments