3737import java .io .UnsupportedEncodingException ;
3838import java .io .Writer ;
3939import java .net .URL ;
40- import java .nio .ByteBuffer ;
41- import java .nio .channels .Channels ;
4240import java .nio .channels .FileChannel ;
43- import java .nio .channels .ReadableByteChannel ;
44- import java .nio .channels .WritableByteChannel ;
4541import java .nio .charset .Charset ;
4642import java .nio .file .Files ;
4743import java .nio .file .Path ;
@@ -71,6 +67,10 @@ public final class IOUtil {
7167
7268 private static final int DEFAULT_BLOCK_SIZE = 0xffff ;// 65535
7369
70+ // ThreadLocal buffer pools to avoid repeated allocations in hot paths
71+ private static final ThreadLocal <byte []> BYTE_ARRAY_POOL = ThreadLocal .withInitial ( () -> new byte [DEFAULT_BLOCK_SIZE ] );
72+ private static final ThreadLocal <char []> CHAR_BUFFER_POOL = ThreadLocal .withInitial ( () -> new char [DEFAULT_BLOCK_SIZE ] );
73+
7474 /**
7575 * copy an inputstream to an outputstream
7676 *
@@ -326,24 +326,18 @@ public static final void copy(InputStream in, OutputStream out, int offset, int
326326 * @throws IOException If an I/O error occurs during the copy operation.
327327 */
328328 private static final void copy (InputStream in , OutputStream out , int blockSize ) throws IOException {
329- // Creating channels from the input and output streams
330- ReadableByteChannel sourceChannel = Channels .newChannel (in );
331- WritableByteChannel destChannel = Channels .newChannel (out );
332-
333- // Allocate a ByteBuffer of the given block size
334- ByteBuffer buffer = ByteBuffer .allocate (blockSize );
335-
336- // Read from the source channel into the buffer, and then write from the buffer to the destination
337- // channel
338- while (sourceChannel .read (buffer ) != -1 ) {
339- // Flip the buffer to prepare for writing
340- buffer .flip ();
341-
342- // Write to the destination channel
343- destChannel .write (buffer );
329+ // Use pooled buffer for default block size, otherwise allocate
330+ byte [] buffer ;
331+ if ( blockSize == DEFAULT_BLOCK_SIZE ) {
332+ buffer = BYTE_ARRAY_POOL .get ();
333+ }
334+ else {
335+ buffer = new byte [blockSize ];
336+ }
344337
345- // Clear the buffer for the next read
346- buffer .clear ();
338+ int len ;
339+ while ( ( len = in .read ( buffer ) ) != -1 ) {
340+ out .write ( buffer , 0 , len );
347341 }
348342 }
349343
@@ -356,7 +350,7 @@ private static final void copy(InputStream in, OutputStream out, int blockSize)
356350 * @throws IOException
357351 */
358352 public static final boolean copyMax (InputStream in , OutputStream out , long max ) throws IOException {
359- byte [] buffer = new byte [ DEFAULT_BLOCK_SIZE ] ;
353+ byte [] buffer = BYTE_ARRAY_POOL . get () ;
360354 int len ;
361355 long total = 0 ;
362356 while ((len = in .read (buffer )) != -1 ) {
@@ -418,7 +412,14 @@ public static final void copy(Reader reader, Writer writer, boolean closeReader,
418412 */
419413 private static final void copy (Reader r , Writer w , int blockSize , long timeout ) throws IOException {
420414 if (timeout < 1 ) {
421- char [] buffer = new char [blockSize ];
415+ // Use pooled buffer for default block size, otherwise allocate
416+ char [] buffer ;
417+ if ( blockSize == DEFAULT_BLOCK_SIZE ) {
418+ buffer = CHAR_BUFFER_POOL .get ();
419+ }
420+ else {
421+ buffer = new char [blockSize ];
422+ }
422423 int len ;
423424
424425 while ((len = r .read (buffer )) != -1 )
0 commit comments