本系列的第一篇文章,預計本系列最后面會有兩三個案例。
java與C、C++不一樣Java不需要Coder進行手動內存管理,而這一切都交給JVM進行自動內存管理,這從某種程度上來說也減輕了我們Coder不少的編碼量,而我們是否還有必要了解JVM的內存管理機制呢,答案是否定的;因為Java也會和C、C++一樣發生內存泄漏、內存溢出,盡管它發生這些事故會少很多,但一旦發生了而你又不了解他的內存管理機制這將是非常棘手的問題;還有個原因就是Java是運行在JVM上的,而不能JVM參數可能會影響到程序的執行性能,我們要想JVM在具體的應用中達到最優的性能那就必須了解JVM的內部機制;廢話不多說現在開始JVM探索系列之——內存管理
根據《Java虛擬機規范》所規定的,Java虛擬機執行Java程序時它他管理的內存劃分為幾個區域,也就是運行時數據區(Run-Time Data Areas);這些區域的功能、生命周期各不相同,主要分為兩大類:一種是隨著JVM進程的啟動而創建,隨JVM進程消亡而銷毀;一種是隨著線程的創建而創建,隨著線程的銷毀而銷毀,《Java虛擬機規范》規定的內存區域有如下圖:
紅色邊框的兩塊區域為所有線程共享的(JVM進程的啟動而創建、進程消亡而銷毀)
其他三塊區域為線程隔離的(線程的創建而創建,隨著線程的銷毀而銷毀)
如圖所示,運行時數據區(Run-time Areas)分為:方法區(Method Areas)、堆(Heap)、Java棧(Java Stacks)、本地方法棧(Native method stacks)、PC寄存器(Register)組成;
1、 PC寄存器(PC Register)
PC寄存器(PC Register),用戶存儲當前運行的指令(字節碼指令)地址,線程所私有的每個線程都有個獨立的寄存器;如正在執行的是Java方法則存字節碼指令地址,如是Native方法則值為空(undefined)。
2、 Java虛擬機棧(Java Virtual Machine Stacks)
Java虛擬機棧,線程獨有生命周期與線程一致;Java虛擬機棧用于存放棧幀,Java方法執行時會創建一個棧幀(Stack Frame)存儲局部變量表、操作數棧、動態鏈接、方法出口等信息,方法開始執行棧幀(Stack Frame)入Java虛擬機棧中,方法執行完成則出棧。(《Java虛擬機規范》規定Java虛擬機棧會拋出兩種異常:StackOverlowError與OutOfMemoryError,第一種為棧線程請求棧容量超過Java虛擬機允許的最大容量,第二種為無法分配到足夠的內存)。
3、 堆(Heap)
在java虛擬機中堆是所有線程鎖共享的,Java虛擬機啟動的時候創建,用于存放對象實例與數組內存分配,
4、 本地方法棧(Native Method stack)
用于執行Native方法,有些虛擬機把他與Java虛擬機棧合在一起,(如:HotSpot),拋出兩種異常:StackOverlowError與OutOfMemoryError。
5、 方法區(Method Areas)
方法區與Java堆一樣虛擬機啟動的時候創建,所有線程共享;存儲被虛擬機加載的類信息、運行時常量池、字段、方法數據即時編譯器編譯后的字節碼內容等,存儲的內容基本上來自class文件;不同的虛擬機實現方法區不一樣,在HotSpot虛擬機中可以把方法區稱為永生代,GC分代收集會對方法區進行回收。當方法區無法滿足內存分配時,Java虛擬機將拋出一個OutOfMemoryError異常。
5.1 運行時常量池(Runtime Constant Pool)
運行時常量池,方法區的一部分,類或接口常量池的運行時表現形式,存儲編譯后生成的字面量與符號引用(方法、字段的引用);可以在運行期間加入常量,String類的intern(),方法就是如此。無法申請到內存是拋出OutOfMemoryError異常。
介紹完JVM內存的各個區域后,我們來看一下下面的代碼:
public class Model {
PRivate static int i=1;
public Model() {
}
}
當我們實例化Model model=new Model()后,i將存儲到方法區(Method Aeras)的運行時常量池(Runtime Constant Pool)中,實例化后的model的引用(reference)將存儲到Java虛擬機棧本地變量表中,而new Model()對應的實例(實例數據)將存儲到Java堆(Java Heap)中,構造函數Model()也將存儲到方法區中。
個人博客同時更新站點:Http://www.solinx.co
新聞熱點
疑難解答