From 9dc1d533e3da4ef05092a29bdb376cc2d040db54 Mon Sep 17 00:00:00 2001 From: Chris Vest Date: Fri, 21 May 2021 17:28:07 +0200 Subject: [PATCH] Fix remaining tests and make the build work on Java 11 --- .../io/netty/buffer/api/internal/Statics.java | 79 ++++++++++++++++++- buffer-memseg-dummy/pom.xml | 30 +++++++ .../src/main/java/module-info.java | 19 +++++ buffer-tests/pom.xml | 27 +++++++ buffer-tests/src/main/java/module-info.java | 4 +- .../tests/BufferReferenceCountingTest.java | 1 + pom.xml | 14 ++++ 7 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 buffer-memseg-dummy/pom.xml create mode 100644 buffer-memseg-dummy/src/main/java/module-info.java diff --git a/buffer-api/src/main/java/io/netty/buffer/api/internal/Statics.java b/buffer-api/src/main/java/io/netty/buffer/api/internal/Statics.java index 76d2605..f6ab7a1 100644 --- a/buffer-api/src/main/java/io/netty/buffer/api/internal/Statics.java +++ b/buffer-api/src/main/java/io/netty/buffer/api/internal/Statics.java @@ -18,7 +18,10 @@ package io.netty.buffer.api.internal; import io.netty.buffer.api.Buffer; import io.netty.buffer.api.Drop; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.lang.ref.Cleaner; import java.nio.ByteBuffer; @@ -38,6 +41,28 @@ public interface Statics { return "NO_OP_DROP"; } }; + MethodHandle BB_SLICE_OFFSETS = getByteBufferSliceOffsetsMethodHandle(); + MethodHandle BB_PUT_OFFSETS = getByteBufferPutOffsetsMethodHandle(); + + static MethodHandle getByteBufferSliceOffsetsMethodHandle() { + try { + Lookup lookup = MethodHandles.lookup(); + MethodType type = MethodType.methodType(ByteBuffer.class, int.class, int.class); + return lookup.findVirtual(ByteBuffer.class, "slice", type); + } catch (Exception ignore) { + return null; + } + } + + static MethodHandle getByteBufferPutOffsetsMethodHandle() { + try { + Lookup lookup = MethodHandles.lookup(); + MethodType type = MethodType.methodType(ByteBuffer.class, int.class, ByteBuffer.class, int.class, int.class); + return lookup.findVirtual(ByteBuffer.class, "put", type); + } catch (Exception ignore) { + return null; + } + } static VarHandle findVarHandle(Lookup lookup, Class recv, String name, Class type) { try { @@ -77,16 +102,62 @@ public interface Statics { * support Java 11. */ static ByteBuffer bbslice(ByteBuffer buffer, int fromOffset, int length) { - return buffer.slice(fromOffset, length); -// return buffer.clear().position(fromOffset).limit(fromOffset + length).slice(); + if (BB_SLICE_OFFSETS != null) { + return bbsliceJdk13(buffer, fromOffset, length); + } + return bbsliceFallback(buffer, fromOffset, length); + } + + private static ByteBuffer bbsliceJdk13(ByteBuffer buffer, int fromOffset, int length) { + try { + return (ByteBuffer) BB_SLICE_OFFSETS.invokeExact(buffer, fromOffset, length); + } catch (RuntimeException re) { + throw re; + } catch (Throwable throwable) { + throw new LinkageError("Unexpected exception from ByteBuffer.slice(int,int).", throwable); + } + } + + private static ByteBuffer bbsliceFallback(ByteBuffer buffer, int fromOffset, int length) { + if (fromOffset < 0) { + throw new IndexOutOfBoundsException("The fromOffset must be positive: " + fromOffset + '.'); + } + int newLimit = fromOffset + length; + if (newLimit > buffer.capacity()) { + throw new IndexOutOfBoundsException( + "The limit of " + newLimit + " would be greater than capacity: " + buffer.capacity() + '.'); + } + try { + return buffer.position(fromOffset).limit(newLimit).slice(); + } finally { + buffer.clear(); + } } /** * The ByteBuffer put-buffer-with-offset-and-length method is not available in Java 11. */ static void bbput(ByteBuffer dest, int destPos, ByteBuffer src, int srcPos, int length) { - dest.put(destPos, src, srcPos, length); -// dest.position(destPos).put(bbslice(src, srcPos, length)); + if (BB_PUT_OFFSETS != null) { + bbputJdk16(dest, destPos, src, srcPos, length); + } else { + bbputFallback(dest, destPos, src, srcPos, length); + } + } + + private static void bbputJdk16(ByteBuffer dest, int destPos, ByteBuffer src, int srcPos, int length) { + try { + @SuppressWarnings("unused") // We need to cast the return type in order to invokeExact. + ByteBuffer ignore = (ByteBuffer) BB_PUT_OFFSETS.invokeExact(dest, destPos, src, srcPos, length); + } catch (RuntimeException re) { + throw re; + } catch (Throwable throwable) { + throw new LinkageError("Unexpected exception from ByteBuffer.put(int,ByteBuffer,int,int).", throwable); + } + } + + private static void bbputFallback(ByteBuffer dest, int destPos, ByteBuffer src, int srcPos, int length) { + dest.position(destPos).put(bbslice(src, srcPos, length)); } static IllegalStateException bufferIsClosed() { diff --git a/buffer-memseg-dummy/pom.xml b/buffer-memseg-dummy/pom.xml new file mode 100644 index 0000000..1c1a759 --- /dev/null +++ b/buffer-memseg-dummy/pom.xml @@ -0,0 +1,30 @@ + + + + 4.0.0 + + + io.netty.incubator + netty-incubator-buffer-parent + 0.0.1.Final-SNAPSHOT + + + netty-incubator-buffer-memseg-dummy + 0.0.1.Final-SNAPSHOT + diff --git a/buffer-memseg-dummy/src/main/java/module-info.java b/buffer-memseg-dummy/src/main/java/module-info.java new file mode 100644 index 0000000..bc63aed --- /dev/null +++ b/buffer-memseg-dummy/src/main/java/module-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2021 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +module netty.incubator.buffer.memseg { + // Java 11 compatible stand-in module for the memory segment implementation. + // We need this module in order for the tests module to pull in the memseg module. +} diff --git a/buffer-tests/pom.xml b/buffer-tests/pom.xml index 2d05e9a..2ed3b2d 100644 --- a/buffer-tests/pom.xml +++ b/buffer-tests/pom.xml @@ -1,4 +1,19 @@ + @@ -92,5 +107,17 @@ + + Java 11 support for tests + + !17 + + + + io.netty.incubator + netty-incubator-buffer-memseg-dummy + + + \ No newline at end of file diff --git a/buffer-tests/src/main/java/module-info.java b/buffer-tests/src/main/java/module-info.java index 7c72be3..2560866 100644 --- a/buffer-tests/src/main/java/module-info.java +++ b/buffer-tests/src/main/java/module-info.java @@ -21,5 +21,7 @@ open module netty.incubator.buffer.tests { requires static java.logging; requires netty.incubator.buffer; - requires static netty.incubator.buffer.memseg; + // We need to require memseg in order for its implementation to be service loaded. + // Just having it on the module path is not enough. + requires netty.incubator.buffer.memseg; } diff --git a/buffer-tests/src/test/java/io/netty/buffer/api/tests/BufferReferenceCountingTest.java b/buffer-tests/src/test/java/io/netty/buffer/api/tests/BufferReferenceCountingTest.java index f7f2515..147d936 100644 --- a/buffer-tests/src/test/java/io/netty/buffer/api/tests/BufferReferenceCountingTest.java +++ b/buffer-tests/src/test/java/io/netty/buffer/api/tests/BufferReferenceCountingTest.java @@ -266,6 +266,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { assertThrows(IllegalArgumentException.class, () -> buf.slice(0, -1)); + assertThrows(IllegalArgumentException.class, () -> buf.slice(2, -1)); // Verify that the slice is closed properly afterwards. assertTrue(buf.isOwned()); } diff --git a/pom.xml b/pom.xml index 5d343b4..4ea1568 100644 --- a/pom.xml +++ b/pom.xml @@ -105,6 +105,15 @@ buffer-memseg + + Java 11 support for tests + + !17 + + + buffer-memseg-dummy + + @@ -383,6 +392,11 @@ netty-incubator-buffer-memseg ${project.version} + + io.netty.incubator + netty-incubator-buffer-memseg-dummy + ${project.version} + io.netty