類生命週期、載入機制、雙親委派模型
類的生命週期:
載入、連線(包括驗證、準備、解析)、初始化、使用、解除安裝
載入:
1、將.class檔案的二進位制資料讀入記憶體中,並放入執行時資料區的方法區。
2、堆區建立一個java.lang.Class物件,用來封裝類在方法區內的的資料結構,並提供訪問方法區內資料結構的介面。
驗證:確保被載入類的正確性(檔案格式、元資料、位元組碼、符號引用等)
準備:為類的靜態變數分配記憶體並賦初始值(若靜態變數被final修飾,直接賦予程式碼中定義的值)
解析:將符號引用轉換為直接引用
初始化:為類的靜態變數賦正確的初始值,初始化步驟如下:
1、若該類未被載入和連線,則先載入並連線該類
2、若該類的直接父類未被初始化,則先初始化其直接父類
3、若類中有初始化語句,則系統一次執行這些初始化語句
初始化時機:new物件、呼叫靜態方法、反射、初始化該類的子類
類載入器:啟動類載入器、擴充套件類載入器、應用程式類載入器
父子載入器並不存在繼承關係,而是採用包裝的形式關聯。
JVM類載入機制:
1、全盤負責,當一個類載入器負責載入某個Class時,該Class所依賴的和引用的其他Class也將由該類載入器負責載入,除非顯示使用另外一個類載入器來載入
2、父類委託,先讓父類載入器試圖載入該類,只有在父類載入器無法載入該類時才嘗試從自己的類路徑中載入該類
3、快取機制,快取機制將會保證所有載入過的Class都會被快取,當程式中需要使用某個Class時,類載入器先從快取區尋找該Class,只有快取區不存在,系統才會讀取該類對應的二進位制資料,並將其轉換成Class物件,存入快取區。這就是為什麼修改了Class後,必須重啟JVM,程式的修改才會生效
類載入三種方式:
1、命令列啟動應用時,由JVM初始化載入
2、通過Class.forName()方法動態載入
3、通過ClassLoader.loadClass()方法動態載入
雙親委派模型:若一個類載入器收到了類載入的請求,它會將請求委託給父載入器,因此所有的類載入請求都會被傳遞到頂層的啟動類載入器中。只有當父載入器無法完成該載入時,子類才會嘗試自己去載入該類
雙親委派的意義:
1、避免同一jvm記憶體中出現重複的類位元組碼
2、保證java程式安全穩定執行
思考題:
能不能自己寫個類叫java.lang.System?
通常不可以,但可以採取另類方法達到這個需求。
由於類載入採用雙親委託模型,在載入該類時會將該載入請求一直傳遞到啟動類載入器中,由於在jvm啟動時,已經有了該類存在,不會再次進行載入。
若要達到載入目的,可以通過自定義一個載入器,繞過雙親委派,實現類載入。