NioEventLoop should also use our special SelectionKeySet on Java9 and later. (#8260)

Motivation:

In Java8 and earlier we used reflection to replace the used key set if not otherwise told. This does not work on Java9 and later without special flags as its not possible to call setAccessible(true) on the Field anymore.

Modifications:

- Use Unsafe to instrument the Selector with out special set when sun.misc.Unsafe is present and we are using Java9+.

Result:

NIO transport produce less GC on Java9 and later as well.
This commit is contained in:
Norman Maurer 2018-09-05 07:23:03 +02:00 committed by GitHub
parent ade60c11e1
commit 3c2dbdb5db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 3 deletions

View File

@ -29,6 +29,7 @@ import org.jctools.util.Pow2;
import org.jctools.util.UnsafeAccess; import org.jctools.util.UnsafeAccess;
import java.io.File; import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
@ -567,6 +568,14 @@ public final class PlatformDependent {
PlatformDependent0.putLong(data, index, value); PlatformDependent0.putLong(data, index, value);
} }
public static void putObject(Object o, long offset, Object x) {
PlatformDependent0.putObject(o, offset, x);
}
public static long objectFieldOffset(Field field) {
return PlatformDependent0.objectFieldOffset(field);
}
public static void copyMemory(long srcAddr, long dstAddr, long length) { public static void copyMemory(long srcAddr, long dstAddr, long length) {
PlatformDependent0.copyMemory(srcAddr, dstAddr, length); PlatformDependent0.copyMemory(srcAddr, dstAddr, length);
} }

View File

@ -568,6 +568,10 @@ final class PlatformDependent0 {
UNSAFE.putLong(data, BYTE_ARRAY_BASE_OFFSET + index, value); UNSAFE.putLong(data, BYTE_ARRAY_BASE_OFFSET + index, value);
} }
static void putObject(Object o, long offset, Object x) {
UNSAFE.putObject(o, offset, x);
}
static void copyMemory(long srcAddr, long dstAddr, long length) { static void copyMemory(long srcAddr, long dstAddr, long length) {
// Manual safe-point polling is only needed prior Java9: // Manual safe-point polling is only needed prior Java9:
// See https://bugs.openjdk.java.net/browse/JDK-8149596 // See https://bugs.openjdk.java.net/browse/JDK-8149596

View File

@ -43,7 +43,6 @@ import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -188,8 +187,8 @@ public final class NioEventLoop extends SingleThreadEventLoop {
}); });
if (!(maybeSelectorImplClass instanceof Class) || if (!(maybeSelectorImplClass instanceof Class) ||
// ensure the current selector implementation is what we can instrument. // ensure the current selector implementation is what we can instrument.
!((Class<?>) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) { !((Class<?>) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) {
if (maybeSelectorImplClass instanceof Throwable) { if (maybeSelectorImplClass instanceof Throwable) {
Throwable t = (Throwable) maybeSelectorImplClass; Throwable t = (Throwable) maybeSelectorImplClass;
logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, t); logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, t);
@ -207,6 +206,23 @@ public final class NioEventLoop extends SingleThreadEventLoop {
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys"); Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
// Let us try to use sun.misc.Unsafe to replace the SelectionKeySet.
// This allows us to also do this in Java9+ without any extra flags.
long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
long publicSelectedKeysFieldOffset =
PlatformDependent.objectFieldOffset(publicSelectedKeysField);
if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
PlatformDependent.putObject(
unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
PlatformDependent.putObject(
unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
return null;
}
// We could not retrieve the offset, lets try reflection as last-resort.
}
Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true); Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true);
if (cause != null) { if (cause != null) {
return cause; return cause;