使用 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 窗口的输出

java Runtime.exec 异常

如何从 Runtime.exec 创建的 cmd 会话写入 Unix 终端?

无法使用 Runtime.Exec 传递远程命令 (ssh)

Java Runtime.exec()的使用