private void start(final Properties properties, final File workingDirectory) {
    final List<String> jvmArgumentsList = new ArrayList<>();

    if (properties != null) {
      for (Map.Entry<Object, Object> entry : properties.entrySet()) {
        if (!entry.getKey().equals(LOG_FILE)) {
          jvmArgumentsList.add("-D" + entry.getKey() + "=" + entry.getValue());
        }
      }
    }

    if (headless) {
      jvmArgumentsList.add("-Djava.awt.headless=true");
    }

    if (jvmArguments != null) {
      Collections.addAll(jvmArgumentsList, jvmArguments);
    }

    try {
      synchronized (exitValue) {
        final String[] command =
            defineCommand(jvmArgumentsList.toArray(new String[jvmArgumentsList.size()]),
                workingDirectory.getCanonicalPath());
        process = new ProcessBuilder(command).directory(workingDirectory).start();

        final StringBuilder processCommand = new StringBuilder();
        boolean addSpace = false;

        for (String string : command) {
          if (addSpace) {
            processCommand.append(" ");
          }
          processCommand.append(string);
          addSpace = true;
        }

        final String commandString = processCommand.toString();
        logger.info("Starting " + commandString);

        final ProcessStreamReader stdOut = new ProcessStreamReader(commandString,
            process.getInputStream(), this);
        final ProcessStreamReader stdErr = new ProcessStreamReader(commandString,
            process.getErrorStream(), this);

        stdout = stdOut;
        stderr = stdErr;
        outputReader = new ProcessOutputReader(process, stdOut, stdErr);
        started = true;
      }

      outputReader.start();
      outputReader.waitFor(PROCESS_TIMEOUT_MILLIS, MILLISECONDS);
      boolean exited = process.waitFor(PROCESS_TIMEOUT_MILLIS, MILLISECONDS);

      synchronized (exitValue) {
        exitValue.set(exited ? process.exitValue() : 0);
        stopped = exited;
      }

    } catch (InterruptedException e) {
      synchronized (exitValue) {
        interrupted = true;
        processException = e;
      }
    } catch (Throwable t) {
      synchronized (exitValue) {
        processException = t;
      }
    }
  }
Wraps spawned {@link Process} to capture output and provide interaction with the process.

@since GemFire 4.1.1
geode-junit/src/main/java/org/apache/geode/test/process/ProcessWrapper.java