天天看點

java加載階段記憶體配置設定_Java核心:類加載和JVM記憶體的配置設定

類的加載:

指的是将class檔案的二進制資料讀入到運作時資料區(JVM在記憶體中劃分的)

中,并在方法區内建立一個class對象。

類加載器:

負責加載編譯後的class檔案(位元組碼檔案)到JVM(Java虛拟機)當中。

而類加載器主要分為以下幾種:

1.Bootstrap class loader (引導類加載器)

負責加載Java核心類庫。在jre\lib目錄下,包括rt.jar(Java基礎類庫),這些

都是Java的核心類庫。而且這個加載器是由C語言編寫的,是以在Java程式中是擷取

不到的。

2.Extension class loader(擴充類加載器)

負責加載Java平台下擴充功能的jar包,這些jar包在jre\lib\ext目錄下。這個加載

器由Java語言編寫的。

3.System class loader(系統類加載器)

負責加載classpath目錄下的所有類庫,classpath目錄下的class檔案一般

是我們自己寫的java檔案編譯後的。而這個加載器是由Java語言寫的。

這些類加載器協同起來完成整個類的加載過程,是以這些類的加載模式基于

”雙親委托模型“。

”雙親委托模型“:

程式運作後,編譯器把Java檔案編譯成class檔案後,首先負責加載的是

系統類加載器,但它不會馬上加載,而是将此任務移送給它的父類加載器擴充

類加載器加載,擴充類加載器也是将此任務移送給引導類加載器加載。

class檔案到了引導類加載器那,它先判斷能不能加載這個類,如果能,就

加載;不能,移送給其子加載器,以此類推。最終我們編寫的class都會配置在

classpath環境中,是以,這個類加載任務還是由系統類加載器完成。如果系統

類加載器都不能加載,就抛出ClassNotFoundException。

當一個class加載到JVM中,類加載階段已經完成。接下來JVM配置設定記憶體,對整個

class檔案(檔案裡面都是二進制的彙編指令)進行内容解析(JVM對二進制的命

令逐行解析,交由CPU執行)。

記憶體配置設定:

JVM運作起來時就給記憶體劃分空間,這塊空間就稱為運作時資料區。

運作時資料區被劃分為以下幾塊内容:

1.棧:

每一個線程運作起來的時候就會對應一個棧(線程棧),棧中存放的資料被目前

線程所獨享(不會産生資源共享情況,是以線程是安全的)。而棧當中存放的是棧幀,

當線程調用方法時,就是形成一個棧幀,并将這個棧幀進行壓棧操作。方法執行完後,

進行出棧操作。這個棧幀裡面包括(局部變量,操作數棧,指向目前方法對應類的常

量池引用,方法傳回位址等資訊)。

2.本地方法棧:

本地方法棧的機制和棧的相似,差別在于,棧運作的是Java實作的方法,而本地

方法棧運作的是本地方法。本地方法指的是JVM需要調用非Java語言所實作的方法,

例如C語言。在JVM規範中,沒有強化性要求實作方一定要劃分出本地方法棧(例如:

HotSpot虛拟機将本地方法棧和棧合二為一)和具體實作(不同的作業系統,對JVM

規範的具體實作都不一樣)。

3.程式計數器:

程式計數器也可以稱為PC寄存器(通俗講就是  指令緩存)。它主要用于緩存目前

程式下一條指令的指令位址,CPU根據這個位址找到将要執行的指令。這個寄存器是JVM

内部實作的,不是實體概念上的計數器,不過和JVM的實作邏輯一樣。

4.堆:

堆記憶體主要存放建立的對象和數組。堆記憶體在JVM中是唯一的,能被多個線程所共享。

堆裡面的每一個對象都存放着執行個體的執行個體變量。堆記憶體的對象沒有被引用,會自動被Java

垃圾回收機制回收。

當在方法中定義了局部變量,如果這個變量是基本資料類型,那麼這個變量的值就直接

存放在棧中;如果這個變量是引用資料類型,那麼變量值就存放在堆記憶體中,而棧中存放的是

指向堆中的引用位址。

5.方法區:

方法區在JVM也是一個非常重要的一塊記憶體區域,和堆一樣,可以被多個線程多共享。

主要存放每一個加載class的資訊。class資訊主要包含魔數(确定是否是一個class檔案),常量

池,通路标志(目前的類是普通類還是接口,是否是抽象類,是否被public修飾,是否使用了final

修飾等描述資訊......),字段表集合資訊(使用什麼通路修飾符,是執行個體變量還是靜态變量,是否

使用了final修飾等描述資訊.....),方法表集合資訊(使用什麼通路修飾符,是否靜态方法,是否

使用了final修飾,是否使用了synchronized修飾,是否是native方法......)等内容。當一個類加

載器加載了一個類的時候,會根據這個class檔案建立一個class對象,class對象就包含了上述的資訊。

後續要建立這個類的執行個體,都根據這個class對象建立出來的。

6.常量池:

常量池是方法區中的一部分,存放class對象中最重要的資源。JVM為每一個class對象都維護一個

常量池。它主要存儲兩種類型的常量:

1.字面常量:

字面常量通常就是在Java中定義的字面量值。例如:int = 1,中的 1,String s = "hello",這個

hello就是字面量。或者使用final修飾的常量值。

2.符号引用:

符号引用主要包括類和接口的完整類名,屬性的名稱和描述符,方法名和描述符等。

-----------------------------------------------------------