From bca35b0449d2ce16a39a86a4be7aa9d5ae2bdb70 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 31 Aug 2017 10:00:47 +0200 Subject: [PATCH] Allow to construct UnpooledByteBufAllocator that explictly always use sun.misc.Cleaner Motivation: When the user want to have the direct memory explicitly managed by the GC (just as java.nio does) it is useful to be able to construct an UnpooledByteBufAllocator that allows this without the chances to see any memory leak. Modifications: Allow to explicitly disable the usage of reflection to construct direct ByteBufs and so be sure these will be collected by GC. Result: More flexible way to use the UnpooledByteBufAllocator. --- .../buffer/UnpooledByteBufAllocator.java | 21 +++++++++++++++++-- .../util/internal/PlatformDependent.java | 4 ++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java b/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java index 770cce298f..4edf0dcd3d 100644 --- a/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java +++ b/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java @@ -28,6 +28,7 @@ public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator imp private final UnpooledByteBufAllocatorMetric metric = new UnpooledByteBufAllocatorMetric(); private final boolean disableLeakDetector; + private final boolean noCleaner; /** * Default instance which uses leak-detection for direct buffers. @@ -55,8 +56,25 @@ public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator imp * direct buffers when not explicit released. */ public UnpooledByteBufAllocator(boolean preferDirect, boolean disableLeakDetector) { + this(preferDirect, disableLeakDetector, PlatformDependent.useDirectBufferNoCleaner()); + } + + /** + * Create a new instance + * + * @param preferDirect {@code true} if {@link #buffer(int)} should try to allocate a direct buffer rather than + * a heap buffer + * @param disableLeakDetector {@code true} if the leak-detection should be disabled completely for this + * allocator. This can be useful if the user just want to depend on the GC to handle + * direct buffers when not explicit released. + * @param tryNoCleaner {@code true} if we should try to use {@link PlatformDependent#allocateDirectNoCleaner(int)} + * to allocate direct memory. + */ + public UnpooledByteBufAllocator(boolean preferDirect, boolean disableLeakDetector, boolean tryNoCleaner) { super(preferDirect); this.disableLeakDetector = disableLeakDetector; + noCleaner = tryNoCleaner && PlatformDependent.hasUnsafe() + && PlatformDependent.hasDirectBufferNoCleanerConstructor(); } @Override @@ -70,8 +88,7 @@ public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator imp protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) { final ByteBuf buf; if (PlatformDependent.hasUnsafe()) { - buf = PlatformDependent.useDirectBufferNoCleaner() ? - new InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(this, initialCapacity, maxCapacity) : + buf = noCleaner ? new InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(this, initialCapacity, maxCapacity) : new InstrumentedUnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity); } else { buf = new InstrumentedUnpooledDirectByteBuf(this, initialCapacity, maxCapacity); diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent.java b/common/src/main/java/io/netty/util/internal/PlatformDependent.java index 8fc7f5f07d..662013929a 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java @@ -190,6 +190,10 @@ public final class PlatformDependent { } } + public static boolean hasDirectBufferNoCleanerConstructor() { + return PlatformDependent0.hasDirectBufferNoCleanerConstructor(); + } + public static byte[] allocateUninitializedArray(int size) { return UNINITIALIZED_ARRAY_ALLOCATION_THRESHOLD < 0 || UNINITIALIZED_ARRAY_ALLOCATION_THRESHOLD > size ? new byte[size] : PlatformDependent0.allocateUninitializedArray(size);