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 java.io.IOException;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.channels.CancelledKeyException;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
|
@ -15,14 +16,8 @@ import java.nio.channels.Selector;
|
|||
import java.nio.channels.SelectionKey;
|
||||
|
||||
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.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
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.
|
||||
if (maybeSelectorImplClass == null ||
|
||||
!maybeSelectorImplClass.isAssignableFrom(unwrappedSelector.getClass())) {
|
||||
if (maybeSelectorImplClass == null || !maybeSelectorImplClass.isAssignableFrom(unwrappedSelector.getClass())) {
|
||||
return new SelectorTuple(unwrappedSelector);
|
||||
}
|
||||
|
||||
|
@ -167,40 +161,19 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
|||
try {
|
||||
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
|
||||
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 = trySetAccessible(selectedKeysField, true);
|
||||
if (cause != null) {
|
||||
return cause;
|
||||
maybeException = cause;
|
||||
}
|
||||
cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
|
||||
cause = trySetAccessible(publicSelectedKeysField, true);
|
||||
if (cause != null) {
|
||||
return cause;
|
||||
maybeException = cause;
|
||||
}
|
||||
|
||||
selectedKeysField.set(unwrappedSelector, selectedKeySet);
|
||||
publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
|
||||
return null;
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
maybeException = e;
|
||||
}
|
||||
|
||||
if (maybeException instanceof Exception) {
|
||||
selectedKeys = null;
|
||||
Exception e = (Exception) maybeException;
|
||||
|
@ -763,4 +736,40 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
|||
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