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.
精彩评论