• java8-ClassLoader


    支持并行加载,通过对每个类名放置不同的锁来实现。

    static {
        ClassLoader.registerAsParallelCapable();
    }

    当且仅当父类也是可以并行加载时才会有此属性。最终会落入到此方法,先登记一下。

     /**
             * Registers the given class loader type as parallel capabale.
             * Returns {@code true} is successfully registered; {@code false} if
             * loader's super class is not registered.
             */
            static boolean register(Class<? extends ClassLoader> c) {
                synchronized (loaderTypes) {
                    if (loaderTypes.contains(c.getSuperclass())) {
                        // register the class loader as parallel capable
                        // if and only if all of its super classes are.
                        // Note: given current classloading sequence, if
                        // the immediate super class is parallel capable,
                        // all the super classes higher up must be too.
                        loaderTypes.add(c);
                        return true;
                    } else {
                        return false;
                    }
                }
            }

    ClassLoader会保存每一个它加载过的类

    // The classes loaded by this class loader. The only purpose of this table
        // is to keep the classes from being GC'ed until the loader is GC'ed.
        private final Vector<Class<?>> classes = new Vector<>();
    // Invoked by the VM to record every loaded class with this loader.
        void addClass(Class<?> c) {
            classes.addElement(c);
        }

    上面那个方法。由VM调用,然后把c加入到classes.

    protected ClassLoader() {
            this(checkCreateClassLoader(), getSystemClassLoader());
        }

    如果没有指定父类加载器,使用系统类加载器(加载classpath的类加载器)。

    类加载过程:

    1.Invoke findLoadedClass(String) to check if the class has already been loaded.
    2.Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
    3.Invoke the findClass(String) method to find the class.

    1.首先自己检查是否已经加载过

    2.有父类加载器,调用父类加载器。

    3.调用findClass方法去寻找类。如果resolve指定为true,那么,链接这个类。

    但是代码有个这样的代码。

    if (parent != null) 
    {
                            c = parent.loadClass(name, false);
                        
    }
     else 
    {
                            c = findBootstrapClassOrNull(name);
                       
    }

    如果父加载器是null,使用启动类加载器。以下,并行加载器原理

     protected Object getClassLoadingLock(String className) {
            Object lock = this;
            if (parallelLockMap != null) {
                Object newLock = new Object();
                lock = parallelLockMap.putIfAbsent(className, newLock);
                if (lock == null) {
                    lock = newLock;
                }
            }
            return lock;
        }

    如果以前注册过并行加载,返回lock不是this而已,这样在loadClass的synchronized的时候锁的对象不同.

    此类的findClass方法永远都抛出异常.实现者必须重写这个方法。

    protected Class<?> findClass(String name) throws ClassNotFoundException {
            throw new ClassNotFoundException(name);
        }

    findResource方法也应该重写了

    /**
         * Finds the resource with the given name. Class loader implementations
         * should override this method to specify where to find resources.
         *
         * @param  name
         *         The resource name
         *
         * @return  A <tt>URL</tt> object for reading the resource, or
         *          <tt>null</tt> if the resource could not be found
         *
         * @since  1.2
         */
        protected URL findResource(String name) {
            return null;
        }

    findLibrary方法用于寻找库

    /**
         * Returns the absolute path name of a native library.  The VM invokes this
         * method to locate the native libraries that belong to classes loaded with
         * this class loader. If this method returns <tt>null</tt>, the VM
         * searches the library along the path specified as the
         * "<tt>java.library.path</tt>" property.
         *
         * @param  libname
         *         The library name
         *
         * @return  The absolute path of the native library
         *
         * @see  System#loadLibrary(String)
         * @see  System#mapLibraryName(String)
         *
         * @since  1.2
         */
        protected String findLibrary(String libname) {
            return null;
        }

    返回本地库的绝对路径,VM调用此方法获取属于此ClassLoader的本地库,如果方法返回null,VM在 java.library.path 属性指定的路径中搜索本地库。

    usr_paths = initializePath("java.library.path");
    sys_paths = initializePath("sun.boot.library.path");
  • 相关阅读:
    Codeforces Round #578 (Div. 2) 训练总结及题解
    docker
    使用java遍历Map集合的方式
    SpringCloud集成rabbitmq:org.springframework.amqp.AmqpConnectException: java.net.ConnectException的解决办法
    创建新Docker容器时出现“The container name "/xxx" is already in use by container xxxxxxxxxxx...”问题的解决办法
    springBoot 项目中,使用定时任务报错
    java获取当前日期和前一周、前一月、前一年的日期
    用户行为PV&UV
    使用IDEA开发,多模块依赖中,找不到依赖: 程序包xxx.xxx.xxx不存在的问题
    Java获取本地IP地址和主机名
  • 原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/11165336.html
Copyright © 2020-2023  润新知