支持並行加載,經過對每一個類名放置不一樣的鎖來實現。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");