天天看點

JVM優化:java虛拟機的記憶體管理

作者:日拱一卒程式猿

一、JVM整體架構

根據 JVM 規範,JVM 記憶體共分為虛拟機棧、堆、方法區、程式計數器、本地方法棧五個部分。

JVM優化:java虛拟機的記憶體管理
JVM優化:java虛拟機的記憶體管理

JVM分為五大子產品: 類裝載器子系統 、 運作時資料區 、 執行引擎 、 本地方法接口 和 垃圾收集子產品 。

JVM優化:java虛拟機的記憶體管理

二、JVM運作時記憶體

Java 虛拟機有自動記憶體管理機制,如果出現面的問題,排查錯誤就必須要了解虛拟機是怎樣使用記憶體的。

JVM優化:java虛拟機的記憶體管理

Java7和Java8記憶體結構的不同主要展現在方法區的實作

方法區是java虛拟機規範中定義的一種概念上的區域,不同的廠商可以對虛拟機進行不同的實作。 我們通常使用的Java SE都是由Sun JDK和OpenJDK所提供,這也是應用最廣泛的版本。而該版本使用的VM就是 HotSpot VM。通常情況下,我們所講的java虛拟機指的就是HotSpot的版本。

JDK7 記憶體結構

JVM優化:java虛拟機的記憶體管理

JDK8 的記憶體結構

JVM優化:java虛拟機的記憶體管理

針對JDK8虛拟機記憶體詳解

JVM優化:java虛拟機的記憶體管理

JDK7和JDK8變化小結

JVM優化:java虛拟機的記憶體管理

對于Java8,HotSpots取消了永久代,那麼是不是就沒有方法區了呢?

當然不是,方法區隻是一個規範,隻不過它的實作變了。 在Java8中,元空間(Metaspace)登上舞台,方法區存在于元空間(Metaspace)。同時,元空間不再與堆連續,而且是 存在于本地記憶體(Native memory)。

方法區Java8之後的變化

  • 移除了永久代(PermGen),替換為元空間(Metaspace)
  • 永久代中的class metadata(類元資訊)轉移到了native memory(本地記憶體,而不是虛拟機)
  • 永久代中的interned Strings(字元串常量池) 和 class static variables(類靜态變量)轉移到了Java heap
  • 永久代參數(PermSize MaxPermSize)-> 元空間參數(MetaspaceSize MaxMetaspaceSize)

Java8為什麼要将永久代替換成Metaspace?

字元串存在永久代中,容易出現性能問題和記憶體溢出。 類及方法的資訊等比較難确定其大小,是以對于永久代的大小指定比較困難,太小容易出現永久代溢出,太 大則容易導緻老年代溢出。 永久代會為 GC 帶來不必要的複雜度,并且回收效率偏低。 Oracle 可能會将HotSpot 與 JRockit 合二為一,JRockit沒有所謂的永久代。