This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch feat/use-scratch-bytes in repository https://gitbox.apache.org/repos/asf/commons-io.git
commit 73155fde9e0f1217f067a9efad9287a6f9c14423 Author: Piotr P. Karwasz <[email protected]> AuthorDate: Sun Oct 19 10:36:20 2025 +0200 Extend scratch buffer usage in `IOUtils` This PR applies scratch buffer reuse to three additional methods (and their dependents) for more consistent memory behavior. It improves memory usage and ensures that `consume(inputStream)` can safely replace `skip(inputStream, Long.MAX_VALUE)` without unnecessary allocations. --- src/changes/changes.xml | 1 + src/main/java/org/apache/commons/io/IOUtils.java | 26 +++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3aa419401..680868304 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -72,6 +72,7 @@ The <action> type attribute can be add,update,fix,remove. <action dev="pkarwasz" type="add" due-to="Piotr P. Karwasz">Add NIO channel support to `AbstractStreamBuilder`.</action> <action dev="pkarwasz" type="add" due-to="Piotr P. Karwasz">Add CloseShieldChannel to close-shielded NIO Channels #786.</action> <action dev="pkarwasz" type="add" due-to="Piotr P. Karwasz">Added IOUtils.checkFromIndexSize as a Java 8 backport of Objects.checkFromIndexSize #790.</action> + <action dev="pkarwasz" type="add" due-to="Piotr P. Karwasz">Use scratch buffers in more IOUtils methods.</action> <!-- UPDATE --> <action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">Bump org.apache.commons:commons-parent from 85 to 89 #774, #783.</action> <action type="update" dev="ggregory" due-to="Gary Gregory">[test] Bump commons-codec:commons-codec from 1.18.0 to 1.19.0.</action> diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java index 5d3d7cc58..6071530c0 100644 --- a/src/main/java/org/apache/commons/io/IOUtils.java +++ b/src/main/java/org/apache/commons/io/IOUtils.java @@ -1499,7 +1499,9 @@ public static QueueInputStream copy(final java.io.ByteArrayOutputStream outputSt * @since 2.7 */ public static long copy(final Reader reader, final Appendable output) throws IOException { - return copy(reader, output, CharBuffer.allocate(DEFAULT_BUFFER_SIZE)); + try (ScratchChars scratch = IOUtils.ScratchChars.get()) { + return copy(reader, output, CharBuffer.wrap(scratch.array())); + } } /** @@ -1702,7 +1704,9 @@ public static long copy(final URL url, final OutputStream outputStream) throws I */ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream) throws IOException { - return copy(inputStream, outputStream, DEFAULT_BUFFER_SIZE); + try (ScratchBytes scratch = ScratchBytes.get()) { + return copyLarge(inputStream, outputStream, scratch.array()); + } } /** @@ -2651,16 +2655,18 @@ public static long skip(final ReadableByteChannel input, final long toSkip) thro if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } - final ByteBuffer skipByteBuffer = ByteBuffer.allocate((int) Math.min(toSkip, DEFAULT_BUFFER_SIZE)); long remain = toSkip; - while (remain > 0) { - skipByteBuffer.position(0); - skipByteBuffer.limit((int) Math.min(remain, DEFAULT_BUFFER_SIZE)); - final int n = input.read(skipByteBuffer); - if (n == EOF) { - break; + try (ScratchBytes scratch = ScratchBytes.get()) { + final ByteBuffer skipByteBuffer = ByteBuffer.wrap(scratch.array()); + while (remain > 0) { + skipByteBuffer.position(0); + skipByteBuffer.limit((int) Math.min(remain, DEFAULT_BUFFER_SIZE)); + final int n = input.read(skipByteBuffer); + if (n == EOF) { + break; + } + remain -= n; } - remain -= n; } return toSkip - remain; }
