ClassCastException and ClassLoaders

Discussion in 'Java' started by Luther Baker, Sep 9, 2003.

  1. Luther Baker

    Luther Baker Guest

    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");
    }
    }
    Luther Baker, Sep 9, 2003
    #1
    1. Advertising

  2. Luther Baker

    Dave Glasser Guest

    (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
    Dave Glasser, Sep 9, 2003
    #2
    1. Advertising

  3. In article <>, 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");
    > }
    > }
    A. Bolmarcich, Sep 9, 2003
    #3
  4. Luther Baker

    Luther Baker Guest

    9.net (A. Bolmarcich) wrote in message news:<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/weblog/2003/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/developer/TechTips/2000/tt1027.html

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

    -Luther
    Luther Baker, Sep 10, 2003
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Brown
    Replies:
    3
    Views:
    4,035
    John C. Bollinger
    Aug 9, 2004
  2. Erik Berglund

    Tomcat and classloaders

    Erik Berglund, Sep 6, 2004, in forum: Java
    Replies:
    7
    Views:
    3,416
    Albretch
    Sep 18, 2004
  3. Replies:
    3
    Views:
    324
    John C. Bollinger
    Feb 7, 2005
  4. Josef Garvi

    Generics and ClassLoaders

    Josef Garvi, Apr 29, 2005, in forum: Java
    Replies:
    4
    Views:
    3,044
    Josef Garvi
    Apr 30, 2005
  5. Replies:
    2
    Views:
    404
    Chris Uppal
    Jun 22, 2005
Loading...

Share This Page