Não é mais possível fazer postagens ou usar assinaturas novas da Usenet nos Grupos do Google. O conteúdo histórico continua disponível.
Dismiss

why do I get this runtime error

2 visualizações
Pular para a primeira mensagem não lida

Aryeh M. Friedman

não lida,
5 de out. de 2007, 06:05:5305/10/2007
para
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

não lida,
5 de out. de 2007, 09:40:2205/10/2007
para
Aryeh M. Friedman wrote:
> 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;

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);
> 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)

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.

--
Lew

Daniel Pitts

não lida,
5 de out. de 2007, 11:37:1005/10/2007
para

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.

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

Joshua Cranmer

não lida,
5 de out. de 2007, 17:16:4905/10/2007
para
Aryeh M. Friedman wrote:
> When I run this:
>
> [ snip ]

> I get:
> Exception in thread "main" java.lang.ClassCastException: scratch.Main
> 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.
--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Roedy Green

não lida,
6 de out. de 2007, 00:16:2206/10/2007
para
On Fri, 05 Oct 2007 10:05:53 -0000, "Aryeh M. Friedman"
<Aryeh.F...@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.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

0 nova mensagem