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.符號引用:

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

 

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM