为什么Java类加载器找不到我的接口?

时间:2010-11-17 23:39:59

标签: java classloader

在下面的代码中,我使用sun.tools.javac.Main动态生成一个类。我将使用Reflection创建此类的新实例。问题是,我想避免使用Reflection来调用我为这个类定义的方法,所以我创建了一个ProxyInvoker,它引用了我在项目中定义的接口。为了让类加载器看到这一点,我将类路径添加到我的类加载器的Executable接口。在“编译”步骤中,我仍然收到一条错误,指出我的界面未找到。

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;

    }

}

1 个答案:

答案 0 :(得分:6)

以下是您的代码的工作版本:

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;

    }

}

主要更改:类加载器和编译部分错误。