private void setup() throws IOException {
		if (disposestate != DisposeState.NOT_DISPOSED) {
			throw new IOException("Decompiler has been disposed");
		}
		if (nativeProcess != null) {
			// Something bad happened to the process or the interface
			// and now we try to restart
			nativeProcess.destroy(); // Make sure previous bad process is killed           			
			nativeProcess = null;
		}
		if (exepath == null || exepath.length == 0 || exepath[0] == null) {
			throw new IOException("Could not find decompiler executable");
		}
		IOException exc = null;
		statusGood = false;
		
		try {
			nativeProcess = runtime.exec(exepath);
			
			// Give process time to load and report possible error
			try {
				nativeProcess.waitFor(200, TimeUnit.MILLISECONDS);
			}
			catch (InterruptedException e) {
				// Restore interrupted thread state since we are continuing with setup.
				// It does not appear that the decompiler interface is affected by an
				// interrupted thread so why stop here.
				Thread.currentThread().interrupt();
			}
			
			nativeIn = nativeProcess.getInputStream();
			nativeOut = nativeProcess.getOutputStream();
			
			statusGood = nativeProcess.isAlive();
			if (!statusGood) {
				if (!getAndSetErrorDisplayed()) {
					String err = new String(nativeProcess.getErrorStream().readAllBytes());
					String errorDetail = "Decompiler executable may not be compatible with your system and may need to be rebuilt.\n" +
							"(see GettingStarted.md, 'Building Native Components').\n\n" +
							err;		
					Msg.showError(this, null, "Failed to launch Decompiler process", errorDetail);
				}
			}
		}
		catch (IOException e) {
			exc = e; // permission error, etc.
		}
		finally {
			if (!statusGood) {
				disposestate = DisposeState.DISPOSED_ON_STARTUP_FAILURE;
				if (nativeProcess != null) {
					nativeProcess.destroy();          			
					nativeProcess = null;
				}
				if (exc == null) {
					exc = new IOException("Decompiler process failed to launch (see log for details)");
				}
				throw exc;
			}
		}
	}
Class for communicating with a single decompiler process.
The process controls decompilation for a single Program.
The process is initiated by the registerProgram method.
If the process is ready, the statusGood flag will be set
to true.  This flag must be checked via the isReady method
prior to invoking any of the public methods.  If the
process isn't ready, the only way to recover is by
reissuing the registerProgram call and making any other
necessary initialization calls.
Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java