一.簡述
當我們看到myclass mc = new myclass()的時候,或者說當我們看到new這個關鍵字的時候,我們就知道,會有乙個myclass類的例項被建立出來,也知道myclass例項是經過jvm根據myclass類檔案建立的。但是我們有沒有想過乙個問題:jvm在遇到new這樣關鍵字的時候到底做了什麼?
你可能會說:在堆(heap)中開闢乙個記憶體空間用來儲存myclass物件,然後呼叫對應的構造方法初始化這個物件。
如果你掌握的更加深入一點,也許會說:
1.檢索構造器所在的類的符號引用,並利用這個符號引用找到位於方法區常量池中對應的類資訊;
2.如果沒有找到這個類資訊,則載入這個類;
3.在堆中開闢記憶體空間,然後將其分成三部分,物件頭+例項資料+對其填充;
4.再然後將除了物件頭之外的記憶體空間整體清零(想一想作用是什麼?保證物件的每個字段具有乙個初值);
5.之後寫入物件頭的資訊;
6.最後呼叫相應的構造方法。
回過頭來,我們看一看2號語句:「載入這個類」說得很模糊,只有在遇到new的時候載入麼?載入到哪?如何載入?(經典的when,where,how)。
二:何時jvm會載入乙個類?when?
jvm很規範,或者說很死板,當且僅當它遇到以下5中情況的時候,它才會執行類載入過程:
1.遇到new,getstatic,setstatic,invokestatic這四條指令碼的時候且相應的類沒有載入到常量池中,那麼開始載入過程。通俗的說:遇到新建物件,獲取/設定某各類的靜態變數,呼叫某各類的靜態方法的時候,會進行類載入工作。
2.通過反射呼叫乙個類的時候,進行類載入。這一條很簡單,不載入類,怎麼反射?
3.初始化乙個類的時候,如果類a的父類b還沒有載入,那麼會先載入類b,然後再載入類a。如果b是乙個介面,那麼會推遲b的載入,等到使用到b的介面方法的時候才會載入b。
4.對於主函式(main函式)所在的類先載入。
三.將類載入到**?where
虛擬機會將類資訊儲存到方法區中,包括類資訊,靜態變數,類的方法符號引用和一些字面量將會儲存到方法區的執行時常量池中。
四.如何載入類?how
1.class檔案是乙個二進位制檔案。jvm通過類的全限定名獲取這個類的二進位制位元組流;
2.將類的靜態儲存結構存入方法區中相應的位置。
類初始化過程:先將static變數宣告順序初始化,然後進行static塊的初始化。乙個類只會初始化一次。
3.為這個類生成乙個class物件,作為方法區中這個類的各種資料的訪問入口。
五. 一些補充:
1. 關於類載入器:
這時候我們就要介紹jvm中大名鼎鼎的雙親委派模型。
每個類的載入過程都是通過類載入器來進行載入的。jvm中類載入器分為三種,這三種類載入器分別負責載入不同的類。
1)啟動類載入器:
2)擴充套件類載入器:
3)應用程式類載入器:
java類載入機制
載入類時,每個類載入器總是首先將家在任務交給父類載入器,若父類載入器載入不到,自己才去載入 bootstrap loader時最頂級的載入器,其父載入器為null test test new test 11j class testclass test.getclass classloader cla...
Java類載入機制
解析階段是虛擬機器將常量池內的符號引用替換為直接引用的過程。符號引用 symbolic reference 符號引用以一組符號來描述所引用的目標,符號引用可以是任何形式的字面量,符號引用與虛擬機器實現的記憶體布局無關,引用的目標並不一定已經在記憶體中。直接引用 direct reference 直接...
Java類載入機制
在虛擬機器的生命週期中乙個類只被載入一次。類載入的原則 延遲載入,能少載入就少載入,因為虛擬機器的空間是有限的。類載入的時機 1 第一次建立物件要載入類.2 呼叫靜態方法時要載入類,訪問靜態屬性時會載入類。3 載入子類時必定會先載入父類。4 建立物件引用不載入類.5 子類呼叫父類的靜態方法時 1 當...