類別的載入
類別的載入指的是將類別的.class檔案中的二進位資料讀入到記憶體中,將其放在執行時資料區的方法區內,然後在堆區建立一個java .lang.Class對象,用來封裝類別在方法區內的資料結構。
載入.class檔案的方式:
1.從本機系統中直接載入
2.透過網路下載.class檔案
3.從檔案中載入等檔案中返回檔案中」.專有資料庫中提取.class檔案
5.將Java原始檔案動態編譯為.class檔案
類別的載入的最終產品是位於堆疊區域中的Class物件。
Class物件封裝了類別在方法區內的資料結構,並且向Java程式設計師提供了存取方法區內的資料結構的介面。
類加載器
加載器有兩種類型:
1.Java虛擬器自帶的加載器
擴充類別載入器(Extension)
系統類載入器或稱為應用程式載入器(System)
後兩種載入器是Java實作的,根類別載入器是C++寫的,程式設計師無法在Java程式碼中取得該類別。
2.用戶自定義的類加載器
java.lang.ClassLoader的子類
用戶可以定制類的加載方式
類加載器並不需要等到某個類被首次主動使用時再加載它。
JVM規範允許類別載入器在預料某個類別將要被使用時就預先載入它,如果在預先載入的過程中遇到了.class檔案缺失或存在錯誤,類別載入器必須在程式首次主動使用該類時才報告錯誤(LinkageError)。如果這個類別一直沒有被程式主動使用,那麼類別載入器就不會報告錯誤。
類的卸載機制
類的生命週期當Sample類別被載入、連接和初始化後,它的生命週期就開始了。
當代表Sample類別的Class物件不再被引用,也就是不可觸及時,Class物件就會結束生命週期,Sample類別在方法區內的資料也會被卸載,從而結束Sample類別的生命週期。
由此可見,一個類別何時結束生命週期,取決於代表它的Class物件何時結束生命週期。
引用關係
載入器與Class物件: 在類別載入器的內部實作中,用一個Java集合來存放所載入類別的參考。
另一方面,一個Class物件總是會引用它的類別載入器。呼叫Class物件的getClassLoader()方法,就能取得它的類別載入器。
由此可見,Class實例和載入它的載入器之間為雙向關聯關係。
類別、類別的Class物件、類別的實例物件:
一個類別的實例總是引用代表這個類別的Class物件。
在Object類別中定義了getClass()方法,這個方法傳回代表物件所屬類別的Class物件的參考。
此外,所有的Java類別都有一個靜態屬性class,它引用代表這個類別的Class物件。
類的卸載
由Java虛擬機自帶的類別載入器所載入的類別,在虛擬機的生命週期中,始終不會被卸載。 前面介紹過,Java虛擬機自帶的類別載入器包括根類別載入器、擴充類別載入器和系統類別載入器。
Java虛擬機本身會始終引用這些類別載入器,而這些類別載入器則會始終引用它們所載入的類別的Class對象,因此這些Class物件始終是可觸及的。
由使用者自訂的類別載入器載入的類別是可以被卸載的。
具體例子
loader1變數和obj變數間接應用代表Sample類別的Class對象,而objClass變數則直接引用它。如果程式運作過程中,將上圖左側三個參考變數都置為null,此時Sample物件結束生命週期,MyClassLoader物件結束生命週期,代表Sample類別的Class物件也結束生命週期,Sample類別在方法區內的二進位資料被卸載。
當再次有需要時,會檢查Sample類別的Class物件是否存在,如果存在會直接使用,不再重新載入;如果不存在Sample類別會被重新載入,在Java虛擬機器的堆疊區域會產生一個新的代表Sample類別的Class實例(可以透過雜湊碼查看是否是同一個實例)。
更多從JVM分析Java的類別的載入和卸載機制相關文章請關注PHP中文網!