All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xnio.nio.NioXnio Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source
 *
 * Copyright 2014 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.xnio.nio;

import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.xnio.FileSystemWatcher;
import org.xnio.IoUtils;
import org.xnio.Options;
import org.xnio.Xnio;
import org.xnio.OptionMap;
import org.xnio.XnioWorker;
import org.xnio.management.XnioProviderMXBean;
import org.xnio.management.XnioServerMXBean;
import org.xnio.management.XnioWorkerMXBean;

import static org.xnio.nio.Log.log;

/**
 * An NIO-based XNIO provider for a standalone application.
 */
final class NioXnio extends Xnio {

    static final boolean IS_HP_UX;
    static final boolean HAS_BUGGY_EVENT_PORT;

    interface SelectorCreator {
        Selector open() throws IOException;
    }

    final SelectorCreator tempSelectorCreator;
    final SelectorCreator mainSelectorCreator;

    static {
        log.greeting(Version.getVersionString());
        IS_HP_UX = AccessController.doPrivileged(new PrivilegedAction() {
            public Boolean run() {
                final String bugLevel = System.getProperty("sun.nio.ch.bugLevel");
                if (bugLevel == null) System.setProperty("sun.nio.ch.bugLevel", "");
                return Boolean.valueOf(System.getProperty("os.name", "unknown").equalsIgnoreCase("hp-ux"));
            }
        }).booleanValue();
        // if a JDK is released with a fix, we can try to detect it and set this to "false" for those JDKs.
        HAS_BUGGY_EVENT_PORT = true;
    }

    /**
     * Construct a new NIO-based XNIO provider instance.  Should only be invoked by the service loader.
     */
    NioXnio() {
        super("nio");
        final Object[] objects = AccessController.doPrivileged(
            new PrivilegedAction() {
                public Object[] run() {
                    String jdkVersion = System.getProperty("java.specification.version", "1.8");
                    final boolean jdk9 = ! (jdkVersion.equals("1.8") || jdkVersion.equals("8"));
                    final SelectorProvider defaultProvider = SelectorProvider.provider();
                    final String chosenProvider = System.getProperty("xnio.nio.selector.provider");
                    SelectorProvider provider = null;
                    if (chosenProvider != null) {
                        try {
                            provider = Class.forName(chosenProvider, true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                            provider.openSelector().close();
                        } catch (Throwable e) {
                            // not available
                            provider = null;
                        }
                    }
                    if (! jdk9) {
                        // try to probe the best available provider
                        if (provider == null) {
                            try {
                                // Mac OS X and BSD
                                provider = Class.forName("sun.nio.ch.KQueueSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                                provider.openSelector().close();
                            } catch (Throwable e) {
                                // not available
                                provider = null;
                            }
                        }
                        if (provider == null) {
                            try {
                                // Linux
                                provider = Class.forName("sun.nio.ch.EPollSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                                provider.openSelector().close();
                            } catch (Throwable e) {
                                // not available
                                provider = null;
                            }
                        }
                        if (provider == null && ! HAS_BUGGY_EVENT_PORT) {
                            try {
                                // Solaris (Java 8+)
                                provider = Class.forName("sun.nio.ch.EventPortSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                                provider.openSelector().close();
                            } catch (Throwable e) {
                                // not available
                                provider = null;
                            }
                        }
                        if (provider == null) {
                            try {
                                // Solaris
                                provider = Class.forName("sun.nio.ch.DevPollSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                                provider.openSelector().close();
                            } catch (Throwable e) {
                                // not available
                                provider = null;
                            }
                        }
                        if (provider == null) {
                            try {
                                // Solaris (Java 8+)
                                provider = Class.forName("sun.nio.ch.EventPortSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                                provider.openSelector().close();
                            } catch (Throwable e) {
                                // not available
                                provider = null;
                            }
                        }
                        if (provider == null) {
                            try {
                                // AIX
                                provider = Class.forName("sun.nio.ch.PollsetSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                                provider.openSelector().close();
                            } catch (Throwable e) {
                                // not available
                                provider = null;
                            }
                        }
                    }
                    if (provider == null) {
                        try {
                            defaultProvider.openSelector().close();
                            provider = defaultProvider;
                        } catch (Throwable e) {
                            // not available
                        }
                    }
                    if (provider == null) {
                        try {
                            // Nothing else works, not even the default
                            provider = Class.forName("sun.nio.ch.PollSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                            provider.openSelector().close();
                        } catch (Throwable e) {
                            // not available
                            provider = null;
                        }
                    }
                    if (provider == null) {
                        throw log.noSelectorProvider();
                    }
                    log.selectorProvider(provider);
                    final boolean defaultIsPoll = "sun.nio.ch.PollSelectorProvider".equals(provider.getClass().getName());
                    final String chosenMainSelector = System.getProperty("xnio.nio.selector.main");
                    final String chosenTempSelector = System.getProperty("xnio.nio.selector.temp");
                    final SelectorCreator defaultSelectorCreator = new DefaultSelectorCreator(provider);
                    final Object[] objects = new Object[3];
                    objects[0] = provider;
                    if (chosenTempSelector != null) try {
                        final ConstructorSelectorCreator creator = new ConstructorSelectorCreator(chosenTempSelector, provider);
                        IoUtils.safeClose(creator.open());
                        objects[1] = creator;
                    } catch (Exception e) {
                        // not available
                    }
                    if (chosenMainSelector != null) try {
                        final ConstructorSelectorCreator creator = new ConstructorSelectorCreator(chosenMainSelector, provider);
                        IoUtils.safeClose(creator.open());
                        objects[2] = creator;
                    } catch (Exception e) {
                        // not available
                    }
                    if (! defaultIsPoll && ! jdk9) {
                        // default is fine for main selectors; we should try to get poll for temp though
                        if (objects[1] == null) try {
                            SelectorProvider pollSelectorProvider = Class.forName("sun.nio.ch.PollSelectorProvider", true, NioXnio.class.getClassLoader()).asSubclass(SelectorProvider.class).getConstructor().newInstance();
                            pollSelectorProvider.openSelector().close();
                            objects[1] = new DefaultSelectorCreator(provider);
                        } catch (Exception e) {
                            // not available
                        }
                    }
                    if (objects[1] == null) {
                        objects[1] = defaultSelectorCreator;
                    }
                    if (objects[2] == null) {
                        objects[2] = defaultSelectorCreator;
                    }
                    return objects;
                }
            }
        );
        tempSelectorCreator = (SelectorCreator) objects[1];
        mainSelectorCreator = (SelectorCreator) objects[2];
        log.selectors(mainSelectorCreator, tempSelectorCreator);
        register(new XnioProviderMXBean() {
            public String getName() {
                return "nio";
            }

            public String getVersion() {
                return Version.getVersionString();
            }
        });
    }

    protected XnioWorker build(final XnioWorker.Builder builder) {
        final NioXnioWorker worker = new NioXnioWorker(builder);
        worker.start();
        return worker;
    }

    @Override
    public FileSystemWatcher createFileSystemWatcher(String name, OptionMap options) {
        try {
            boolean daemonThread = options.get(Options.THREAD_DAEMON, true);
            return new WatchServiceFileSystemWatcher(name, daemonThread);
        } catch (LinkageError e) {
            //ignore
        }
        return super.createFileSystemWatcher(name, options);
    }

    @Override
    protected void handleThreadExit() {
        log.tracef("Invoke selectorThreadLocal.remove() on Thread [%s] exits", Thread.currentThread().getName());
        selectorThreadLocal.remove();
        super.handleThreadExit();
    }

    private final ThreadLocal selectorThreadLocal = new ThreadLocal() {
        public void remove() {
            // if no selector was created, none will be closed
            FinalizableSelectorHolder holder = get();
            if(holder != null) {
                IoUtils.safeClose(holder.selector);
            }
            super.remove();
        }
    };

    Selector getSelector() throws IOException {
        final ThreadLocal threadLocal = selectorThreadLocal;
        FinalizableSelectorHolder holder = threadLocal.get();
        if (holder == null) {
            holder = new FinalizableSelectorHolder(tempSelectorCreator.open());
            threadLocal.set(holder);
        }
        return holder.selector;
    }

    private static class DefaultSelectorCreator implements SelectorCreator {
        private final SelectorProvider provider;

        private DefaultSelectorCreator(final SelectorProvider provider) {
            this.provider = provider;
        }

        public Selector open() throws IOException {
            return provider.openSelector();
        }

        public String toString() {
            return "Default system selector creator for provider " + provider.getClass();
        }
    }

    private static class ConstructorSelectorCreator implements SelectorCreator {

        private final Constructor constructor;
        private final SelectorProvider provider;

        public ConstructorSelectorCreator(final String name, final SelectorProvider provider) throws ClassNotFoundException, NoSuchMethodException {
            this.provider = provider;
            final Class selectorImplClass = Class.forName(name, true, null).asSubclass(Selector.class);
            final Constructor constructor = selectorImplClass.getDeclaredConstructor(SelectorProvider.class);
            constructor.setAccessible(true);
            this.constructor = constructor;
        }

        public Selector open() throws IOException {
            try {
                return constructor.newInstance(provider);
            } catch (InstantiationException e) {
                return Selector.open();
            } catch (IllegalAccessException e) {
                return Selector.open();
            } catch (InvocationTargetException e) {
                try {
                    throw e.getTargetException();
                } catch (IOException | Error | RuntimeException e2) {
                    throw e2;
                } catch (Throwable t) {
                    throw log.unexpectedSelectorOpenProblem(t);
                }
            }
        }

        public String toString() {
            return String.format("Selector creator %s for provider %s", constructor.getDeclaringClass(), provider.getClass());
        }
    }

    protected static Closeable register(XnioWorkerMXBean workerMXBean) {
        return Xnio.register(workerMXBean);
    }

    protected static Closeable register(XnioServerMXBean serverMXBean) {
        return Xnio.register(serverMXBean);
    }

    private static final class FinalizableSelectorHolder {
        final Selector selector;


        private FinalizableSelectorHolder(Selector selector) {
            this.selector = selector;
        }

        @Override
        protected void finalize() throws Throwable {
            IoUtils.safeClose(selector);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy