public void exitProcess() {
   if (classLoader != null) {
     // Just to get rid of the warning....
     classLoader.getClass();
   }
   // Send a request to shutdown the spawned process and return...
   classLoader = null;
 }
  public void spawnProcess() throws IOException, InterruptedException {
    log.debug("INSIDE spawnProcess");
    // Setup the classloader and determine the port used to process the incoming requests.
    // TODO: make the java command configurable.
    String javaHome = System.getProperty("java.home");
    String javaExe = javaHome + File.separator + "bin" + File.separator + "java";
    int port = -1;
    String hostname = null;
    ClassLoader parent = Thread.currentThread().getContextClassLoader();
    parent = (ClassLoader.getSystemClassLoader() == parent) ? null : parent;
    if (parent != null) {
      server = new ServerSocket(0);
      port = server.getLocalPort();
      hostname = InetAddress.getLocalHost().getHostName();
      classLoader = new SpawnerClassLoader(server, parent, identifier);
      classLoader.start();
    }
    List<String> command = new LinkedList<String>();
    command.add(javaExe);
    command.addAll(jvmArgs);
    command.add("-cp");
    command.add(System.getProperty("java.class.path") + File.pathSeparator + spawnedClassPath);
    command.add(Spawned.class.getName());
    // Create a remote class loader only if the current thread has a context class loader set.
    if (parent != null) {
      command.add(Options.PORT);
      command.add(String.valueOf(port));
      command.add(Options.HOST);
      command.add(hostname);
    } else {
      command.add(Options.NOCLASSLOADER);
    }
    command.add(Options.CLASSNAME);
    command.add(className);
    if (methodName != null) {
      command.add(Options.METHODNAME);
      command.add(methodName);
    }
    // Store the system properties to a file that will be loaded by the spawned application.
    Properties props = System.getProperties();
    File file = File.createTempFile("spawned", ".properties");
    Writer out = new FileWriter(file);
    props.store(out, "Spawned properties");
    out.close();
    command.add(Options.PROPERTYFILE);
    command.add(file.getAbsolutePath());
    log.info("command: {}", command);
    ProcessBuilder processBuilder = new ProcessBuilder(command);
    processBuilder = processBuilder.redirectErrorStream(true);
    process = processBuilder.start();
    BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
    new Thread(
        new Runnable() {

          private BufferedReader input;

          Runnable setInput(BufferedReader input) {
            this.input = input;
            return this;
          }

          public void run() {
            log.debug("Inside run");
            String line;
            try {
              while ((line = input.readLine()) != null) {
                log.info("stdout: {}", line);
              }
            } catch (IOException e) {
              log.debug("An exception was raised while trying to read the next line", e);
            }
          }
        }.setInput(input)) {
      {
        setName(Spawner.this.identifier + getName());
        start();
      }
    };

    new Thread() {
      private File file;

      public void run() {
        try {
          int result = process.waitFor();
          log.info("Exiting process with: {}", result);
        } catch (InterruptedException e) {
          log.error("An exception was generated when waiting for process to exit", e);
        } finally {
          Spawner.this.processExited = true;
          if (file.exists()) {
            file.delete();
          }
        }
      }

      public void setFile(File file) {
        this.file = file;
        setName(Spawner.this.identifier + getName());
        start();
      }
    }.setFile(file);
  }