摘要:下面的截圖內容來自從規(guī)范我們可以看到,規(guī)范要求的運行時數(shù)據區(qū)域有程序計數(shù)器虛擬機棧堆方法區(qū)本地方法棧運行時常量池這及部分。查了一下,還是沒有查到官方對于運行時數(shù)據區(qū)域的說明,但是許多博客都指出將字符串常量池移動到了堆中。
不少java程序員一提JVM運行時數(shù)據區(qū)域,就會說堆和棧,當然也有java程序員給出方法區(qū)、虛擬機棧、本地方法棧、堆、程序計數(shù)器這個答案,但是還有人給出永久代、虛擬機棧、本地方法棧、堆、程序計數(shù)器這個答案。那么究竟哪種答案是正確的呢?
首先我們介紹兩個概念,這對于我們回答上面的問題來說是必不可少的。
1.虛擬機: 簡單的說虛擬機是一種抽象的計算機。
2.Java虛擬機規(guī)范: 虛擬機規(guī)范是一種對Java虛擬機的約束,Java虛擬機負責對虛擬機規(guī)范進行實現(xiàn)。
我們平常所說JAVA虛擬機一般是指的一種具體的JAVA虛擬機規(guī)范的實現(xiàn),比如說HotSpot。當然市面上還有其他的Java虛擬機。
下面的截圖內容來自https://docs.oracle.com/javas...
從JVM6規(guī)范,我們可以看到,規(guī)范要求的運行時數(shù)據區(qū)域有: PC Register(程序計數(shù)器)、Java Virtual Machine Stacks(java 虛擬機棧)、Heap(堆)、Method Area(方法區(qū))、Native Method Stacks(本地方法棧)、Runtime Constant Pool(運行時常量池這及部分)。
注意標紅部分,我們可以看到運行時常量池位于方法區(qū)內。
根據規(guī)范我們可以大概的畫出JVM運行實數(shù)據區(qū)域(執(zhí)行引擎、本地庫接口在后面的文章中會進行詳細介紹)。
在認真的看完JVM6、7、8的運行時數(shù)據區(qū)域規(guī)范之后,JVM6、7、8關于對運行時的數(shù)據區(qū)域要求一點變化都沒有,還是程序計數(shù)器、Java虛擬棧、堆、方法區(qū)、本地方法棧、運行時常量池這幾個部分。
那永久代是方法區(qū)的別名咯,準確的說是方法區(qū)的實現(xiàn)。規(guī)范是這么要求的,但是虛擬機會對這些區(qū)域進行調整,或者說是調整對JVM規(guī)范的實現(xiàn)。
查找了很多資料以后,還是沒有找到官方對于永久代的描述(有找到官方文檔關于永久代(Permanent Generation)的描述的,請聯(lián)系我)。綜合了很多博客和一些資料之后,我們可以做出如下判斷,永久代是HotSpot虛擬機特有的概念,HotSpot團隊使用永久代來實現(xiàn)JVM規(guī)范中的方法區(qū)。對于其他虛擬機來說是不存在永久代這個概念的。jdk8移除了永久代,關于這點我們將在后文進行詳細的介紹。
那么為什么稱方法區(qū)為永久代呢?
這跟GC分代收集有一定的關系,內存回收發(fā)生在方法區(qū)和堆中。
我們使用-XX:+PrintGCDetails參數(shù),在IDEA中查看堆中的信息。
注意到PSYoungGen和ParOldGen這兩個單詞,從控制臺的信息我們可以看出堆中的區(qū)域劃分
PSYoungGen
eden space from space to space
ParOldGen
PS和Par代表垃圾回收器
也就是說堆里面又可以再分為年輕代、老年代,堆是垃圾回收機制的重點區(qū)域,將方法區(qū)也納入垃圾回收范圍,與年輕代、老年代相對,稱方法區(qū)為永久代。
這就是永久代的來歷。
接下來介紹一下JVM1.7和1.6的不同。
在介紹JVM1.6和1.7的區(qū)別之前,我們先介紹String類的intern()方法
字符串在調用該方法的時候,如果字符串常量池里面還沒有該字符串,則將該字符串添加進字符串常量池中。
查了一下,還是沒有查到HotSpot官方對于運行時數(shù)據區(qū)域的說明,但是許多博客都指出jdk1.7將字符串常量池移動到了堆中。
以下是分別在1.6、1.8的測試例子
1.6結果: false
1.7以上的結果:true
我們來解釋一下原因,1.6中字符串常量池放在永久代中和堆是隔離的。
我們來畫個圖來解釋一下,
1.6
1.7的虛擬機做了調整,常量池中不需要在存儲一份對象了,可以存儲堆中的引用,更為靈活。
1.7及以上的圖
請看下一張圖。
jdk版本在1.8。MetaSpace是什么鬼?
Jdk1.8移除了永久代或者說用MetaSpace去實現(xiàn)虛擬機規(guī)范中的方法區(qū)。
詳見:JEP 122: Remove the Permanent Generation
我查了很多資料,還是沒有找到官方對MetaSpace的解釋和描述,到是在深入探究 JVM | 探秘 Metaspace這篇博客中看到了MetaSpace的相關描述。
In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.
字符串常量池仍然在堆中,方法區(qū)移動至MetaSpace中
那么如果有人問你JVM運行時區(qū)域由幾部分組成,那么應該如何回答呢?
我認為答案可以是這樣的:JVM規(guī)范中的要求JVM運行時區(qū)域有以下及部分:
方法區(qū)
java虛擬機棧
本地方法棧
堆
程序計數(shù)器
運行時常量池(位于方法區(qū)中)
但是不同的虛擬機對規(guī)范有著不同的實現(xiàn),HotSpot1.6對方法區(qū)的實現(xiàn)叫永久代,1.7將字符串常量池移動到了堆中,1.8移除了永久代改用元數(shù)據區(qū)實現(xiàn)方法區(qū),字符串常量池仍然在堆中。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/77895.html
摘要:方法區(qū)在實際內存空間站可以是不連續(xù)的。這一規(guī)定,可以說是給了虛擬機廠商很大的自由。但是值得注意的是,堆其實還未每一個線程單獨分配了一塊空間,這部分空間在分配時是線程獨享的,在使用時是線程共享的。 在我的博客中,之前有很多文章介紹過JVM內存結構,相信很多看多我文章的朋友對這部分知識都有一定的了解了。 那么,請大家嘗試著回答一下以下問題: 1、JVM管理的內存結構是怎樣的? 2、不同的...
摘要:棧因為是運行單位,因此里面存儲的信息都是跟當前線程相關的信息。基本類型和對象的引用都是在存放在棧中,而且都是幾個字節(jié)的一個數(shù),因此在程序運行時,他們的處理方式是統(tǒng)一的。對象,是由基本類型組成的。 一、概念 數(shù)據類型 java虛擬機中,數(shù)據類型可以分為兩類: 基本類型 引用類型 基本類型的變量保存原始值,即:他代表的值就是數(shù)值本身;而引用類型的變量保存引用值?;绢愋桶ǎ篵yte,sh...
閱讀 3493·2021-11-25 09:43
閱讀 1247·2021-09-08 09:45
閱讀 2626·2021-09-07 09:59
閱讀 1456·2021-08-09 13:45
閱讀 3292·2019-08-30 15:54
閱讀 659·2019-08-29 18:35
閱讀 476·2019-08-29 17:18
閱讀 976·2019-08-29 14:10