《Understanding the JVM》讀書筆記之五——類加載器

一、JVM中類唯一性的確認
  對於任意一個類,都需要由加載它的類加載器和這個類本身來確定其在JVM中的唯一性。
即:只有在兩個類是由同一個類加載器加載時,才能比較兩個類是否相等。

  類相等包括:類的Class對象的equals()方法,isAssignableFrom()方法,isInstance()方法的返回結果,instanceof判定結果等。


二、兩種不同的類加載器:
  1. 啓動類加載器——C++實現,是JVM自身的一部分。
  2. 所有其他類加載器——Java實現,獨立於JVM存在,全都是抽象類java.lang.ClassLoader的子類。
虛擬機提供的3中類加載器:
    1. 啓動類加載器(Bootstrap ClassLoader):
      • 負責加載<JAVA_HOME>\lib目錄中的類或被參數-Xbootclasspath參數指定的路徑中的類(這些類一定要能被JVM識別)。
      • 在定義自己的類加載器時,如果需要把加載請求委託給啓動類加載器,直接用null代替即可。
    2. 擴展類加載器(Extension ClassLoader):
      • 負責加載<JAVA_HOME>\lib\ext目錄中的類或被java.ext.dirs系統變量所指定的路徑中的所有類庫。
    3. 應用程序類加載器(Application ClassLoader):
      • 負責加載用戶路徑(ClassPath)上所指定的類庫,如果程序中沒有自定義過自己的類加載器,默認爲應用程序類加載器
      • 這個類加載器是ClassLoader類中的getSystemClassLoader()方法的返回值,也稱爲“系統類加載器”。


三、雙親委派模型:

  
  這裏的類加載器之間的父子關係不通過繼承實現,而是使用組合關係來複用父加載器的代碼。
雙親委派模型的工作機制:
  • 一個類加載器收到了類的加載請求,會先把這個請求委託給父類加載器去完成,每一層的類加載器如此。
  • 所有的加載請求都會傳送到頂層的啓動類加載器,只有當父加載器無法完成這一請求時,子類加載器纔會嘗試自己去加載。
  **這種機制保證了Object類在程序的各種類加載器中都是同一個類,如果沒有雙親委派,用戶自己編寫一個java.lang.Object類,並放到ClassPath路徑中,那麼系統中會出現多個不同的Object類,Java體系則被破壞。


四、破壞雙親委派模型的方式:
  1. 重寫loadClass()方法
  2. 通過Thread類的setContextClassLoader()方法設置線程上下文類加載器
  3. OSGI技術
    • 雙親委派的具體邏輯都子啊loadClass()方法中實現,修改了loadClass()方法也就修改了雙親委派模型。
    • Thread Context Class Loader線程上下文類加載器,如果線程創建時未設置此加載器,則會在父線程中繼承一個,默認時應用程序類加載器。可以實現JavaAPI對用戶代碼的調用操作。
    • OSGI用於實現代碼的熱替換、模塊熱部署等操作,當收到類加載請求時,OSGI按如下順序進行搜索(只有前兩種情況符合雙親委派):
      a. 將java.*開頭的類委託給父類加載器加載;
      b. 將委派列表名單中的類委派給父類加載器加載;
      c. 將Import列表中的類委派給Export這個類的Bundle的類加載器加載;
      d. 查看當前Bundle的ClassPath,使用自己的類加載器加載;
      e. 查找類是否在自己的FragmengBundle中,如果在,委託給FragmentBundle的類加載器加載;
      f. 查找DynamicImport列表的Bundle,委派給對應的Bundle的類加載器加載
      g. 都不存在,則失敗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章