在正常情况下我们可以用Project.waitfor()的返回值是否等于0的方法来判断java调用外部程序是Pass或者是Fail。

但是这个方法往往会被因进程堵塞而导致程序发生死锁,无法再继续执行外部程序。

因为本地的系统对标准输入和输出所提供的缓冲池有限,所以错误的对标准输出快速的写入和从标准输入快速的读入都有可能造成子进程死锁。问题的关键在缓冲区这个地方:可执行程序的标准输出比较多,而运行窗口的标准缓冲区不够大,所以发生阻塞。接着来分析缓冲区,当Runtime对象调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立三个管道连接:标准输入,标准输出和标准错误流。假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitfor()这里。

但是在其中过程中真正起关键作用的缓冲区是getErrorStream()对应的那个缓冲区没有被清空,意思就是说其实只要及时读取标准错误流缓冲区的数据程序就不会被block。

原先的代码

//run bat file
Process project = Runtime.getRuntime().exec("cmd.exe /c " + batpath.replaceAll(" ", "\" \""));
int exitcode=project.waitFor();
//kill the process
project.destroy();
logger.info(exitcode);
//if the exitcode is 0, the RIA TEST is passed,else the RIA TEST is failed
if(exitcode==0){
logger.info("============ is Passed============");
}
else{
Boolean resultFlag=false;
logger.info("============ is Failed============");
Assert.assertTrue(bugID+"Failed",resultFlag);
}

修改后的代码:

增加两个线程来读取标准输出流和标准错误流

		try{
//run bat file
Process project = Runtime.getRuntime().exec("cmd.exe /c " + batpath.replaceAll(" ", "\" \""));
final InputStream br = project.getInputStream();
final InputStream br_error = project.getErrorStream();
//run 2 threads to read the standard InputStream and the ErrorStream to avoid the project.
//waitfor()method blocked
new Thread() {
public void run() {
BufferedReader br1 = new BufferedReader(new InputStreamReader(br));
try {
String line1 = null;
while ((line1 = br1.readLine()) != null) {
if (line1 != null){
logger.info("RIATest info: "+line1);
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
//run thread to read the standard ErrorStream
new Thread() {
public void run() {
BufferedReader br2 = new BufferedReader(new InputStreamReader(br_error));
try {
String line2 = null;
while ((line2 = br2.readLine()) != null) {
if (line2 != null){
logger.info("Error: "+line2);
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
br_error.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start(); try{ int exitcode=project.waitFor();
//kill the process
project.destroy();
logger.info(exitcode);
//if the exitcode is 0, the RIA TEST is passed,else the RIA TEST is failed
if(exitcode==0){
logger.info("============ is Passed============");
}
else{
Boolean resultFlag=false;
logger.info("============ is Failed============");
Assert.assertTrue(bugID+"Failed",resultFlag);
} }
catch(Throwable e){ e.printStackTrace(); } }
catch(IOException e){
e.printStackTrace();
try
{
project.getErrorStream().close();
project.getInputStream().close();
project.getOutputStream().close();
}
catch(Exception ee){}
}

关于JAVA Project.waitfor()死锁问题的更多相关文章

  1. java 代码执行cmd 返回值异常 (关于JAVA Project.waitfor()返回值是1)

    关于JAVA Project.waitfor()返回值是1   0条评论 Project.waitfor()返回值是1,找了很久从网上没有发现关于1的说明. 这时对源代码调试了一下,发现Project ...

  2. 关于JAVA Project.waitfor()返回值是1

    Project.waitfor()返回值是1,找了很久从网上没有发现关于1的说明. 这时对源代码调试了一下,发现Project=null.而去根目录下点击被调用的bat文件发现也可以被正确执行. 这时 ...

  3. java compiler level does not match the version of the installed java project facet 解决方案

    项目出现 java compiler level does not match the version of the installed java project facet 错误,一般是项目移植出现 ...

  4. java compiler level does not match the version of the installed java project facet

    Java compiler level does not match the version of the installed java project facet错误的解决 因工作的关系,Eclip ...

  5. export a java project to runable jar

    When a java project needs to be transfered to another machine, e.g. vps, we need to export it to a r ...

  6. Using Maven to generate a Java Project or Web project

    I often to generate a Java project or Web project with Eclipse tool. Well, I have no idea when I wan ...

  7. Java compiler level does not match the version of the installed Java project facet.(转)

    Java compiler level does not match解决方法 从别的地方导入一个项目的时候,经常会遇到eclipse/Myeclipse报Description  Resource P ...

  8. maven项目 Java compiler level does not match the version of the installed Java project facet

    因工作的关系,Eclipse开发的Java项目拷来拷去,有时候会报一个很奇怪的错误.明明源码一模一样,为什么项目复制到另一台机器上,就会报“java compiler level does not m ...

  9. Java compiler level does not match the version of the installed Java project facet.问题

    从同事那里拷贝过来的web项目,导入到eclipse中,出现Java compiler level does not match the version of the installed Java p ...

随机推荐

  1. linux配置ssh+rsync

    ssh  远程登录 sftp    文件共享 类似ftp  ssh  secure file transfer client scp    文件共享 类似cp   ssh配置文件 /etc/ssh/s ...

  2. WPF 自带Datagrid编辑后无法更新数据源的问题

    原文  WPF 自带Datagrid编辑后无法更新数据源的问题 解决办法: 在列的绑定属性里加上UpdateSourceTrigger,示例XAML如下 <DataGrid Grid.Row=& ...

  3. 设置MAVEN_OPTS环境变量

    运行mvn命令实际上是执行了Java命令,既然是运行Java,那么运行Java命令可用的参数当然也应该在运行mvn命令时可用.这个时候,MAVEN_OPTS环境变量就能派上用场. 通常需要设置MAVE ...

  4. response.sendRedirect("")和request.getRequestDispatcher("").forward(req,resp);

    1:request.getRequestDispatcher("转发路径").forward(req,resp)该语句是实现请求转发的,当请求进入到该servlet中执行到该语句时 ...

  5. 修改合同号的bapi

    这个例子是在合同号中新增项目号: 1.先要读取该合同号的信息用一个BAPI BAPI_CONTRACT_GETDETAIL 2.调用修改合同号的BAPI. 代码如下: REPORT ztest_cla ...

  6. Servlet的学习之Request请求对象(3)

    本篇接上一篇,将Servlet中的HttpServletRequest对象获取RequestDispatcher对象后能进行的[转发]forward功能和[包含]include功能介绍完. 首先来看R ...

  7. PrimusUI

    小身材大用途,用PrimusUI驾驭你的页面 “PrimusUI”是自己在借鉴了如今网上很多开源的UI库,再经过自己整理加工的一个简单代码集合. 每个功能块的CSS代码都很少,力求简单易懂,低门槛,代 ...

  8. 全面解读WM_NOTIFY

    VC中的消息的分类有3种:窗口消息.命令消息和控件通知消息,我们这里要谈的是最后一种:控件通知消息. 控件通知消息,是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通知父窗口.通知消息只适用于 ...

  9. 【Demo 0005】Android 资源

    本章学习要点:        1.  了解Android中资源用途:        2.  掌握资源使用通用规则:        3.  掌握具体资源使用方法; 一.Android资源       a ...

  10. 解决SVG跨浏览器兼容性问题

    Raphael JS:SVG/VML+JS实现跨浏览器的矢量图形实现方案 http://blog.csdn.net/tiewen/article/details/8535748 SVG那些小事儿 ht ...