給我一個CPU,給我一塊記憶體,我來執行一段代碼。 我要如何分配呢? ![](https://img2023.cnblogs.com/blog/3256961/202308/3256961-20230824111951962-1088592200.jpg) ` ` `new User();` 這裡有一 ...
給我一個CPU,給我一塊記憶體,我來執行一段代碼。
我要如何分配呢?
new User();
這裡有一個有一個User類,如果我要new出來User對象,必須先知道它長什麼樣子,我先搞一塊區域出來,把User類的樣子給存下來。
可以把“User類的樣子” 比作造房子的“圖紙”或者“模板”;
這塊區域命名為方法區。
那方法區應該保存類的哪些信息呢?
我想一下,應該是只要程式運行時需要用到的類的數據都要保存下來吧。
比如,類型信息、方法信息,常量、靜態變數、即時編譯器編譯後的代碼緩存等數據。
既然這個區域要把所有的類的信息都記錄下來,每個線程都可能需要這些信息的,那就是要讓所有線程都能訪問的。
new User();
然後是要new一個新的User類對象,我先從方法區獲取User類信息,再新建這個對象,再直接在記憶體里存起來不就好了,但是如果我下次想要獲取這個對象,好像就沒辦法找到,因為只是分配了記憶體給這個新對象,卻沒有記錄這個實例對象的任何信息,所以沒辦法獲取到這個對象,這種方式行不通。
於是有了這種寫法
User user1 = new User();
這樣好像合理了很多,user1存儲了新建的User類對象的地址值,這樣我只要知道記住引用變數user1,就能知道我新建的User類對象了。
User user1 = new User();
=號前面的部分和=號後面的部分,這兩個部分的功能不一樣,最好給他們分類,放在不一樣的地方存放。
=號前面的部分放置區域叫虛擬機棧,具體是放在虛擬機棧的棧幀中。
每個方法被執行的時候,Java虛擬機都會同步創建一個棧幀用於存儲局部變數表、操作數棧、動態連接、方法出口等信息。每一個方法被調用直至執行完畢的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。
局部變數表:存放方法參數和方法內定義的局部變數
操作數棧:存放被操作數據的棧結構,1+2對應的操作數棧是1,2。
動態鏈接:動態鏈接的作用就是為了將這些符號引用轉換位調用方法的直接引用。
方法出口:正常完成出口,異常完成出口
為什麼前面要強調是虛擬機棧呢,因為還有個本地方法棧,java語言中有native修飾的本地方法,其調用的可能就是c,c++語言寫的方法,而不是java方法,因此才又分出來一個區域,但是他們的作用是非常相似的。
=號後面的部分放置區域叫堆,主要是用來放實例的數據的。
方法的是通過壓棧和彈棧的方式來執行的。
線程之間的執行是通過搶占CPU時間片資源的,因此線程之間會不斷的切換,還要劃分一塊區域出來專門存儲線程執行的進度,要不然下次切換回來都不知道要從哪個地方繼續了。
這塊區域叫PC寄存器,也可以叫程式計數器。
上圖紅色區域為線程共用的,其他為線程私有的。
下一個章節,會講解堆區的分配及原因和垃圾回收機制,可以點個關註!!!