java:在运行时编译继承类

标签 java classloader java-compiler-api

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

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

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

    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)....

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

最佳答案

我没有意识到一些错误,但通过 LKTN.25 提示我发现了它们。

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

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

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

更新: 我认为我必须在用户类中插入一个构造函数,因为我无法在运行时创建实例。 users 类根本不需要构造函数(就像 java 中通常的那样)。它从父类(super class)中获取它。

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

    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();
                    }

关于java:在运行时编译继承类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41886306/

相关文章:

Java Map 与 TimeToLive 与每个键/值对相关联

java - 什么是NullPointerException,我该如何解决?

Android 应用无法在 PathClassLoader 中的某些手机上加载

java 运行时类生成框架

java - CompilationTask.call() 引入了 ClassNotFoundException。在 JDK6 中工作,不在 JDK7 中工作

java - 在内部类中访问外部类变量

java - 在 docker 容器中部署简单的独立 spring mvc 应用程序

java - 测试重新部署 Web 应用程序时是否存在内存泄漏

android - 开始新 Activity 时打开进度对话框

eclipse - 如何以编程方式使用 JDT 编译器?