java nio SelectorProvider源码分析

目录

简介

字段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;
   }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值