我正在使用JUnit来运行许多需要运行外部服务器(tomcat)的测试。我目前正在使用以下代码启动tomcat。
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Runtime.getRuntime().exec("{path to tomcat}/bin/startup.bat");
} catch (IOException exception) {
}
}
});
thread.setDaemon(true);
当所有测试都完成时,问题就出现了,JVM挂起等待tomcat关闭。如果我手动关闭tomcat,JVM会按预期关闭。
有没有办法运行tomcat,这样一旦所有测试完成(所有其他线程结束),JVM都不会被阻塞并关闭?
答案 0 :(得分:1)
您需要清空进程中的输入流,否则当填充缓冲区大小时它会“很奇怪”。假设p
是.exec()返回的进程:
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String in;
while ((in = br.readLine()) != null);
您可以更改while循环以添加{}并实际打印tomcat输出(如果您愿意),但实际上您只需要清空缓冲区。
答案 1 :(得分:1)
在这种情况下,结束用于执行startup.bat
批处理脚本的线程不会结束tomcat服务器。解决方案:
您需要执行shutdown.bat
来停止tomcat。
如果您查看startup.bat
行56
,您会看到脚本运行命令call "%EXECUTABLE%" start %CMD_LINE_ARGS%
。 %EXECUTABLE%
设置在38
行:set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
。如果您查看catalina.bat
,您会看到在设置一些标准变量并检查参数后,在行242
(if ""%1"" == ""start"" goto doStart
)中,它会跳转到:doStart
,位于279
行的_EXECJAVA
对参数进行了一些改变,并将start [...]
设置为%_EXECJAVA%
它最终执行start
内的任何内容。在开始的情况下,这将涉及bin
命令。正如您从this documentation of the start
command所见:
启动程序,命令或批处理脚本(在新窗口中打开。)
基本上你正在开始的过程是运行脚本,启动另一个程序然后结束,自动结束您的流程并允许线程完成。事实上,您无法直接控制tomcat,只能使用 Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Runtime.getRuntime().exec("{path to tomcat}/bin/shutdown.bat");
} catch (IOException exception) {
}
}
});
目录中的脚本。
因此,在程序结束时执行以下操作应该很容易(您可以使用关闭挂钩):
startup.bat
所以你运行shutdown.bat
启动tomcat,{{1}}结束它。
很抱歉回答了一个老问题。
答案 2 :(得分:0)
即使您无法使用@Xabster解决问题,还有一件事需要将错误流重定向到输入流,就像这样
ProcessBuilder processBuilder = new ProcessBuilder(prepareCommand(table));
ProcessBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
BufferedReader stream = new BufferedReader(new nputStreamReader(process.getInputStream()));
String readLine = null;
while((readLine = stream.readLine()) != null){
// you can do anything you want with what you read from stream
}