記憶體區域
程式計數器
這個就跟處理器中的程式計數器的功能差不多,是記錄下一條字節碼的位址
不過處理器的程式計數器是為進程服務的,jvm中的程式計數器是為執行緒服務的
所以jvm的程式計數器是執行緒私有的,宣告週期和執行緒相同,各執行緒之間的程式計數器互不干擾
因為是記錄下一位元組碼的位址,所以不對java中native方法服務,native方法會直接開啟一個進程,由cpu中的程式計數器來控制
程式計數器是jvm中唯一不會拋出OutOfmemoryError的區域
虛擬機棧
cpu中的堆疊的作用差不多,進入方法時,在棧中入棧一個棧幀,棧幀中記錄著局部變數表、操作數棧、動態連結、方法出口。當退出這個方法時,出棧當前棧幀
絕大多數對像生活的地方。自然也是垃圾收集器的重點照顧對象。
該區域負責儲存物件的實例,在這裡進行物件的記憶體空間的分配。因為絕大多數物件都生活在這裡,所以他是所有線程共享的區域。
堆也細分為新生代區域和老生代區域。新生代區域主要存活的是「朝生夕死」的對象,頻繁的出生,又頻繁的被消滅,這是被垃圾收集器集火的區域。老生代區域存活的需要穩定存活的對象,所以垃圾收集器比較少光顧這裡。
方法區
方法區記錄已載入類別的資訊。如全限定名(包名+類別名)、方法、欄位、描述符、參數、常數、靜態變數。此區域也被所有執行緒共享。
這個區域還有一個名稱-永生代,表示這個區域很少被清理。因為類別的可清理幅度很小,以及判斷一個類別是否是不再被需要的類別要求比較苛刻,所以垃圾收集器很少清理這個區域。
運行時常量池
這個區域記錄著編譯期產生的字面量和符號引用。同樣也是被所有執行緒共享的。
字面量
字面量包括是被雙引號""標明的字串,以及在程式碼中寫死的一些基本資料類型,這些都屬於常數。
在jdk1.6,運行時常量池是屬於方法區的一部分。發現一個常數,首先檢查運行時常量池中是否已經存放了這個常數,如果沒有存放,則複製一份到運行時常量池中。以後每一次試圖創建相同值的常數,都直接引用運行時常數池。
從jdk1.7開始,運行時常量池已經分割到了堆中。對於首次出現的常數,不再複製到執行時間常數池,而是在運行時常數池中保留一份引用,指向首次出現常數的記憶體位址。
直接記憶體
這個區域其實上不是jvm的一部分,而且屬於其他進程的。當呼叫一個native方法的時候,就可能會產生一份直接記憶體。
直接記憶體指的是native方法中使用的那一塊記憶體空間。例如NIO操作,它是使用native方法來讀寫檔案的,這時就會產生一份直接記憶體指向讀寫檔案的記憶體(快取)。
注意直接記憶體並不在jvm中,但是會在jvm堆中保持一個引用,指向記憶體空間的直接記憶體。這樣就避免了類似NIO操作頻繁的從記憶體空間和java堆中來回複製資料。