views:

3582

answers:

3

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

+5  A: 

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).

Fabian Steeg
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
+3  A: 

If you do decide to use Runtime, read "When Runtime.exec Won't..."

duffymo
+1 This article will save you from a lot of headaches. Highly recommended!
Outlaw Programmer
+2  A: 

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.
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