Selector通过调用Selector.open()方法启动的:
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
SelectorProvider.provider()方法如下,返回值为SelectorProvider:
private static final Object lock = new Object();
private static SelectorProvider provider = null;
public static SelectorProvider provider() {
synchronized (lock) {
if (provider != null)
return provider;
return AccessController.doPrivileged(
new PrivilegedAction<SelectorProvider>() {
public SelectorProvider run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}
首先判断provider是否为null,如果不为null则直接返回当前已经存在的provider;
如果provider为null,可以看到在run()方法中一共有三种生成provider的方法。
第一个if调用了loadProviderFromProperty()方法:
private static boolean loadProviderFromProperty() {
String cn = System.getProperty("java.nio.channels.spi.SelectorProvider");
if (cn == null)
return false;
try {
Class<?> c = Class.forName(cn, true,
ClassLoader.getSystemClassLoader());
provider = (SelectorProvider)c.newInstance();
return true;
} catch (ClassNotFoundException x) {
throw new ServiceConfigurationError(null, x);
} catch (IllegalAccessException x) {
throw new ServiceConfigurationError(null, x);
} catch (InstantiationException x) {
throw new ServiceConfigurationError(null, x);
} catch (SecurityException x) {
throw new ServiceConfigurationError(null, x);
}
}
先通过System.getProperty(“java.nio.channels.spi.SelectorProvider”)获取键值为java.nio.channels.spi.SelectorProvider的系统属性,如果没有设置该系统属性,则返回false;否则通过类加载器获取其实现类,并通过反射机制获取其实例化对象为provider 赋值,并返回true。
第二个if调用了loadProviderAsService()方法:
private static boolean loadProviderAsService() {
ServiceLoader<SelectorProvider> sl =
ServiceLoader.load(SelectorProvider.class,
ClassLoader.getSystemClassLoader());
Iterator<SelectorProvider> i = sl.iterator();
for (;;) {
try {
if (!i.hasNext())
return false;
provider = i.next();
return true;
} catch (ServiceConfigurationError sce) {
if (sce.getCause() instanceof SecurityException) {
// Ignore the security exception, try the next provider
continue;
}
throw sce;
}
}
}
通过ServiceLoader的load方法加载"META-INF/services/"路径下指明的SelectorProvider.class的实现类,如果设置有相应的文件则成功赋值并返回true,否则返回false。
如果以上两步判断都为false,则使用默认的SelectorProvider,即调用sun.nio.ch.DefaultSelectorProvider.create():
public static SelectorProvider create() {
return new WindowsSelectorProvider();
}
public WindowsSelectorProvider() {
}
直接返回WindowsSelectorProvider作为provider的值。
run方法运行结束后,SelectorProvider一定会有值。
接下来看SelectorProvider的openSelector方法:
public abstract AbstractSelector openSelector()
throws IOException;
这是一个抽象方法,真正的实现是在WindowsSelectorProvider中:
public AbstractSelector openSelector() throws IOException {
return new WindowsSelectorImpl(this);
}
WindowsSelectorImpl(SelectorProvider var1) throws IOException {
super(var1);
this.wakeupSourceFd = ((SelChImpl)this.wakeupPipe.source()).getFDVal();
SinkChannelImpl var2 = (SinkChannelImpl)this.wakeupPipe.sink();
var2.sc.socket().setTcpNoDelay(true);
this.wakeupSinkFd = var2.getFDVal();
this.pollWrapper.addWakeupSocket(this.wakeupSourceFd, 0);
}
WindowsSelectorImpl的构造方法中先调用了父类SelectorImpl的构造方法:
protected Set<SelectionKey> selectedKeys = new HashSet();
protected HashSet<SelectionKey> keys = new HashSet();
private Set<SelectionKey> publicKeys;
private Set<SelectionKey> publicSelectedKeys;
protected SelectorImpl(SelectorProvider var1) {
super(var1);
if (Util.atBugLevel("1.4")) {
this.publicKeys = this.keys;
this.publicSelectedKeys = this.selectedKeys;
} else {
this.publicKeys = Collections.unmodifiableSet(this.keys);
this.publicSelectedKeys = Util.ungrowableSet(this.selectedKeys);
}
}
SelectorImpl同样调用了其父类AbstractSelector的构造方法:
private final SelectorProvider provider;
protected AbstractSelector(SelectorProvider provider) {
this.provider = provider;
}
在AbstractSelector的构造方法中完成了对provider的赋值。
回到WindowsSelectorImpl的构造方法,有成员如下:
private final Pipe wakeupPipe = Pipe.open();
public static Pipe open() throws IOException {
return SelectorProvider.provider().openPipe();
}
其中SelectorProvider.provider()在上边已经分析过了,openPipe的具体实现在SelectorProviderImpl中:
public Pipe openPipe() throws IOException {
return new PipeImpl(this);`在这里插入代码片`
}
调用了PipeImpl的构造方法,传入了当前的SelectorProvider。
PipeImpl(SelectorProvider var1) throws IOException {
try {
AccessController.doPrivileged(new PipeImpl.Initializer(var1));
} catch (PrivilegedActionException var3) {
throw (IOException)var3.getCause();
}
}
该构造方法传入了SelectorProvider到PipeImpl的内部类Initializer并运行其run方法(private class Initializer implements PrivilegedExceptionAction):
private final SelectorProvider sp;
private IOException ioe;
private Initializer(SelectorProvider var2) {
this.ioe = null;
this.sp = var2;
}
该构造方法令ioe为null,并将sp赋值为SelectorProvider。
public Void run() throws IOException {
PipeImpl.Initializer.LoopbackConnector var1 = new PipeImpl.Initializer.LoopbackConnector();
var1.run();
if (this.ioe instanceof ClosedByInterruptException) {
this.ioe = null;
Thread var2 = new Thread(var1) {
public void interrupt() {
}
};
var2.start();
while(true) {
try {
var2.join();
break;
} catch (InterruptedException var4) {
;
}
}
Thread.currentThread().interrupt();
}
if (this.ioe != null) {
throw new IOException("Unable to establish loopback connection", this.ioe);
} else {
return null;
}
}
在run方法中先产生LoopbackConnector对象,LoopbackConnector是Initializer的内部类,然后再通过LoopbackConnector的实例化对象调用其run方法:
private LoopbackConnector() {
}
public void run() {
ServerSocketChannel var1 = null;
SocketChannel var2 = null;
SocketChannel var3 = null;
try {
ByteBuffer var4 = ByteBuffer.allocate(16);
ByteBuffer var5 = ByteBuffer.allocate(16);
InetAddress var6 = InetAddress.getByName("127.0.0.1");
assert var6.isLoopbackAddress();
InetSocketAddress var7 = null;
while(true) {
if (var1 == null || !var1.isOpen()) {
var1 = ServerSocketChannel.open();
var1.socket().bind(new InetSocketAddress(var6, 0));
var7 = new InetSocketAddress(var6, var1.socket().getLocalPort());
}
var2 = SocketChannel.open(var7);
PipeImpl.RANDOM_NUMBER_GENERATOR.nextBytes(var4.array());
do {
var2.write(var4);
} while(var4.hasRemaining());
var4.rewind();
var3 = var1.accept();
do {
var3.read(var5);
} while(var5.hasRemaining());
var5.rewind();
if (var5.equals(var4)) {
PipeImpl.this.source = new SourceChannelImpl(Initializer.this.sp, var2);
PipeImpl.this.sink = new SinkChannelImpl(Initializer.this.sp, var3);
break;
}
var3.close();
var2.close();
}
} catch (IOException var18) {
try {
if (var2 != null) {
var2.close();
}
if (var3 != null) {
var3.close();
}
} catch (IOException var17) {
;
}
Initializer.this.ioe = var18;
} finally {
try {
if (var1 != null) {
var1.close();
}
} catch (IOException var16) {
;
}
}
}
定义了一个ServerSocketChannel var1两个SocketChannel var2和var3以及两个ByteBuffer var4和var5;生成了一个InetAddress var6。
在while循环中检查ServerSocketChannel是否为null或者未打开,如果未true则打开ServerSocketChannel并为其绑定地址var6和端口号0,令var7的地址是var6的地址,端口号为ServerSocketChannel的端口号;通过var7将SocketChannel var2与ServerSocketChannel var1建立连接,生成随机数通过SocketChannel var2发送给ServerSocketChannel var1。接着ServerSocketChannel调用accept方法侦听刚才的连接产生一个SocketChannel对象var3,从var3中读取数据存放在缓冲区var5中。比较var4和var5,如果一致则给PipeImpl的成员source和sink分别初始化保存起来,若不一致就继续循环,直至一致。如果出现IO异常则将异常保存在ioe中,关闭所有channel,循环结束。
回到Initializer的run方法,如果ioe中保存的异常是ClosedByInterruptException则需要开启一个新的线程重新运行LoopbackConnector的run方法,并调用join方法保证运行顺序。如果ioe不为null,则抛出异常。
回到WindowsSelectorImpl的构造方法,用wakeupSourceFd保存source(SourceChannelImpl)的fdVal值,用wakeupSinkFd保存sink(SinkChannelImpl)的fdVal值;禁用Nagle算法,最后使用pollWrpper成员保存source的fdVal值。至此selector创建完毕。