標籤:dfa obb 內容 set awd apn dnn eth bdd
運行時資料區域Java虛擬機器在執行Java程式的過程中會把它管理的記憶體劃分為若干個不同的資料區域。這些地區都有各自的用途,以及建立和銷毀的時間,有的地區隨著虛擬機器進程的啟動而存在, 有些地區則是依賴使用者線程的啟動和結束而建立和銷毀。1.1 程式計數器是一塊記憶體比較小的空間。作用:用來標誌當前線程所執行的位元組碼的行號指標(即在位元組碼中添加編號)。在jvm中,位元組碼解譯器工作時就是通過改變這個計數器上的值來選取下一條需要執行的位元組碼指令。在分支、迴圈、跳轉、異常處理、線程恢複等功能都需要依賴計數器去完成。在多線程中, 各條線程之間的計數器互不影響,隔離儲存區 (Isolated Storage)。不會存在OutOfMemoryError情況的地區。1.2 Java虛擬機器棧Java虛擬機器棧也是線程私人的, 生命週期與線程相同。虛擬機器棧描述的是Java方法執行的記憶體模型:每個方法被執行的時候都會建立一個棧幀用於儲存局部變數表、運算元棧、動態串連、方法出口等,並且每個方法被調用直至執行完成的過程就對應著一個棧幀在虛擬機器棧中從入棧到出棧的過程。先理解什麼是棧幀:是用於支援虛擬機器進行方法調用和方法執行的資料結構。棧幀是基於虛擬機器棧上的,一個虛擬機器棧儲存了多個棧幀,每個棧幀記錄Java方法中局部標量表、運算元棧等資訊同時也記錄該方法從入棧到出棧的過程。儲存結構在編譯器代碼的時候,棧幀中需要多大的局部變數表,多深的運算元棧都已經完全確定,並且寫入到方法表的Code屬性之中,因此一個棧幀需要分配多少記憶體,不會受到程式運行期變數資料的影響,而僅僅取決於具體的虛擬機器實現。局部變數表: 是一組變數值得儲存空間,用於存放方法參數、局部變數和對象參考型別。在編譯器代碼後就確定需要局部變數的最大容量。變數槽是局部變數表中的最小單位。一個solt可以存放(x32)boolean、byte、char、short、int、float、reference 和 returnAddress(執行位元組碼指令的地址);對於64位的long和double變數則需要分配兩個連續的slot空間。為了節省棧空間Slot是可以重用的。不過有時也會影響記憶體回收行為。圖一圖二從圖一和圖二中可以看出,圖二中變數槽是可以重用的,變數a複用了placeholder的slot,導致placheholder的引用被刪除,記憶體被回收。運算元棧:常稱為操作棧是一個後入先出棧。其最大的棧深度也在編譯過程中就確定了並儲存在Class檔案的Code屬性中。應用情境:在方法進行參數傳遞的時候是通過運算元棧進行的。 在概念性模型中,兩個棧幀作為虛擬機器棧的袁術, 相互之間是完全獨立的, 但是大多數虛擬機器的實現裡都會做些最佳化處理,使得兩個棧幀出現一部分重疊。讓下棧幀的部分操作與上面棧幀的部分局部變數表重疊在一起,這樣在進行方法調用返回時就可以共用一分部資料,而無需進行額外的參數複製傳遞了。動態串連:每個棧幀都包含一個執行運行時常量池中該棧幀所屬方法的引用,持有這個引用是為了支援方法調用過程中的動態串連。Class檔案中存放了大量的符號引用,位元組碼中的方法調用執行就是以常量池中指向方法的符號引用作為參數。這些符號引用一部分會在類載入階段或第一次使用時轉化為直接引用,這種轉化稱為靜態解析。另一部分將在每一次運行期間轉化為直接引用,這部分稱為動態串連。方法出口:方法出口分為兩種, 一種收到返回命令,正常退出;第二種執行遇到異常導致方法退出。 虛擬機器棧會出現兩種異常:StackOverflowError和OutOfMemoryError1.3 本地方法棧本地方法棧與虛擬機器棧作用非常相似,其區別不過是虛擬機器棧為執行Java方法(位元組碼)服務,而本地方法棧則是為虛擬機器使用到的Native方法服務。Native方法:並不一定指Java中用native方法(如String.intern() :native方法),也包括其他庫或者其他語言中的方法如C、C++。本地方法棧也會出現兩種異常:StackOverflowError和OutOfMemoryError1.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異常總結:1、區分下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方法主線程調用棧
Java運行時資料區域