加载文件流_jvm类加载的过程
下面來看一下類加載的過程,即加載、驗證、準備、解析、初始化5個階段都做了什么事:
階段1:加載
加載階段虛擬機主要3件事:通過類的全名獲取其二進制字節流;
將字節流代表的靜態結構轉化為方法區識別的運行時數據結構;
在內存中實例化這個類的java.lang.Class對象(不一定在堆內存中的,HotSpot就將Class對象放在了方法區里),程序訪問這個類在方法區中的類型數據時會通過這個類去訪問;
以上三點虛擬機并不要求如何實現,只是一個規范,比如第一步,通過類全名獲取其二進制流,動態代理技術是在運行時獲取、JSP應用是根據jsp文件獲取并生成對應的Class以及從ZIP包中獲取(JAR、EAR、WA同理)等
階段2:驗證
驗證階段大體上會完成4個階段的驗證(文件格式驗證、元數據驗證、字節碼驗證、符號引用驗證),以保證虛擬機中類的規范和安全。文件格式驗證,校驗字節流是否復合Class文件的格式:
驗證文件是否以魔數0xCAFEBABE(十六進制class文件中的前4個字節)開頭;
主、次版本號(十六進制class文件中的第5、第6個字節)能否被當前版本的虛擬機處理;
常量池中是否有不被支持的類型;
指向常量的索引中是否指向了不存在的常量;
Class文件中各個部分以及文件本身是否有被刪除或附加的其他信息;
……
元數據類型,校驗語義是否符合Java語言規范的要求:
驗證類是否有父類(除了java.lang.Object);
驗證父類是否繼承了不可被繼承的類;
如果不是抽象類,那么要判斷是否實現了父類或接口的所要求實現的所有方法;
……
字節碼驗證,校驗類的方法體,確定語義是否符合邏輯:
保證操作數棧中的數據類型與指令序列一致;
保證跳轉指令不會跳到方法體外的字節碼指令上;
保證方法體中的類型轉換有效;
……
階段3:準備
準備階段是為類變量分配內存并設置類變量初始值的階段這里所說的初始值并不是指代碼賦的值,而是數據類型的默認值,如public static int value = 123; 在準備階段過后,value會被置為0,而不是123。同時要注意,public static final int value = 123; 這種使用final修飾的變量,在準備階段就會被賦值為123,而不是初始值。
階段4:解析
解析階段會將常量池內的符號引用轉換為直接引用,關于符號引用和直接引用的解釋如下:符號引用:以一組符號來描述所引用的目,比如定義了在類IntF中定義了intValue = 123,接著讓Test.foo中的a變量指向Intf.intValue:
????????public?void?foo(){
????????????int?a?=?Intf.intValue;
????????}
????}
????class?Intf{
????????public?static?int?intValue?=?123;
????}
編譯代碼之后我們用javap -verbose Test來查看class文件中的內容:
???Constant?pool:???#1?=?Methodref??????????#4.#12?????????//?java/lang/Object."":()V
???#2?=?Fieldref???????????#13.#14????????//?Intf.intValue:I
???#3?=?Class??????????????#15????????????//?Test
???#4?=?Class??????????????#16????????????//?java/lang/Object
?//?省略部分代碼...
??public?void?foo();
????descriptor:?()V
????flags:?ACC_PUBLIC
????Code:
??????stack=1,?locals=2,?args_size=1
?????????0:?getstatic?????#2??????????????????//?Field?Intf.intValue:I
?????????3:?istore_1
?????????4:?return
??????LineNumberTable:
????????line?3:?0
????????line?4:?
可以看到常量池第2項是一個符號引用,指向了Intf.intValue
直接引用:就是我們常說的指針或者句柄,直接引用的目標一定會在虛擬機內存中存在。
階段5:初始化
初始化階段是類加載的最后一個階段,主要執行類的方法(不同與方法,方法是在顯式調用constructor時執行,而方法在初始化階段就會執行),()方法會執行賦值操作和執行靜態語句快中的內容,換句話說,如果代碼中沒有靜態語句塊和賦值操作,那么就可以沒有()方法。
這個階段虛擬機會保證父類的()方法會在子類的()方法前執行,而且在多線程環境中,虛擬機會保證()方法的同步。
總結
以上是生活随笔為你收集整理的加载文件流_jvm类加载的过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php七牛分片上传_七牛视频切片方案 -
- 下一篇: c++ 多重背包状态转移方程_Pytho