The ControlDaemon class implements the Runnable interface and is started as a separate thread. The constructor gets the set of the parameters that were read from the properties files and converts them to a set of ParamsAndHandle objects:
private final Set<ParamsAndHandle> handlers; public ControlDaemon(Set<Parameters> params) { handlers = params .stream() .map( s -> new ParamsAndHandle(s,null)) .collect(Collectors.toSet()); }
Because the processes are not started at this point, the handles are all null. The run() method starts the processes:
@Override public void run() { try { for (ParamsAndHandle pah : handlers) { log.log(DEBUG, "Starting {0}", pah.params); ProcessHandle handle = start(pah.params); pah.handle = ...