對於JVM,你就只知道堆和棧嗎?

很多java程序員一提JVM運行時數據區域,就會說堆和棧,固然也有java程序員給出方法區、虛擬機棧、本地方法棧、堆、程序計數器這個答案,可是還有人給出永久代、虛擬機棧、本地方法棧、堆、程序計數器這個答案。那麼究竟哪一種答案是正確的呢?html

首先咱們介紹兩個概念,這對於咱們回答上面的問題來講是必不可少的。
1.虛擬機: 簡單的說虛擬機是一種抽象的計算機。
2.Java虛擬機規範: 虛擬機規範是一種對Java虛擬機的約束,Java虛擬機負責對虛擬機規範進行實現。
咱們日常所說JAVA虛擬機通常是指的一種具體的JAVA虛擬機規範的實現,好比說HotSpot。固然市面上還有其餘的Java虛擬機。
下面的截圖內容來自https://docs.oracle.com/javas...
clipboard.pngjava

從JVM6規範,咱們能夠看到,規範要求的運行時數據區域有: PC Register(程序計數器)、Java Virtual Machine Stacks(java 虛擬機棧)、Heap(堆)、Method Area(方法區)、Native Method Stacks(本地方法棧)、Runtime Constant Pool(運行時常量池這及部分)。
注意標紅部分,咱們能夠看到運行時常量池位於方法區內。
根據規範咱們能夠大概的畫出JVM運行實數據區域(執行引擎、本地庫接口在後面的文章中會進行詳細介紹)。
clipboard.png
在認真的看完JVM六、七、8的運行時數據區域規範以後,JVM六、七、8關於對運行時的數據區域要求一點變化都沒有,仍是程序計數器、Java虛擬棧、堆、方法區、本地方法棧、運行時常量池這幾個部分。
那永久代是方法區的別名咯,準確的說是方法區的實現。規範是這麼要求的,可是虛擬機會對這些區域進行調整,或者說是調整對JVM規範的實現。
查找了不少資料之後,仍是沒有找到官方對於永久代的描述(有找到官方文檔關於永久代(Permanent Generation)的描述的,請聯繫我)。綜合了不少博客和一些資料以後,咱們能夠作出以下判斷,永久代是HotSpot虛擬機特有的概念,HotSpot團隊使用永久代來實現JVM規範中的方法區。對於其餘虛擬機來講是不存在永久代這個概念的。jdk8移除了永久代,關於這點咱們將在後文進行詳細的介紹。
那麼爲何稱方法區爲永久代呢?
這跟GC分代收集有必定的關係,內存回收發生在方法區和堆中。
咱們使用-XX:+PrintGCDetails參數,在IDEA中查看堆中的信息。
clipboard.png
注意到PSYoungGen和ParOldGen這兩個單詞,從控制檯的信息咱們能夠看出堆中的區域劃分
PSYoungGen程序員

eden space
from space
to    space

ParOldGen
PS和Par表明垃圾回收器
也就是說堆裏面又能夠再分爲年輕代、老年代,堆是垃圾回收機制的重點區域,將方法區也歸入垃圾回收範圍,與年輕代、老年代相對,稱方法區爲永久代。
這就是永久代的來歷。
接下來介紹一下JVM1.7和1.6的不一樣。
在介紹JVM1.6和1.7的區別以前,咱們先介紹String類的intern()方法
字符串在調用該方法的時候,若是字符串常量池裏面尚未該字符串,則將該字符串添加進字符串常量池中。
查了一下,仍是沒有查到HotSpot官方對於運行時數據區域的說明,可是許多博客都指出jdk1.7將字符串常量池移動到了堆中。
如下是分別在1.六、1.8的測試例子
clipboard.png
1.6結果: false
1.7以上的結果:true
咱們來解釋一下緣由,1.6中字符串常量池放在永久代中和堆是隔離的。
咱們來畫個圖來解釋一下,
1.6
clipboard.png
1.7的虛擬機作了調整,常量池中不須要在存儲一份對象了,能夠存儲堆中的引用,更爲靈活。
1.7及以上的圖oracle

clipboard.png

請看下一張圖。
jdk版本在1.8。MetaSpace是什麼鬼?jvm

clipboard.png

Jdk1.8移除了永久代或者說用MetaSpace去實現虛擬機規範中的方法區。
詳見:JEP 122: Remove the Permanent Generation
我查了不少資料,仍是沒有找到官方對MetaSpace的解釋和描述,到是在深刻探究 JVM | 探祕 Metaspace這篇博客中看到了MetaSpace的相關描述。post

In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.

字符串常量池仍然在堆中,方法區移動至MetaSpace中
那麼若是有人問你JVM運行時區域由幾部分組成,那麼應該如何回答呢?
我認爲答案能夠是這樣的:JVM規範中的要求JVM運行時區域有如下及部分:測試

  1. 方法區
  2. java虛擬機棧
  3. 本地方法棧
  4. 程序計數器
  5. 運行時常量池(位於方法區中)

可是不一樣的虛擬機對規範有着不一樣的實現,HotSpot1.6對方法區的實現叫永久代,1.7將字符串常量池移動到了堆中,1.8移除了永久代改用元數據區實現方法區,字符串常量池仍然在堆中。this

相關文章
相關標籤/搜索