Code review comment: why not just output to the `outputStream`? So that we don't need to buffer a log of content in memory?

Code before review:
public void run() {
BufferedReader outReader = null;
String line = null;
long startTime = System.currentTimeMillis();
try {
outReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (!isStop && (line = outReader.readLine()) != null) {
outputBuffer.append(line + '\n');
SparkLoadAppHandle.State oldState = handle.getState();
SparkLoadAppHandle.State newState = oldState;
if (line.contains(STATE)) {
String state = regexGetState(line);
if (state != null) {
YarnApplicationState yarnState = YarnApplicationState.valueOf(state);
newState = fromYarnState(yarnState);
if (newState != oldState) {
handle.setState(newState);
}
}
String appId = regexGetAppId(line);
if (appId != null) {
if (!appId.equals(handle.getAppId())) {
handle.setAppId(appId);
}
}
LOG.debug("spark appId that handle get is {}, state: {}", handle.getAppId(), handle.getState().toString());
switch (newState) {
case UNKNOWN:
case CONNECTED:
case SUBMITTED:
if (System.currentTimeMillis() - startTime > submitTimeoutMs) {
isStop = true;
handle.kill();
}
break;
case RUNNING:
case FINISHED:
isStop = true;
break;
case KILLED:
case FAILED:
case LOST:
isStop = true;
handle.kill();
break;
default:
Preconditions.checkState(false, "wrong spark app state");
}
}
else if (line.contains(QUEUE) || line.contains(START_TIME) || line.contains(FINAL_STATUS) ||
line.contains(URL) || line.contains(USER)) {
String value = getValue(line);
if (!Strings.isNullOrEmpty(value)) {
try {
if (line.contains(QUEUE)) {
handle.setQueue(value);
} else if (line.contains(START_TIME)) {
handle.setStartTime(Long.parseLong(value));
} else if (line.contains(FINAL_STATUS)) {
handle.setFinalStatus(FinalApplicationStatus.valueOf(value));
} else if (line.contains(URL)) {
handle.setUrl(value);
} else if (line.contains(USER)) {
handle.setUser(value);
}
} catch (IllegalArgumentException e) {
LOG.warn("parse log encounter an error, line: {}, msg: {}", line, e.getMessage());
}
}
}
}
if (outputStream != null) {
outputStream.write(outputBuffer.toString().getBytes());
}
} catch (Exception e) {
LOG.warn("Exception monitoring process.", e);
} finally {
try {
if (outReader != null) {
outReader.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
LOG.warn("close buffered reader error", e);
}
}
}

Line under review: outputBuffer.append(line + '\n');

Code after addressing the review:
public void run() {
BufferedReader outReader = null;
String line = null;
long startTime = System.currentTimeMillis();
try {
outReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (!isStop && (line = outReader.readLine()) != null) {
if (outputStream != null) {
outputStream.write((line + "\n").getBytes());
}
SparkLoadAppHandle.State oldState = handle.getState();
SparkLoadAppHandle.State newState = oldState;
if (line.contains(STATE)) {
String state = regexGetState(line);
if (state != null) {
YarnApplicationState yarnState = YarnApplicationState.valueOf(state);
newState = fromYarnState(yarnState);
if (newState != oldState) {
handle.setState(newState);
}
}
String appId = regexGetAppId(line);
if (appId != null) {
if (!appId.equals(handle.getAppId())) {
handle.setAppId(appId);
}
}
LOG.debug("spark appId that handle get is {}, state: {}", handle.getAppId(), handle.getState().toString());
switch (newState) {
case UNKNOWN:
case CONNECTED:
case SUBMITTED:
if (System.currentTimeMillis() - startTime > submitTimeoutMs) {
isStop = true;
handle.kill();
}
break;
case RUNNING:
case FINISHED:
isStop = true;
break;
case KILLED:
case FAILED:
case LOST:
isStop = true;
handle.kill();
break;
default:
Preconditions.checkState(false, "wrong spark app state");
}
}
else if (line.contains(QUEUE) || line.contains(START_TIME) || line.contains(FINAL_STATUS) ||
line.contains(URL) || line.contains(USER)) {
String value = getValue(line);
if (!Strings.isNullOrEmpty(value)) {
try {
if (line.contains(QUEUE)) {
handle.setQueue(value);
} else if (line.contains(START_TIME)) {
handle.setStartTime(Long.parseLong(value));
} else if (line.contains(FINAL_STATUS)) {
handle.setFinalStatus(FinalApplicationStatus.valueOf(value));
} else if (line.contains(URL)) {
handle.setUrl(value);
} else if (line.contains(USER)) {
handle.setUser(value);
}
} catch (IllegalArgumentException e) {
LOG.warn("parse log encounter an error, line: {}, msg: {}", line, e.getMessage());
}
}
}
}
} catch (Exception e) {
LOG.warn("Exception monitoring process.", e);
} finally {
try {
if (outReader != null) {
outReader.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
LOG.warn("close buffered reader error", e);
}
}
}