ProcessBuilder - Start another process / JVM - How

2019-03-31 18:19发布

问题:

I'm writing a network app, where each Client has a Singleton ClientManager. For testing, I would like to create several clients (each in their own VM / process) without starting the program by hand n-times.

The following two questions on stackoverflow already describe how-to do that:

  • Is this really the best way to start a second JVM from Java code?
  • Java: Executing a Java application in a separate process

My Code is based on these, but it's not working:

  • The main program doesn't continue after spawn is called.
  • The spawned code doesn't get executed.

Here's the complete code using ProcessBuilder:

public class NewVM {
  static class HelloWorld2 {
    public static void main(String[] args) {
      System.out.println("Hello World");
      System.err.println("Hello World 2");
    }
  }
  public static void main(String[] args) throws Exception {
    startSecondJVM(HelloWorld2.class, true);
    startSecondJVM(HelloWorld2.class, false);
    System.out.println("Main");
  }
  public static void startSecondJVM(Class<? extends Object> clazz, boolean redirectStream) throws Exception {
    System.out.println(clazz.getCanonicalName());
    String separator = System.getProperty("file.separator");
    String classpath = System.getProperty("java.class.path");
    String path = System.getProperty("java.home")
            + separator + "bin" + separator + "java";
    ProcessBuilder processBuilder = 
            new ProcessBuilder(path, "-cp", 
            classpath, 
            clazz.getCanonicalName());
    processBuilder.redirectErrorStream(redirectStream);
    Process process = processBuilder.start();
    process.waitFor();
    System.out.println("Fin");
  }
}

What am I doing wrong???

Btw:

  • I'm using Eclipse.
  • The Singleton problem is a simplified example. Please do not suggest creating a factory.

Solution: HelloWorld2 mustn't be an inner class.

回答1:

I suggest you make HelloWorld2 a top level class. It appears java expects a top level class.

This is the code I tried.

class Main
{
    static class Main2
    {
        public static void main ( String [ ] args )
        {
            System . out . println ( "YES!!!!!!!!!!!" ) ;
        }
    }

    public static void main ( String [ ] args )
    {
        System . out . println ( Main2 . class . getCanonicalName ( ) ) ;
        System . out . println ( Main2 . class . getName ( ) ) ;
    }
}

class Main3
{
    public static void main ( String [ ] args )
    {
        System . out . println ( "YES!!!!!!!!!!!" ) ;
    }
}
  1. getCanonicalName and getName return different names. Which one is right? They are both wrong.
  2. Main3 works.


回答2:

I think I see a fix for part of the problem: process.waitFor() prevents control from returning to main() before the subprocess ends.

To figure out why your spawned process isn't starting, I'd recommend printing out all the arguments to the ProcessBuilder constructor and checking that a hand-called JVM called with those arguments succeeds. In particular, you need that class name to be the name of a class having a static void main(String[]).