閱讀684 返回首頁    go 阿裏雲 go 技術社區[雲棲]


JVM的持久代——何去何從?

本文會介紹一些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所特有的。

JVM棧

  • 和Java類中的方法密切相關
  • 它會存儲局部變量以及方法調用的中間結果及返回值
  • Java中的每個線程都有自己專屬的棧,這個棧是別的線程無法訪問的。
  • 可以通過JVM選項-Xss來進行調整

本地棧

  • 用於本地方法(非Java代碼)
  • 按線程分配

PC寄存器

  • 特定線程的程序計數器
  • 包含JVM正在執行的指令的地址(如果是本地方法的話它的值則未定義)

好吧,這就是JVM內存分區的基礎知識了。現在再說說持久代這個話題吧。

那麼持久代上哪去了?

事實上,持久代已經被徹底刪除了,取代它的是另一個內存區域也被稱為元空間。

元空間 —— 快速入門

  • 它是本地堆內存中的一部分
  • 它可以通過-XX:MetaspaceSize和-XX:MaxMetaspaceSize來進行調整
  • 當到達XX:MetaspaceSize所指定的閾值後會開始進行清理該區域
  • 如果本地空間的內存用盡了會收到java.lang.OutOfMemoryError: Metadata space的錯誤信息。
  • 和持久代相關的JVM參數-XX:PermSize及-XX:MaxPermSize將會被忽略掉。

當然了,這隻是冰山一角。想要更深入地了解JVM,最好的資料莫過於它自己的虛擬機規範了!

本文最早發布於我的個人博客: Java譯站

最後更新:2017-05-23 16:02:56

  上一篇:go  科普丨【計算機視覺】OpenCV中直方圖處理函數簡述
  下一篇:go  【iFeve】並發網技術沙龍集錦(含視頻)