开发者

Loading inner classes at runtime

I have a program where I compile java code that somebody writes in a text box, and run it. They type out the full source code, class and all

I save the class they write to a random java source file, and then compile and load the class through a classloader. This works perfectly.

I have a new issue though, that of sub classes. I give the outer class a unique name,开发者_StackOverflow and load that class.

Ex.

TEMP1110.java -> TEMP1110.class, etc. With inner classes, it compiles to TEMP1110$InnerClass.class I try loading this class through my class loader, but when the outer class makes a call to it: new InnerClass().method();

it gives me this: java.lang.NoClassDefFoundError: TEMP1110$InnerClass

Is there some quirk or something I am doing wrong?

My classloader:

private static class JClassLoader extends ClassLoader {
    public Class buildClass(final byte[] data, final String className) {
        return (Class) defineClass(className, data, 0, data.length);
    }
}

className being TEMPCLASS$InnerClass, and data being the bytes that represent the class file. This works for outer classes.


I suppose 'new InnerClass()' uses normal classloading and classpath search to Find classes. Since your generated .class file is not on classpath it can not be found.

Try dynamically manipulating classpath to add your folder where your .class files reside:

String currentPath = System.getProperty("java.library.path");
System.setProperty( "java.library.path", current + ":/path/to/my/classfiles" );

// this forces JVM to reload "java.library.path" property
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );


From the API spec, it looks like the NoClassDefFoundError is thrown when the name that you send to defineClass does not match the binary name of the class represented by bytes.

You could try passing null for the className for the inner class.


My eventual solution, with I being the interface:

ClassLoader cl = new URLClassLoader(new URL[] {new File("TEMP/").toURI().toURL()});
Class classd = cl.loadClass(className);
return (I) classd.newInstance();

Previously, I was using some older documentation that just complicated the whole process.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜