1

我正在使用 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就不会被阻塞并关闭?

4

3 回答 3

1

在这种情况下,结束用于执行startup.bat批处理脚本的线程不会结束 tomcat 服务器。解决方案:


简短说明:

你需要执行shutdown.bat来停止tomcat。


长解释:

如果您查看startup.batline 56,您会看到脚本运行命令call "%EXECUTABLE%" start %CMD_LINE_ARGS%%EXECUTABLE%设置在行中38set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"。如果你看一下catalina.bat,你会发现在设置了一些标准变量并检查了参数之后,在 line 242( if ""%1"" == ""start"" goto doStart) 中它会跳转到:doStart,它位于 line279中,对参数进行一些转换魔法,并设置_EXECJAVAstart [...]最终执行里面的任何内容%_EXECJAVA%。如果开始,这将涉及start命令。正如您从start命令的文档中看到的:

启动程序、命令或批处理脚本(在新窗口中打开。)

所以基本上你开始的进程正在运行脚本,它启动另一个程序然后结束,它会自动结束你的进程并允许线程完成。实际上你不能直接控制tomcat,你只能使用bin目录里面的脚本。


结论:

因此,在程序结束时执行以下操作应该很容易(您可能会使用关闭挂钩):

    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启动tomcat并shutdown.bat结束它。

很抱歉回答一个老问题。

于 2015-03-30T14:38:48.590 回答
0

您需要从进程中清空输入流,否则当它填充缓冲区大小时它会表现得“奇怪”。假设p是 .exec() 返回的进程:

BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String in;
while ((in = br.readLine()) != null);

您可以更改 while 循环以添加 { } 并根据需要实际打印 tomcat 输出,但实际上您只需要清空缓冲区即可。

于 2013-08-23T06:56:22.237 回答
-1

即使您无法使用@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
}
于 2013-08-23T08:02:33.877 回答