目錄
簡介
字段lock,provider,構造函數,方法loadProviderFromProperty,loadProviderAsService,provider
方法2個openDatagramChannel,openPipe/Selector/ServerSocketChannel/SocketChannel,inheritedChannel
簡介
package java.nio.channels.spi;
import java.io.IOException;
import java.net.ProtocolFamily;
import java.nio.channels.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.ServiceLoader;
import java.util.ServiceConfigurationError;
import sun.security.action.GetPropertyAction;
/**
* 用于選擇器和可選擇通道的服務提供程式類。
*
* <p> 選擇器提供程式是這個類的一個具體子類,它有無參構造函數,并實作下面指定的抽象方法。
* Java虛拟機的給定調用,維護一個單系統範圍的預設提供程式執行個體,該執行個體由provider方法傳回。
* 該方法的第一次調用将定位預設提供程式,如下所示。
*
* <p> 系統預設提供程式由DatagramChannel、Pipe、Selector、ServerSocketChannel和SocketChannel類的靜态open方法使用。
* 它也被System.inheritedChannel()方法使用。
* 程式可以使用預設提供程式之外的提供程式,通過執行個體化該提供程式,然後直接調用該類中定義的open方法。
*
* <p> 這個類中的所有方法對于多個并發線程使用都是安全的。
*
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
*/
public abstract class SelectorProvider

字段lock,provider,構造函數,方法loadProviderFromProperty,loadProviderAsService,provider
private static final Object lock = new Object();
// 内部儲存一個靜态的provider
private static SelectorProvider provider = null;
/**
* 初始化這個類的執行個體
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link RuntimePermission}<tt>("selectorProvider")</tt>
*/
protected SelectorProvider() {
// 檢查能否使用selectorProvider
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new RuntimePermission("selectorProvider"));
}
private static boolean loadProviderFromProperty() {
String cn = System.getProperty("java.nio.channels.spi.SelectorProvider");
if (cn == null)
return false;
try {
// 調用系統加載器,調用它的無參構造器,指派給provider
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);
}
}
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;
}
}
}
/**
* 傳回此Java虛拟機調用的系統範圍預設選擇器提供程式。
*
* <p> 這個方法的第一次調用,定位了預設的provider對象,如下所示:</p>
*
* <ol>
*
* <li><p> 如果系統屬性為java.nio.channels.spi.SelectorProvider被定義,然後它被當作一個具體提供程式類的完全限定名。
* 類被加載并執行個體化;
* 如果此過程失敗,則抛出一個未指定的錯誤。</p></li>
*
* <li><p> 如果提供程式類已安裝在系統類加載器可見的jar檔案中,并且該jar檔案包含一個名為java.nio.channels.spi.SelectorProvider的提供程式配置檔案,
* 在資源目錄 META-INF/services,然後擷取該檔案中指定的第一個類名稱。
* 類被加載并執行個體化;
* 如果此過程失敗,則抛出一個未指定的錯誤。</p></li>
*
* <li><p> 最後,如果上述任何一個都沒有指定提供程式,則執行個體化系統預設的提供程式類并傳回結果。</p></li>
*
* </ol>
*
* <p> 此方法的後續調用将傳回第一次調用所傳回的提供者。 </p>
*
* @return The system-wide default selector provider
*/
public static SelectorProvider provider() {
synchronized (lock) {
if (provider != null)
return provider;
return AccessController.doPrivileged(
new PrivilegedAction<SelectorProvider>() {
public SelectorProvider run() {
// 先從系統屬性獲得,再從service獲得,最後傳回預設provider
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}
方法2個openDatagramChannel,openPipe/Selector/ServerSocketChannel/SocketChannel,inheritedChannel
/**
* 打開資料報通道。
*
* @return The new channel
*
* @throws IOException
* If an I/O error occurs
*/
public abstract DatagramChannel openDatagramChannel()
throws IOException;
/**
* 打開資料報通道。
*
* @param family
* The protocol family
*
* @return A new datagram channel
*
* @throws UnsupportedOperationException
* If the specified protocol family is not supported
* @throws IOException
* If an I/O error occurs
*
* @since 1.7
*/
public abstract DatagramChannel openDatagramChannel(ProtocolFamily family)
throws IOException;
/**
* 打開管道。
*
* @return The new pipe
*
* @throws IOException
* If an I/O error occurs
*/
public abstract Pipe openPipe()
throws IOException;
/**
* 打開一個選擇器
*
* @return The new selector
*
* @throws IOException
* If an I/O error occurs
*/
public abstract AbstractSelector openSelector()
throws IOException;
/**
* 打開一個伺服器-套接字通道。
*
* @return The new channel
*
* @throws IOException
* If an I/O error occurs
*/
public abstract ServerSocketChannel openServerSocketChannel()
throws IOException;
/**
* 打開套接字通道。
*
* @return The new channel
*
* @throws IOException
* If an I/O error occurs
*/
public abstract SocketChannel openSocketChannel()
throws IOException;
/**
* 傳回從建立此java虛拟機的實體繼承的通道。
*
* <p> 在許多作業系統上,程序(如Java虛拟機)的啟動方式允許程序從建立該程序的實體繼承一個通道。
* 這樣做的方式是依賴于系統的,因為是可能的實體,該通道可能被連接配接。
* 例如,在UNIX系統上,Internet服務守護程序(inetd)用于啟動程式,在請求到達關聯的網絡端口時為請求提供服務。
* 在本例中,啟動的程序繼承表示網絡套接字的通道。
*
* <p> 在繼承的通道代表一個網絡套接字的情況下,
* 然後通道類型由方法傳回,如下:
*
* <ul>
*
* <li><p> 如果繼承的通道表示面向流的連接配接套接字,則傳回SocketChannel。
* 套接字通道(至少在開始時)在阻塞模式下綁定到套接字位址,并連接配接到對等點。
* </p></li>
*
* <li><p> 如果繼承的通道表示面向流偵聽套接字,則傳回ServerSocketChannel。
* 伺服器-套接字通道(至少在開始時)處于阻塞模式,并綁定到套接字位址。
* </p></li>
*
* <li><p> 如果繼承的通道是面向資料的套接字,那麼傳回一個DatagramChannel。
* 資料報通道至少在初始階段處于阻塞模式,并綁定到一個套接字位址。
* </p></li>
*
* </ul>
*
* <p> 除了所描述的面向網絡的通道之外,這種方法将來還可能傳回其他類型的通道。
*
* <p> 該方法的第一次調用将建立傳回的通道。該方法的後續調用将傳回相同的通道。</p>
*
* @return The inherited channel, if any, otherwise <tt>null</tt>.
*
* @throws IOException
* If an I/O error occurs
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link RuntimePermission}<tt>("inheritedChannel")</tt>
*
* @since 1.5
*/
public Channel inheritedChannel() throws IOException {
return null;
}