在下面的代码中,我使用 sun.tools.javac.Main
动态生成一个类。我将使用反射创建此类的新实例。问题是,我想避免使用 Reflection 来调用我为此类定义的方法,因此我创建了一个 ProxyInvoker 来引用我在项目中定义的接口(interface)。为了让类加载器看到这一点,我将类路径添加到类加载器的可执行接口(interface)中。在“编译”步骤中我仍然收到错误消息,提示找不到我的接口(interface)。
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class MyClassGenerator {
static final String generatedClassName = "TestHello_" + System.currentTimeMillis();
static final String javaFileName = generatedClassName + ".java";
static URLClassLoader classLoader;
public static void main(final String args[])
throws MalformedURLException {
final ProxyInvoker proxy = new ProxyInvoker();
generateClass();
loadExecutableInterface();
if (compileClass()) {
System.out.println("Running " + generatedClassName + ":\n\n");
final Executable ex = createExecutable();
ex.execute();
}
else {
System.out.println(javaFileName + " is bad.");
}
}
public static void loadExecutableInterface()
throws MalformedURLException {
final File file = new File("."); // <-- the directory where the generated java class is defined
final File file2 = new File("src"); // <-- the directory where interface Executable is defined
try {
classLoader = URLClassLoader.newInstance(new URL[] { file.toURI().toURL(), file2.toURI().toURL() });
try {
classLoader.loadClass("Executable");
}
catch (final ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch (final MalformedURLException e) {
e.printStackTrace();
}
System.out.println(file.toURI().toURL());
System.out.println(file2.toURI().toURL());
}
public static void generateClass() {
try {
final FileWriter aWriter = new FileWriter(javaFileName, true);
aWriter.write("public class " + generatedClassName + " implements Executable {");
aWriter.write("\n");
aWriter.write("\n");
aWriter.write(" public void invoke() {");
aWriter.write(" System.out.println(\"Hello World!\");");
aWriter.write(" }");
aWriter.write("\n");
aWriter.write("}");
aWriter.flush();
aWriter.close();
}
catch (final Exception e) {
e.printStackTrace();
}
}
public static boolean compileClass() {
final String[] source = { new String(javaFileName) };
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
new sun.tools.javac.Main(baos, source[0]).compile(source);
System.out.print(baos.toString());
return (baos.toString().indexOf("error") == -1);
}
public static Executable createExecutable() {
Executable instance = null;
try {
final Class<?> genClass = Class.forName(generatedClassName, true, classLoader);
instance = (Executable) genClass.newInstance();
}
catch (final Exception e) {
e.printStackTrace();
}
return instance;
}
}
class ProxyInvoker {
Executable myExecutable;
public void runIt() {
final Executable myExecutable;
}
}
最佳答案
这是您的代码的工作版本:
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class MyClassGenerator {
static final String generatedClassName = "TestHello_" + System.currentTimeMillis();
static final String javaFileName = generatedClassName + ".java";
static URLClassLoader classLoader;
public static void main(final String args[])
throws MalformedURLException {
generateClass();
loadExecutableInterface();
if (compileClass()) {
System.out.println("Running " + generatedClassName + ":\n\n");
final Executable ex = createExecutable();
ex.execute();
}
else {
System.out.println(javaFileName + " is bad.");
}
}
public static void loadExecutableInterface()
throws MalformedURLException {
final File file = new File("."); // <-- the directory where the generated java class is defined
try {
classLoader = URLClassLoader.newInstance(new URL[] { file.toURI().toURL() }, Executable.class.getClassLoader());
try {
classLoader.loadClass("Executable");
}
catch (final ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch (final MalformedURLException e) {
e.printStackTrace();
}
System.out.println(file.toURI().toURL());
}
public static void generateClass() {
try {
final FileWriter aWriter = new FileWriter(javaFileName, true);
aWriter.write("public class " + generatedClassName + " implements Executable {");
aWriter.write("\n");
aWriter.write("\n");
aWriter.write(" public void execute() {");
aWriter.write(" System.out.println(\"Hello World!\");");
aWriter.write(" }");
aWriter.write("\n");
aWriter.write("}");
aWriter.flush();
aWriter.close();
}
catch (final Exception e) {
e.printStackTrace();
}
}
public static boolean compileClass() {
final String[] source = { "-classpath", "target/classes", javaFileName };
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
new sun.tools.javac.Main(baos, source[0]).compile(source);
System.out.print(baos.toString());
return (baos.toString().indexOf("error") == -1);
}
public static Executable createExecutable() {
Executable instance = null;
try {
final Class<?> genClass = Class.forName(generatedClassName, true, classLoader);
instance = (Executable) genClass.newInstance();
}
catch (final Exception e) {
e.printStackTrace();
}
return instance;
}
}
主要变化:类加载器和编译部分是错误的。
关于java - 为什么 Java 类加载器找不到我的接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4210346/