19

I want to be able to launch a Java server process from an existing java application and monitor the stdoutput and stderror and redirect that output to a file. Is the best approach to use 'Runtime.exec' and treat the app like any other OS process or is there something more suited for new JVMs.

This is on Java 1.5

Berlin Brown
  • 11,504
  • 37
  • 135
  • 203
  • Yes, having a means to tell the JVM to execute a new JVM that ran a given class `main()` method would be nice. I guess that would only be acceptable if the new JVM used the current class-loader, otherwise which class implementations were used would be too unpredictable. But that would be very hard, perhaps impossible, because of the need to prevent a process starting the JVM with a trojan class-loader. – Raedwald Mar 21 '13 at 18:40
  • If you do decide to use Runtime, read ["When Runtime.exec Won't..."](http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html) – duffymo Jan 26 '09 at 17:37

2 Answers2

18

Instead of Runtime, you should probably use ProcessBuilder, though I don't know if something else is even more appropriate in your case (running a Java process in particular).

Gautam
  • 7,868
  • 12
  • 64
  • 105
Fabian Steeg
  • 44,988
  • 7
  • 85
  • 112
  • 2
    ProcessBuilder is exactly the tool for this purpose. You can easily hook the out/err of the process and even redirect the err to out so you don't have to monitor two streams (unless you want to). You will have to write the stream I/O code yourself ... see BufferedInputReader. – basszero Jan 26 '09 at 17:09
  • And what if this external process hangs, process.destroy will never be able to kill it, in linux you can send a SIGINT but then it will kill the whole program not just this process, launching something which is not tested, might be on the safe side to launch in altogether a new process unless there is a way to kill this particular process. or if there is then tell me, i laucnh e.g nslookup and then there is no way to kill it, (except the quit) so how can you really kill the process if it hangs?? – Space Rocker Mar 15 '13 at 11:09
12

I know I am late in this thread, but in case someone needs it, in my experience, it is easier to use ANT to launch a Java application. This has the benefit of being platform independent. Here is a sample class that does that:

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);
}
}
Mel T.
  • 121
  • 1
  • 3
  • Hi, I've tried something similar to this but it always hang when it reach project.init(). It doesn't produce any error but just won't move from that line. Any comment on that? – Iso Jun 09 '10 at 00:48
  • Thanks for the idea with Ant to be platform-independent. Needed to run a executable-jar from within SoapUI which also has to run on a CI later. – lostiniceland Sep 17 '15 at 07:00
  • you have to install apache ant and need to set "ANT_HOME" as a path variable. see https://www.mkyong.com/ant/how-to-install-apache-ant-on-windows/ – Sameera Manorathna Apr 18 '18 at 13:46