java8-ClassLoader

支持並行加載,經過對每一個類名放置不一樣的鎖來實現。java

static {
    ClassLoader.registerAsParallelCapable();
}

當且僅當父類也是能夠並行加載時纔會有此屬性。最終會落入到此方法,先登記一下。ide

 /**
         * 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會保存每個它加載過的類ui

// 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.this

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

若是沒有指定父類加載器,使用系統類加載器(加載classpath的類加載器)。spa

類加載過程:code

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.有父類加載器,調用父類加載器。blog

3.調用findClass方法去尋找類。若是resolve指定爲true,那麼,連接這個類。ssl

可是代碼有個這樣的代碼。ci

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");
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息