1

I run the program like this:

    Process process;
    try {
        process = new ProcessBuilder("java", "-jar", "test.jar", "1", "20").start();
        BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        while ((line = in.readLine()) != null) {
          System.out.println(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

The program I call uses standard output System.out.println("Hello!"); However, the the calling program gets nothing back. Am I using ProcessBuilder() wrong? Thanks!

  • please show all code, how do you call this piece of code? – tostao Nov 12 '15 at 08:59
  • 1
    Are you 100% positive that `java -jar test.jar 1 20" outputs something? Have you tried to also redirect the error stream? – assylias Nov 12 '15 at 09:05
  • 1
    you can follow this example in stackoverflow [clickhere](http://stackoverflow.com/questions/17985036/run-a-jar-file-from-java-program) – Richard Elite Nov 12 '15 at 09:17
  • 1
    @ManojKrishna good hint, but preferably write your comment that way: "you can follow [this example](http://stackoverflow.com/questions/17985036/run-a-jar-file-from-java-program) in stackoverflow" – Binkan Salaryman Nov 12 '15 at 09:19
  • 1
    Is there a constraint to run a second JVM? Why not running the code in the current JVM using another class loader? – SubOptimal Nov 12 '15 at 10:01
  • If you don’t get the expected output, it’s a good move to check whether `getErrorStream()` has something valuable to read. Or use `new ProcessBuilder(…) .redirectError( ProcessBuilder.Redirect.INHERIT) .start()` to let it print error messages of the sub process directly to the console of your main process. – Holger Nov 12 '15 at 12:47

1 Answers1

1

If there is no constraint to start another JVM (for example: usage of System.exit() in test.jar) you could load and run the test.jar inside the current JVM.

Following snippet shows the principle.

File file = new File("/tmp/test.jar");
URLClassLoader loader = new URLClassLoader(
        new URL[]{file.toURI().toURL()}
);

String className = new JarFile(file)
        .getManifest()
        .getMainAttributes()
        .getValue(Attributes.Name.MAIN_CLASS);

Method main = loader
        .loadClass(className)
        .getDeclaredMethod("main", String[].class);

Object arg = new String[]{"1", "20"};

try {
    main.invoke(null, arg);
} catch (Exception e) {
    // do appropriate exception handling here
    e.printStackTrace(System.err);
}
SubOptimal
  • 22,518
  • 3
  • 53
  • 69
  • But could you capture the output of that jar without using processBuilder? – firstpostcommenter Nov 30 '17 at 15:32
  • @firstpostcommenter You mean to redirect the output of `test.jar` to something else then `System.out`? – SubOptimal Nov 30 '17 at 16:45
  • yes, this code doesn't allow to consume the System.out where as processBuilder makes it possible (We could use a shell script to pipe the first jar output to second jar input if required but that is different solution) – firstpostcommenter Nov 30 '17 at 16:47
  • @firstpostcommenter It depends what are your requirements and what you want to achieve. Instead of starting another JVM from within the current JVM using a loggin framework would be a less memory consuming and probaly faster (related to the startup time for the additional JVM) solution. – SubOptimal Dec 06 '17 at 07:16