【问题标题】:Process is not terminating Properly in java (Runtime)进程未在 java 中正确终止(运行时)
【发布时间】:2017-11-24 12:06:37
【问题描述】:

我正在通过创建 .exe 文件使用 java 进程执行 CSharp 程序,但该文件的进程没有响应 0 exitCode。错误为空。在 Visual Studio 中它运行良好,但使用 java 时会产生问题。没有输出也没有错误,我被困在这个请帮助。我正在使用 Java 7。 我正在使用Csc (inbuild compiler in .Net framework for windows) 它给了我dll 参考错误。命令如下

csc /nologo /r:D:/simulatorConfig/ArrayConversion.dll /out:D:\\apache-tomcat-7.0.64\\temp\\tmp749792186557790590.exe D:\\apache-tomcat-7.0.64\\temp\\tmp749792186557790590.cs

stream = new BufferedReader(new InputStreamReader(proc.getErrorStream())); 

上面是Error,它是空字符串。

代码在这里,请看。

public File compile(File sourceFile, LANGUAGE lang) throws InterruptedException, IOException, CompilerException, ConfigurationException {
    String absolutePath = sourceFile.getCanonicalPath();
    // System.out.println("absolutePath : " + absolutePath);
    String destFile;
    if (OsUtils.isWindows()) {
        destFile = absolutePath.replace(lang.getFileExtension(), EXECUTABLE_FILE_SUFFIX);
    } else {
        destFile = absolutePath.replace(lang.getFileExtension(), "");
    }

    String compileCommand = generateCommand(absolutePath, destFile, lang);
    logger.error("compileCommand : " + compileCommand);
    // Compiles and create exe file for execution
    Process proc = Runtime.getRuntime().exec(compileCommand);

    // Wait for process to complete
    int returnValue = proc.waitFor();

    if (returnValue != 0) {
        String errorMsg = getCompilerMessage(sourceFile, proc, lang);
        throw new CompilerException(errorMsg);
    }

    proc.destroy();

    return new File(destFile);
}

private String getCompilerMessage(File sourceFile, Process proc, LANGUAGE lang) throws IOException {

    StringBuilder message = new StringBuilder();
    BufferedReader stream = null;
    String line = null;

    switch (lang) {
    case C:
    case CPP:
        // GNU C/CPP compiler prints compiler errors in standard errors
        // tream
        stream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
        break;

    case CSHARP:
        // CSharp compiler prints compiler errors in standard output stream
        stream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
        break;

    }

    while ((line = stream.readLine()) != null) {
        logger.error(line);
        line = line.substring(line.indexOf(sourceFile.getName()) + (int) sourceFile.getName().length());
        if (message.toString().isEmpty()) {
            message.append(lang == LANGUAGE.CSHARP ? "Line" : "").append(line);
        } else {
            message.append("<br/>Line").append(line);
        }
        // message.append(line).append(SystemUtils.LINE_SEPARATOR);
    }

    stream.close();

    return message.toString();
}

private String generateCommand(String sourceFile, String destFile, LANGUAGE lang) throws ConfigurationException {
    // System.out.println("sourceFile : " + sourceFile + " -- destFile : " +
    // destFile);
    Configuration config = new PropertiesConfiguration("system.properties");
    String cmd = "";
    switch (lang) {
    case C:
    case CPP:
        sourceFile = sourceFile.replace("\\", "\\\\");
        destFile = destFile.replace("\\", "\\\\");
        cmd = "g++ " + sourceFile + " -o " + destFile + " " + config.getString("C_CPP_HEADERFILE").trim();
        break;

    case CSHARP:
        sourceFile = sourceFile.replace("\\", "\\\\");
        destFile = destFile.replace("\\", "\\\\");
        logger.error("Config Path : "+config.getString("MONO_PATH"));
        if (OsUtils.isWindows()) {
            cmd = "csc /nologo /r:" + config.getString("CS_HEADERFILE_WIN") + " /out:" + destFile + " " + sourceFile;
        } else {
            cmd = "/opt/mono/bin/mcs /reference:" + config.getString("CS_HEADERFILE") + " /out:" + destFile + " "
                    + sourceFile;
        }

        break;
    }
    logger.info("Command :" + cmd);
    return cmd;
}

【问题讨论】:

  • 你没有消费流...
  • 好像你没有关闭 InputStreamReader,女巫正在创建一个 BufferedReader ctor
  • 我遇到了类似的问题,通过添加对 Environment.Exit(1); 的调用解决了这个问题。在 c# main 方法的末尾。现在它将 1 作为返回码返回给 java。
  • Java 流..no
  • 是的,它返回退出代码为 1 在正常情况下应该是 0

标签: java c# process mono csc


【解决方案1】:

当使用Runtime#exec 启动命令时,您必须在每种情况下都使用错误流和标准流(不仅在返回码为 != 0 时),否则内部缓冲区可能/将会变满,子进程将无限期地等待,直到有人消费它们。

这个问题的常见症状是一个永不返回的过程,使整体看起来陷入僵局。

有几种方法可以纠正这个问题,这里描述了一种最简单的方法:https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#redirect-input

另外,这里似乎有问题:

// CSharp compiler prints compiler errors in standard output stream
    stream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
    break;

在注释中,您告诉编译器确实在标准输出上输出错误,但您正在使用错误流。

【讨论】:

  • 也许,这取决于可执行文件。经验法则是:使用 java 启动命令时(Runtime#exec 和朋友),不要想太多:从消耗所有东西开始(stdout 和 stderr)然后分析输出并开始假设你为什么得到一个特定的返回代码以及是否可以忽略它。一些写得不好的 exe 确实返回了不能描述实际执行状态的东西(我记得 Maven 返回“0”但未能构建我的项目的时候。在 CI 环境中非常有趣)
【解决方案2】:

当我尝试在命令提示符下对演示文件执行相同操作时,出现.dll 链接错误。通过将.dll 文件和.exe 文件保存在同一目录中,它解决了我的目的程序以正确的方式完美运行退出代码 (0)。 所以将其他.dll 文件保留在此路径D:\apache-tomcat-7.0.64\temp\ 中。很好。

拇指规则说.dll.exe 应该在同一个目录中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 2023-03-11
    相关资源
    最近更新 更多