JAVA8永久代
????在Java虛擬機(jī)(以下簡(jiǎn)稱JVM)中,類包含其對(duì)應(yīng)的元數(shù)據(jù),比如類的層級(jí)信息,方法數(shù)據(jù)和方法信息(如字節(jié)碼,棧和變量大小),運(yùn)行時(shí)常量池,已確定的符號(hào)引用和虛方法表。
???在過去(當(dāng)自定義類加載器使用不普遍的時(shí)候),類幾乎是“靜態(tài)的”并且很少被卸載和回收,因此類也可以被看成“永久的”。另外由于類作為JVM實(shí)現(xiàn)的一部分,它們不由程序來創(chuàng)建,因?yàn)樗鼈円脖徽J(rèn)為是“非堆”的內(nèi)存。
???在JDK8之前的HotSpot虛擬機(jī)中,類的這些“永久的”數(shù)據(jù)存放在一個(gè)叫做永久代的區(qū)域。永久代一段連續(xù)的內(nèi)存空間,我們?cè)贘VM啟動(dòng)之前可以通過設(shè)置-XX:MaxPermSize的值來控制永久代的大小,32位機(jī)器默認(rèn)的永久代的大小為64M,64位的機(jī)器則為85M。永久代的垃圾回收和老年代的垃圾回收是綁定的,一旦其中一個(gè)區(qū)域被占滿,這兩個(gè)區(qū)都要進(jìn)行垃圾回收。但是有一個(gè)明顯的問題,由于我們可以通過?XX:MaxPermSize 設(shè)置永久代的大小,一旦類的元數(shù)據(jù)超過了設(shè)定的大小,程序就會(huì)耗盡內(nèi)存,并出現(xiàn)內(nèi)存溢出錯(cuò)誤(OOM)。
備注:在JDK7之前的HotSpot虛擬機(jī)中,納入字符串常量池的字符串被存儲(chǔ)在永久代中,因此導(dǎo)致了一系列的性能問題和內(nèi)存溢出錯(cuò)誤。
???隨著Java8的到來,我們?cè)僖惨姴坏接谰么恕5沁@并不意味著類的元數(shù)據(jù)信息也消失了。這些數(shù)據(jù)被移到了一個(gè)與堆不相連的本地內(nèi)存區(qū)域,這個(gè)區(qū)域就是我們要提到的元空間。這項(xiàng)改動(dòng)是很有必要的,因?yàn)閷?duì)永久代進(jìn)行調(diào)優(yōu)是很困難的。永久代中的元數(shù)據(jù)可能會(huì)隨著每一次Full GC發(fā)生而進(jìn)行移動(dòng)。并且為永久代設(shè)置空間大小也是很難確定的,因?yàn)檫@其中有很多影響因素,比如類的總數(shù),常量池的大小和方法數(shù)量等。
???同時(shí),HotSpot虛擬機(jī)的每種類型的垃圾回收器都需要特殊處理永久代中的元數(shù)據(jù)。將元數(shù)據(jù)從永久代剝離出來,不僅實(shí)現(xiàn)了對(duì)元空間的無縫管理,還可以簡(jiǎn)化Full GC以及對(duì)以后的并發(fā)隔離類元數(shù)據(jù)等方面進(jìn)行優(yōu)化。
移除永久代的影響
????由于類的元數(shù)據(jù)分配在本地內(nèi)存中,元空間的最大可分配空間就是系統(tǒng)可用內(nèi)存空間。因此,我們就不會(huì)遇到永久代存在時(shí)的內(nèi)存溢出錯(cuò)誤,也不會(huì)出現(xiàn)泄漏的數(shù)據(jù)移到交換區(qū)這樣的事情。最終用戶可以為元空間設(shè)置一個(gè)可用空間最大值,如果不進(jìn)行設(shè)置,JVM會(huì)自動(dòng)根據(jù)類的元數(shù)據(jù)大小動(dòng)態(tài)增加元空間的容量。
注意:永久代的移除并不代表自定義的類加載器泄露問題就解決了。因此,你還必須監(jiān)控你的內(nèi)存消耗情況,因?yàn)橐坏┌l(fā)生泄漏,會(huì)占用你的大量本地內(nèi)存,并且還可能導(dǎo)致交換區(qū)交換更加糟糕。
元空間內(nèi)存管理
????元空間的內(nèi)存管理由元空間虛擬機(jī)來完成。先前,對(duì)于類的元數(shù)據(jù)我們需要不同的垃圾回收器進(jìn)行處理,現(xiàn)在只需要執(zhí)行元空間虛擬機(jī)的C++代碼即可完成。在元空間中,類和其元數(shù)據(jù)的生命周期和其對(duì)應(yīng)的類加載器是相同的。話句話說,只要類加載器存活,其加載的類的元數(shù)據(jù)也是存活的,因而不會(huì)被回收掉。
????我們從行文到現(xiàn)在提到的元空間稍微有點(diǎn)不嚴(yán)謹(jǐn)。準(zhǔn)確的來說,每一個(gè)類加載器的存儲(chǔ)區(qū)域都稱作一個(gè)元空間,所有的元空間合在一起就是我們一直說的元空間。當(dāng)一個(gè)類加載器被垃圾回收器標(biāo)記為不再存活,其對(duì)應(yīng)的元空間會(huì)被回收。在元空間的回收過程中沒有重定位和壓縮等操作。但是元空間內(nèi)的元數(shù)據(jù)會(huì)進(jìn)行掃描來確定Java引用。
????元空間虛擬機(jī)負(fù)責(zé)元空間的分配,其采用的形式為組塊分配。組塊的大小因類加載器的類型而異。在元空間虛擬機(jī)中存在一個(gè)全局的空閑組塊列表。當(dāng)一個(gè)類加載器需要組塊時(shí),它就會(huì)從這個(gè)全局的組塊列表中獲取并維持一個(gè)自己的組塊列表。當(dāng)一個(gè)類加載器不再存活,那么其持有的組塊將會(huì)被釋放,并返回給全局組塊列表。類加載器持有的組塊又會(huì)被分成多個(gè)塊,每一個(gè)塊存儲(chǔ)一個(gè)單元的元信息。組塊中的塊是線性分配(指針碰撞分配形式)。組塊分配自內(nèi)存映射區(qū)域。這些全局的虛擬內(nèi)存映射區(qū)域以鏈表形式連接,一旦某個(gè)虛擬內(nèi)存映射區(qū)域清空,這部分內(nèi)存就會(huì)返回給操作系統(tǒng)。
參考如下鏈接:http://www.infoq.com/cn/articles/Java-PERMGEN-Removed?from=groupmessage&isappinstalled=0
轉(zhuǎn)載于:https://www.cnblogs.com/moonandstar08/p/5001914.html
總結(jié)
- 上一篇: 16进制字符和图片之间相互转换
- 下一篇: POJ - 3470 Walls