JAVA類加載器實現了一部分 JRE加載JAVA CLASSES到 JVM 的功能。bootstrap
ClssLoader 實現了懶加載,而且使得JVM沒必要關心加載文件以及所使用的文件系統。數組
類加載器雖然只用於實現類的加載動做,但它在JAVA程序中所起到的做用遠遠不限於類加載階段。對於任意一個類,都須要有由加載它的類加載器和這個類自己一同確立其在JAVA虛擬機中的惟一性,每個類加載器,都擁有一個獨立的類名稱空間。這意味着惟一肯定一個JAVA的類須要確認
JavaClassloader + Java Class 相同。app
JVM啓動時,這三種加載器將被啓動:ui
1 Bootstrap class loaderthis
C++語言實現,是虛擬機自身一部分,其餘都是JAVA實現繼承java.lang.ClassLoader。負責加載code
雙親委派模型Parents Delegation Modelorm
雙親委派模型是經過Composition模式實現
對象
雙親委派模型的基本思路是,一個類加載器收到了類加載請求,本身不會加載,而是調用父類加載器去完成blog
sun.misc.Launcher中繼承關係以下
ClassLoader解釋以下
java.lang.ClassLoader
A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a 「class file」 of that name from a file system.…
ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine’s built-in class loader, called the 「bootstrap class loader」, does not itself have a parent but may serve as the parent of a ClassLoader instance.
Class loaders that support concurrent loading of classes are known as parallel capable class loaders and are required to register themselves at their class initialization time by invoking the registerAsParallelCapable() method. Note that the ClassLoader class is registered as parallel capable by default. However, its subclasses still need to register themselves if they are parallel capable.
In environments in which the delegation model is not strictly hierarchical, class loaders need to be parallel capable, otherwise class loading can lead to deadlocks because the loader lock is held for the duration of the class loading process (see loadClass methods).
Normally, the Java virtual machine loads classes from the local file system in a platform-dependent manner. For example, on UNIX systems, the virtual machine loads classes from the directory defined by the CLASSPATH environment variable.
However, some classes may not originate from a file; they may originate from other sources, such as the network, or they could be constructed by an application. The method defineClass converts an array of bytes into an instance of class Class. Instances of this newly defined class can be created using Class.newInstance.
基本能夠總結以下:
ClassLoader.loadClass 源碼以下
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 從父加載器中查詢類加載結果,避免重複加載 Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { //若父加載器不爲空 調用父節加載器進行加載 //若無父加載器 調用啓動類加載器加載 if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // 若果父加載器依然沒法加載 在調用自己findClass方法進行類加載 long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; }
一個類實例化是被其餘的類或方法進行調用,其實際的情況以下:
ClassLoader loader = new NetworkClassLoader(host, port); Object main = loader.loadClass("Main", true).newInstance();
類加載器在進行類加載以後,再對類進行實例化。
這時候有個疑問,咱們常常獲取的類的Class到底是什麼?根據源碼定義
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
咱們能夠知道:
一般咱們獲取ClassLoader是經過獲取
public ClassLoader getClassLoader() { ClassLoader cl = getClassLoader0(); if (cl == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); } return cl; }
getClassLoader0()是Jvm本地方法,其實是獲取當前類加載時的加載器。Class在運行初會加載本地方法集,這部分會在Jvm中實現。Class的構造方法是私有的,只能有JVM在實例化Class的時候進行調用,所以getClassLoader0()實際就是從JVM中獲取加載器相關信息。
private static native void registerNatives(); static { registerNatives(); } /* * Private constructor. Only the Java Virtual Machine creates Class objects. * This constructor is not used and prevents the default constructor being * generated. */ private Class(ClassLoader loader) { // Initialize final field for classLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; }