天天看點

<html>

本文會介紹一些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将會被忽略掉。