終於有人把Java記憶體區域說清楚了!(不是記憶體模型,不要再混淆了)
不要再把Java記憶體區域和Java記憶體模型混淆,再問就自閉啦。?
小橙出品 必屬精品。先贊後看 養成習慣 。
上次我們講了JVM的
類載入
機制,主要涉及了
雙親委派機制
,
如何破壞雙親委派機制
,不明白的小夥伴可以移步上篇
。
網上有很多關於Java區域和記憶體模型的文章,但是很多人讀完之後還是搞不清楚,主要是因為大家把這兩個混為一談,也不關心JDK版本。所以概念一多,非常容易混淆。
所以下面將重點說明Java記憶體區域,主要涉及
執行時的幾大區域劃分
,
每個區域的職責
。而Java記憶體模型的文章可以參考我之前寫的
。
一、簡介
我們都知道作為計算機界的老大哥C語言,其是面向記憶體進行開發的。對於每個物件,我們都需要手動的建立,開闢記憶體,銷燬,如果不銷燬,他可能永遠刪除不了啦。
但是Java並不是這樣的,其有一整套虛擬機器自動記憶體管理機制,我們不需要手動的建立物件,開闢記憶體,乃至銷燬,不易發生記憶體溢位和洩露。這樣看上去是不是爽歪歪。
但是這也是頭疼的,對於其內部,我們是完全懵逼的狀態。一旦出現問題,完全不知道咋整。
所以我們接下來,就要學習Java記憶體到底是如何工作的,各部分如何劃分。
二、整體框架
首先我們JVM會載入類到記憶體中,所以 JVM 中必然會有一塊記憶體區域來存放我們寫的那些類。Java中有類物件、普通物件、本地變數、方法資訊等等各種物件資訊,所以JVM會對記憶體區域進行劃分:
三、方法區
方法區與堆一樣,也是執行緒共享的記憶體區域,主要用來存放類的資訊。
方法區只存在於JDK1.8以前的版本,主要是儲存從”.class“檔案里載入進來的類,包括類的名稱、方法資訊、欄位資訊、靜態變數、常量以及編譯器編譯後的程式碼等。其也被稱為“永久代”,但是這兩者並不等價,只是垃圾收集器的分代收集理論擴充套件到了方法區,使得垃圾收集器能夠像管理Java堆一樣管理記憶體,省去了專門為方法區編寫程式碼的工作。
注意:這只是對於HotSpot的虛擬機器有用,對於其他的虛擬機器,如IBM J9,是不存在永久代的概念的。
而且其有大小限制,我們可以設定-XX:MaxPermSize的大小來控制方法區的上限。但是其有利有弊。有利的是我們更容易把控程式啟動後所佔據的記憶體,有弊的是一旦超出了限制,就會出現java.lang.OutOfMemoryError: PermGen報錯。(此處可考面試題,線上調優經驗,注意注意。)
從JDK1.8開始,這塊區域的名字改成了後設資料區(Metaspace),後設資料區直接使用本地記憶體。比1.8之前的版本對比,其直接向記憶體申請,不會再出現之前記憶體不夠的情況啦。如果不夠,那就要加伺服器配置的事情啦。但也不能無限擴充套件,因此可以使用 -XX:MaxMetaspaceSize來控制最大記憶體。
舉個例子:
public
class
Test
{
public
static
void
main
(
String
[
] args
)
{
}
}
我們新建了一個Test類,裡面有個空的main方法,當通過類載入,其類相關的資訊就會被載入到方法區中,如下圖。
四、程式計數器
其是很小的一塊記憶體空間,可以看作是當前執行緒所執行的位元組碼的行號。因為Java虛擬機器的多執行緒時通過執行緒輪流切換,輪流得到處理器的資源來進行的,所以就需要線上程中有一個計數器來記錄執行到哪一行,方便切換回來,所以每個執行緒都需要一個獨立的程式計數器,他們相互獨立,互不影響。
白話解釋:
這個大冬天的,正躺著愉快刷劇,突然餓了,要去泡個泡麵吃吃,這時候是不是要暫停,先泡個面?等泡麵好了,再回來繼續看。那麼這邊的暫停就相等於程式計數器。
在上面例子的基礎,我們多加兩行程式碼:
public
class
Test
{
public
static
void
main
(
String
[
] args
)
{
//java學習交流:737251827 進入可領取學習資源及對十年開發經驗大佬提問,免費解答!
A a
=
new
A
(
)
;
a
.
load
(
)
;
}
}
當JVM載入類資訊到記憶體之後,實際就會使用自己的位元組碼執行引擎,去執行這些位元組碼指令, 程式計數器是執行緒私有的,也就是說每個執行緒都有個自己的程式計數器,記錄當前執行緒執行到了哪一條位元組碼指令。
五、Java虛擬機器棧
Java虛擬機器棧,其實是一種描述Java方法執行的資料結構。每個方法被執行的時候,都會建立一個棧幀(Stack Frame)用於儲存區域性變數表、操作棧、動作連結、方法出口等資訊。
每個方法從被呼叫到執行完成的過程,其實就是一個棧幀在虛擬機器棧中從入棧到出棧的過程。
比如main執行緒執行了main()方法,那麼就會建立一個棧幀(裡面存放a區域性變數),並將其壓入main執行緒自己的Java虛擬機器棧中,如下圖:
然後main執行緒繼續執行load方法,再執行A類中的方法,其如果有區域性變數,就會再建立一個棧幀,壓入自己的虛擬機器棧中,如下圖。
六、本地方法棧
本地方法棧,其作用和Java虛擬機器棧類似,區別在於本地方法棧是為虛擬機器所使用到的Native方法服務,而Java虛擬機器棧為虛擬機器執行Java方法(也就是位元組碼)服務。本地方法棧也是執行緒私有的。
JDK中的很多底層API,比如IO、NIO、網路等,如果大家去看它的原始碼,會發現很多地方是呼叫的native修飾的方法,如CAS,這塊先暫且擱下,後面併發說。
比如下面這樣:
public native int hashCode();
在呼叫native方法時,也會有執行緒對應的棧來儲存native方法底層用到的區域性變數表之類的資訊,這就是本地方法棧的作用。
七、Java堆
是資料管理中最大的一塊。所有執行緒共享的一塊記憶體內容,在虛擬機器啟動時就已經自動建立的。這一塊主要存放物件,也就是平時經常說的垃圾回收區域。
Java堆記憶體,這是JVM記憶體區域中最重要的一塊區域,存放著各種Java物件,是執行緒共享區域。
下面程式碼中,new A()建立了一個物件例項,這個物件例項的相關資訊就存放在Java堆記憶體中:
public
class
Test
{
public
static
void
main
(
String
[
] args
)
{
A a
=
new
A
(
)
;
a
.
load
(
)
;
}
}
main執行緒在執行main()方法時,會為其建立一個棧幀併入棧,棧幀中的區域性變數a存放著A物件例項在Java堆記憶體中的地址:
八、總結
該篇主要講了JVM的執行時記憶體區域,主要包括他們各自的劃分,每個部分具體儲存的是什麼,中間結合程式碼詳細說明了過程,希望能給大家一點幫助,不要再以為裡面是個黑匣子,一臉懵逼的狀態。(主要為了面試不懵逼,哈哈哈)
如果覺得寫得還行,麻煩給個贊?,您的認可才是我寫作的動力!
如果覺得有說的不對的地方,歡迎評論指出。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010294/viewspace-2846304/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 終於有人把Java記憶體模型說清楚了Java記憶體模型
- 【教程】終於有人把Java記憶體模型說清楚了!Java記憶體模型
- Java記憶體區域和記憶體模型Java記憶體模型
- Java記憶體區域(執行時資料區域)和記憶體模型(JMM)Java記憶體模型
- Java記憶體區域Java記憶體
- Java記憶體模型是什麼,為什麼要有Java記憶體模型,Java記憶體模型解決了什麼問題?Java記憶體模型
- C#:終於有人把 ValueTask、IValueTaskSource、ManualResetValueTaskSourceCore 說清楚了!C#
- Redis記憶體——記憶體消耗(記憶體都去哪了?)Redis記憶體
- 終於有人把MYSQL索引講清楚了MySql索引
- JAVA記憶體區域與記憶體溢位異常Java記憶體溢位
- 求你了,再問你Java記憶體模型的時候別再給我講堆疊方法區了…Java記憶體模型
- Java記憶體區域學習Java記憶體
- 終於有人把ERP和OA的區別講清楚了!
- Java記憶體模型Java記憶體模型
- Java 記憶體模型Java記憶體模型
- 千萬不要再這樣建立集合了!極容易記憶體洩露!記憶體洩露
- 再探JVM記憶體模型JVM記憶體模型
- Java的記憶體管理機制之記憶體區域劃分Java記憶體
- JVM(2)-Java記憶體區域與記憶體溢位異常JVMJava記憶體溢位
- JVM記憶體結構、Java記憶體模型和Java物件模型JVM記憶體Java模型物件
- JVM 記憶體區域JVM記憶體
- 【JVM記憶體區域】JVM記憶體
- Java記憶體模型FAQ(一) 什麼是記憶體模型Java記憶體模型
- Java的記憶體區域劃分Java記憶體
- Java記憶體區域與分配策略Java記憶體
- Java(6)-Java記憶體區域和作用Java記憶體
- 可能是把Java記憶體區域講的最清楚的一篇文章Java記憶體
- 你瞭解Java記憶體模型麼(Java7、8、9記憶體模型的區別)Java記憶體模型
- 探索Java記憶體模型Java記憶體模型
- 理解Java記憶體模型Java記憶體模型
- JMM Java 記憶體模型Java記憶體模型
- Java記憶體模型-(1)Java記憶體模型
- Java物件記憶體模型Java物件記憶體模型
- Java的記憶體模型Java記憶體模型
- Java記憶體區域與記憶體溢位異常 - 執行時資料區Java記憶體溢位
- JVM的記憶體區域JVM記憶體
- Java記憶體區域有哪些構成?Java記憶體
- 什麼是Java記憶體模型(JMM)中的主記憶體和本地記憶體?Java記憶體模型