code: public <C extends StreamControl, SO, SE> ProcessMonitor<SO, SE> launch(ProcessTracker processTracker, StreamContext<C, SO, SE> streamContext) throws ProcessException {
          C streamControl;
          try {
              streamControl = streamContext.produceControl();
          } catch (IOException e) {
              throw new ProcessLaunchException("failed to produce output context", e);
          }
          // a one-time use executor service; it is shutdown immediately after exactly one task is submitted
          ListeningExecutorService launchExecutorService = launchExecutorServiceFactory.get();
          ProcessMissionControl.Execution<SO, SE> execution = new ProcessMissionControl(this, processTracker, launchExecutorService)
                  .launch(streamControl, exitCode -> {
                      StreamContent<SO, SE> content = streamContext.transform(exitCode, streamControl);
                      return ProcessResult.direct(exitCode, content);
                  });
          ListenableFuture<ProcessResult<SO, SE>> fullResultFuture = execution.getFuture();
          launchExecutorService.shutdown(); // previously submitted tasks are executed
          ProcessMonitor<SO, SE> monitor = new BasicProcessMonitor<>(execution.getProcess(), fullResultFuture, processTracker);
          return monitor;
      }
docs: Launches a subprocess. Use {@link #launcher(ProcessTracker)} to build a launcher
  and invoke {@link Launcher#launch()} for a more fluent way of executing this method.
  @param processTracker process tracker to use
  @param streamContext stream context
  @param <C> stream control type
  @param <SO> type of captured standard output content
  @param <SE> type of captured standard error content
  @return a process monitor
  @throws ProcessException if the process cannot be launched