首先我們需要先復(fù)習(xí)一下jvm的大致內(nèi)存圖,如下:
哦~ ,想起來了,原來方法區(qū)屬于jvm的運(yùn)行時數(shù)據(jù)區(qū),且作用就是存儲類信息、方法信息、常量池信息等靜態(tài)數(shù)據(jù)。
?(補(bǔ)充一下:運(yùn)行時數(shù)據(jù)區(qū)中的紅色是指方法區(qū)和堆是線程共享的,其他幾個都是線程私有的)
好的,回想起來方法區(qū)的相關(guān)概念后,我們進(jìn)入正題:
方法區(qū)是什么?
其實呢,我們經(jīng)常說的方法區(qū)只是java虛擬機(jī)規(guī)范的一個概念,就像是一個接口;那么接口總要有人實現(xiàn)吧,所以永久代和元空間就起著這樣的作用,它們實際上都是方法區(qū),是方法區(qū)在不同jdk版本的實現(xiàn)。
永久代是什么?
在jdk7以及jdk7之前,方法區(qū)被稱為永久代(PermGen)
此時永久代是 Java 堆(Java Heap)的一部分,用于存儲類信息、方法信息、常量池信息等靜態(tài)數(shù)據(jù)。
而 Java 堆是 JVM 中存儲對象實例和數(shù)組的內(nèi)存區(qū)域,也就是說,永久代是 Java 堆的一個子區(qū)域。
換句話說,永久代中存儲的靜態(tài)數(shù)據(jù)與堆中存儲的對象實例和數(shù)組是分開的,它們有不同的生命周期和分配方式。
但是,永久代和堆的大小是相互影響的,因為它們都使用了 JVM 堆內(nèi)存,因此它們的大小都受到 JVM 堆大小的限制。
對字符串常量池的一個擴(kuò)展:
注:jdk7之前字符串常量池也存放在永久代中,而jdk7時,脫離了永久代,存放于堆空間中。
?永久代的分布如下:
元空間是什么?
在jdk8時,徹底移除了永久代,方法區(qū)正式改名為元空間(Metaspace);??
首先需要確認(rèn)的是,它們的功能并沒有改變,仍然是用于存儲類信息、方法信息、常量池信息等靜態(tài)數(shù)據(jù)。
它們最大的區(qū)別就是永久代存在于Java堆中,它的大小受到 Java 虛擬機(jī)本身大小的限制;而元空間則是一塊本機(jī)內(nèi)存區(qū)域,和 JVM 內(nèi)存區(qū)域是分開的,?所以只受本機(jī)可用內(nèi)存的限制。
那么既然與永久代不同,那元空間就具有一些永久代沒有的優(yōu)點,如下:
-
它不會導(dǎo)致 OutOfMemoryError 錯誤,因為元空間的大小可以動態(tài)調(diào)整。
-
元空間使用本機(jī)內(nèi)存,而不是 JVM 堆內(nèi)存,這可以避免堆內(nèi)存的碎片化問題。
-
元空間中的垃圾收集與堆中的垃圾收集是分離的,這可以避免應(yīng)用程序在運(yùn)行過程中因為進(jìn)行類加載和卸載而頻繁地觸發(fā) Full GC。
對字符串常量池的一個擴(kuò)展:
jdk8中,字符串常量池都存放在堆中,而它最開始的老東家永久代已經(jīng)搖身一變成為了元空間,并且脫離了java堆空間,存放在堆以外的本地內(nèi)存中。
元空間分布如下:
以上就是我對方法區(qū)這幾個概念的理解,如果有需要補(bǔ)充的地方,記得留言評論哦~
最后,其實這篇文章中我覺得大家最需要搞清楚的一句話就是:永久代和元空間是方法區(qū)不同jdk版本的實現(xiàn),搞清楚這三個概念,不記混淆了,就是很大的收獲了,大家就已經(jīng)很棒了~
文章來源:http://www.zghlxwxcb.cn/news/detail-486983.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-486983.html
到了這里,關(guān)于JVM中方法區(qū)、永久代、元空間詳解以及關(guān)系?的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!