【问题标题】:Java Compiler keeps saying "error while writing className: className.class (Permission denied)"Java 编译器一直说“编写类名时出错:className.class(权限被拒绝)”
【发布时间】:2017-09-03 11:47:38
【问题描述】:

我正在为我的大学开发一个 Tomcat WebApp,它使学生能够编译他们的 Java 代码并查看跟踪。我将它安装在 RHEL7 VM 上。但是当我测试编译功能(这个不是我实现的)时,我提供的方法返回:

error while writing className: className.class (Permission denied)
Error on line 1 in className.java

我会告诉你我认为生成这个的方法:

public String compileJavaCode(String javaCode, String javaFileName, File workingDir) throws IOException, TimeoutException{

    javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
    this.createJavaFile(javaCode, javaFileName, workingDir);
    JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode);

    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
    compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();

    String diagn = "";
    for ( Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()){
        diagn+=diagnostic.getMessage(null)+"\n";//E.g. cannot find symbol symbol: variable variablename
        diagn+="Error on line "+Long.toString(diagnostic.getLineNumber())+" in "+diagnostic.getSource().toUri();//E.g. Error on line 22 in ClassName.java
    }
       fileManager.close();
       compiler.run(null, null, null, workingDir.getAbsolutePath()+File.separator+javaFileName);
       return diagn;
}

学生将看到 diagn 变量的内容作为他们提交代码的结果。

有趣的事实是,我设法在workingDir 目录中获得了className.class,但我不断从上面的for 循环中得到该错误。问题可能出在compiler.getTask(...).call() 上吗?我的意思是,compiler.run 可能能够正确生成 .class,但 compiler.getTask(...).call() 正在尝试将 .class 写入我无权写入的其他地方。

附:这是一个非常遗留的代码,所以请宽容它。 :)

正如@Alexander 所问,这是 Java 文件的内容:

public class Sommatore {

    public int somma(int i, int j) {
        return i+j;
    }

    public int differenza(int i, int j) {
        return i-j;
    }
}

【问题讨论】:

  • 目前信息太少。 “className.java”文件的内容是什么?如果将其加载到 IDE,它会显示任何错误吗?你为什么不通过'fileManager.getJavaFileObjectsFromFiles()'读回它,当你尝试这个而不是'JavaSourceFromString()'时会发生什么?
  • 另外:你从'compiler.run()'得到任何输出吗?请检查日志。
  • 不应该是一些有效的java源代码吗?我希望至少class Something {}
  • @Alexander 事实是,在我的机器和所有合作者的机器上,所有这些都运行良好。我只在大学提供给我们的虚拟机上遇到这种问题。
  • @Alexander 和我刚刚附加到问题中的 Java 文件是我们之前在本地机器上用来测试的同一个文件。

标签: java web-applications compiler-errors compiler-warnings rhel


【解决方案1】:

您使用的用户似乎没有写入目标文件夹的权限。 workingDir 的权限是什么?

有趣的事实是,我设法在 workingDir 目录中获取了 className.class,但我不断从上面的 for 循环中得到该错误。问题可能出在 compiler.getTask(...).call() 上吗?我的意思是也许 compiler.run 能够正确生成 .class 但 compiler.getTask(...).call() 正试图将 .class 写入我无权写入的其他地方。

为了验证这是否属实,您可以创建一个具有打开权限的文件夹并尝试。 例如,您可以尝试使用 as workingDir = /tmp 并检查会发生什么。

编辑

我试图复制你的代码:

    public class JavaCompiler {
    public static void main(String args[]) throws IOException, TimeoutException {
        File dir = new File(System.getProperty("user.dir") + "/src/main/java/");
        System.out.println(compileJavaCode(dir));
    }
    public static String compileJavaCode(File workingDir) throws IOException,      TimeoutException {

        javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
      //    this.createJavaFile(javaCode, javaFileName, workingDir);
      //    JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode);

        Iterable<? extends JavaFileObject> compilationUnits = fileManager
                .getJavaFileObjectsFromStrings(Arrays.asList(System.getProperty("user.dir") + "/src/main/java/Foo.java"));
//    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
        compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();

        String diagn = "";
        for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
            diagn += diagnostic.getMessage(null) + "\n";//E.g. cannot find symbol symbol: variable variablename
            diagn += "Error on line " + Long.toString(diagnostic.getLineNumber()) + " in " + diagnostic.getSource().toUri();//E.g. Error on line 22 in ClassName.java
        }
        fileManager.close();
        compiler.run(null, null, null, workingDir.getAbsolutePath() + File.separator + "Foo.java");
        return diagn;
    }
}

Foo.java

public class Foo {

    public int somma(int i, int j) {
        return i+j;
    }

    public int differenza(int i, int j) {
        return i-j;
    }
}

有一些变化,但结果应该是一样的。 我注意到在

中指定了“路径”
File workingDir

将在

中使用
compiler.run(null, null, null, workingDir.getAbsolutePath() + File.separator + "Foo.java");

JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode);
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);

在我的例子中:

Iterable<? extends JavaFileObject> compilationUnits = fileManager
.getJavaFileObjectsFromStrings(Arrays.asList(System.getProperty("user.dir") + "/src/main/java/Foo.java"));

什么包含你的

workingDir

和“文件”?

JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode);

就我而言,都是一样的。

我尝试使用不同的用户执行代码,如果我使用的用户无法在此文件夹中写入,我会获得

/tmp/testSO/src/main/java/Foo.java:5: error: error while writing Foo: /tmp/testSO/src/main/java/Foo.class (Permission denied)
public class Foo {
       ^
1 error
error while writing Foo: /tmp/testSO/src/main/java/Foo.class (Permission denied)
Error on line 5 in file:/tmp/testSO/src/main/java/Foo.java

【讨论】:

  • 感谢您的回答@DurdenP。我认为这也是问题所在。我读到 compiler.gettask 试图在源文件夹中创建一个 .class 文件。那可能是有罪的目录吗?关于 workingDir 我结束了 777 的尝试,但似乎什么也没发生......
  • 我解决了使用编译器的“-d”参数指定目标目录的问题。谢谢大家
猜你喜欢
  • 2012-03-22
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
相关资源
最近更新 更多