为什么Java类加载器找不到我的接口? [英] Why can't the Java class loader find my interface?

查看:88
本文介绍了为什么Java类加载器找不到我的接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我使用 sun.tools.javac.Main 动态生成一个类。我将使用Reflection创建此类的新实例。问题是,我想避免使用Reflection调用为该类定义的方法,因此我创建了一个ProxyInvoker来引用我在项目中定义的接口。为了让类加载器能够看到这一点,我将类路径添加到我的类加载器的Executable接口中。在编译步骤期间,仍然出现错误,提示找不到我的界面。

In the code below I generate a class dynamically using sun.tools.javac.Main. I will create a new instance of this class using Reflection. The problem is, I want to avoid using Reflection to invoke the method I defined for this class, so I created a ProxyInvoker that references an interface I defined in my project. In order for the classloader to see this, I add the classpath to the Executable interface to my classloader. I still get an error during the 'compilation' step that says that my interface was not found.

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;

    }

}


推荐答案

这是您代码的有效版本:

Here is a working version of your code:

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;

    }

}

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

The main changes: classloader and compilation parts were wrong.

这篇关于为什么Java类加载器找不到我的接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆