zoukankan      html  css  js  c++  java
  • netty中的PlatformDependent

    通过类名就知道这是一个平台有关的类,通过对该类的学习可以帮助我们实现一个跨平台的应用。但是有些方法放的实现不是很好,比如:isWindows0。通过File的separator就可以判断出来。没必要那么复杂把。 目前平台的判断是推崇能力判断,这里也是通过这样来判断是否是android的,jdk的版本。这种思想最初好像是js来判断浏览器的版本。还有就是PlatformDependent是一个对外的接口,真正的实现为PlatformDependent0类,这是一个代理模式吗

    能力判断:

     Class.forName("android.app.Application", false, getSystemClassLoader());

    上面是判断平台是否为android.  该方法用来判断该类是否存在,false表示不实例化一个Class对象。

     反射作用:

    JDK中有很多的类的字段或者方法是私有的,通过反射我们就可以访问这些私有的属性和方法。下面是怎么创建一个UnSafe对象的代码

                    Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
                    unsafeField.setAccessible(true);
                    unsafe = (Unsafe) unsafeField.get(null);

    Unsafe.getUnsafe()不能直接访问

     Unsafe的使用

    在这个类中大量使用了unsafe的功能

    /*
     * Copyright 2012 The Netty Project
     *
     * The Netty Project licenses this file to you 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 io.netty.util.internal;
    
    import io.netty.util.CharsetUtil;
    import io.netty.util.internal.chmv8.ConcurrentHashMapV8;
    import io.netty.util.internal.logging.InternalLogger;
    import io.netty.util.internal.logging.InternalLoggerFactory;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.nio.ByteBuffer;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    import java.util.Queue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;
    import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
    import java.util.concurrent.atomic.AtomicLongFieldUpdater;
    import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    
    /**
     *
     * 用来检测运行时系统的属性的工具类,可以通过设置io.netty.noUnsafe属性禁止使用sun.misc.Unsafe对象
     * System.setProperty("io.netty.allocator.type","pooled");
     * System.setPropperty("io.netty.noUnsafe",false)
     * -XX:MaxDirectMemorySize
     *
     * 该类实现实现:class加载的时候获取系统的属性保存到statuc变量中,然后访问的时候直接返回这个变量
     */
    public final class PlatformDependent {
    
        private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent.class);
    
        private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile(
                "\s*-XX:MaxDirectMemorySize\s*=\s*([0-9]+)\s*([kKmMgG]?)\s*$");
    
        private static final boolean IS_ANDROID = isAndroid0();
        private static final boolean IS_WINDOWS = isWindows0();
        private static final boolean IS_ROOT = isRoot0();
    
        private static final int JAVA_VERSION = javaVersion0();
    
        /**
         * android不支持TCP_NODELAY这个TCP选项
         */
        private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid();
    
        private static final boolean HAS_UNSAFE = hasUnsafe0();
        private static final boolean CAN_USE_CHM_V8 = HAS_UNSAFE && JAVA_VERSION < 8;
        private static final boolean DIRECT_BUFFER_PREFERRED =
                HAS_UNSAFE && !SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false);
        private static final long MAX_DIRECT_MEMORY = maxDirectMemory0();
    
    
        /**
         * 字节数组的基本偏移
         * arrayBaseOffset方法是一个本地方法,可以获取数组第一个元素的偏移地址
         * 数组是个对象,数组存储了数据和一些对象信息
         */
        private static final long ARRAY_BASE_OFFSET = arrayBaseOffset0();
    
        private static final boolean HAS_JAVASSIST = hasJavassist0();
    
        private static final File TMPDIR = tmpdir0();
    
        private static final int BIT_MODE = bitMode0();
    
        private static final int ADDRESS_SIZE = addressSize0();
    
        static {
            if (logger.isDebugEnabled()) {
                logger.debug("-Dio.netty.noPreferDirect: {}", !DIRECT_BUFFER_PREFERRED);
            }
    
            if (!hasUnsafe() && !isAndroid()) {
                logger.info(
                        "Your platform does not provide complete low-level API for accessing direct buffers reliably. " +
                        "Unless explicitly requested, heap buffer will always be preferred to avoid potential system " +
                        "unstability.");
            }
        }
    
        /**
         * Returns {@code true} if and only if the current platform is Android
         */
        public static boolean isAndroid() {
            return IS_ANDROID;
        }
    
        /**
         * Return {@code true} if the JVM is running on Windows
         */
        public static boolean isWindows() {
            return IS_WINDOWS;
        }
    
        /**
         * Return {@code true} if the current user is root.  Note that this method returns
         * {@code false} if on Windows.
         */
        public static boolean isRoot() {
            return IS_ROOT;
        }
    
        /**
         * Return the version of Java under which this library is used.
         */
        public static int javaVersion() {
            return JAVA_VERSION;
        }
    
        /**
         * Returns {@code true} if and only if it is fine to enable TCP_NODELAY socket option by default.
         */
        public static boolean canEnableTcpNoDelayByDefault() {
            return CAN_ENABLE_TCP_NODELAY_BY_DEFAULT;
        }
    
        /**
         * 如果classpath下sun.misc.Unsafe可用,那么返回True,用来提高访问direct内存的性能
         * @return
         */
        public static boolean hasUnsafe() {
            return HAS_UNSAFE;
        }
    
        /**
         * Returns {@code true} if the platform has reliable low-level direct buffer access API and a user specified
         * {@code -Dio.netty.preferDirect} option.
         *
         * 如果用户定义了 -Dio.netty.preferDirect的参数同时可以通过api访问direct buffer
         */
        public static boolean directBufferPreferred() {
            return DIRECT_BUFFER_PREFERRED;
        }
    
        /**
         * Returns the maximum memory reserved for direct buffer allocation.
         */
        public static long maxDirectMemory() {
            return MAX_DIRECT_MEMORY;
        }
    
        /**
         * Returns {@code true} if and only if Javassist is available.
         */
        public static boolean hasJavassist() {
            return HAS_JAVASSIST;
        }
    
        /**
         * Returns the temporary directory.
         */
        public static File tmpdir() {
            return TMPDIR;
        }
    
        /**
         * Returns the bit mode of the current VM (usually 32 or 64.)
         */
        public static int bitMode() {
            return BIT_MODE;
        }
    
        /**
         * Return the address size of the OS.
         * 4 (for 32 bits systems ) and 8 (for 64 bits systems).
         */
        public static int addressSize() {
            return ADDRESS_SIZE;
        }
    
        public static long allocateMemory(long size) {
            return PlatformDependent0.allocateMemory(size);
        }
    
        public static void freeMemory(long address) {
            PlatformDependent0.freeMemory(address);
        }
    
        /**
         * Raises an exception bypassing compiler checks for checked exceptions.
         */
        public static void throwException(Throwable t) {
            if (hasUnsafe()) {
                PlatformDependent0.throwException(t);
            } else {
                PlatformDependent.<RuntimeException>throwException0(t);
            }
        }
    
        @SuppressWarnings("unchecked")
        private static <E extends Throwable> void throwException0(Throwable t) throws E {
            throw (E) t;
        }
    
        /**
         * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform.
         */
        public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap() {
            if (CAN_USE_CHM_V8) {
                return new ConcurrentHashMapV8<K, V>();
            } else {
                return new ConcurrentHashMap<K, V>();
            }
        }
    
        /**
         * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform.
         */
        public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(int initialCapacity) {
            if (CAN_USE_CHM_V8) {
                return new ConcurrentHashMapV8<K, V>(initialCapacity);
            } else {
                return new ConcurrentHashMap<K, V>(initialCapacity);
            }
        }
    
        /**
         * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform.
         */
        public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(int initialCapacity, float loadFactor) {
            if (CAN_USE_CHM_V8) {
                return new ConcurrentHashMapV8<K, V>(initialCapacity, loadFactor);
            } else {
                return new ConcurrentHashMap<K, V>(initialCapacity, loadFactor);
            }
        }
    
        /**
         * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform.
         */
        public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(
                int initialCapacity, float loadFactor, int concurrencyLevel) {
            if (CAN_USE_CHM_V8) {
                return new ConcurrentHashMapV8<K, V>(initialCapacity, loadFactor, concurrencyLevel);
            } else {
                return new ConcurrentHashMap<K, V>(initialCapacity, loadFactor, concurrencyLevel);
            }
        }
    
        /**
         * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform.
         */
        public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(Map<? extends K, ? extends V> map) {
            if (CAN_USE_CHM_V8) {
                return new ConcurrentHashMapV8<K, V>(map);
            } else {
                return new ConcurrentHashMap<K, V>(map);
            }
        }
    
        /**
         * Try to deallocate the specified direct {@link ByteBuffer}.  Please note this method does nothing if
         * the current platform does not support this operation or the specified buffer is not a direct buffer.
         */
        public static void freeDirectBuffer(ByteBuffer buffer) {
            if (hasUnsafe() && !isAndroid()) {
                // only direct to method if we are not running on android.
                // See https://github.com/netty/netty/issues/2604
                PlatformDependent0.freeDirectBuffer(buffer);
            }
        }
    
        public static long directBufferAddress(ByteBuffer buffer) {
            return PlatformDependent0.directBufferAddress(buffer);
        }
    
        public static Object getObject(Object object, long fieldOffset) {
            return PlatformDependent0.getObject(object, fieldOffset);
        }
    
        public static Object getObjectVolatile(Object object, long fieldOffset) {
            return PlatformDependent0.getObjectVolatile(object, fieldOffset);
        }
    
        public static int getInt(Object object, long fieldOffset) {
            return PlatformDependent0.getInt(object, fieldOffset);
        }
    
        public static long objectFieldOffset(Field field) {
            return PlatformDependent0.objectFieldOffset(field);
        }
    
        public static byte getByte(long address) {
            return PlatformDependent0.getByte(address);
        }
    
        public static short getShort(long address) {
            return PlatformDependent0.getShort(address);
        }
    
        public static int getInt(long address) {
            return PlatformDependent0.getInt(address);
        }
    
        public static long getLong(long address) {
            return PlatformDependent0.getLong(address);
        }
    
        public static void putOrderedObject(Object object, long address, Object value) {
            PlatformDependent0.putOrderedObject(object, address, value);
        }
    
        public static void putByte(long address, byte value) {
            PlatformDependent0.putByte(address, value);
        }
    
        public static void putShort(long address, short value) {
            PlatformDependent0.putShort(address, value);
        }
    
        public static void putInt(long address, int value) {
            PlatformDependent0.putInt(address, value);
        }
    
        public static void putLong(long address, long value) {
            PlatformDependent0.putLong(address, value);
        }
    
        public static void copyMemory(long srcAddr, long dstAddr, long length) {
            PlatformDependent0.copyMemory(srcAddr, dstAddr, length);
        }
    
        public static void copyMemory(byte[] src, int srcIndex, long dstAddr, long length) {
            PlatformDependent0.copyMemory(src, ARRAY_BASE_OFFSET + srcIndex, null, dstAddr, length);
        }
    
        public static void copyMemory(long srcAddr, byte[] dst, int dstIndex, long length) {
            PlatformDependent0.copyMemory(null, srcAddr, dst, ARRAY_BASE_OFFSET + dstIndex, length);
        }
    
        /**
         * Create a new optimized {@link AtomicReferenceFieldUpdater} or {@code null} if it
         * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned
         * use {@link AtomicReferenceFieldUpdater#newUpdater(Class, Class, String)} as fallback.
         */
        public static <U, W> AtomicReferenceFieldUpdater<U, W> newAtomicReferenceFieldUpdater(
                Class<U> tclass, String fieldName) {
            if (hasUnsafe()) {
                try {
                    return PlatformDependent0.newAtomicReferenceFieldUpdater(tclass, fieldName);
                } catch (Throwable ignore) {
                    // ignore
                }
            }
            return null;
        }
    
        /**
         * Create a new optimized {@link AtomicIntegerFieldUpdater} or {@code null} if it
         * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned
         * use {@link AtomicIntegerFieldUpdater#newUpdater(Class, String)} as fallback.
         */
        public static <T> AtomicIntegerFieldUpdater<T> newAtomicIntegerFieldUpdater(
                Class<?> tclass, String fieldName) {
            if (hasUnsafe()) {
                try {
                    return PlatformDependent0.newAtomicIntegerFieldUpdater(tclass, fieldName);
                } catch (Throwable ignore) {
                    // ignore
                }
            }
            return null;
        }
    
        /**
         * Create a new optimized {@link AtomicLongFieldUpdater} or {@code null} if it
         * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned
         * use {@link AtomicLongFieldUpdater#newUpdater(Class, String)} as fallback.
         */
        public static <T> AtomicLongFieldUpdater<T> newAtomicLongFieldUpdater(
                Class<?> tclass, String fieldName) {
            if (hasUnsafe()) {
                try {
                    return PlatformDependent0.newAtomicLongFieldUpdater(tclass, fieldName);
                } catch (Throwable ignore) {
                    // ignore
                }
            }
            return null;
        }
    
        /**
         * Create a new {@link Queue} which is safe to use for multiple producers (different threads) and a single
         * consumer (one thread!).
         */
        public static <T> Queue<T> newMpscQueue() {
            return new MpscLinkedQueue<T>();
        }
    
        /**
         * Return the {@link ClassLoader} for the given {@link Class}.
         */
        public static ClassLoader getClassLoader(final Class<?> clazz) {
            return PlatformDependent0.getClassLoader(clazz);
        }
    
        /**
         * Return the context {@link ClassLoader} for the current {@link Thread}.
         */
        public static ClassLoader getContextClassLoader() {
            return PlatformDependent0.getContextClassLoader();
        }
    
        /**
         * Return the system {@link ClassLoader}.
         */
        public static ClassLoader getSystemClassLoader() {
            return PlatformDependent0.getSystemClassLoader();
        }
    
        private static boolean isAndroid0() {
            boolean android;
            try {
                /**
                 * 下面只是判断android.app.Application是否存在,而不用实例化class对象
                 */
                Class.forName("android.app.Application", false, getSystemClassLoader());
                android = true;
            } catch (Exception e) {
                // Failed to load the class uniquely available in Android.
                android = false;
            }
    
            if (android) {
                logger.debug("Platform: Android");
            }
            return android;
        }
    
        private static boolean isWindows0() {
            boolean windows = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).contains("win");
            if (windows) {
                logger.debug("Platform: Windows");
            }
            return windows;
        }
    
        private static boolean isRoot0() {
            if (isWindows()) {
                return false;
            }
    
            String[] ID_COMMANDS = { "/usr/bin/id", "/bin/id", "id", "/usr/xpg4/bin/id"};
            Pattern UID_PATTERN = Pattern.compile("^(?:0|[1-9][0-9]*)$");
            for (String idCmd: ID_COMMANDS) {
                Process p = null;
                BufferedReader in = null;
                String uid = null;
                try {
                    p = Runtime.getRuntime().exec(new String[] { idCmd, "-u" });
                    in = new BufferedReader(new InputStreamReader(p.getInputStream(), CharsetUtil.US_ASCII));
                    uid = in.readLine();
                    in.close();
    
                    for (;;) {
                        try {
                            int exitCode = p.waitFor();
                            if (exitCode != 0) {
                                uid = null;
                            }
                            break;
                        } catch (InterruptedException e) {
                            // Ignore
                        }
                    }
                } catch (Exception e) {
                    // Failed to run the command.
                    uid = null;
                } finally {
                    if (in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            // Ignore
                        }
                    }
                    if (p != null) {
                        try {
                            p.destroy();
                        } catch (Exception e) {
                            // Android sometimes triggers an ErrnoException.
                        }
                    }
                }
    
                if (uid != null && UID_PATTERN.matcher(uid).matches()) {
                    logger.debug("UID: {}", uid);
                    return "0".equals(uid);
                }
            }
    
            logger.debug("Could not determine the current UID using /usr/bin/id; attempting to bind at privileged ports.");
    
            Pattern PERMISSION_DENIED = Pattern.compile(".*(?:denied|not.*permitted).*");
            for (int i = 1023; i > 0; i --) {
                ServerSocket ss = null;
                try {
                    ss = new ServerSocket();
                    ss.setReuseAddress(true);
                    ss.bind(new InetSocketAddress(i));
                    if (logger.isDebugEnabled()) {
                        logger.debug("UID: 0 (succeded to bind at port {})", i);
                    }
                    return true;
                } catch (Exception e) {
                    // Failed to bind.
                    // Check the error message so that we don't always need to bind 1023 times.
                    String message = e.getMessage();
                    if (message == null) {
                        message = "";
                    }
                    message = message.toLowerCase();
                    if (PERMISSION_DENIED.matcher(message).matches()) {
                        break;
                    }
                } finally {
                    if (ss != null) {
                        try {
                            ss.close();
                        } catch (Exception e) {
                            // Ignore.
                        }
                    }
                }
            }
    
            logger.debug("UID: non-root (failed to bind at any privileged ports)");
            return false;
        }
    
        /**
         * 通过Class.forName来检测JDK的版本6,7,8
         * @return
         */
        @SuppressWarnings("LoopStatementThatDoesntLoop")
        private static int javaVersion0() {
            int javaVersion;
    
            // Not really a loop
            for (;;) {
                // Android
                if (isAndroid()) {
                    javaVersion = 6;
                    break;
                }
    
                try {
                    Class.forName("java.time.Clock", false, getClassLoader(Object.class));
                    javaVersion = 8;
                    break;
                } catch (Exception e) {
                    // Ignore
                }
    
                try {
                    Class.forName("java.util.concurrent.LinkedTransferQueue", false, getClassLoader(BlockingQueue.class));
                    javaVersion = 7;
                    break;
                } catch (Exception e) {
                    // Ignore
                }
    
                javaVersion = 6;
                break;
            }
    
            if (logger.isDebugEnabled()) {
                logger.debug("Java version: {}", javaVersion);
            }
            return javaVersion;
        }
    
    
        /**
         * 是否可以使用sun.misc.Unsafe
         * @return
         */
        private static boolean hasUnsafe0() {
            boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
            logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe);
    
            if (isAndroid()) {
                logger.debug("sun.misc.Unsafe: unavailable (Android)");
                return false;
            }
    
            if (noUnsafe) {
                logger.debug("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)");
                return false;
            }
    
            // Legacy properties
            boolean tryUnsafe;
            if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) {
                tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true);
            } else {
                tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true);
            }
    
            if (!tryUnsafe) {
                logger.debug("sun.misc.Unsafe: unavailable (io.netty.tryUnsafe/org.jboss.netty.tryUnsafe)");
                return false;
            }
    
            try {
                boolean hasUnsafe = PlatformDependent0.hasUnsafe();
                logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable");
                return hasUnsafe;
            } catch (Throwable t) {
                // Probably failed to initialize PlatformDependent0.
                return false;
            }
        }
    
        private static long arrayBaseOffset0() {
            if (!hasUnsafe()) {
                return -1;
            }
    
            return PlatformDependent0.arrayBaseOffset();
        }
    
        /**
         * 可用的最大的director memory
         * @return
         */
        private static long maxDirectMemory0() {
            long maxDirectMemory = 0;
            try {
                // Try to get from sun.misc.VM.maxDirectMemory() which should be most accurate.
                Class<?> vmClass = Class.forName("sun.misc.VM", true, getSystemClassLoader());
                Method m = vmClass.getDeclaredMethod("maxDirectMemory");
                maxDirectMemory = ((Number) m.invoke(null)).longValue();
            } catch (Throwable t) {
                // Ignore
            }
    
            if (maxDirectMemory > 0) {
                return maxDirectMemory;
            }
    
            try {
                // Now try to get the JVM option (-XX:MaxDirectMemorySize) and parse it.
                // Note that we are using reflection because Android doesn't have these classes.
                Class<?> mgmtFactoryClass = Class.forName(
                        "java.lang.management.ManagementFactory", true, getSystemClassLoader());
                Class<?> runtimeClass = Class.forName(
                        "java.lang.management.RuntimeMXBean", true, getSystemClassLoader());
    
                Object runtime = mgmtFactoryClass.getDeclaredMethod("getRuntimeMXBean").invoke(null);
    
                @SuppressWarnings("unchecked")
                List<String> vmArgs = (List<String>) runtimeClass.getDeclaredMethod("getInputArguments").invoke(runtime);
                for (int i = vmArgs.size() - 1; i >= 0; i --) {
                    Matcher m = MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN.matcher(vmArgs.get(i));
                    if (!m.matches()) {
                        continue;
                    }
    
                    maxDirectMemory = Long.parseLong(m.group(1));
                    switch (m.group(2).charAt(0)) {
                        case 'k': case 'K':
                            maxDirectMemory *= 1024;
                            break;
                        case 'm': case 'M':
                            maxDirectMemory *= 1024 * 1024;
                            break;
                        case 'g': case 'G':
                            maxDirectMemory *= 1024 * 1024 * 1024;
                            break;
                    }
                    break;
                }
            } catch (Throwable t) {
                // Ignore
            }
    
            if (maxDirectMemory <= 0) {
                maxDirectMemory = Runtime.getRuntime().maxMemory();
                logger.debug("maxDirectMemory: {} bytes (maybe)", maxDirectMemory);
            } else {
                logger.debug("maxDirectMemory: {} bytes", maxDirectMemory);
            }
    
            return maxDirectMemory;
        }
    
        /**
         * javassist可以动态的生成类
         * @return
         */
        private static boolean hasJavassist0() {
            if (isAndroid()) {
                return false;
            }
    
            boolean noJavassist = SystemPropertyUtil.getBoolean("io.netty.noJavassist", false);
            logger.debug("-Dio.netty.noJavassist: {}", noJavassist);
    
            if (noJavassist) {
                logger.debug("Javassist: unavailable (io.netty.noJavassist)");
                return false;
            }
    
            try {
                JavassistTypeParameterMatcherGenerator.generate(Object.class, getClassLoader(PlatformDependent.class));
                logger.debug("Javassist: available");
                return true;
            } catch (Throwable t) {
                // Failed to generate a Javassist-based matcher.
                logger.debug("Javassist: unavailable");
                logger.debug(
                        "You don't have Javassist in your class path or you don't have enough permission " +
                        "to load dynamically generated classes.  Please check the configuration for better performance.");
                return false;
            }
        }
    
        /**
         * 通过io.netty.tmpdir 或者 java.io.tmpdir 配置netty的临时目录
         * @return
         */
        private static File tmpdir0() {
            File f;
            try {
                f = toDirectory(SystemPropertyUtil.get("io.netty.tmpdir"));
                if (f != null) {
                    logger.debug("-Dio.netty.tmpdir: {}", f);
                    return f;
                }
    
                f = toDirectory(SystemPropertyUtil.get("java.io.tmpdir"));
                if (f != null) {
                    logger.debug("-Dio.netty.tmpdir: {} (java.io.tmpdir)", f);
                    return f;
                }
    
                // This shouldn't happen, but just in case ..
                if (isWindows()) {
                    f = toDirectory(System.getenv("TEMP"));
                    if (f != null) {
                        logger.debug("-Dio.netty.tmpdir: {} (%TEMP%)", f);
                        return f;
                    }
    
                    String userprofile = System.getenv("USERPROFILE");
                    if (userprofile != null) {
                        f = toDirectory(userprofile + "\AppData\Local\Temp");
                        if (f != null) {
                            logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\AppData\Local\Temp)", f);
                            return f;
                        }
    
                        f = toDirectory(userprofile + "\Local Settings\Temp");
                        if (f != null) {
                            logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\Local Settings\Temp)", f);
                            return f;
                        }
                    }
                } else {
                    f = toDirectory(System.getenv("TMPDIR"));
                    if (f != null) {
                        logger.debug("-Dio.netty.tmpdir: {} ($TMPDIR)", f);
                        return f;
                    }
                }
            } catch (Exception ignored) {
                // Environment variable inaccessible
            }
    
            // Last resort.
            if (isWindows()) {
                f = new File("C:\Windows\Temp");
            } else {
                f = new File("/tmp");
            }
    
            logger.warn("Failed to get the temporary directory; falling back to: {}", f);
            return f;
        }
    
        @SuppressWarnings("ResultOfMethodCallIgnored")
        private static File toDirectory(String path) {
            if (path == null) {
                return null;
            }
    
            File f = new File(path);
            f.mkdirs();
    
            if (!f.isDirectory()) {
                return null;
            }
    
            try {
                return f.getAbsoluteFile();
            } catch (Exception ignored) {
                return f;
            }
        }
    
        /**
         * 获取操作系统是多少位的32 或者64
         * @return
         */
        private static int bitMode0() {
            // Check user-specified bit mode first.
            int bitMode = SystemPropertyUtil.getInt("io.netty.bitMode", 0);
            if (bitMode > 0) {
                logger.debug("-Dio.netty.bitMode: {}", bitMode);
                return bitMode;
            }
    
            // And then the vendor specific ones which is probably most reliable.
            bitMode = SystemPropertyUtil.getInt("sun.arch.data.model", 0);
            if (bitMode > 0) {
                logger.debug("-Dio.netty.bitMode: {} (sun.arch.data.model)", bitMode);
                return bitMode;
            }
            bitMode = SystemPropertyUtil.getInt("com.ibm.vm.bitmode", 0);
            if (bitMode > 0) {
                logger.debug("-Dio.netty.bitMode: {} (com.ibm.vm.bitmode)", bitMode);
                return bitMode;
            }
    
            // os.arch also gives us a good hint.
            String arch = SystemPropertyUtil.get("os.arch", "").toLowerCase(Locale.US).trim();
            if ("amd64".equals(arch) || "x86_64".equals(arch)) {
                bitMode = 64;
            } else if ("x86".equals(arch) || "i386".equals(arch) || "i486".equals(arch) || "i586".equals(arch) || "i686".equals(arch)) {
                bitMode = 32;
            }
    
            if (bitMode > 0) {
                logger.debug("-Dio.netty.bitMode: {} (os.arch: {})", bitMode, arch);
            }
    
            // Last resort: guess from VM name and then fall back to most common 64-bit mode.
            String vm = SystemPropertyUtil.get("java.vm.name", "").toLowerCase(Locale.US);
            Pattern BIT_PATTERN = Pattern.compile("([1-9][0-9]+)-?bit");
            Matcher m = BIT_PATTERN.matcher(vm);
            if (m.find()) {
                return Integer.parseInt(m.group(1));
            } else {
                return 64;
            }
        }
    
        private static int addressSize0() {
            if (!hasUnsafe()) {
                return -1;
            }
            return PlatformDependent0.addressSize();
        }
    
        private PlatformDependent() {
            // only static method supported
        }
    }
  • 相关阅读:
    Odoo13_多选下拉框
    Odoo13_联动下拉框
    Odoo13_上传文件并指定保存到位置
    Flask_cookie和session
    云原生设计理念
    docker 清理掉none对象,未使用网络,缓存等命令
    解决ssh连接中断问题
    python更改程序运行目录为程序所在文件夹
    Vuejs Cron 表达式校验
    Kubernetes WebSocket: Error during WebSocket handshake: Unexpected response code: 403
  • 原文地址:https://www.cnblogs.com/gaoxing/p/4288090.html
Copyright © 2011-2022 走看看