Source:
<code>public void sendNotification(Notification notification) throws NotificationException { byte[] notificationJson; try { notificationJson = mapper.writeValueAsBytes(notification); } catch (JsonProcessingException e) { throw Throwables.propagate(e); } ExecutorService executor = Executors.newSingleThreadExecutor(); ProcessBuilder processBuilder = new ProcessBuilder() .redirectErrorStream(true) .redirectInput(PIPE) .command("/bin/sh", "-c", command); try { Process process = processBuilder.start(); executor.execute(() -> { try { OutputStream stream = process.getOutputStream(); ByteStreams.copy(new ByteArrayInputStream(notificationJson), stream); stream.flush(); stream.close(); } catch (IOException e) { throw Throwables.propagate(e); } }); boolean exited = process.waitFor(timeoutMs, MILLISECONDS); <START> BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream())); Stream<String> lines = br.lines(); StringBuilder sb = new StringBuilder(); lines.forEach(line -> { sb.append(line); sb.append(System.lineSeparator()); }); <END> String processLog = sb.toString(); if (!exited) { process.destroyForcibly(); throw new NotificationException("Notification shell command timed out: " + command + ", command log:" + System.lineSeparator() + processLog); } int exitCode = process.exitValue(); if (exitCode != 0) { throw new NotificationException("Notification shell command failed: " + command + ", exit code = " + exitCode + ", command log:" + System.lineSeparator() + processLog); } logger.info("Notification shell command: " + command); logger.info("Notification shell command log:" + System.lineSeparator() + processLog); } catch (IOException e) { throw new NotificationException("Failed to execute notification shell command: " + command, e); } catch (InterruptedException e) { throw Throwables.propagate(e); } }</code><technical_language>If process create large error message, this out of memory problem. set max size of log (e.x. 64k)</technical_language>

Target:
public void sendNotification(Notification notification) throws NotificationException { byte[] notificationJson; try { notificationJson = mapper.writeValueAsBytes(notification); } catch (JsonProcessingException e) { throw Throwables.propagate(e); } ExecutorService executor = Executors.newSingleThreadExecutor(); ProcessBuilder processBuilder = new ProcessBuilder() .redirectErrorStream(true) .redirectInput(PIPE) .command("/bin/sh", "-c", command); try { Process process = processBuilder.start(); executor.execute(() -> { try { OutputStream stream = process.getOutputStream(); ByteStreams.copy(new ByteArrayInputStream(notificationJson), stream); stream.flush(); stream.close(); } catch (IOException e) { throw Throwables.propagate(e); } }); try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) { String line; while ((line = br.readLine()) != null) { logger.info("[ShellNotification](" + command + "): " + line); } } boolean exited = process.waitFor(timeoutMs, MILLISECONDS); if (!exited) { process.destroyForcibly(); throw new NotificationException("Notification shell command timed out: " + command); } int exitCode = process.exitValue(); if (exitCode != 0) { throw new NotificationException("Notification shell command failed: " + command + ", exit code = " + exitCode); } } catch (IOException e) { throw new NotificationException("Failed to execute notification shell command: " + command, e); } catch (InterruptedException e) { throw Throwables.propagate(e); } }