diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java index 4a13d821b9..c8c40a5d24 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java @@ -43,13 +43,22 @@ import static io.netty.util.internal.MathUtil.isOutOfBounds; */ public abstract class AbstractByteBuf extends ByteBuf { private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractByteBuf.class); - private static final String PROP_MODE = "io.netty.buffer.bytebuf.checkAccessible"; + private static final String LEGACY_PROP_CHECK_ACCESSIBLE = "io.netty.buffer.bytebuf.checkAccessible"; + private static final String PROP_CHECK_ACCESSIBLE = "io.netty.buffer.checkAccessible"; private static final boolean checkAccessible; + private static final String PROP_CHECK_BOUNDS = "io.netty.buffer.checkBounds"; + private static final boolean checkBounds; static { - checkAccessible = SystemPropertyUtil.getBoolean(PROP_MODE, true); + if (SystemPropertyUtil.contains(PROP_CHECK_ACCESSIBLE)) { + checkAccessible = SystemPropertyUtil.getBoolean(PROP_CHECK_ACCESSIBLE, true); + } else { + checkAccessible = SystemPropertyUtil.getBoolean(LEGACY_PROP_CHECK_ACCESSIBLE, true); + } + checkBounds = SystemPropertyUtil.getBoolean(PROP_CHECK_BOUNDS, true); if (logger.isDebugEnabled()) { - logger.debug("-D{}: {}", PROP_MODE, checkAccessible); + logger.debug("-D{}: {}", PROP_CHECK_ACCESSIBLE, checkAccessible); + logger.debug("-D{}: {}", PROP_CHECK_BOUNDS, checkBounds); } } @@ -97,11 +106,18 @@ public abstract class AbstractByteBuf extends ByteBuf { return readerIndex; } + private static void checkIndexBounds(final int readerIndex, final int writerIndex, final int capacity) { + if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity) { + throw new IndexOutOfBoundsException(String.format( + "readerIndex: %d, writerIndex: %d (expected: 0 <= readerIndex <= writerIndex <= capacity(%d))", + readerIndex, writerIndex, capacity)); + } + } + @Override public ByteBuf readerIndex(int readerIndex) { - if (readerIndex < 0 || readerIndex > writerIndex) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex: %d (expected: 0 <= readerIndex <= writerIndex(%d))", readerIndex, writerIndex)); + if (checkBounds) { + checkIndexBounds(readerIndex, writerIndex, capacity()); } this.readerIndex = readerIndex; return this; @@ -114,10 +130,8 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf writerIndex(int writerIndex) { - if (writerIndex < readerIndex || writerIndex > capacity()) { - throw new IndexOutOfBoundsException(String.format( - "writerIndex: %d (expected: readerIndex(%d) <= writerIndex <= capacity(%d))", - writerIndex, readerIndex, capacity())); + if (checkBounds) { + checkIndexBounds(readerIndex, writerIndex, capacity()); } this.writerIndex = writerIndex; return this; @@ -125,10 +139,8 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf setIndex(int readerIndex, int writerIndex) { - if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex: %d, writerIndex: %d (expected: 0 <= readerIndex <= writerIndex <= capacity(%d))", - readerIndex, writerIndex, capacity())); + if (checkBounds) { + checkIndexBounds(readerIndex, writerIndex, capacity()); } setIndex0(readerIndex, writerIndex); return this; @@ -271,11 +283,12 @@ public abstract class AbstractByteBuf extends ByteBuf { if (minWritableBytes <= writableBytes()) { return; } - - if (minWritableBytes > maxCapacity - writerIndex) { - throw new IndexOutOfBoundsException(String.format( - "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s", - writerIndex, minWritableBytes, maxCapacity, this)); + if (checkBounds) { + if (minWritableBytes > maxCapacity - writerIndex) { + throw new IndexOutOfBoundsException(String.format( + "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s", + writerIndex, minWritableBytes, maxCapacity, this)); + } } // Normalize the current capacity to the power of 2. @@ -618,15 +631,21 @@ public abstract class AbstractByteBuf extends ByteBuf { return this; } + private static void checkReadableBounds(final ByteBuf src, final int length) { + if (length > src.readableBytes()) { + throw new IndexOutOfBoundsException(String.format( + "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src)); + } + } + @Override public ByteBuf setBytes(int index, ByteBuf src, int length) { checkIndex(index, length); if (src == null) { throw new NullPointerException("src"); } - if (length > src.readableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src)); + if (checkBounds) { + checkReadableBounds(src, length); } setBytes(index, src, src.readerIndex(), length); @@ -889,9 +908,11 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf readBytes(ByteBuf dst, int length) { - if (length > dst.writableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds dst.writableBytes(%d) where dst is: %s", length, dst.writableBytes(), dst)); + if (checkBounds) { + if (length > dst.writableBytes()) { + throw new IndexOutOfBoundsException(String.format( + "length(%d) exceeds dst.writableBytes(%d) where dst is: %s", length, dst.writableBytes(), dst)); + } } readBytes(dst, dst.writerIndex(), length); dst.writerIndex(dst.writerIndex() + length); @@ -1065,9 +1086,8 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf writeBytes(ByteBuf src, int length) { - if (length > src.readableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src)); + if (checkBounds) { + checkReadableBounds(src, length); } writeBytes(src, src.readerIndex(), length); src.readerIndex(src.readerIndex() + length); @@ -1357,26 +1377,30 @@ public abstract class AbstractByteBuf extends ByteBuf { checkIndex0(index, fieldLength); } - final void checkIndex0(int index, int fieldLength) { - if (isOutOfBounds(index, fieldLength, capacity())) { + private static void checkRangeBounds(final int index, final int fieldLength, final int capacity) { + if (isOutOfBounds(index, fieldLength, capacity)) { throw new IndexOutOfBoundsException(String.format( - "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity())); + "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity)); + } + } + + final void checkIndex0(int index, int fieldLength) { + if (checkBounds) { + checkRangeBounds(index, fieldLength, capacity()); } } protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) { checkIndex(index, length); - if (isOutOfBounds(srcIndex, length, srcCapacity)) { - throw new IndexOutOfBoundsException(String.format( - "srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity)); + if (checkBounds) { + checkRangeBounds(srcIndex, length, srcCapacity); } } protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) { checkIndex(index, length); - if (isOutOfBounds(dstIndex, length, dstCapacity)) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity)); + if (checkBounds) { + checkRangeBounds(dstIndex, length, dstCapacity); } } @@ -1394,17 +1418,22 @@ public abstract class AbstractByteBuf extends ByteBuf { protected final void checkNewCapacity(int newCapacity) { ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity + " (expected: 0-" + maxCapacity() + ')'); + if (checkBounds) { + if (newCapacity < 0 || newCapacity > maxCapacity()) { + throw new IllegalArgumentException("newCapacity: " + newCapacity + + " (expected: 0-" + maxCapacity() + ')'); + } } } private void checkReadableBytes0(int minimumReadableBytes) { ensureAccessible(); - if (readerIndex > writerIndex - minimumReadableBytes) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s", - readerIndex, minimumReadableBytes, writerIndex, this)); + if (checkBounds) { + if (readerIndex > writerIndex - minimumReadableBytes) { + throw new IndexOutOfBoundsException(String.format( + "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s", + readerIndex, minimumReadableBytes, writerIndex, this)); + } } } diff --git a/microbench/src/main/java/io/netty/microbench/buffer/ByteBufBenchmark.java b/microbench/src/main/java/io/netty/microbench/buffer/ByteBufBenchmark.java index 70d1ceef53..c1cfa39add 100644 --- a/microbench/src/main/java/io/netty/microbench/buffer/ByteBufBenchmark.java +++ b/microbench/src/main/java/io/netty/microbench/buffer/ByteBufBenchmark.java @@ -20,6 +20,7 @@ import io.netty.buffer.PooledByteBufAllocator; import io.netty.buffer.Unpooled; import io.netty.microbench.util.AbstractMicrobenchmark; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.TearDown; @@ -27,10 +28,13 @@ import java.nio.ByteBuffer; public class ByteBufBenchmark extends AbstractMicrobenchmark { static { - System.setProperty("io.netty.buffer.bytebuf.checkAccessible", "false"); + System.setProperty("io.netty.buffer.checkAccessible", "false"); } private static final byte BYTE = '0'; + @Param({ "true", "false" }) + public String checkBounds; + private ByteBuffer byteBuffer; private ByteBuffer directByteBuffer; private ByteBuf buffer; @@ -39,6 +43,7 @@ public class ByteBufBenchmark extends AbstractMicrobenchmark { @Setup public void setup() { + System.setProperty("io.netty.buffer.checkBounds", checkBounds); byteBuffer = ByteBuffer.allocate(8); directByteBuffer = ByteBuffer.allocateDirect(8); buffer = Unpooled.buffer(8); diff --git a/microbench/src/main/java/io/netty/microbench/buffer/HeapByteBufBenchmark.java b/microbench/src/main/java/io/netty/microbench/buffer/HeapByteBufBenchmark.java index b7cf0c5fa8..06df3af9cb 100644 --- a/microbench/src/main/java/io/netty/microbench/buffer/HeapByteBufBenchmark.java +++ b/microbench/src/main/java/io/netty/microbench/buffer/HeapByteBufBenchmark.java @@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.microbench.util.AbstractMicrobenchmark; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.TearDown; @@ -26,6 +27,9 @@ import java.lang.reflect.Constructor; public class HeapByteBufBenchmark extends AbstractMicrobenchmark { + @Param({ "true", "false" }) + public String checkBounds; + private ByteBuf unsafeBuffer; private ByteBuf buffer; @@ -39,6 +43,7 @@ public class HeapByteBufBenchmark extends AbstractMicrobenchmark { @Setup public void setup() throws Exception { + System.setProperty("io.netty.buffer.bytebuf.checkBounds", checkBounds); unsafeBuffer = newBuffer("io.netty.buffer.UnpooledUnsafeHeapByteBuf"); buffer = newBuffer("io.netty.buffer.UnpooledHeapByteBuf"); unsafeBuffer.writeLong(1L);