From d8e59ca638b8aa4fe4d18c52c70bd92a0150de58 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Sat, 17 Aug 2019 09:43:01 +0200 Subject: [PATCH] =?UTF-8?q?Avoid=20creating=20FileInputStream=20and=20File?= =?UTF-8?q?OutputStream=20for=20obtaining=20Fil=E2=80=A6=20(#8110)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Motivation: If all we need is the FileChannel we should better use RandomAccessFile as FileInputStream and FileOutputStream use a finalizer. Modifications: Replace FileInputStream and FileOutputStream with RandomAccessFile when possible. Result: Fixes https://github.com/netty/netty/issues/8078. --- .../ReadOnlyDirectByteBufferBufTest.java | 7 +-- .../http/multipart/AbstractDiskHttpData.java | 55 ++++++++++--------- .../multipart/AbstractMemoryHttpData.java | 15 +++-- .../netty/handler/stream/ChunkedNioFile.java | 6 +- .../socket/SocketFileRegionTest.java | 8 +-- 5 files changed, 45 insertions(+), 46 deletions(-) diff --git a/buffer/src/test/java/io/netty/buffer/ReadOnlyDirectByteBufferBufTest.java b/buffer/src/test/java/io/netty/buffer/ReadOnlyDirectByteBufferBufTest.java index 5af2539601..f92d576682 100644 --- a/buffer/src/test/java/io/netty/buffer/ReadOnlyDirectByteBufferBufTest.java +++ b/buffer/src/test/java/io/netty/buffer/ReadOnlyDirectByteBufferBufTest.java @@ -21,9 +21,8 @@ import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; +import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ReadOnlyBufferException; import java.nio.channels.FileChannel; @@ -307,12 +306,12 @@ public class ReadOnlyDirectByteBufferBufTest { ByteBuf b2 = null; try { - output = new FileOutputStream(file).getChannel(); + output = new RandomAccessFile(file, "rw").getChannel(); byte[] bytes = new byte[1024]; PlatformDependent.threadLocalRandom().nextBytes(bytes); output.write(ByteBuffer.wrap(bytes)); - input = new FileInputStream(file).getChannel(); + input = new RandomAccessFile(file, "r").getChannel(); ByteBuffer m = input.map(FileChannel.MapMode.READ_ONLY, 0, input.size()); b1 = buffer(m); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java index 544bc7c82d..94309186b4 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java @@ -22,10 +22,9 @@ import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; @@ -125,9 +124,10 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { } return; } - FileOutputStream outputStream = new FileOutputStream(file); + RandomAccessFile accessFile = new RandomAccessFile(file, "rw"); + accessFile.setLength(0); try { - FileChannel localfileChannel = outputStream.getChannel(); + FileChannel localfileChannel = accessFile.getChannel(); ByteBuffer byteBuffer = buffer.nioBuffer(); int written = 0; while (written < size) { @@ -136,7 +136,7 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { buffer.readerIndex(buffer.readerIndex() + written); localfileChannel.force(false); } finally { - outputStream.close(); + accessFile.close(); } setCompleted(); } finally { @@ -163,8 +163,8 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { file = tempFile(); } if (fileChannel == null) { - FileOutputStream outputStream = new FileOutputStream(file); - fileChannel = outputStream.getChannel(); + RandomAccessFile accessFile = new RandomAccessFile(file, "rw"); + fileChannel = accessFile.getChannel(); } while (written < localsize) { written += fileChannel.write(byteBuffer); @@ -182,8 +182,8 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { file = tempFile(); } if (fileChannel == null) { - FileOutputStream outputStream = new FileOutputStream(file); - fileChannel = outputStream.getChannel(); + RandomAccessFile accessFile = new RandomAccessFile(file, "rw"); + fileChannel = accessFile.getChannel(); } fileChannel.force(false); fileChannel.close(); @@ -217,10 +217,11 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { delete(); } file = tempFile(); - FileOutputStream outputStream = new FileOutputStream(file); + RandomAccessFile accessFile = new RandomAccessFile(file, "rw"); + accessFile.setLength(0); int written = 0; try { - FileChannel localfileChannel = outputStream.getChannel(); + FileChannel localfileChannel = accessFile.getChannel(); byte[] bytes = new byte[4096 * 4]; ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); int read = inputStream.read(bytes); @@ -232,7 +233,7 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { } localfileChannel.force(false); } finally { - outputStream.close(); + accessFile.close(); } size = written; if (definedSize > 0 && definedSize < size) { @@ -290,8 +291,8 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { return EMPTY_BUFFER; } if (fileChannel == null) { - FileInputStream inputStream = new FileInputStream(file); - fileChannel = inputStream.getChannel(); + RandomAccessFile accessFile = new RandomAccessFile(file, "r"); + fileChannel = accessFile.getChannel(); } int read = 0; ByteBuffer byteBuffer = ByteBuffer.allocate(length); @@ -349,15 +350,15 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { if (!file.renameTo(dest)) { // must copy IOException exception = null; - FileInputStream inputStream = null; - FileOutputStream outputStream = null; + RandomAccessFile inputAccessFile = null; + RandomAccessFile outputAccessFile = null; long chunkSize = 8196; long position = 0; try { - inputStream = new FileInputStream(file); - outputStream = new FileOutputStream(dest); - FileChannel in = inputStream.getChannel(); - FileChannel out = outputStream.getChannel(); + inputAccessFile = new RandomAccessFile(file, "r"); + outputAccessFile = new RandomAccessFile(dest, "rw"); + FileChannel in = inputAccessFile.getChannel(); + FileChannel out = outputAccessFile.getChannel(); while (position < size) { if (chunkSize < size - position) { chunkSize = size - position; @@ -367,9 +368,9 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { } catch (IOException e) { exception = e; } finally { - if (inputStream != null) { + if (inputAccessFile != null) { try { - inputStream.close(); + inputAccessFile.close(); } catch (IOException e) { if (exception == null) { // Choose to report the first exception exception = e; @@ -378,9 +379,9 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { } } } - if (outputStream != null) { + if (outputAccessFile != null) { try { - outputStream.close(); + outputAccessFile.close(); } catch (IOException e) { if (exception == null) { // Choose to report the first exception exception = e; @@ -422,17 +423,17 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { throw new IllegalArgumentException( "File too big to be loaded in memory"); } - FileInputStream inputStream = new FileInputStream(src); + RandomAccessFile accessFile = new RandomAccessFile(src, "r"); byte[] array = new byte[(int) srcsize]; try { - FileChannel fileChannel = inputStream.getChannel(); + FileChannel fileChannel = accessFile.getChannel(); ByteBuffer byteBuffer = ByteBuffer.wrap(array); int read = 0; while (read < srcsize) { read += fileChannel.read(byteBuffer); } } finally { - inputStream.close(); + accessFile.close(); } return array; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java index 4cb7e567b2..5a0f322d4d 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java @@ -20,10 +20,9 @@ import io.netty.buffer.CompositeByteBuf; import io.netty.handler.codec.http.HttpConstants; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; @@ -131,8 +130,8 @@ public abstract class AbstractMemoryHttpData extends AbstractHttpData { throw new IllegalArgumentException("File too big to be loaded in memory"); } checkSize(newsize); - FileInputStream inputStream = new FileInputStream(file); - FileChannel fileChannel = inputStream.getChannel(); + RandomAccessFile accessFile = new RandomAccessFile(file, "r"); + FileChannel fileChannel = accessFile.getChannel(); byte[] array = new byte[(int) newsize]; ByteBuffer byteBuffer = ByteBuffer.wrap(array); int read = 0; @@ -140,7 +139,7 @@ public abstract class AbstractMemoryHttpData extends AbstractHttpData { read += fileChannel.read(byteBuffer); } fileChannel.close(); - inputStream.close(); + accessFile.close(); byteBuffer.flip(); if (byteBuf != null) { byteBuf.release(); @@ -232,8 +231,8 @@ public abstract class AbstractMemoryHttpData extends AbstractHttpData { return true; } int length = byteBuf.readableBytes(); - FileOutputStream outputStream = new FileOutputStream(dest); - FileChannel fileChannel = outputStream.getChannel(); + RandomAccessFile accessFile = new RandomAccessFile(dest, "rw"); + FileChannel fileChannel = accessFile.getChannel(); int written = 0; if (byteBuf.nioBufferCount() == 1) { ByteBuffer byteBuffer = byteBuf.nioBuffer(); @@ -249,7 +248,7 @@ public abstract class AbstractMemoryHttpData extends AbstractHttpData { fileChannel.force(false); fileChannel.close(); - outputStream.close(); + accessFile.close(); return written == length; } diff --git a/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java b/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java index 339a3e5776..0743a0dc65 100644 --- a/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java +++ b/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java @@ -21,8 +21,8 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.FileRegion; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; +import java.io.RandomAccessFile; import java.nio.channels.FileChannel; /** @@ -45,7 +45,7 @@ public class ChunkedNioFile implements ChunkedInput { * Creates a new instance that fetches data from the specified file. */ public ChunkedNioFile(File in) throws IOException { - this(new FileInputStream(in).getChannel()); + this(new RandomAccessFile(in, "r").getChannel()); } /** @@ -55,7 +55,7 @@ public class ChunkedNioFile implements ChunkedInput { * {@link #readChunk(ChannelHandlerContext)} call */ public ChunkedNioFile(File in, int chunkSize) throws IOException { - this(new FileInputStream(in).getChannel(), chunkSize); + this(new RandomAccessFile(in, "r").getChannel(), chunkSize); } /** diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java index 881acd1bcf..ae85825425 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java @@ -32,9 +32,9 @@ import org.hamcrest.CoreMatchers; import org.junit.Test; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.RandomAccessFile; import java.nio.channels.WritableByteChannel; import java.util.Random; import java.util.concurrent.atomic.AtomicReference; @@ -121,7 +121,7 @@ public class SocketFileRegionTest extends AbstractSocketTest { // Request file region which is bigger then the underlying file. FileRegion region = new DefaultFileRegion( - new FileInputStream(file).getChannel(), 0, data.length + 1024); + new RandomAccessFile(file, "r").getChannel(), 0, data.length + 1024); assertThat(cc.writeAndFlush(region).await().cause(), CoreMatchers.instanceOf(IOException.class)); cc.close().sync(); @@ -183,8 +183,8 @@ public class SocketFileRegionTest extends AbstractSocketTest { Channel cc = cb.connect(sc.localAddress()).sync().channel(); FileRegion region = new DefaultFileRegion( - new FileInputStream(file).getChannel(), startOffset, data.length - bufferSize); - FileRegion emptyRegion = new DefaultFileRegion(new FileInputStream(file).getChannel(), 0, 0); + new RandomAccessFile(file, "r").getChannel(), startOffset, data.length - bufferSize); + FileRegion emptyRegion = new DefaultFileRegion(new RandomAccessFile(file, "r").getChannel(), 0, 0); if (!defaultFileRegion) { region = new FileRegionWrapper(region);