從圖一和圖二中能夠看出,圖二中變量槽是能夠重用的,變量a複用了placeholder的slot,致使placheholder的引用被刪除,內存被回收。
操做數棧:常稱爲操做棧是一個後入先出棧。其最大的棧深度也在編譯過程當中就肯定了並保存在Class文件的Code屬性中。應用場景:在方法進行參數傳遞的時候是經過操做數棧進行的。 在概念模型中,兩個棧幀做爲虛擬機棧的元素, 相互之間是徹底獨立的, 可是大多數虛擬機的實現裏都會作些優化處理,使得兩個棧幀出現一部分重疊。讓下棧幀的部分操做與上面棧幀的部分局部變量表重疊在一塊兒,這樣在進行方法調用返回時就能夠共用一分部數據,而無需進行額外的參數複製傳遞了。
動態鏈接:每一個棧幀都包含一個執行運行時常量池中該棧幀所屬方法的引用,持有這個引用是爲了支持方法調用過程當中的動態鏈接。Class文件中存放了大量的符號引用,字節碼中的方法調用執行就是以常量池中指向方法的符號引用做爲參數。這些符號引用一部分會在類加載階段或第一次使用時轉化爲直接引用,這種轉化稱爲靜態解析。另外一部分將在每一次運行期間轉化爲直接引用,這部分稱爲動態鏈接。
方法出口:方法出口分爲兩種, 一種收到返回命令,正常退出;第二種執行遇到異常致使方法退出。
虛擬機棧會出現兩種異常:StackOverflowError和OutOfMemoryError
1.3 本地方法棧
本地方法棧與虛擬機棧做用很是類似,其區別不過是虛擬機棧爲執行Java方法(字節碼)服務,而本地方法棧則是爲虛擬機使用到的Native方法服務。
Native方法:並不必定指Java中用native方法(如String.intern() :native方法),也包括其餘庫或者其餘語言中的方法如C、C++。
本地方法棧也會出現兩種異常:StackOverflowError和OutOfMemoryError
1.4 Java堆
Java堆是Java虛擬機所管理的內存中最大的一塊。是被全部線程共享的一塊內存區域,虛擬機啓動時建立。此內存區域的惟一目的就是存放對象實例。幾乎全部的對象實例都在這裏分配內存,但隨着jit編譯器的發展會有微妙的變化。
Java heap 是垃圾收集器管理的主要區域。在Java中,堆被劃分紅兩個不一樣的區域:新生代(Young)和老年代(Old)。新生代又被劃分爲三個區域:Eden空間、From Survivor空間、To Survivor空間。這樣劃分的目的是爲了更好地管理內存中的對象,包括內存的分配以及回收。堆的內存模型如圖(jdk1.6)
從圖中能夠看出:堆大小=新生代+老年代。其中堆大小能夠經過參數-Xms、-Xmx來設置。
Java 堆會有OutOfMemoryError異常
1.5 方法區
方法區與Java堆同樣,是各個線程共享的內存區域,可是存儲的內容不一樣。方法區用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯後的代碼等數據。別名Non-Heap. 另外方法區並非連續的,因此垃圾收集行爲在這個區域是不多出現的。
方法區還包括一部分:常量池。常量池是用於存放編譯器生成的各類字面量和符號引用,這部份內容將在類加載後存放到方法區的運行時常量池中。大小能夠經過-XX:PermSize和-XX:MaxPermSize設置。
方法區會有OutOfMemoryError異常
總結:
一、區分下java棧、java堆和方法區分別存儲內容:
public class Demo{
private String name ;
public Demo(String name){
this.name = name;
}
public static void main(String[] args){
Demo d = new Demo("test");
}
}
java堆 方法區 java棧
new Demo() Demo類信息 Demo d、局部變量name
Demo中的方法名 調用main方法主線程調用棧