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載入衝突。

參考文獻

外部連結

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.