我的问题包含了一些我不了解的使用" cmd.exe"," / c"在Windows中从Java执行子流程时。基本上,我无法找到关于何时以及为何需要它们的好解释。
我的具体问题:我有一个用于子流程执行的小框架。一种用途是一种Java应用程序,它可以管理" ProcessBuilders创建的其他几个JVM。其中一个关键要求是当子流程卡住或托管应用程序终止时,它必须能够终止子流程。
问题是,一方面,这样做:
new ProcessBuilder("java", "...").start();
原因:
Could not find or load main class ...
好像系统变量或目录不同(他们不是)。另一方面,将其包装在cmd.exe中,如下所示:
new ProcessBuilder("cmd.exe", "/c", "java", "...").start();
WORKS,但是创建了另一个cmd.exe进程,它有一个副作用:子JVM现在是一个子子进程,process.destroy();
没有杀死它(一个已知的bug)我找到的Windows JRE)。
这个特定的问题是在不同的层面上处理的,因为所有这些应用程序都是我们的,我们知道他们的PID。但它是一个示例,cmd.exe如何使一切工作方式不同(或阻止JVM完全工作)。所以我想知道那里究竟发生了什么。
这里框架本身也是如此。它也将被我们的测试平台使用。我想提供一个API,允许通过参数用cmd.exe / c包装命令。但是,该参数究竟是什么意思呢?用户如何决定是否需要cmd.exe包装?
我非常感激的奖励:在其他操作系统中是否有任何相关性?比方说,它在Linux中有某种等价物吗?
答案 0 :(得分:2)
再次碰到它,发现了问题,以及一些额外的见解。
@HarryJohnston - 好的一点,根据javadoc,子进程从ProcessBuilder
和Runtime.getRuntime.exec(...)
API继承了环境,所以这不是问题(事实上java.exe实际上是这样发现的)显然是可用的。)
但似乎某些命令行功能丢失了。除此之外,它是命令行中的这种%VARIABLE%用法 - 除非命令以cmd.exe /c
开头,否则不会解释它们。
在这种未找到类的情况下(它也可能导致NoClassDefFoundError),我在类路径中使用了几个变量(也许我应该发布整个命令,但它有点长)。当我用文学路径替换它们时,一切都有效。
基本上:
java -cp %classpath% Main
- 糟糕
cmd.exe /c java -cp %classpath% Main
- 好
java -cp D:\proj\bin Main
- 好
那么,关于一般问题的行为与cmd.exe的行为有何不同:
process.destroy()
不会将其删除。这可能是以后版本中修复的错误(我使用的是Java 7和8,Windows 7和Server 2012)。start
和call
仅在cmd.exe下可用。命令级别错误的行为也不同:使用cmd.exe时,错误只会出现在输出流中,而如果没有它,则API会抛出异常,这可能也会略有错误不同的描述。
例如:
nothing
会导致 java.io.IOException:CreateProcess error = 2,系统找不到指定的文件
cmd.exe /c nothing
将返回输出:'nothing'不被识别为内部或外部命令,可操作程序或批处理文件,返回值为1(唯一的指示是错)。
关于为什么的更深层次的问题,这是完整的差异列表,我仍然不知道。看起来JVM有运行命令的方式,您可以使用cmd.exe“包装”其他功能和保护。
另一个有趣的事实是,当您运行批处理时,它实际上是在cmd.exe(具有其所有功能)下运行的。从我的测试来看,似乎process.destroy()
只能等待外部任何东西(例如,如果卡在pause
上),有或没有额外的cmd.exe / c包装,但是如果它运行则不会子进程 - 与第3点中提到的cmd.exe限制一致。