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

jopen 10年前發布 | 25K 次閱讀 JVM Java開發

本文會介紹一些JVM內存結構的基本概念,然后很快會講到持久代,來看下Java SE 8發布后它究竟到哪去了。

基礎知識

JVM只不過是運行在你系統上的另一個進程而已,這一切的魔法始于一個java命令。正如任何一個操作系統進程那樣,JVM也需要內存來完成它的運 行時操作。記住——JVM本身是硬件的一層軟件抽象,在這之上才能夠運行Java程序,也才有了我們所吹噓的平臺獨立性以及WORA(一次編寫,處處運 行)。

快速過一遍JVM的內存結構

正如虛擬機規范所說的那樣,JVM中的內存分為5個虛擬的區域。

  • 方法區(非堆)
  • JVM棧
  • 本地棧
  • PC寄存器

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

  • 你的Java程序中所分配的每一個對象都需要存儲在內存里。堆是這些實例化的對象所存儲的地方。是的——都怪new操作符,是它把你的Java堆都占滿了的!
  • 它由所有線程共享
  • 當堆耗盡的時候,JVM會拋出java.lang.OutOfMemoryError 異常
  • 堆的大小可以通過JVM選項-Xms和-Xmx來進行調整

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

堆被分為:

  • 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,最好的資料莫過于它自己的虛擬機規范了!

原創文章轉載請注明出處:JVM的持久代——何去何從?

英文原文鏈接

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!