使用 Runtime.exec 从 Java 应用程序启动 JVM 进程?
Posted
技术标签:
【中文标题】使用 Runtime.exec 从 Java 应用程序启动 JVM 进程?【英文标题】:Launch JVM process from a Java application use Runtime.exec? 【发布时间】:2010-10-03 14:03:36 【问题描述】:我希望能够从现有的 java 应用程序启动 Java 服务器进程并监视 stdoutput 和 stderror 并将该输出重定向到文件。是使用“Runtime.exec”并将应用程序视为任何其他操作系统进程的最佳方法,还是有更适合新 JVM 的方法。
这是在 Java 1.5 上
【问题讨论】:
如果您决定使用运行时,请阅读"When Runtime.exec Won't..." 是的,有办法告诉 JVM 执行一个运行给定类main()
方法的新 JVM 会很好。我想这只有在新的 JVM 使用当前的类加载器时才可以接受,否则使用哪些类实现将太不可预测。但这将是非常困难的,也许是不可能的,因为需要防止进程使用木马类加载器启动 JVM。
【参考方案1】:
您可能应该使用ProcessBuilder
而不是Runtime
,尽管我不知道在您的情况下是否更合适(特别是运行Java 进程)。
【讨论】:
ProcessBuilder 正是用于此目的的工具。您可以轻松地挂钩进程的输出/错误,甚至将错误重定向到输出,这样您就不必监视两个流(除非您愿意)。您必须自己编写流 I/O 代码……请参阅 BufferedInputReader。 如果这个外部进程挂起,process.destroy 将永远无法杀死它,在 linux 中你可以发送一个 SIGINT 但它会杀死整个程序,而不仅仅是这个进程,启动一些未经测试,除非有办法杀死这个特定的进程,否则完全启动一个新进程可能是安全的。或者如果有然后告诉我,我 laucnh 例如 nslookup 然后没有办法杀死它,(除了退出)那么如果进程挂起,你怎么能真正杀死它??【参考方案2】:我知道我在这个线程中迟到了,但如果有人需要它,根据我的经验,使用 ANT 启动 Java 应用程序更容易。这具有独立于平台的好处。这是一个示例类:
package com.trilliantnetworks.scheduler.quartz.test;
import java.io.File;
import java.io.PrintStream;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.DemuxOutputStream;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Echo;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.Path;
public class MyLaunchTest
public static void main(String[] args)
Project project = new Project();
project.setBaseDir(new File(System.getProperty("user.dir")));
project.init();
DefaultLogger logger = new DefaultLogger();
project.addBuildListener(logger);
logger.setOutputPrintStream(System.out);
logger.setErrorPrintStream(System.err);
logger.setMessageOutputLevel(Project.MSG_INFO);
System.setOut(new PrintStream(new DemuxOutputStream(project, false)));
System.setErr(new PrintStream(new DemuxOutputStream(project, true)));
project.fireBuildStarted();
System.out.println("running");
Throwable caught = null;
try
Echo echo = new Echo();
echo.setTaskName("Echo");
echo.setProject(project);
echo.init();
echo.setMessage("Launching Some Class");
echo.execute();
Java javaTask = new Java();
javaTask.setTaskName("runjava");
javaTask.setProject(project);
javaTask.setFork(true);
javaTask.setFailonerror(true);
javaTask.setClassname(MyClassToLaunch.class.getName());
Path path = new Path(project, new File(System.getProperty("user.dir") + "/classes").getAbsolutePath());
javaTask.setClasspath(path);
javaTask.init();
int ret = javaTask.executeJava();
System.out.println("java task return code: " + ret);
catch (BuildException e)
caught = e;
project.log("finished");
project.fireBuildFinished(caught);
【讨论】:
嗨,我尝试过类似的方法,但是当它到达 project.init() 时它总是挂起。它不会产生任何错误,但不会从该行移动。对此有何评论? 感谢 Ant 的想法是独立于平台的。需要从 SoapUI 中运行一个可执行 jar,该 jar 稍后也必须在 CI 上运行。 您必须安装 apache ant 并且需要将“ANT_HOME”设置为路径变量。见mkyong.com/ant/how-to-install-apache-ant-on-windows以上是关于使用 Runtime.exec 从 Java 应用程序启动 JVM 进程?的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Opensuse 上运行 Java Runtime.exec()
如何通过在 java 中使用 Runtime.exec() 运行 sqlplus 来捕获 sqlplus 窗口的输出
如何从 Runtime.exec 创建的 cmd 会话写入 Unix 终端?