本文會介紹一些JVM記憶體結構的基本概念,然後非常快會講到持久代,來看下Java SE 8公布後它到底到哪去了。
基礎知識
JVM僅僅隻是是執行在你系統上的還有一個程序而已。這一切的魔法始于一個java指令。正如不論什麼一個作業系統程序那樣。JVM也須要記憶體來完畢它的執行時操作。記住——JVM本身是硬體的一層軟體抽象,在這之上才可以執行Java程式,也才有了我們所吹噓的平台獨立性以及WORA(一次編寫,處處執行)。
高速過一遍JVM的記憶體結構
正如虛拟機規範所說的那樣,JVM中的記憶體分為5個虛拟的區域。
- 堆
- 方法區(非堆)
- JVM棧
- 本地棧
- PC寄存器
- 你的Java程式中所配置設定的每個對象都須要存儲在記憶體裡。堆是這些執行個體化的對象所存儲的地方。是的——都怪new操作符。是它把你的Java堆都占滿了的!
- 它由全部線程共享
- 當堆耗盡的時候,JVM會抛出java.lang.OutOfMemoryError 異常
- 堆的大小能夠通過JVM選項-Xms和-Xmx來進行調整
堆被分為:
- Eden區 —— 新對象或者生命周期非常短的對象會存儲在這個區域中,這個區的大小能夠通過-XX:NewSize和-XX:MaxNewSize參數來調整。新生代GC(垃圾回收器)會清理這一區域。
- Survivor區 —— 那些曆經了Eden區的垃圾回收仍能存活下來的依然存在引用的對象會待在這個區域。這個區的大小能夠由JVM參數-XX:SurvivorRatio來進行調節。
- 老年代 —— 那些在曆經了Eden區和Survivor區的多次GC後仍然存活下來的對象(當然了。是拜那些揮之不去的引用所賜)會存儲在這個區裡。這個區會由一個特殊的垃圾回收器來負責。年老代中的對象的回收是由老年代的GC(major GC)來進行的。
方法區
- 也被稱為非堆區域(在HotSpot JVM的實作其中)
- 它被分為兩個基本的子區域
持久代 —— 這個區域會存儲包含類定義,結構,字段,方法(資料及代碼)以及常量在内的類相關資料。它能夠通過-XX:PermSize及-XX:MaxPermSize來進行調節。假設它的空間用完了,會導緻java.lang.OutOfMemoryError: PermGen space的異常。
代碼緩存——這個緩存區域是用來存儲編譯後的代碼。編譯後的代碼就是本地代碼(硬體相關的)。它是由JIT(Just In Time)編譯器生成的,這個編譯器是Oracle HotSpot JVM所特有的。
- 和Java類中的方法密切相關
- 它會存儲局部變量以及方法調用的中間結果及傳回值
- Java中的每一個線程都有自己專屬的棧,這個棧是别的線程無法訪問的。
- 能夠通過JVM選項-Xss來進行調整
- 用于本地方法(非Java代碼)
- 按線程配置設定
- 特定線程的程式計數器
- 包括JVM正在運作的指令的位址(假設是本地方法的話它的值則沒有定義)
好吧。這就是JVM記憶體分區的基礎知識了。如今再說說持久代這個話題吧。
那麼持久代上哪去了?
元空間 —— 高速入門
- 它是本地堆記憶體中的一部分
- 它能夠通過-XX:MetaspaceSize和-XX:MaxMetaspaceSize來進行調整
- 當到達XX:MetaspaceSize所指定的門檻值後會開始進行清理該區域
- 假設本地空間的記憶體用盡了會收到java.lang.OutOfMemoryError: Metadata space的錯誤資訊。
- 和持久代相關的JVM參數-XX:PermSize及-XX:MaxPermSize将會被忽略掉。