【问题标题】:JavaCompiler API force compile with errors?JavaCompiler API 强制编译时出错?
【发布时间】:2012-06-06 23:00:50
【问题描述】:

我目前正在制作一个工具,该工具将根据用户输入输出 Java 类文件以供使用。我输出了一组 .java 文件,其中一些引用了当前上下文中不存在的类和变量。因此,当我编译时,输出文件会记录这些错误并且不会编译该类。我的问题是:有没有办法使用 JavaCompiler 按原样编译类文件?

编译代码如下:

public static void compileAll(File file) throws IOException{
    String fileToCompile = "C:/test.java";
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    FileOutputStream errorStream = new FileOutputStream("Errors.txt");
    int compilationResult = compiler.run(null, null, errorStream, "-verbose", fileToCompile );
    if(compilationResult == 0){
        System.out.println("Compilation is successful");
    }else{
        System.out.println("Compilation Failed");
    }
}

【问题讨论】:

    标签: java class compiler-construction compilation


    【解决方案1】:

    问:有没有办法使用 JavaCompiler 直接编译类文件?

    是的:根据需要创建虚拟方法和/或虚拟类,以便您可以编译:)

    【讨论】:

    • 更好的是,将它们定义为接口,然后添加实现它们的虚拟方法。这样替换它们可能会更快。
    • 所以你是说没有办法做到这一点?因为重新制作所有必要的课程会很麻烦。
    【解决方案2】:

    你想要的是不可能的,因为 Java 编译器需要在字节码生成时知道类型以及变量和方法的名称。因为 Java 字节码是类型化的,并且 JVM 不知道一些 Java 源级转换(例如,拆箱转换纯粹是 Java 编译器约定),所以编译器无法逃避发出“加载字段f”或"调用方法foo";编译器必须说“double 类型的加载字段f”或“int(double, Object) 类型的调用方法f”。

    考虑读取对象的未知字段并将其分配给double 局部变量:

    double d = o.f;
    

    如果f 的类型是double,编译器将简单地使用getfield 后跟dstored 的局部变量槽中。如果f 的类型为int,编译器将在getfielddstore 之间发出i2d 指令,以将int 转换为double。如果f 的类型为Double,编译器将发出对doubleValue() 的调用,以便在存储之前将加载的值拆箱。如果fObject 类型,则在没有强制转换的Java 中赋值是非法的(如果它是合法的,它将是checkcast 指令)。如果x 的类没有名为x 的字段,则该作业无法翻译。

    在调用具有未知签名的方法时也需要考虑类似的问题,这可能需要对其每个参数进行转换和/或为可变参数调用创建一个数组。此外,在 JVM 级别,允许对返回类型进行重载,因此即使只有一个参数类型列表,也必须指定返回类型。

    您能做的最好的事情是提供未知类的虚拟声明,以便编译器知道该做什么,正如 paulsm4 的回答所建议的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-10
      • 2013-10-16
      • 2010-12-30
      • 1970-01-01
      • 2012-08-25
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多