1 對(duì)比圖

2 方法區(qū)的變化
JDK1.8 與JDK1.7 最大的區(qū)別是:JDK1.8 將永久代取消,取而代之的是元空間,在 JDK1.8 中方法區(qū)是由元空間來(lái)實(shí)現(xiàn),所以原來(lái)屬于方法區(qū)的運(yùn)行時(shí)常量池就屬于元空間了。
??元空間屬于本地內(nèi)存,所以元空間的大小僅受本地內(nèi)存限制,但是可以通過 -XX:MaxMetaspaceSize 進(jìn)行增長(zhǎng)上限的最大值設(shè)置,默認(rèn)值為 4G,元空間的初始空間大小可以通過 -XX:MetaspaceSize 進(jìn)行設(shè)置,默認(rèn)值為 20.8M,還有一些其他參數(shù)可以進(jìn)行設(shè)置,元空間大小會(huì)自動(dòng)進(jìn)行調(diào)整。
3 數(shù)據(jù)的遷移
- 在 JDK1.7 之前運(yùn)行時(shí)常量池,字符串常量池,靜態(tài)域等存放在方法區(qū), 運(yùn)行時(shí)常量池邏輯包含字符串常量池,此時(shí)hotspot虛擬機(jī)對(duì)方法區(qū)的實(shí)現(xiàn)為永久代。
- 在 JDK1.7 中字符串常量池和靜態(tài)域被從方法區(qū)(永久代)拿到了堆中(在堆中另開辟了一塊空間),這里沒有提到運(yùn)行時(shí)常量池,也就是說字符串常量池被單獨(dú)拿到堆,運(yùn)行時(shí)常量池剩下的東西還在方法區(qū),也就是 HotSpot 中的永久代。
- 在 JDK1.8 中 HotSpot 移除了永久代,用元空間(Metaspace)取而代之, 這時(shí)候字符串常量池還在堆,運(yùn)行時(shí)常量池還在方法區(qū),只不過方法區(qū)的實(shí)現(xiàn)從永久代變成了元空間(Metaspace)。
4 元空間簡(jiǎn)介
用于存儲(chǔ)已被虛擬機(jī)加載的類元數(shù)據(jù),符號(hào)引用,即包括運(yùn)行時(shí)常量池。元空間的本質(zhì)和永久代類似,都是對(duì) JVM 規(guī)范中方法區(qū)的實(shí)現(xiàn)。
不過元空間與永久代之間最大的區(qū)別在于:元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。因此,默認(rèn)情況下,元空間的大小僅受本地內(nèi)存限制,但可以通過以下參數(shù)來(lái)指定元空間的大小:-XX:MetaspaceSize。
4.1 元數(shù)據(jù)
元數(shù)據(jù)(Meta Data),關(guān)于數(shù)據(jù)的數(shù)據(jù)或者叫做用來(lái)描述數(shù)據(jù)的數(shù)據(jù)或者叫做信息的信息。
??這些定義都很是抽象,我們可以把元數(shù)據(jù)簡(jiǎn)單的理解成,最小的數(shù)據(jù)單位。元數(shù)據(jù)可以為數(shù)據(jù)說明其元素、屬性(名稱、大小、數(shù)據(jù)類型、等),、結(jié)構(gòu)(長(zhǎng)度、字段、數(shù)據(jù)列)、相關(guān)數(shù)據(jù)(位于何處、如何聯(lián)系、擁有者)等。
4.2 為什么移除永久代?
- 由于永久代使用 JVM 內(nèi)存經(jīng)常不夠用或發(fā)生內(nèi)存泄露,引發(fā)惱人的 OutOfMemoryError 異常(在 Java Web 開發(fā)中非常常見)。
- 移除永久代可以促進(jìn) HotSpot 與 JRockit 兩種虛擬機(jī)的融合,因?yàn)?JRockit 沒有永久代。
- 對(duì)永久代進(jìn)行調(diào)優(yōu)是很困難的。永久代中的元數(shù)據(jù)可能會(huì)隨著每一次Full GC發(fā)生而進(jìn)行移動(dòng)。
4.3 為什么要引入元空間?
- 字符串常量存在永久代中,容易出現(xiàn)性能問題和內(nèi)存溢出。
- 類及方法的信息等比較難確定其大小,因此對(duì)于永久代的大小指定比較困難,太小容易出現(xiàn)永久代溢出,太大則容易導(dǎo)致老年代溢出。
- 永久代會(huì)為 GC 帶來(lái)不必要的復(fù)雜度,并且回收效率偏低。
- Oracle 可能會(huì)將HotSpot與Jrockit兩種虛擬機(jī)合二為一。