java:在运行时编译继承类

时间:2017-01-27 02:42:51

标签: java classloader java-compiler-api

我目前正在为我的大学做一个项目。 我正在开发一个允许用户在文本区域中键入java方法的应用程序。然后,应用程序将这些方法放入一个类中,并在用户点击编译按钮时编译它。

到目前为止,我使用了这种方法: https://stackoverflow.com/a/2946402

起初它对我有用,但它只编译一个简单的(独立)类。我必须在运行时编译的类扩展了应用程序中的另一个类。 通过这种方式,用户应该可以访问我实现的超类中的一些方法。 这是我用来编译类的方法:

    public Class<?> loadClass(String filename) {
        WorkingDirectory workingDirectory = WorkingDirectory.getInstance();
        File directory = workingDirectory.getCompileDirectory();
        File javaFile = workingDirectory.createJavaFileFromUserProgram(filename);
        Class<?> cls = null;
        try {

            // Compile source file.
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

            compiler.run(null, null, null, javaFile.getPath());

            URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { directory.toURI().toURL() });
            cls = Class.forName(filename, true, classLoader);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cls;
    }

这适用于没有扩展任何内容的类。当我添加扩展时,我最终会收到以下错误消息:

    error: cannot find symbol
    public class UsersClass extends ExistingClass { public void main() {
                                    ^
      symbol: class ExistingClass
    1 error
    java.lang.ClassNotFoundException: UsersClass
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at utils.SimulatorClassloader.loadClass(SimulatorClassloader.java:51)
        at simulator.Simulator.lambda$4(Simulator.java:171)....

有人知道我需要在我的方法中添加/更改内容吗?我做了几个小时的研究,但从那以后我没有取得进展。

1 个答案:

答案 0 :(得分:0)

我没有发现一些错误,但是用LKTN.25提示我找到了它们。

首先:UsersClass在导入部分有一个拼写错误。 在这个错误消失之后又出现了另一个错误。

第二:我的基类也没有默认构造函数和子类。并且子类没有覆盖其他构造函数。因此,不能创建子类的实例。

显然“有人知道我需要添加/更改我的方法吗?”这不是正确的问题。错误在别的地方。

更新: 我以为我必须在users类中插入构造函数,因为我无法在运行时创建实例。 users类根本不需要构造函数(就像在java中一样)。它来自超级班。

显然以下代码段不起作用。

    Class<?> cls = new SimulatorClassloader().loadClass(this.simulatorGUI.getStageTitle());
                try {
                    Method method = cls.getMethod("main");
                    try {
                        method.invoke(cls.newInstance());
                    } catch (Exception e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }

但是这个(略微修改过的代码)实际上确实有效:

    Class<?> cls = new SimulatorClassloader().loadClass(this.simulatorGUI.getStageTitle());
                try {
                    Method method = cls.getMethod("main");
                    try {
                        Object obj = cls.newInstance();
                        method.invoke(obj);
                    } catch (Exception e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }