第二章: NioEventLoop
第五节: 优化selector
在剖析selector轮询之前, 我们先讲解一下selector的创建过程, 回顾之前的小节, 在创建NioEventLoop中初始化了唯一绑定的selector:
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider, ?????????????SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) { ???super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler); ???//代码省略 ???provider = selectorProvider; ???selector = openSelector(); ???selectStrategy = strategy;}
这里selector = openSelector()初始化了selector, 我们跟到openSelector()中:
private Selector openSelector() { ???final Selector selector; ???try { ???????//调用jdk底层的api ???????selector = provider.openSelector(); ???} catch (IOException e) { ???????throw new ChannelException("failed to open a new selector", e); ???} ???//判断是否需要优化(默认false, 也就是默认需要优化) ???if (DISABLE_KEYSET_OPTIMIZATION) { ???????return selector; ???} ???//用这个数据结构替换原生的SelectionKeySet ???final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet(); ???Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction<Object>() { ???????@Override ???????public Object run() { ???????????try { ???????????????//通过反射拿到sun.nio.ch.SelectorImpl这个类的class对象 ???????????????return Class.forName("sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader()); ???????????} catch (ClassNotFoundException e) { ???????????????return e; ???????????} catch (SecurityException e) { ???????????????return e; ???????????} ???????} ???}); ???//判断拿到的是不是class对象并且是不是Selector的实现类 ???if (!(maybeSelectorImplClass instanceof Class) ||!((Class<?>) maybeSelectorImplClass).isAssignableFrom(selector.getClass())) { ???????if (maybeSelectorImplClass instanceof Exception) { ???????????Exception e = (Exception) maybeSelectorImplClass; ???????????logger.trace("failed to instrument a special java.util.Set into: {}", selector, e); ???????} ???????//如果不是他的实现, 就直接返回原生select ???????return selector; ???} ???//如果是它的实现, 就拿到其class对象 ???final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass; ???Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() { ???????@Override ???????public Object run() { ???????????try { ???????????????//通过反射拿到selectedKeys和publicSelectedKeys两个属性, 默认这两个属性底层都是hashSet方式实现的 ???????????????Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); ???????????????Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys"); ???????????????//设置成可修改的 ???????????????selectedKeysField.setAccessible(true); ???????????????publicSelectedKeysField.setAccessible(true); ???????????????//将selector的这两个属性替换成Netty的selectedKeySet ???????????????selectedKeysField.set(selector, selectedKeySet); ???????????????publicSelectedKeysField.set(selector, selectedKeySet); ???????????????return null; ???????????} catch (NoSuchFieldException e) { ???????????????return e; ???????????} catch (IllegalAccessException e) { ???????????????return e; ???????????} catch (RuntimeException e) { ???????????????if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) { ???????????????????return e; ???????????????} else { ???????????????????throw e; ???????????????} ???????????} ???????} ???}); ???if (maybeException instanceof Exception) { ???????selectedKeys = null; ???????Exception e = (Exception) maybeException; ???????logger.trace("failed to instrument a special java.util.Set into: {}", selector, e); ???} else { ???????//将优化后的keySet保存成NioEventLoop的成员变量 ???????selectedKeys = selectedKeySet; ???????logger.trace("instrumented a special java.util.Set into: {}", selector); ???} ???return selector;}
这里代码比较长, 我们一点一点的剖析:
首先selector = provider.openSelector()这里创建了jdk底层的selector
if (DISABLE_KEYSET_OPTIMIZATION) { ???return selector;}
这里判断了是否关闭优化功能, 默认是false, 也就是需要优化, 这里的意思就是netty需要对jdk原生的selector进行了优化, 我们知道selector在select()操作时候, 会通过selector.selectedKeys()操作返回一个Set<SelectionKey>, 这个是Set类型, netty对这个set进行了处理, 使用SelectedSelectionKeySet的数据结构进行替换, 当在select()操作时将key存入一个SelectedSelectionKeySet的数据结构中
final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
这里一步创建了这个优化后的数据结构, 简单跟一下这个类的构造方法:
SelectedSelectionKeySet() { ???keysA = new SelectionKey[1024]; ???keysB = keysA.clone();}
初始化了两个属性keysA和keysB, 说明这类其实底层是通过数组实现的, 通过操作数组下标会有更高的效率
这个类的的flip()方法, 则返SelectionKey[]数组
SelectionKey[] flip() { ???if (isA) { ???????isA = false; ???????keysA[keysASize] = null; ???????keysBSize = 0; ???????return keysA; ???} else { ???????isA = true; ???????keysB[keysBSize] = null; ???????keysASize = 0; ???????return keysB; ???}}
再看下其他方法:
@Overridepublic boolean remove(Object o) { ???return false;}@Overridepublic boolean contains(Object o) { ???return false;}@Overridepublic Iterator<SelectionKey> iterator() { ???throw new UnsupportedOperationException();}
我们看到remove()方法, contains()方法都返回了false, 说明其不支持删除方法和包含方法, iterator()方法则直接抛出异常, 说明其不支持迭代器操作
再往下看, 这里通过Class.forName("sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader())创建了一个SelectorImpl的class对象
if(!(maybeSelectorImplClass instanceof Class) ||!((Class<?>) maybeSelectorImplClass).isAssignableFrom(selector.getClass()))
这里判断拿到的对象是否为class对象并且是否为Selector的实现类, 如果不是, 则直接返回jdk的selector
如果是, 就继续转化成class对象
然后就做了真正的替换操作:
//通过反射拿到selectedKeys和publicSelectedKeys两个属性, 默认这两个属性底层都是hashSet方式实现的Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");//设置成可修改的selectedKeysField.setAccessible(true);publicSelectedKeysField.setAccessible(true);//将selector的这两个属性替换成Netty的selectedKeySetselectedKeysField.set(selector, selectedKeySet);publicSelectedKeysField.set(selector, selectedKeySet);
通过注释我们不难看出, 这里将新创建selectedKeySet替换了selector对象中的selectedKeysField, 和selectedKeysField两个属性
最后通过selectedKeys = selectedKeySet将优化的数据结构selectedKeySet保存在NioEventLoop的成员变量中
最后返回优化后的selector
这样, selector在select()操作的过程中, 如果有就绪时间则会将返回的key存放在selectedKeySet所对应的数组中
Netty源码分析第2章(NioEventLoop)---->第5节: 优化selector
原文地址:https://www.cnblogs.com/xiangnan6122/p/10203116.html