1. 程式人生 > >JVM記憶體的劃分及職能(各種變數所儲存得位置)

JVM記憶體的劃分及職能(各種變數所儲存得位置)

大佬的文章就是不一樣圖文並茂。
首先根據這篇文章入手瞭解。
這一次,徹底解決Java的值傳遞和引用傳遞
JVM記憶體的劃分及職能
Java語言本身是不能操作記憶體的,它的一切都是交給JVM來管理和控制的,因此Java記憶體區域的劃分也就是JVM的區域劃分,在說JVM的記憶體劃分之前,我們先來看一下Java程式的執行過程,如下圖:
在這裡插入圖片描述
有圖可以看出:Java程式碼被編譯器編譯成位元組碼之後,JVM開闢一片記憶體空間(也叫執行時資料區),通過類載入器加到到執行時資料區來儲存程式執行期間需要用到的資料和相關資訊,在這個資料區中,它由以下幾部分組成:
虛擬機器棧,堆 ,程式計數器,方法區,本地方法棧
在這裡插入圖片描述


我們接著來了解一下每部分的原理以及具體用來儲存程式執行過程中的哪些資料。

  1. 虛擬機器棧(棧區)
    棧是執行緒私有的,也就是執行緒之間的棧是隔離的(每一個執行緒都有一個虛擬機器站);當程式中某個執行緒開始執行一個方法時就會相應的建立一個棧幀並且入棧(位於棧頂),在方法結束後,棧幀出棧。每個方法在執行的同時都會建立一個棧幀(Stack Frame),每個棧幀分別對應一個被呼叫的方法,方法的呼叫過程對應棧幀在虛擬機器中入棧到出棧的過程。
    1.每個執行緒包含一個棧區,棧中只儲存基礎資料型別的物件和自定義物件的引用(不是物件),物件都存放在堆區中
    2.每個棧中的資料(原始型別和物件引用)都是私有的,其他棧不能訪問。
    3.棧分為3個部分:基本型別變數區、執行環境上下文、操作指令區(存放操作指令)。

每個棧幀中包括:
1.區域性變量表:用來儲存方法中的區域性變數(非靜態變數、函式形參)。當變數為基本資料型別時,直接儲存值,當變數為引用型別時(物件),儲存的是指向具體物件的引用(物件得地址而非正真的資料)。
2.運算元棧:Java虛擬機器的解釋執行引擎被稱為"基於棧的執行引擎",其中所指的棧就是指運算元棧。
3.指向執行時常量池的引用:儲存程式執行時可能用到常量的引用。
4.方法返回地址:儲存方法執行完成後的返回地址。

在這裡插入圖片描述

int age=50;
int weight=50;
int grade=6;

當我們寫“int age=50;”,其實是分為兩步的:

int age;
//定義變數 age=50;//賦值

在一個虛擬機器棧的棧偵裡:
在這裡插入圖片描述
首先JVM建立一個名為age的變數,存於區域性變量表中,然後去棧中查詢是否存在有字面量值為50的內容,如果有就直接把age指向這個地址,如果沒有,JVM會在棧中開闢一塊空間來儲存“50”這個內容,並且把age指向這個地址。因此我們可以知道:
我們宣告並初始化基本資料型別的區域性變數時,變數名以及字面量值都是儲存在棧中,而且是真實的內容。
我們再來看“int weight=50;”,按照剛才的思路:字面量為50的內容在棧中已經存在,因此weight是直接指向這個地址的。由此可見**:棧中的資料在當前執行緒下是共享的。**

基本資料型別的資料本身是不會改變的,當局部變數重新賦值時,並不是在記憶體中改變字面量內容,而是重新在棧中尋找已存在的相同的資料,若棧中不存在,則重新開闢記憶體存新資料,並且把要重新賦值的區域性變數的引用指向新資料所在地址。
在這裡插入圖片描述
我們看per的地址指向的是堆記憶體中的一塊區域,我們來還原一下程式碼:

public class Person{
private int age;
 private String name;
  private int grade;
//篇幅較長,省略setter getter方法
  static void run(){
    System.out.println("run...."); 
   };
}
//呼叫
Person per=new Person();

同樣是區域性變數的age、name、grade卻被儲存到了堆中為per物件開闢的一塊空間中。因此可知:基本資料型別的成員變數名和值都儲存於堆中,其生命週期和物件的是一致的。
2.方法區(又叫靜態區)
1.又叫靜態區,跟堆一樣,被所有的執行緒共享。方法區包含所有的class和static變數。
2.方法區中包含的都是在整個程式中永遠唯一的元素,如class,static變數。
儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料
3.堆區
1.儲存的全部是物件,每個物件都包含一個與之對應的class的資訊。(class的目的是得到操作指令)
2.jvm只有一個堆區(heap)被所有執行緒共享,堆中不存放基本型別和物件引用(物件地址),只存放物件本身

引用一下部落格
https://www.cnblogs.com/fengbs/p/7029013.html

https://mp.weixin.qq.com/s?__biz=MzU2MzY3ODI4OA==&mid=2247483796&idx=1&sn=c1885dc01707fc1f73dbcf08e8fb27f4&chksm=fc57dcabcb2055bd0c342eb1bbc265ae0e2cbf89cb9e1df85bf2afe0a643b8d46505e2fc8ac3&mpshare=1&scene=1&srcid=1031epRmyxssOs0gQOfQMTig#rd