Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / October 2007

Tip: Looking for answers? Try searching our database.

why do I get this runtime error

Thread view: 
Aryeh M. Friedman - 05 Oct 2007 11:05 GMT
When I run this:

package scratch;

import java.io.*;

public class Main extends ClassLoader
{
       public Main()
       {
               super(Main.class.getClassLoader());
       }

       public static void main(String[] args)
               throws Throwable
       {
               Main m=new Main();

               File f=null;

               f = new File("/usr/home/plos/obj/scratch/Main.class");
               int size = (int)f.length();
               byte buff[] = new byte[size];
               FileInputStream fis = new FileInputStream(f);
               DataInputStream dis = new DataInputStream(fis);
               dis.readFully(buff);
               dis.close();

               Class klass=m.defineClass("scratch.Main",buff,
0,buff.length);

               Main m2=(Main) klass.newInstance();
       }
}

I get:
Exception in thread "main" java.lang.ClassCastException: scratch.Main
cannot be cast to scratch.Main
         at scratch.Main.main(Main.java:29)

Notes:

This is distilled from attempting to write a class loader and every
attempt ends with the same error (even cutting and pasting web and
junit examples of class loaders and calling them instead of mine).
Lew - 05 Oct 2007 14:40 GMT
> When I run this:
>
[quoted text clipped - 15 lines]
>
>                 File f=null;

Side point: why initialize f to null?  You throw away the value immediately,
so why use it at all?

>                 f = new File("/usr/home/plos/obj/scratch/Main.class");
>                 int size = (int)f.length();

Why not "long size = ..."?

>                 byte buff[] = new byte[size];
>                 FileInputStream fis = new FileInputStream(f);
[quoted text clipped - 13 lines]
> cannot be cast to scratch.Main
>           at scratch.Main.main(Main.java:29)

Looks to me like the two classes are loaded from different class loaders.  The
cast uses Main from the "normal" class loader to cast a Main from the custom
class loader, thus not compatible.

I'm very inexperienced with ClassLoader idioms so I am far from sure of this
analysis.

Maybe you'd be better off using a ClassLoader that isn't the class already
loaded in order to run the ClassLoader that it itself is.

Signature

Lew

Daniel Pitts - 05 Oct 2007 16:37 GMT
> When I run this:
>
[quoted text clipped - 41 lines]
> attempt ends with the same error (even cutting and pasting web and
> junit examples of class loaders and calling them instead of mine).

The "same" class loaded by a different class loader is considered a
different class.  Think of it as an invisible runtime namespace.
<customClassLoader>.scratch.Main cannot be cast to
<systemClassLoader>.scratch.Main.

Remember, if you're trying to dynamically load/unload/reload a class,
you can't have any reference to that class in the system class loader.
You also can't expect non-reflective communication between your
dynamically loaded class and the rest of your application, unless the
class implements/extends an interface/class which is loaded in the
system class loader. And then you can only rely on the methods in your
base class/interface.

HTH.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Joshua Cranmer - 05 Oct 2007 22:16 GMT
> When I run this:
>
[quoted text clipped - 3 lines]
> cannot be cast to scratch.Main
>           at scratch.Main.main(Main.java:29)

Fun exceptions happen when working with class loaders.

The short answer:
Multiple class loaders don't mix. One can change the default class
loader through some java -D option; I don't remember what it is however.

The long answer:
A class is uniquely determined by its instantiating class loader and its
fully-qualified name.

This is an example of a working loadClass function. I did not write this
myself, and it is based off of a very old version of Java (discussion of
custom class loaders is almost nil), so I do not know which parts are
irrelevant.

public final Class<?> loadClass(String name, boolean resolve) throws
    ClassNotFoundException {
    // Don't bother loading Java classes
    if (name.startsWith("java.") || name.startsWith("javax."))
        return super.loadClass(name, resolve);

    // Did we already define it?
    Class result = findLoadedClass(name);
    if (result == null) {
        String internalName = name.replace('.', '/') + ".class";
        InputStream is = getParent().getResourceAsStream(internalName);
        if (is != null) {
            try {
                // Load the raw bytes.
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                int b;
                while ((b=is.read())!=-1)
                bos.write((byte)b);
                byte[] bytes = bos.toByteArray();
                result = defineClass(name, bytes, 0, bytes.length);
            } catch (IOException ex) {
                throw new ClassNotFoundException(name +
                    " could not be loaded", ex);
            }
        }
    }

    if (result != null) {
        if (resolve) {
            resolveClass(result);
        }
    } else {
        // Let someone else find it.
        result = super.loadClass(name, resolve);
    }
    return result;
}

Even here, it is still incompatible with system-default loaded classes.
Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Roedy Green - 06 Oct 2007 05:16 GMT
On Fri, 05 Oct 2007 10:05:53 -0000, "Aryeh M. Friedman"
<Aryeh.Friedman@gmail.com> wrote, quoted or indirectly quoted someone
who said :

>Main m2=(Main) klass.newInstance();

It would help people help you if you told them the exception occurred
in this line and there was no other stack trace.

see:
http://mindprod.com/jgloss/runerrormessages.html#CLASSCASTEXCEPTION

Hint:  class X is not the same as class X if they were loaded with
different class loaders.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.