Allow to free direct buffers on java9 again
Motivation: Java9 adds a new method to Unsafe which allows to free direct ByteBuffer via the cleaner without the need to use an commandline arguments. Modifications: - Add Cleaner interface - Add CleanerJava9 which will be used when using Java9+ and take care of release direct ByteBuffer - Let Cleaner0 implement Cleaner Result: Be able to free direct ByteBuffer on Java9+ again without any commandline arguments.
This commit is contained in:
parent
4c77e7c55a
commit
7b6119a0a4
29
common/src/main/java/io/netty/util/internal/Cleaner.java
Normal file
29
common/src/main/java/io/netty/util/internal/Cleaner.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 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:
|
||||||
|
*
|
||||||
|
* http://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.
|
||||||
|
*/
|
||||||
|
package io.netty.util.internal;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to free direct {@link ByteBuffer}s.
|
||||||
|
*/
|
||||||
|
interface Cleaner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a direct {@link ByteBuffer} if possible
|
||||||
|
*/
|
||||||
|
void freeDirectBuffer(ByteBuffer buffer);
|
||||||
|
}
|
@ -29,41 +29,32 @@ import java.nio.ByteBuffer;
|
|||||||
*
|
*
|
||||||
* For more details see <a href="https://github.com/netty/netty/issues/2604">#2604</a>.
|
* For more details see <a href="https://github.com/netty/netty/issues/2604">#2604</a>.
|
||||||
*/
|
*/
|
||||||
final class Cleaner0 {
|
final class CleanerJava6 implements Cleaner {
|
||||||
private static final long CLEANER_FIELD_OFFSET;
|
private static final long CLEANER_FIELD_OFFSET;
|
||||||
private static final Method CLEAN_METHOD;
|
private static final Method CLEAN_METHOD;
|
||||||
private static final boolean CLEANER_IS_RUNNABLE;
|
|
||||||
|
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Cleaner0.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(CleanerJava6.class);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ByteBuffer direct = ByteBuffer.allocateDirect(1);
|
|
||||||
Field cleanerField;
|
|
||||||
long fieldOffset = -1;
|
long fieldOffset = -1;
|
||||||
Method clean = null;
|
Method clean = null;
|
||||||
boolean cleanerIsRunnable = false;
|
|
||||||
Throwable error = null;
|
Throwable error = null;
|
||||||
if (PlatformDependent0.hasUnsafe()) {
|
if (PlatformDependent0.hasUnsafe()) {
|
||||||
|
ByteBuffer direct = ByteBuffer.allocateDirect(1);
|
||||||
try {
|
try {
|
||||||
cleanerField = direct.getClass().getDeclaredField("cleaner");
|
Field cleanerField = direct.getClass().getDeclaredField("cleaner");
|
||||||
fieldOffset = PlatformDependent0.objectFieldOffset(cleanerField);
|
fieldOffset = PlatformDependent0.objectFieldOffset(cleanerField);
|
||||||
Object cleaner = PlatformDependent0.getObject(direct, fieldOffset);
|
Object cleaner = PlatformDependent0.getObject(direct, fieldOffset);
|
||||||
try {
|
clean = cleaner.getClass().getDeclaredMethod("clean");
|
||||||
// Cleaner implements Runnable from JDK9 onwards.
|
clean.invoke(cleaner);
|
||||||
Runnable runnable = (Runnable) cleaner;
|
|
||||||
runnable.run();
|
|
||||||
cleanerIsRunnable = true;
|
|
||||||
} catch (ClassCastException ignored) {
|
|
||||||
clean = cleaner.getClass().getDeclaredMethod("clean");
|
|
||||||
clean.invoke(cleaner);
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// We don't have ByteBuffer.cleaner().
|
// We don't have ByteBuffer.cleaner().
|
||||||
fieldOffset = -1;
|
fieldOffset = -1;
|
||||||
clean = null;
|
clean = null;
|
||||||
cleanerIsRunnable = false;
|
|
||||||
error = t;
|
error = t;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
error = new UnsupportedOperationException("sun.misc.Unsafe unavailable");
|
||||||
}
|
}
|
||||||
if (error == null) {
|
if (error == null) {
|
||||||
logger.debug("java.nio.ByteBuffer.cleaner(): available");
|
logger.debug("java.nio.ByteBuffer.cleaner(): available");
|
||||||
@ -72,31 +63,24 @@ final class Cleaner0 {
|
|||||||
}
|
}
|
||||||
CLEANER_FIELD_OFFSET = fieldOffset;
|
CLEANER_FIELD_OFFSET = fieldOffset;
|
||||||
CLEAN_METHOD = clean;
|
CLEAN_METHOD = clean;
|
||||||
CLEANER_IS_RUNNABLE = cleanerIsRunnable;
|
|
||||||
|
|
||||||
// free buffer if possible
|
|
||||||
freeDirectBuffer(direct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeDirectBuffer(ByteBuffer buffer) {
|
static boolean isSupported() {
|
||||||
if (CLEANER_FIELD_OFFSET == -1 || !buffer.isDirect()) {
|
return CLEANER_FIELD_OFFSET != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeDirectBuffer(ByteBuffer buffer) {
|
||||||
|
if (!buffer.isDirect()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert CLEAN_METHOD != null || CLEANER_IS_RUNNABLE:
|
|
||||||
"CLEANER_FIELD_OFFSET != -1 implies CLEAN_METHOD != null or CLEANER_IS_RUNNABLE == true";
|
|
||||||
try {
|
try {
|
||||||
Object cleaner = PlatformDependent0.getObject(buffer, CLEANER_FIELD_OFFSET);
|
Object cleaner = PlatformDependent0.getObject(buffer, CLEANER_FIELD_OFFSET);
|
||||||
if (cleaner != null) {
|
if (cleaner != null) {
|
||||||
if (CLEANER_IS_RUNNABLE) {
|
CLEAN_METHOD.invoke(cleaner);
|
||||||
((Runnable) cleaner).run();
|
|
||||||
} else {
|
|
||||||
CLEAN_METHOD.invoke(cleaner);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable cause) {
|
||||||
// Nothing we can do here.
|
PlatformDependent0.throwException(cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cleaner0() { }
|
|
||||||
}
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 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:
|
||||||
|
*
|
||||||
|
* http://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.
|
||||||
|
*/
|
||||||
|
package io.netty.util.internal;
|
||||||
|
|
||||||
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a way to clean a ByteBuffer on Java9+.
|
||||||
|
*/
|
||||||
|
final class CleanerJava9 implements Cleaner {
|
||||||
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(CleanerJava9.class);
|
||||||
|
|
||||||
|
private static final Method INVOKE_CLEANER;
|
||||||
|
|
||||||
|
static {
|
||||||
|
final Method method;
|
||||||
|
final Throwable error;
|
||||||
|
if (PlatformDependent0.hasUnsafe()) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(1);
|
||||||
|
Object maybeInvokeMethod;
|
||||||
|
try {
|
||||||
|
// See https://bugs.openjdk.java.net/browse/JDK-8171377
|
||||||
|
Method m = PlatformDependent0.UNSAFE.getClass().getDeclaredMethod("invokeCleaner", ByteBuffer.class);
|
||||||
|
m.invoke(PlatformDependent0.UNSAFE, buffer);
|
||||||
|
maybeInvokeMethod = m;
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
maybeInvokeMethod = e;
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
maybeInvokeMethod = e;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
maybeInvokeMethod = e;
|
||||||
|
}
|
||||||
|
if (maybeInvokeMethod instanceof Throwable) {
|
||||||
|
method = null;
|
||||||
|
error = (Throwable) maybeInvokeMethod;
|
||||||
|
} else {
|
||||||
|
method = (Method) maybeInvokeMethod;
|
||||||
|
error = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
method = null;
|
||||||
|
error = new UnsupportedOperationException("sun.misc.Unsafe unavailable");
|
||||||
|
}
|
||||||
|
if (error == null) {
|
||||||
|
logger.debug("java.nio.ByteBuffer.cleaner(): available");
|
||||||
|
} else {
|
||||||
|
logger.debug("java.nio.ByteBuffer.cleaner(): unavailable", error);
|
||||||
|
}
|
||||||
|
INVOKE_CLEANER = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isSupported() {
|
||||||
|
return INVOKE_CLEANER != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeDirectBuffer(ByteBuffer buffer) {
|
||||||
|
try {
|
||||||
|
INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer);
|
||||||
|
} catch (Throwable cause) {
|
||||||
|
PlatformDependent0.throwException(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -67,9 +67,6 @@ public final class PlatformDependent {
|
|||||||
private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile(
|
private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile(
|
||||||
"\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$");
|
"\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$");
|
||||||
|
|
||||||
// this must be initialized before any code below triggers initialization of PlatformDependent0
|
|
||||||
private static final boolean IS_EXPLICIT_NO_UNSAFE = explicitNoUnsafe0();
|
|
||||||
|
|
||||||
private static final boolean IS_ANDROID = isAndroid0();
|
private static final boolean IS_ANDROID = isAndroid0();
|
||||||
private static final boolean IS_WINDOWS = isWindows0();
|
private static final boolean IS_WINDOWS = isWindows0();
|
||||||
private static final boolean MAYBE_SUPER_USER;
|
private static final boolean MAYBE_SUPER_USER;
|
||||||
@ -99,9 +96,17 @@ public final class PlatformDependent {
|
|||||||
private static final AtomicLong DIRECT_MEMORY_COUNTER;
|
private static final AtomicLong DIRECT_MEMORY_COUNTER;
|
||||||
private static final long DIRECT_MEMORY_LIMIT;
|
private static final long DIRECT_MEMORY_LIMIT;
|
||||||
private static final ThreadLocalRandomProvider RANDOM_PROVIDER;
|
private static final ThreadLocalRandomProvider RANDOM_PROVIDER;
|
||||||
|
private static final Cleaner CLEANER;
|
||||||
|
|
||||||
public static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
public static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
|
||||||
|
private static final Cleaner NOOP = new Cleaner() {
|
||||||
|
@Override
|
||||||
|
public void freeDirectBuffer(ByteBuffer buffer) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
if (javaVersion() >= 7) {
|
if (javaVersion() >= 7) {
|
||||||
RANDOM_PROVIDER = new ThreadLocalRandomProvider() {
|
RANDOM_PROVIDER = new ThreadLocalRandomProvider() {
|
||||||
@ -122,7 +127,7 @@ public final class PlatformDependent {
|
|||||||
logger.debug("-Dio.netty.noPreferDirect: {}", !DIRECT_BUFFER_PREFERRED);
|
logger.debug("-Dio.netty.noPreferDirect: {}", !DIRECT_BUFFER_PREFERRED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasUnsafe() && !isAndroid() && !IS_EXPLICIT_NO_UNSAFE) {
|
if (!hasUnsafe() && !isAndroid()) {
|
||||||
logger.info(
|
logger.info(
|
||||||
"Your platform does not provide complete low-level API for accessing direct buffers reliably. " +
|
"Your platform does not provide complete low-level API for accessing direct buffers reliably. " +
|
||||||
"Unless explicitly requested, heap buffer will always be preferred to avoid potential system " +
|
"Unless explicitly requested, heap buffer will always be preferred to avoid potential system " +
|
||||||
@ -158,6 +163,18 @@ public final class PlatformDependent {
|
|||||||
logger.debug("io.netty.maxDirectMemory: {} bytes", maxDirectMemory);
|
logger.debug("io.netty.maxDirectMemory: {} bytes", maxDirectMemory);
|
||||||
|
|
||||||
MAYBE_SUPER_USER = maybeSuperUser0();
|
MAYBE_SUPER_USER = maybeSuperUser0();
|
||||||
|
|
||||||
|
if (!isAndroid()) {
|
||||||
|
// only direct to method if we are not running on android.
|
||||||
|
// See https://github.com/netty/netty/issues/2604
|
||||||
|
if (javaVersion() >= 9) {
|
||||||
|
CLEANER = CleanerJava9.isSupported() ? new CleanerJava9() : NOOP;
|
||||||
|
} else {
|
||||||
|
CLEANER = CleanerJava6.isSupported() ? new CleanerJava6() : NOOP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CLEANER = NOOP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -322,15 +339,11 @@ public final class PlatformDependent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if
|
* Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if
|
||||||
* the current platform does not support this operation or the specified buffer is not a direct buffer.
|
* the current platform does not support this operation or the specified buffer is not a direct buffer.
|
||||||
*/
|
*/
|
||||||
public static void freeDirectBuffer(ByteBuffer buffer) {
|
public static void freeDirectBuffer(ByteBuffer buffer) {
|
||||||
if (hasUnsafe() && !isAndroid()) {
|
CLEANER.freeDirectBuffer(buffer);
|
||||||
// only direct to method if we are not running on android.
|
|
||||||
// See https://github.com/netty/netty/issues/2604
|
|
||||||
PlatformDependent0.freeDirectBuffer(buffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long directBufferAddress(ByteBuffer buffer) {
|
public static long directBufferAddress(ByteBuffer buffer) {
|
||||||
@ -933,42 +946,13 @@ public final class PlatformDependent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isExplicitNoUnsafe() {
|
|
||||||
return IS_EXPLICIT_NO_UNSAFE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean explicitNoUnsafe0() {
|
|
||||||
final boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
|
|
||||||
logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe);
|
|
||||||
|
|
||||||
if (noUnsafe) {
|
|
||||||
logger.debug("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Legacy properties
|
|
||||||
boolean tryUnsafe;
|
|
||||||
if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) {
|
|
||||||
tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true);
|
|
||||||
} else {
|
|
||||||
tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tryUnsafe) {
|
|
||||||
logger.debug("sun.misc.Unsafe: unavailable (io.netty.tryUnsafe/org.jboss.netty.tryUnsafe)");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean hasUnsafe0() {
|
private static boolean hasUnsafe0() {
|
||||||
if (isAndroid()) {
|
if (isAndroid()) {
|
||||||
logger.debug("sun.misc.Unsafe: unavailable (Android)");
|
logger.debug("sun.misc.Unsafe: unavailable (Android)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_EXPLICIT_NO_UNSAFE) {
|
if (PlatformDependent0.isExplicitNoUnsafe()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,10 +36,12 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
|||||||
final class PlatformDependent0 {
|
final class PlatformDependent0 {
|
||||||
|
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent0.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent0.class);
|
||||||
private static final Unsafe UNSAFE;
|
|
||||||
private static final long ADDRESS_FIELD_OFFSET;
|
private static final long ADDRESS_FIELD_OFFSET;
|
||||||
private static final long BYTE_ARRAY_BASE_OFFSET;
|
private static final long BYTE_ARRAY_BASE_OFFSET;
|
||||||
private static final Constructor<?> DIRECT_BUFFER_CONSTRUCTOR;
|
private static final Constructor<?> DIRECT_BUFFER_CONSTRUCTOR;
|
||||||
|
private static final boolean IS_EXPLICIT_NO_UNSAFE = explicitNoUnsafe0();
|
||||||
|
|
||||||
|
static final Unsafe UNSAFE;
|
||||||
|
|
||||||
// constants borrowed from murmur3
|
// constants borrowed from murmur3
|
||||||
static final int HASH_CODE_ASCII_SEED = 0xc2b2ae35;
|
static final int HASH_CODE_ASCII_SEED = 0xc2b2ae35;
|
||||||
@ -59,7 +61,7 @@ final class PlatformDependent0 {
|
|||||||
Field addressField = null;
|
Field addressField = null;
|
||||||
Unsafe unsafe;
|
Unsafe unsafe;
|
||||||
|
|
||||||
if (PlatformDependent.isExplicitNoUnsafe()) {
|
if (isExplicitNoUnsafe()) {
|
||||||
direct = null;
|
direct = null;
|
||||||
addressField = null;
|
addressField = null;
|
||||||
unsafe = null;
|
unsafe = null;
|
||||||
@ -244,7 +246,7 @@ final class PlatformDependent0 {
|
|||||||
public Object run() {
|
public Object run() {
|
||||||
try {
|
try {
|
||||||
Class<?> bitsClass =
|
Class<?> bitsClass =
|
||||||
Class.forName("java.nio.Bits", false, PlatformDependent.getSystemClassLoader());
|
Class.forName("java.nio.Bits", false, getSystemClassLoader());
|
||||||
Method unalignedMethod = bitsClass.getDeclaredMethod("unaligned");
|
Method unalignedMethod = bitsClass.getDeclaredMethod("unaligned");
|
||||||
Throwable cause = ReflectionUtil.trySetAccessible(unalignedMethod);
|
Throwable cause = ReflectionUtil.trySetAccessible(unalignedMethod);
|
||||||
if (cause != null) {
|
if (cause != null) {
|
||||||
@ -281,10 +283,35 @@ final class PlatformDependent0 {
|
|||||||
|
|
||||||
logger.debug("java.nio.DirectByteBuffer.<init>(long, int): {}",
|
logger.debug("java.nio.DirectByteBuffer.<init>(long, int): {}",
|
||||||
DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable");
|
DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable");
|
||||||
|
}
|
||||||
|
|
||||||
if (direct != null) {
|
static boolean isExplicitNoUnsafe() {
|
||||||
freeDirectBuffer(direct);
|
return IS_EXPLICIT_NO_UNSAFE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean explicitNoUnsafe0() {
|
||||||
|
final boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
|
||||||
|
logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe);
|
||||||
|
|
||||||
|
if (noUnsafe) {
|
||||||
|
logger.debug("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Legacy properties
|
||||||
|
boolean tryUnsafe;
|
||||||
|
if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) {
|
||||||
|
tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true);
|
||||||
|
} else {
|
||||||
|
tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tryUnsafe) {
|
||||||
|
logger.debug("sun.misc.Unsafe: unavailable (io.netty.tryUnsafe/org.jboss.netty.tryUnsafe)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isUnaligned() {
|
static boolean isUnaligned() {
|
||||||
@ -330,12 +357,6 @@ final class PlatformDependent0 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeDirectBuffer(ByteBuffer buffer) {
|
|
||||||
// Delegate to other class to not break on android
|
|
||||||
// See https://github.com/netty/netty/issues/2604
|
|
||||||
Cleaner0.freeDirectBuffer(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long directBufferAddress(ByteBuffer buffer) {
|
static long directBufferAddress(ByteBuffer buffer) {
|
||||||
return getLong(buffer, ADDRESS_FIELD_OFFSET);
|
return getLong(buffer, ADDRESS_FIELD_OFFSET);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user