對比JDK1.7,JDK1.8在運行時的記憶體分配上進行了調整。本篇對JDK1.8版本進行簡要介紹。 先以一張圖片描述運行時記憶體: 程式計數器 記錄當前線程執行的位元組碼行號。如果執行的是native方法,值為null。 虛擬機棧 每一個線程執行時,都對應有一個虛擬機棧,生命周期與線程相同。一個虛擬機棧 ...
對比JDK1.7,JDK1.8在運行時的記憶體分配上進行了調整。本篇對JDK1.8版本進行簡要介紹。
先以一張圖片描述運行時記憶體:
程式計數器
記錄當前線程執行的位元組碼行號。如果執行的是native方法,值為null。
虛擬機棧
每一個線程執行時,都對應有一個虛擬機棧,生命周期與線程相同。一個虛擬機棧有一個一個的棧幀組成,每個java方法被調用時都會創建一個棧幀,然後入棧,方法結束後出棧。一個棧幀由局部變數表,操作數棧,動態鏈接和方法出口信息組成。
如果方法中出現遞歸調用死迴圈,或者棧幀大小超過虛擬機棧限制都會拋出StackOverflowError;
本地方法棧
功能與虛擬機棧差不多,只不過本地方法棧是虛擬機在調用native方法時使用。
堆
堆是JVM占用比例最大的一塊區域,用來存放對象實例。現代JVM大多將堆分為老年代和新生代。老年代與新生代比例為2:1。新生代分為一個Eden和兩個Survivor區域,比例為8:1:1。
JDK1.7之後,運行時常量池從方法區中移入到堆中,存放一些符號引用。
元數據區
在JDK1.7的時候,有一個JVM記憶體區域中有一塊方法區,主要存放虛擬機載入的類信息,靜態變數,常量等。
JDK1.8時,移除了方法區的概念,用一個元數據區代替。元數據區存放的東西和方法區相同,不過元數據區移動到本地記憶體中。本地記憶體,又稱堆外記憶體(Direct Memory),就是指機器記憶體中不是JVM管理的那部分記憶體,由操作系統管理。元數據區移動到本地記憶體以後,可以避免虛擬機載入類過多而引發的記憶體溢出:java.lang.OutOfMemoryError: PermGen,但是同樣不能無限擴展。
JVM常用參數
- -Xms64m 最小堆記憶體 64m
- -Xmx128m 最大堆記憶體 128m
- -XX:NewSize=30m 新生代初始化大小為30m
- -XX:MaxNewSize=40m 新生代最大大小為40m
- -Xss=256k 線程棧大小
- -XX:InitialSurvivorRatio 新生代Eden/Survivor空間的初始比例
- -XX:Newratio 新生代和老年代的記憶體比例
- -XX:MaxMetaspaceSize 元數據區最大記憶體