看到网上这么说:
双亲委派机制描述
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
首先将加载任务委托给父类加载器,依次递归 这句话的意思是所有类都是由Object类的记载器加载的吗?
大家讲道理2017-04-18 10:50:25
Java 虛擬機器的第一個類別載入器是 Bootstrap,這個載入器是嵌套在 Java 虛擬機器核心裡面,它是用 C++ 寫的二進位程式碼(不是字節碼)。
使用委託機制,會遞歸的向父類查找,也就是首選用 Bootstrap 嘗試加載,如果找不到再向下。防止記憶體中出現兩份類別的字節碼。
你誤解了類和類載入器。
當類別記載的時候,先用目前執行緒的類別載入器去載入執行緒中的第一個類,例如這個類別是 ClassA,類別載入器是 ClassLoaderA。
如果 ClassA 引用了 ClassB,則系統會使用 ClassLoaderA 去載入 ClassB。
現在有了 2 個類別(簡化版,其實不只 2 個類別)。
我們考慮一種情況,ClassX 和 ClassY 已經在內存中加載,他們都引用了 ClassZ,那麼 ClassZ 由誰加載呢?
很顯然按照上面描述的加載步驟會出現 2 份 ClassZ:ClassX 加載一次,ClassY 又加載一次。因為 ClassY 不知道 ClassX 已經載入過了。
如何解決這個問題呢,就是向父類遞歸查找。
具體步驟就是,先從 BootstrapClassLoader 查找,如果 BootstrapClassLoader 加載了這個類,就返回,如果 BootstrapClassLoader 沒有加載過這個類,則繼續查找,直到找到這個類。如果一直找到了本執行緒的類別載入器都沒有找到,表示這個類別還沒有加載,則使用目前執行緒的載入器載入。可以使用 getContextClassLoader()
來取得目前執行緒的類別載入器。
高洛峰2017-04-18 10:50:25
Java中有兩類類別載入器:系統類別載入器和使用者自訂類別載入器。
系統類別載入器都會有載入路徑的限定,例如Bootstrap Class Loader
在JDK1.6下,通过System.getProperty("sun.boot.class.path")
可以得到類別載入路徑
JAVA_HOME\jre6\lib\resources.jar;
JAVA_HOME\Java\jre6\lib\rt.jar;
JAVA_HOME\jre6\lib\sunrsasign.jar;
JAVA_HOME\jre6\lib\jsse.jar;JAVA_HOME\jre6\lib\jce.jar;
JAVA_HOME\jre6\lib\charsets.jar;
JAVA_HOME\jre6\lib\modules\jdk.boot.jar;
JAVA_HOME\jre6\classes
這些路徑下的class是由Bootstrap
负责,其它路径下的class的递归到Bootstrap
下也是找不到class文件,就會由下一級類別載入器去對應的路徑去載入。