more work on nio event loop
This commit is contained in:
parent
73188102fe
commit
98d0a34c88
1 changed files with 42 additions and 33 deletions
|
@ -8,6 +8,7 @@ import org.xbib.event.loop.SingleThreadEventLoop;
|
||||||
import org.xbib.event.util.IntSupplier;
|
import org.xbib.event.util.IntSupplier;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.AccessibleObject;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.channels.CancelledKeyException;
|
import java.nio.channels.CancelledKeyException;
|
||||||
import java.nio.channels.SelectableChannel;
|
import java.nio.channels.SelectableChannel;
|
||||||
|
@ -15,14 +16,8 @@ import java.nio.channels.Selector;
|
||||||
import java.nio.channels.SelectionKey;
|
import java.nio.channels.SelectionKey;
|
||||||
|
|
||||||
import java.nio.channels.spi.SelectorProvider;
|
import java.nio.channels.spi.SelectorProvider;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -155,8 +150,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure the current selector implementation is what we can instrument.
|
// ensure the current selector implementation is what we can instrument.
|
||||||
if (maybeSelectorImplClass == null ||
|
if (maybeSelectorImplClass == null || !maybeSelectorImplClass.isAssignableFrom(unwrappedSelector.getClass())) {
|
||||||
!maybeSelectorImplClass.isAssignableFrom(unwrappedSelector.getClass())) {
|
|
||||||
return new SelectorTuple(unwrappedSelector);
|
return new SelectorTuple(unwrappedSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,40 +161,19 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
||||||
try {
|
try {
|
||||||
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
|
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
|
||||||
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
|
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
|
||||||
|
Throwable cause = trySetAccessible(selectedKeysField, true);
|
||||||
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);
|
|
||||||
if (cause != null) {
|
if (cause != null) {
|
||||||
return cause;
|
maybeException = cause;
|
||||||
}
|
}
|
||||||
cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
|
cause = trySetAccessible(publicSelectedKeysField, true);
|
||||||
if (cause != null) {
|
if (cause != null) {
|
||||||
return cause;
|
maybeException = cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedKeysField.set(unwrappedSelector, selectedKeySet);
|
selectedKeysField.set(unwrappedSelector, selectedKeySet);
|
||||||
publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
|
publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
|
||||||
return null;
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
maybeException = e;
|
maybeException = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maybeException instanceof Exception) {
|
if (maybeException instanceof Exception) {
|
||||||
selectedKeys = null;
|
selectedKeys = null;
|
||||||
Exception e = (Exception) maybeException;
|
Exception e = (Exception) maybeException;
|
||||||
|
@ -763,4 +736,40 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
||||||
logger.log(Level.WARNING, "Failed to update SelectionKeys.", t);
|
logger.log(Level.WARNING, "Failed to update SelectionKeys.", t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Throwable trySetAccessible(AccessibleObject object, boolean checkAccessible) {
|
||||||
|
if (checkAccessible && !isExplicitTryReflectionSetAccessible()) {
|
||||||
|
return new UnsupportedOperationException("Reflective setAccessible(true) disabled");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
object.setAccessible(true);
|
||||||
|
return null;
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static boolean isExplicitTryReflectionSetAccessible() {
|
||||||
|
// we disable reflective access
|
||||||
|
boolean defaultValue = javaVersion() < 9 || System.getProperties().containsKey("org.graalvm.nativeimage.imagecode");
|
||||||
|
return Boolean.parseBoolean(System.getProperties().getProperty("io.netty.tryReflectionSetAccessible",
|
||||||
|
Boolean.toString(defaultValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int javaVersion() {
|
||||||
|
return majorVersion(System.getProperties().getProperty("java.specification.version", "1.6"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int majorVersion(String javaSpecVersion) {
|
||||||
|
final String[] components = javaSpecVersion.split("\\.");
|
||||||
|
final int[] version = new int[components.length];
|
||||||
|
for (int i = 0; i < components.length; i++) {
|
||||||
|
version[i] = Integer.parseInt(components[i]);
|
||||||
|
}
|
||||||
|
if (version[0] == 1) {
|
||||||
|
assert version[1] >= 6;
|
||||||
|
return version[1];
|
||||||
|
} else {
|
||||||
|
return version[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue