使用进程使用Java代码编译类

使用进程使用Java代码编译类,java,compiler-construction,Java,Compiler Construction,我有一段代码,当我使用以下代码编译时,它编译了一个名为tspClassName的类: Process compileProc = null; try { compileProc = Runtime.getRuntime().exec("javac -classpath ." + File.separator + "src" + File.separator

我有一段代码,当我使用以下代码编译时,它编译了一个名为tspClassName的类:

           Process compileProc = null;
        try {
            compileProc = Runtime.getRuntime().exec("javac -classpath ."
                       + File.separator + "src" + File.separator
                       + File.separator + "generated." + tspClassName + ".java -d ." + File.separator + "bin");
        // catch exception
           if (compileProc.exitValue() != 0) 
           {
               System.out.println("Compile exit status: "
                          + compileProc.exitValue());
                      System.err.println("Compile error:" +
                              compileProc.getErrorStream());
它的输出是: “编译退出状态:2 编译错误:java.io。FileInputStream@17182c1" 否则类tspClassName.java编译时不会出错,所以我猜它与路径有关,在我的eclipse项目中,tspClassName.java驻留在包homework4.generated in src中,我在代码中使用的路径是否有问题


谢谢您可以使用包装此功能的或。

我认为完成此类工作的正确方法是通过编程使用API,而不是外部流程:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler()
参考资料:


您的Java代码运行的命令如下所示:

javac -classpath ./src//generated.ClassName.java -d ./bin
    String command = String.format(
        "javac -classpath . src%1$sgenerated%1$s%2$s.java -d .%1$sbin",
        File.separator,
        tspClassName
    );
    LOG("Executing " + command);
    //... exec(command) etc
我认为那不是你想要的。我认为您需要更改Java代码,这样它可能会生成以下内容:

javac -classpath . src/generated/ClassName.java -d ./bin
                  ^

注意类路径(“.”)后面的空格。

我建议这样做:

javac -classpath ./src//generated.ClassName.java -d ./bin
    String command = String.format(
        "javac -classpath . src%1$sgenerated%1$s%2$s.java -d .%1$sbin",
        File.separator,
        tspClassName
    );
    LOG("Executing " + command);
    //... exec(command) etc
。。。其中,
LOG
是日志框架用来记录要执行的命令的内容。这将大大有助于调试,因为有人指出,您构建的命令构造错误

或者,您也可以使用
replace

    String command =
        "javac -classpath . src/generated/ClassName.java -d ./bin"
        .replace("/", File.separator)
        .replace("ClassName", tspClassName);
这或许更具可读性


在排放
流程时
流 OP的评论表明,
waitFor()
永远不会返回。这可能是由
javac
过程中的编译错误/警告引起的

发件人:

由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入子流程的输入流或读取子流程的输出流可能会导致子流程阻塞,甚至死锁

您需要不断地排空
进程.getOutputStream()

另见
  • Java难题,难题82:啤酒爆炸
相关问题

问题可能在于文件位置,而不是对exec()使用单值参数 尝试3参数方法,该方法将命令、环境和位置作为参数,帮助我们移动到指定位置并执行命令

检查6和8种方法以供参考


首先,如果您想使用这样的进程,您应该使用apacheexec库。ApacheExec库使事情变得非常简单

其次,您应该打印您正在执行的进程的std输出和std错误流。没有他们,就无法知道执行的是什么,执行的是什么

第三,尝试打印进程正在执行的完整cmd行。复制cmd行并尝试手动运行它。大多数时候,你会发现你的问题是这样的

最后,如果您的目标只是在运行时编译类/生成或修改类文件,请仔细阅读并尝试。它也有例子。您还可以尝试代码生成/类操作库,如BCEL、JavaAssist等


祝你好运。

谢谢,但我在这里遇到了一个空指针异常:JavaCompiler=ToolProvider.getSystemJavaCompiler();DiagnosticCollector diagnostics=新建DiagnosticCollector();StandardJavaFileManager fileManager=compiler.getStandardFileManager(诊断,null,null);因为编译器是空的,我如何解决这个问题?也许你没有安装JDK?没有,我在这里安装了它:C:\Sun\SDK\jdkthanks,我这样做了,但是现在使用debug我发现程序停在这里:compileProc.waitFor();是什么原因造成的?@Noona:很可能是编译错误(请尝试手动编译
.java
文件以确认这一点)。您需要排空
进程的stdin和stderr,否则它们会阻塞.java文件在我的eclipse项目中,并且在那里编译时没有错误。命令应该是这样的(我之前忘记了homework4,但仍然必须有两次src):“javac-classpath./src src/homework4/generated/ClassName.java-d./bin”.replace(“/”,File.separator);试着像Polygene在他的回答中建议的那样排出输入和输出流。