Java 使用Processbuilder运行jar不会';我不能正常工作
我有以下代码:Java 使用Processbuilder运行jar不会';我不能正常工作,java,jar,processbuilder,Java,Jar,Processbuilder,我有以下代码: ProcessBuilder pb = new ProcessBuilder( "java", "-jar", "test.jar", Integer.toString( jobId ), Integer.toString( software ), Integer.toString( entryPoint ), application ); pb.directory( new File("/home/userName/TestBSC") ); Process proc = pb.
ProcessBuilder pb = new ProcessBuilder( "java", "-jar", "test.jar", Integer.toString( jobId ), Integer.toString( software ), Integer.toString( entryPoint ), application );
pb.directory( new File("/home/userName/TestBSC") );
Process proc = pb.start();
使用以下命令从我的终端运行jar文件时:
java-jartest.jar135 3 appName
然后它就像一个符咒。jar在我的数据库中推送了一些东西,所以我看到它正在工作。但是当使用上面提到的processBuilder代码从我的JavaServlet执行此操作时,我的数据库中没有任何数据,也没有任何错误
不管进程本身是如何运行的,我在终端中用“ps ax”检查了它。所以我想知道这里的区别在哪里?我做错了什么
有人有主意吗
编辑:更多代码:
ProcessBuilder pb = new ProcessBuilder( "java", "-jar", "test.jar", Integer.toString( jobId ), Integer.toString( software ), Integer.toString( entryPoint ), application );
pb.directory( new File("/home/userName/TestBSC") );
Process proc = pb.start();
System.out.println( "Job running" );
proc.waitFor(); // wait until jar is finished
System.out.println( "Job finished" );
InputStream in = proc.getInputStream();
InputStream err = proc.getErrorStream();
byte result[] = new byte[ in.available() ];
in.read( result, 0, result.length );
System.out.println( new String( result ) );
byte error[] = new byte[ err.available() ];
err.read( error, 0, error.length );
System.out.println( new String( error ) );
更新: 我尝试调用shell脚本而不是jar。因此,我从java文件中使用processbuilder调用了一个shell脚本 我的shell脚本执行以下操作:
java -jar test.jar "$1" "$2" "$3" "$4"
但还是没用。所以我试了一下:
gnome-terminal -x java -jar test.jar "$1" "$2" "$3" "$4"
突然间,它开始工作了但是它打开gnome终端,执行jar文件
所以我想知道,这是否与eclipse中未显示的输出有关?我真的不明白。这是一个很好的解决办法。但是我真的很想在每次执行jar时都不让终端打开的情况下让它工作。你能试试这个吗 更新 代码:
// Java runtime
Runtime runtime = Runtime.getRuntime();
// Command
String[] command = {"java", "-jar", "test.jar", Integer.toString( jobId ), Integer.toString( software ), Integer.toString( entryPoint ), application};
// Process
Process process = runtime.exec(command, null, new File("/home/userName/TestBSC"));
首先,我无法重现您的问题,因此此答案将仅基于文档 默认情况下,创建的子流程没有自己的终端或服务器 安慰其所有标准I/O(即标准输入、标准输出、标准输出)操作 将重定向到父进程,在那里可以访问它们 通过使用getOutputStream()方法获得的流, getInputStream()和getErrorStream()。父进程使用这些 要向子流程馈送输入并从子流程获取输出的流因为 一些本机平台仅为标准配置提供有限的缓冲区大小 输入和输出流,未能及时写入输入流 或者读取子流程的输出流可能导致子流程 阻止,甚至死锁。 基本上,这告诉您需要正确地处理外部进程流,否则它可能会在某些平台上造成死锁。这意味着如果我们运行的命令产生一些输出,您必须读取该输出 让我们看看你的代码;您正在调用
process.waitFor()
以等待进程完成,但问题是如果不读取/使用它的输出,您的进程将无法完成,因此您正在创建死锁
如何克服这一问题:
InputStreamConsumerThread
正确处理输入/错误流
public class InputStreamConsumerThread extends Thread
{
private InputStream is;
private boolean sysout;
private StringBuilder output = new StringBuilder();
public InputStreamConsumerThread (InputStream is, boolean sysout)
{
this.is=is;
this.sysout=sysout;
}
public void run()
{
try(BufferedReader br = new BufferedReader(new InputStreamReader(is)))
{
for (String line = br.readLine(); line != null; line = br.readLine())
{
if (sysout)
System.out.println(line);
output.append(line).append("\n");
}
}
}
public String getOutput(){
return output.toString();
}
}
你的代码将是
String systemProperties = "-Dkey=value";
ProcessBuilder pb = new ProcessBuilder( "java", systemProperties, "-jar", "test.jar", Integer.toString( jobId ), Integer.toString( software ), Integer.toString( entryPoint ), application );
pb.directory( new File("/home/userName/TestBSC") );
Process proc = pb.start();
InputStreamConsumerThread inputConsumer =
new InputStreamConsumerThread(proc.getInputStream(), true);
InputStreamConsumerThread errorConsumer =
new InputStreamConsumerThread(proc.getErrorStream(), true);
inputConsumer.start();
errorConsumer.start();
System.out.println( "Job running" );
proc.waitFor(); // wait until jar is finished
System.out.println( "Job finished" );
String processOutput = inputConsumer.getOutput();
String processError = errorConsumer.getOutput();
if(!processOutput.isEmpty()){
//there were some output
}
if(!processError.isEmpty()){
//there were some error
}
ProcessBuilder
重定向输出。如果您只希望您的子进程使用与父进程相同的输入/输出流,您可以这样使用
ProcessBuilder pb = new ProcessBuilder( "java", "-jar", "test.jar", Integer.toString( jobId ), Integer.toString( software ), Integer.toString( entryPoint ), application );
pb.directory( new File("/home/userName/TestBSC") );
pb.redirectErrorStream(true); // redirect error stream to output stream
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process proc = pb.start();
System.out.println( "Job running" );
//since process builder will handle the streams for us
//we can call waitFor() safely
proc.waitFor();
System.out.println( "Job finished" );
ProcessBuilder
和消费者线程发生冲突,我知道有两个库可以很好地处理创建子进程的问题
低开销、无阻塞I/O、外部进程执行
Java的实现。它是一个替代品
java.lang.ProcessBuilder和java.lang.Process
你有没有被这样一个事实所困扰过:每当你产生一个
在Java中,您必须创建两个或三个“pumper”线程(用于
每个进程)从stdout和stderr管道中提取数据
将数据输入stdin?如果您的代码启动了许多进程,您可以
有几十个或几百个线程除了泵送数据什么都不做
NuProcess使用JNA库使用特定于平台的本机API
在Java进程和
衍生过程
从运行外部进程时,有许多方法可供选择
JAVA有一些JRE选项,例如Runtime.exec()和
ProcessBuilder。还有ApacheCommonsExec。然而我们
创建了另一个进程库(YAPL)
这一疯狂努力的一些原因
改进了流读取/写入流重定向的处理
从stderr到stdout改进了超时处理改进了检查
出口代码改进了API一行程序,用于非常复杂的用例一
将进程输出转换为访问进程的字符串的行程序
改进了对异步进程的对象可用支持(未来)
支持多进程的SLF4J API日志记录
Java的进程API中还有其他缺陷,请参阅这篇JavaWorld文章以了解更多信息。进程中是否存在任何错误/异常?请尝试给出
Java
@MikaëlB:不,很遗憾没有。@Petermm:我也尝试过,但结果相同。或者等等……你说java是什么意思。你是说jar文件的完整路径还是java jre?@petermm:我现在尝试了这个:/usr/lib64/jvm/java-7-openjdk/bin/java-jar。。。。但这也不起作用。不幸的是,情况也一样。执行该过程。但是没有输出,数据库中也没有存储任何内容。就像这个过程不是真正的加工。这太奇怪了。这个过程的exitValue
是什么?()过程不会停止(这可能是一个优先事项或类似的事情吗?我不这么认为。你还有这个waitFor()
?如果有,你能在System.out.println(新字符串(错误));
?哇,谢谢这个伟大的答案。我目前正在测试方法1。我需要做新的BufferedReader()吗?)而不是InputStreamConsumerThread的run方法中的new BufferedInputStream(),因为它说,我不能从B转换