2015-04-28 88 views
0

我有一个应用程序在我的PC的指定位置调用java测试类。现在路径是硬编码的,我通过从命令行执行它来检查它的工作情况(如果你想看到它:java -cp C:\Users\user\Documents\workspace\test\build\test.jar org.junit.runner.JUnitCore us.test.DynamicWebserviceInvocationTest),所以我知道该命令工作正常。确定是否从另一个java应用程序执行java执行成功

事情是,当我做Runtime.getRuntime().exec(command),如果我尝试记录其生成的过程的结果InputStream和ErrorStream,程序就会陷入困境。我试着用exitValue()和waitFor(),但第一次抛出一个不完整的错误,第二次也卡住了。奇怪的是,如果我没有碰到这些(流,或使用函数)的任何东西,程序没有问题的结局。

所以我的问题是:这是为什么呢?下一步是使用给定的参数构建命令,但是如果我看不到结果输入,我不能完全确定测试是否正在运行。

的代码,如果你想看到它:

Runtime runtime=Runtime.getRuntime(); 
logger.debug("Attempting to execute the test {} at path {}",classpath,applicationLocation); 

String command="java -cp C:\\Users\\user\\Documents\\workspace\\test\\build\\test.jar org.junit.runner.JUnitCore us.test.DynamicWebserviceInvocationTest"; 
Process process=runtime.exec(command); 
BufferedReader stdInput = new BufferedReader(new 
     InputStreamReader(process.getInputStream())); 

BufferedReader stdError = new BufferedReader(new 
     InputStreamReader(process.getErrorStream())); 

System.out.println("Here is the standard output of the command:\n"); 
String s = null; 
while ((s = stdInput.readLine()) != null) { 
    System.out.println(s); 
} 

System.out.println("Here is the standard error of the command (if any):\n"); 
while ((s = stdError.readLine()) != null) { 
    System.out.println(s); 
}  
+0

正如一个测试:你能尝试阅读无论是在时间和交替流一行他们之间只要进程还活着? – Dawnkeeper

+0

使用本地套接字互相连接并进行通信。 – farukdgn

+0

@Dawnkeeper:我试了一下,它打印出整个东西,并退出罚款。现在我只需要处理输出。非常感谢! – KatVolkov

回答

0

请务必关闭2流:

String command="java -cp C:\\Users\\user\\Documents\\workspace\\test\\build\\test.jar org.junit.runner.JUnitCore us.test.DynamicWebserviceInvocationTest"; 
    Process process=runtime.exec(command); 
    BufferedReader stdInput = new BufferedReader(new 
      InputStreamReader(process.getInputStream())); 

    BufferedReader stdError = new BufferedReader(new 
     InputStreamReader(process.getErrorStream())); 

    // read the output from the command 
    System.out.println("Here is the standard output of the command:\n"); 
    String s = null; 
    while ((s = stdInput.readLine()) != null) { 
     System.out.println(s); 
    } 
    stdInput.close(); 

    // read any errors from the attempted command 
    System.out.println("Here is the standard error of the command (if any):\n"); 
    while ((s = stdError.readLine()) != null) { 
     System.out.println(s); 
    } 
    stdError.close(); 
+0

在单线程中这样做并不安全。这取决于孩子输出的数据量以及操作系统使用的缓冲区数量。在你的情况下,如果进程想要写8k错误消息,然后输出1行正常输出,8k将填充错误缓冲区并且根本不写任何标准输出,你的第一个循环将阻塞并且不会消耗stderr。 – eckes

1

你绝对必须阅读在单独的线程两个流。 (阅读Process课程的Javadoc)。如果您等待结束,或先读取一个流,然后再读取其中一个流,则可能会发生命令的输出缓冲区已满并且会阻塞(取决于您先读取的内容,它会在stdout或stderr上)。通常在当前线程中使用waitFor(),并让后台线程排空输出(这也允许在没有轮询的情况下检测子进程的结束)。

如果您只想使用一个(额外)线程,则可以将stderr重定向到stdout。如果您想避免读取流,可以设置 ProcessBuilder功能inheritIO()。这允许将流写入现有输出,因此您不需要一个线程来独立读取。

有BTW各种libararies提供exec工具(例如Apache Commons Exec has some streams),它们为Process提供活动流排水,日志记录或泵送。

此外,它也可能是一个好主意,先关闭标准输入,如果输入的命令等待:p.getOutputStream().close();