Java虛擬機器在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域,
包含程式計數器、虛擬機器棧、本地方法棧、Java堆、方法區(執行時常量池)、直接記憶體等,不同的版本會有所差異
各區域的作用:
1、程式計數器:較小的記憶體空間,當前執行緒執行的位元組碼的行號指示器;各執行緒之間獨立儲存,互不影響;
2、虛擬機器棧:執行緒私有,生命週期和執行緒同生共死,每個方法在執行的同時都會建立一個棧幀用於儲存區域性變數表,運算元棧,動態連結,方法出口等資訊。方法的執行就對應著棧幀在虛擬機器棧中入棧和出棧的過程;
棧裡面存放著各種基本資料型別和物件的引用(-Xss) ;-Xss引數是用來調整JAVA虛擬機器棧的。一個執行緒呼叫多個方法,只會有一個棧。棧的預設大小為1M
3、本地方法棧:本地方法棧儲存的是native方法的資訊,當一個JVM建立的執行緒呼叫native方法後,JVM不再為其在虛擬機器棧中建立棧幀,JVM只是簡單地動態連結並直接呼叫native方法;
堆:
方法區(執行時常量池):也叫永久區(永久代),用於儲存已經被虛擬機器載入的類資訊,常量("zdy","123"等),靜態變數(static變數)等資料(-XX:PermSize;- XX:MaxPermSize;-XX:MetaspaceSize; - XX:MaxMetaspaceSize ),
在JDK7及之前用的是-XX:PermSize;-XX:MaxPermSize;在JDK8及之後用的是(後設資料空間)-XX:MetaspaceSize;-XX:MaxMetaspaceSize
JAVA堆:與我們操作最為緊密的區域,在程式碼中用new物件的時候,操作的就是該區域。幾乎是所有的物件都在堆上分配,與堆相關的命令是:(-Xms;-Xmx;-Xmn;-XX:NewSize;-XX:MaxNewSize)
-Xms;堆的最小值
-Xmx;堆的最大值
-Xmn;新生代的大小
-XX:NewSize;新生代的最小值
-XX:MaxNewSize;新生代的最大值
執行時常量池:嚴格來說是方法區的一部分,JDK8及之後執行時常量池放到了堆裡面。JDK8之後提出了後設資料空間的概念,這個方法區就消失了,方法區從執行時資料區挪到了虛擬機器本身管理之外,只受制於實體記憶體的大小,不再受制於虛擬機器的管理記憶體大小。同時執行時常量池也挪到了方法區。元空間不是直接記憶體,直接記憶體主要用於IO通訊。
不同JDK版本之間執行時資料區也是有所不同的。
如JDK6 的時候,常量池是放在方法區中的
在JDK7的時候,執行時常量池在對中
JDK8及之後執行時常量池放到了堆裡面
棧和堆對比分析 :
棧的特點:
1.以棧幀的方式儲存方法呼叫的過程,並儲存方法呼叫過程中基本資料型別的變數(int、short、long、byte、float、double、boolean、char等)以及物件的引用變數,
2.其記憶體分配在棧上,變數出了作用域就會自動釋放;
3.棧記憶體歸屬於單個執行緒,每個執行緒都會有一個棧記憶體,其儲存的變數只能在其所屬執行緒中可見,即棧記憶體可以理解成執行緒的私有記憶體。
棧的記憶體要遠遠小於堆記憶體,棧的深度是有限制的,可能發生StackOverFlowError問題
堆的特點:
1.堆記憶體用來儲存Java中的物件。無論是成員變數,區域性變數,還是類變數,它們指向的物件都儲存在堆記憶體中
2.堆記憶體中的物件對所有執行緒可見。堆記憶體中的物件可以被所有執行緒訪問