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");
原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/11165336.html