公司做網(wǎng)站流程關(guān)鍵詞挖掘工具愛網(wǎng)
筆者近期在面試的時(shí)候被問到了這個(gè)問題,元空間也是Java8當(dāng)時(shí)的一大重大革新,之前暑期實(shí)習(xí)求職的時(shí)候有專門看過,但是近期秋招的時(shí)候JVM相關(guān)的內(nèi)容確實(shí)有點(diǎn)生疏了,故在此進(jìn)行回顧。
結(jié)構(gòu)
首先,我們應(yīng)了解JVM的堆結(jié)構(gòu),主要有兩個(gè)版本及Java7以及Java8。
元空間的前身-永久代(Permanent Generation)
JAVA永久代的演化
- JDK7開始,字符串常量和符號(hào)引用等就被移出永久代,字符串字面量遷移至Java堆 /符號(hào)引用轉(zhuǎn)移到了native heap。
- JDK8,永久代被徹底地移出了JVM,取而代之的是元空間MetaSpace,把類的元數(shù)據(jù)放到本地化的堆內(nèi)存native heap中,這塊區(qū)域就叫Metaspace。
JDK 1.7 為什么要將字符串常量池移動(dòng)到堆中?
主要是因?yàn)橛谰么?#xff08;方法區(qū)實(shí)現(xiàn))的 GC 回收效率太低,只有在整堆收集 (Full GC)的時(shí)候才會(huì)被執(zhí)行 GC。Java 程序中通常會(huì)有大量的被創(chuàng)建的字符串等待回收,將字符串常量池放到堆中,能夠更高效及時(shí)地回收字符串內(nèi)存。
作用
JVM的MetaSpace存儲(chǔ)JVM的元信息,而且是在堆外存儲(chǔ)。主要涉及以下內(nèi)容:
- JVM中類的元數(shù)據(jù)在Java堆中的存儲(chǔ)區(qū)域
- Java類對(duì)應(yīng)的HotSpot虛擬機(jī)中的內(nèi)部表示也存儲(chǔ)在這里
- 類的層級(jí)信息,字段,名字
- 方法的編譯信息及字節(jié)碼
- 變量
- 常量池和符號(hào)解析
注意到,堆外內(nèi)存就是把內(nèi)存對(duì)象分配在堆(新生代+老年代+永久代)以外的內(nèi)存,這些內(nèi)存直接受操作系統(tǒng)管理(而不是虛擬機(jī)),這樣做的結(jié)果就是能夠在一定程度上減少垃圾回收對(duì)應(yīng)用程序造成的影響。
理論上以上信息占用的內(nèi)存空間在服務(wù)啟動(dòng)后就會(huì)比較穩(wěn)定,并不會(huì)出現(xiàn)上文中提到的一直增長(zhǎng)的,甚至導(dǎo)致OOM的情況出現(xiàn)。
回到正題,元空間的引入是為了替代原來使用的 PermGen 區(qū)域,PermGen 區(qū)域主要用于存儲(chǔ)永久代(Permanent Generation)中的類信息和常量池信息。隨著Java應(yīng)用程序?qū)?nèi)存需求的不斷增加,PermGen 區(qū)域經(jīng)常會(huì)出現(xiàn)內(nèi)存泄漏和 OutOfMemoryError 的問題,因此引入了元空間來解決這些問題。
元空間的大小可以通過參數(shù)配置的方式指定。在啟動(dòng)JVM時(shí),可以使用以下參數(shù)來指定元空間的大小:
-XX:MaxMetaspaceSize:指定元空間的最大大小,單位是字節(jié)。
-XX:MinMetaspaceSize:指定元空間的最小大小,單位是字節(jié)。
-XX:InitialMetaspaceSize:指定元空間的初始大小,單位是字節(jié)。
這些參數(shù)可以通過命令行或配置文件的方式傳遞給JVM。在默認(rèn)情況下,元空間的大小是動(dòng)態(tài)調(diào)整的,根據(jù)應(yīng)用程序的需要自動(dòng)擴(kuò)展或縮小。當(dāng)元空間快要達(dá)到最大或最小大小時(shí),JVM會(huì)嘗試進(jìn)行垃圾回收來釋放不再使用的類信息和常量池信息。
參考資料
JVM Metaspace OOM的排障以及原理分析 - 掘金
https://www.cnblogs.com/snowwhite/p/9532311.html
Java內(nèi)存區(qū)域詳解(重點(diǎn)) | JavaGuide(Java面試 + 學(xué)習(xí)指南)