跳至內容

Java類加載器

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

Java類加載器(英語:Java Classloader)是Java運行時環境(Java Runtime Environment)的一個部件,負責動態加載Java類Java虛擬機的內存空間中。[1]類通常是按需加載,即第一次使用該類時才加載。由於有了類加載器,Java運行時系統不需要知道文件與文件系統。對學習類加載器而言,掌握Java的委派概念是很重要的。

每個Java類必須由某個類加載器裝入到內存。[2]Java程序可以通過類加載器來利用外部庫(即由其他作者編寫的軟件庫)。

JVM中有3個默認的類加載器:[3][4]

  1. 引導(Bootstrap)類加載器。由原生代碼(如C語言)編寫,不繼承自java.lang.ClassLoader。負責加載核心Java庫[5],存儲在<JAVA_HOME>/jre/lib目錄中。
  2. 擴展(Extensions)類加載器。用來在<JAVA_HOME>/jre/lib/ext,[6]java.ext.dirs中指明的目錄中加載 Java的擴展庫。Java 虛擬機的實現會提供一個擴展庫目錄。該類加載器在此目錄裡面查找並加載 Java 類。該類由sun.misc.Launcher$ExtClassLoader實現。
  3. Apps類加載器(也稱系統類加載器)。根據 Java應用程序的類路徑(java.class.path或CLASSPATH環境變量)來加載 Java 類。一般來說,Java 應用的類都是由它來完成加載的。可以通過 ClassLoader.getSystemClassLoader()來獲取它。該類由sun.misc.Launcher$AppClassLoader實現。

每個類裝載器通過組合的方式包含一個父裝載器(parent class loader)。

JDK 1.2之後引入「雙親委派」方式來實現類加載器的層次調用,以儘可能保證JDK的系統API不會被用戶定義的類加載器所破壞,但一些使用場景會打破這個慣例來實現必要的功能。

自定義類加載器

開發可以通過繼承java.lang.ClassLoader類的方式實現自己的類加載器,以滿足一些特殊的需求而不需要完全了解Java虛擬機的類加載的細節。

可用於:

  • 運行時裝載或卸載類。這常用於:
  • 改變Java字節碼的裝入,例如:可用於Java類字節碼的加密裝入。[7]
  • 修改已裝入的字節碼(面向切面編程中用於織入切面代碼)。

JEE的類裝載

Java EE (JEE)應用程序服務器典型地用樹狀的一組類裝載器從已部署的WAR或EAR文檔中裝入類。這使得應用程序之間彼此隔離,但共享已部署模塊。servlet container一般被實現為多個類裝載器。[2][8]

JAR地獄

和DLL地獄一樣,一個組件的特定JAR也存在版本差異,不同版本間的JAR文件的Class文件存在差異(包括Class文件的編譯版本、Class的成員結構、Class繼承關係等)的話,也會在運行時觸發各種因為類文件結果衝突而導致的錯誤警告。對於Servlet容器,還存在容器所需的JAR與應用內所需的JAR雙線衝突的問題。

不同於DLL地獄,Java開發者會使用一些項目管理程序(例如Apache Maven)來解決JAR版本之間的衝突,通過配置依賴關係文件,設定不同組件的JAR版本依賴關係,由項目管理程序自動加載相應合適的JAR,來控制JAR間 的版本關係。而對於Servlet容器,也會通過自己實現類加載器打破JDK的「雙親委派」方式來避免JAR加載衝突。

參考文獻

  1. ^ Mcmanis, Chuck. The basics of Java class loaders. JavaWorld. 1996-10-01 [2008-01-26]. (原始內容存檔於2008-01-20). 
  2. ^ 2.0 2.1 Christudas, Binildas. Internals of Java Class Loading. onjava.com. 2005-01-26 [2009-10-02]. (原始內容存檔於2018-05-10). 
  3. ^ Understanding Extension Class Loading. java.sun.com. 2008-02-14 [2009-12-08]. (原始內容存檔於2009-08-03). 
  4. ^ Sosnoski, Dennis. Classes and class loading. ibm.com. 2003-04-29 [2008-01-26]. (原始內容存檔於2021-01-08). 
  5. ^ 存儲在Jar文件中,如rt.jar, core.jar, server.jar等。
  6. ^ 存档副本. [2014-05-14]. (原始內容存檔於2020-10-24). 
  7. ^ Roubtsov, Vladimir. Cracking Java byte-code encryption. javaworld.com. 2003-05-09 [2008-01-26]. (原始內容存檔於2008-05-02). 
  8. ^ deBoer, Tim; Karasiuk, Gary. J2EE Class Loading Demystified. ibm.com. 2002-08-21 [2008-01-26]. (原始內容存檔於2008-12-11). 

外部連結