如果进程以退出代码 0 结束,我应该调用 Process.destroy() 吗?
Posted
技术标签:
【中文标题】如果进程以退出代码 0 结束,我应该调用 Process.destroy() 吗?【英文标题】:Should I call Process.destroy() if the process ends with exit code 0? 【发布时间】:2016-04-11 21:09:17 【问题描述】:我有一个通过 Spring JMSListener 启动的进程。该过程基本上运行一个运行时 exe 来调用 imagemagick 对图像进行一些重新处理。在 *nix 下,即使 Runtime exec 命令以退出代码 0 退出并且没有引发异常,也会保留一些线程。该应用程序正在使用Gythio Runtime Exec 类来执行其工作。尽管 Gythio 正确处理了运行时可能出现的 StdErr 和 StdOut 周围常见的陷阱,但即使它成功了,我们不应该破坏这个过程吗?
这是一个简单的例子,请忽略代码错误,它不是真正的代码。我的问题是关于 // process done 块:
public class Test
public void doSomething(String cmd, String processProperties, String processDirectory)
try
// cmd is something like convert ... file .. params
Runtime runtime = Runtime.getRuntime();
final Process process = runtime.exec(cmd, processProperties, processDirectory);
int exitValue = process.waitFor();
System.out.println("exit value: " + exitValue);
BufferedReader buf = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line = "";
while ((line = buf.readLine()) != null)
System.out.println("exec response: " + line);
//log = line;
//writeToFile(line);
// process is done... should it be destroyed?
if(process != null)
process.destroy();
// end process done
catch (Exception e)
System.out.println(e);
运行大约一个小时后,在 tomcat 中运行的应用程序显示了这些线程(其中 tomcat 的 pid 为 1641):
[root@server logs]# top -H -p 1641
top - 19:45:24 up 264 days, 10:33, 4 users, load average: 0.00, 0.00, 0.19
Tasks: 5068 total, 0 running, 5068 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.7%us, 1.5%sy, 0.0%ni, 97.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 8061332k total, 6690912k used, 1370420k free, 195348k buffers
Swap: 1888252k total, 77672k used, 1810580k free, 5070148k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1734 adminuser 20 0 5842m 948m 13m S 0.3 12.0 3:03.41 java
1641 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.00 java
1643 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:01.20 java
1644 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:02.31 java
1671 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:02.28 java
1678 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:02.35 java
1686 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:02.20 java
1687 adminuser 20 0 5842m 948m 13m S 0.0 12.0 2:25.66 java
1688 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.11 java
1691 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.08 java
1706 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.00 java
1712 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:53.24 java
1720 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:39.38 java
1721 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:12.96 java
1722 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.00 java
1723 adminuser 20 0 5842m 948m 13m S 0.0 12.0 2:54.47 java
1724 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.00 java
1728 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:03.62 java
1729 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:08.16 java
1731 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.75 java
1732 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:02.58 java
1735 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:03.63 java
1736 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:02.23 java
1737 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:00.92 java
1738 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:03.59 java
1739 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:02.96 java
1740 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:05.07 java
1741 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:02.26 java
1742 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:04.57 java
1743 adminuser 20 0 5842m 948m 13m S 0.0 12.0 3:01.79 java
1744 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:26.27 java
1745 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.10 java
1746 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:10.72 java
1747 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.00 java
1748 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:10.99 java
5611 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.68 java
5620 adminuser 20 0 5842m 948m 13m S 0.0 12.0 0:00.36 java
感谢任何/所有回复!提前致谢!
【问题讨论】:
如果您关闭流(例如使用 try-with-resources),它们会被清理吗? 你不会认为它应该是必要的。你会想如果进程返回了一个它调用exit()
的退出代码或从main返回,那么就没有进程可以销毁。
一个程序不能退出(或返回一个退出代码),直到它完成并且程序已经关闭。
【参考方案1】:
我怀疑您的程序正在创建一个重要的输出。当您在后台运行程序时,它会写入可能只有几 KB 的缓冲区大小。一旦达到缓冲区大小,它就会等待消费者(您的程序)读取输出。这适用于标准输出和错误。
如果您不消耗输出和错误,您生成的程序可能会永远等待,但您首先等待退出代码,这不会发生,因此您会遇到死锁。
我建议你使用ProcessBuilder,将错误重定向到输出,并在等待退出代码之前将它们读到最后。
来自示例。
ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
pb.redirectErrorStream(true);
File log = new File("log");
pb.redirectOutput(Redirect.appendTo(log));
Process p = pb.start();
// no need to copy the output
int exit = p.waitFor();
【讨论】:
这个例子只是为了说明我认为github.com/Alfresco/gytheio/blob/master/gytheio-commons/src/… 类可能需要process.destroy() 的地方。如果您查看课程,则该库正在消耗标准输出和错误,因此我认为不是。我倾向于同意@EJP 上面的 cmets。不过谢谢! @Griff 代码与您问题中的代码非常不同。以上是关于如果进程以退出代码 0 结束,我应该调用 Process.destroy() 吗?的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio Emulator崩溃:进程以退出代码139结束(由信号11中断:SIGSEGV)
模拟器:进程以退出代码 -1073741515 (0xC0000135) 结束