diff --git a/org.eclipse.lsp4j.jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java b/org.eclipse.lsp4j.jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java index 6b4690b9..16999f64 100644 --- a/org.eclipse.lsp4j.jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java +++ b/org.eclipse.lsp4j.jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java @@ -74,8 +74,8 @@ public void listen(MessageConsumer callback) { this.keepRunning = true; this.callback = callback; try { - StringBuilder headerBuilder = null; - StringBuilder debugBuilder = null; + final var headerBuilder = new StringBuilder(); + final var debugBuilder = new StringBuilder(); boolean newLine = false; Headers headers = new Headers(); while (keepRunning) { @@ -84,8 +84,6 @@ public void listen(MessageConsumer callback) { // End of input stream has been reached keepRunning = false; } else { - if (debugBuilder == null) - debugBuilder = new StringBuilder(); debugBuilder.append((char) c); if (c == '\n') { if (newLine) { @@ -100,19 +98,17 @@ public void listen(MessageConsumer callback) { newLine = false; } headers = new Headers(); - debugBuilder = null; + resetStringBuilder(debugBuilder); } else { - if (headerBuilder != null) { + if (headerBuilder.length() > 0) { // A single newline ends a header line parseHeader(headerBuilder.toString(), headers); - headerBuilder = null; + resetStringBuilder(headerBuilder); } newLine = true; } } else if (c != '\r') { // Add the input to the current header line - if (headerBuilder == null) - headerBuilder = new StringBuilder(); headerBuilder.append((char) c); newLine = false; } @@ -131,6 +127,17 @@ public void listen(MessageConsumer callback) { } } + private void resetStringBuilder(final StringBuilder sb) { + // If the builder grew large, shrink its backing byte array to an upper bound + if (sb.length() > 8192) { + // Truncate so trimToSize() can reduce the internal capacity. + sb.setLength(8192); + sb.trimToSize(); + } + // Clear content while keeping the (now trimmed) capacity for reuse. + sb.setLength(0); + } + /** * Log an error. */