1. 程式人生 > >深入理解java虛擬機器(一)java的記憶體區域

深入理解java虛擬機器(一)java的記憶體區域

123

程式計數器可以看作當前執行緒所執行的位元組碼的行號指示器,位元組碼直譯器工作時就是通過改變這個計數器的值來選取下一條 需要執行的位元組碼指令,分支、迴圈、跳轉、異常處理、執行緒恢復等基礎功能都需要依賴這個計數器來實現。每一個執行緒都有一個獨立的程式計數器,各個執行緒之間的計數器互不影響,獨立儲存,我們把這類記憶體區域稱為“執行緒私有”的記憶體。

java虛擬機器棧:與程式計數器一樣,也是執行緒私有的,生命週期與執行緒相同。虛擬機器棧描述的是java方法執行的記憶體模型。棧中儲存的是一個個棧幀,每個棧幀對應一個被呼叫的方法,棧幀之中儲存著區域性變量表、運算元棧、動態連結串列、方法出口等。

呼叫一個方法,即對應一個棧幀入棧,方法呼叫完成,則該方法對應的棧幀出棧。

區域性變量表存放著各種基本資料型別、物件、引用等。

運算元棧,想必學過資料結構中的棧的朋友想必對錶達式求值問題不會陌生,棧最典型的一個應用就是用來對錶達式求值。想想一個執行緒執行方法的過程中,實際上就是不斷執行語句的過程,而歸根到底就是進行計算的過程。因此可以這麼說,程式中的所有計算過程都是在藉助於運算元棧來完成的。

指向執行時常量池的引用,因為在方法執行的過程中有可能需要用到類中的常量,所以必須要有一個引用指向執行時常量。

方法返回地址,當一個方法執行完畢之後,要返回之前呼叫它的地方,因此在棧幀中必須儲存一個方法返回地址。

由於每個執行緒正在執行的方法可能不同,因此每個執行緒都會有一個自己的Java棧,互不干擾。

java堆:java堆是java虛擬機器管理的記憶體中最大的一塊,是被所有執行緒共享的一塊記憶體區域,在虛擬機器啟動時建立。該記憶體區域唯一的 目的就是存放物件例項。所有的物件例項以及陣列都要在堆上分配。java堆是垃圾收集管理的主要區域,所以也被叫做GC堆。java可以分為新生代和老年代。java堆可以處於物理不連續的記憶體空間中。

方法區:用來儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。這裡可以看到常量也會在方法區中,是因為方法區中有一個執行時常量池,為什麼叫執行時常量池,因為在編譯後期生成的是各種字面量(字面量的意思就是值,比如int i=3,這個3就是字面量的意思)和符號引用,這些是存放在一個叫做常量池(這個常量池是在位元組碼檔案中)的地方,當類載入進入方法區時,就會把該常量池中的內容放入執行時常量池中。

物件的建立:

建立物件,在堆中開闢記憶體時是如何分配記憶體的?

       兩種方式:指標碰撞和空閒列表。我們具體使用的哪一種,就要看我們虛擬機器中使用的是什麼了。

       指標碰撞:假設Java堆中記憶體是絕對規整的,所有用過的記憶體度放一邊,空閒的記憶體放另一邊,中間放著一個指標作為分界點的指示器,所分配記憶體就僅僅是把哪個指標向空閒空間那邊挪動一段與物件大小相等的舉例,這種分配方案就叫指標碰撞

       空閒列表:有一個列表,其中記錄中哪些記憶體塊有用,在分配的時候從列表中找到一塊足夠大的空間劃分給物件例項,然後更新列表中的記錄。這就叫做空閒列表

參考部落格:https://www.cnblogs.com/whgk/p/6138522.html