詳解JAVA類加載機制(引薦)。本站提示廣大學習愛好者:(詳解JAVA類加載機制(引薦))文章只能為提供參考,不一定能成為您想要的結果。以下是詳解JAVA類加載機制(引薦)正文
JAVA源碼編譯由三個進程組成:
1、源碼編譯機制。
2、類加載機制
3、類執行機制
我們這裡次要引見編譯和類加載這兩種機制。
一、源碼編譯
代碼編譯由JAVA源碼編譯器來完成。次要是將源碼編譯成字節碼文件(class文件)。字節碼文件格式次要分為兩局部:常量池和辦法字節碼。
二、類加載
類的生命周期是從被加載到虛擬機內存中開端,到卸載出內存完畢。進程共有七個階段,其中到初始化之前的都是屬於類加載的局部
加載----驗證----預備----解析-----初始化----運用-----卸載
零碎能夠在第一次運用某個類時加載該類,也能夠采用預加載機制來加載某個類,當運轉某個java順序時,會啟動一個java虛擬機進程,兩次運轉的java順序處於兩個不同的JVM進程中,兩個jvm之間並不會共享數據。
1、加載階段
這個流程中的加載是類加載機制中的一個階段,這兩個概念不要混雜,這個階段需求完成的事情有:
1)經過一個類的全限定名來獲取定義此類的二進制字節流。
2)將這個字節流所代表的靜態存儲構造轉化為辦法區的運轉時數據構造。
3)在java堆中生成一個代表這個類的Class對象,作為訪問辦法區中這些數據的入口。
由於第一點沒有指明從哪裡獲取以及怎樣獲取類的二進制字節流,所以這一塊區域留給我開發者很大的發揚空間。這個我在前面的類加載器中在停止引見。
2、預備階段
這個階段正式為類變量(被static修飾的變量)分配內存並設置類變量初始值,這個內存分配是發作在辦法區中。
1、留意這裡並沒有對實例變量停止內存分配,實例變量將會在對象實例化時隨著對象一同分配在JAVA堆中。
2、這裡設置的初始值,通常是指數據類型的零值。
private static int a = 3;
這個類變量a在預備階段後的值是0,將3賦值給變量a是發作在初始化階段。
3、初始化階段
初始化是類加載機制的最後一步,這個時分才正真開端執行類中定義的JAVA順序代碼。在後面預備階段,類變量曾經賦過一次零碎要求的初始值,在初始化階段最重要的事情就是對類變量停止初始化,關注的重點是父子類之間各類資源初始化的順序。
java類中對類變量指定初始值有兩種方式:1、聲明類變量時指定初始值;2、運用靜態初始化塊為類變量指定初始值。
初始化的機遇
1)創立類實例的時分,辨別有:1、運用new關鍵字創立實例;2、經過反射創立實例;3、經過反序列化方式創立實例。
new Test(); Class.forName(“com.mengdd.Test”);
2)調用某個類的類辦法(靜態辦法)
Test.doSomething();
3)訪問某個類或接口的類變量,或為該類變量賦值。
int b=Test.a; Test.a=b;
4)初始化某個類的子類。現在始化子類的時分,該子類的一切父類都會被初始化。
5)直接運用java.exe命令來運轉某個主類。
除了下面幾種方式會自動初始化一個類,其他訪問類的方式都稱不會觸發類的初始化,稱為主動援用。
1、子類援用父類的靜態變量,不會招致子類初始化。
public class SupClass { public static int a = 123; static { System.out.println("supclass init"); } } public class SubClass extends SupClass { static { System.out.println("subclass init"); } } public class Test { public static void main(String[] args) { System.out.println(SubClass.a); } }
執行後果:
supclass init
123
2、經過數組定義援用類,不會觸發此類的初始化
public class SupClass { public static int a = 123; static { System.out.println("supclass init"); } } public class Test { public static void main(String[] args) { SupClass[] spc = new SupClass[10]; } }
執行後果:
3、援用常量時,不會觸發該類的初始化
public class ConstClass { public static final String A= "MIGU"; static { System.out.println("ConstCLass init"); } } public class TestMain { public static void main(String[] args) { System.out.println(ConstClass.A); } }
執行後果:
MIGU
用final修飾某個類變量時,它的值在編譯時就曾經確定好放入常量池了,所以在訪問該類變量時,等於直接從常量池中獲取,並沒有初始化該類。
初始化的步驟
1、假如該類還沒有加載和銜接,則順序先加載該類並銜接。
2、假如該類的直接父類沒有加載,則先初始化其直接父類。
3、假如類中有初始化語句,則零碎順次執行這些初始化語句。
在第二個步驟中,假如直接父類又有直接父類,則零碎會再次反復這三個步驟來初始化這個父類,順次類推,JVM最先初始化的總是java.lang.Object類。當順序自動運用任何一個類時,零碎會保證該類以及一切的父類都會被初始化。
以上所述是給大家引見的JAVA類加載機制(引薦),希望對大家有所協助!