java 1.8 vm_HotSpot虚拟机在java 1.8中的新实现
HotSpot
Java HotSpot 虛擬機是 Java SE 平臺的一個核心組件。它實現(xiàn) Java 虛擬機規(guī)范,并作為 Java 運行時環(huán)境中的一個共享庫來提供。作為 Java 字節(jié)碼執(zhí)行引擎,它在多種操作系統(tǒng)和架構(gòu)上提供 Java 運行時設(shè)施,如線程和對象同步。它包括自適應將 Java 字節(jié)碼編譯成優(yōu)化機器指令的動態(tài)編譯器,并使用為降低暫停時間和吞吐量而優(yōu)化的垃圾收集器來高效管理 Java 堆。它為分析、監(jiān)視和調(diào)試工具及應用程序提供數(shù)據(jù)和信息。
最近在研究它在1.8中的新特性:
JAVA 從永久區(qū)(PermGen)到元空間(Metaspace)
JAVA 從永久區(qū)(PermGen)到元空間(Metaspace)
1. 永久代
在說java8內(nèi)存模型之前先說一下永久代的概念。
在Java虛擬機(JVM)內(nèi)部,class文件中包括類的版本、字段、方法、接口等描述信息,還有運行時常量池,用于存放編譯器生成的各種字面量和符號引用。
在過去類大多是”static”的,很少被卸載或收集,因此被稱為“永久的(Permanent)”。
同時,由于類class是JVM實現(xiàn)的一部分,并不是由應用創(chuàng)建的,所以又被認為是“非堆(non-heap)”內(nèi)存。
在JDK8之前的HotSpot JVM,存放這些”永久的”的區(qū)域叫做“永久代(permanent generation)”。
永久代是一片連續(xù)的堆空間,在JVM啟動之前通過在命令行設(shè)置參數(shù)-XX:MaxPermSize來設(shè)定永久代最大可分配的內(nèi)存空間,默認大小是64M(64位JVM由于指針膨脹,默認是85M)。
永久代的垃圾收集是和老年代(old generation)捆綁在一起的,因此無論誰滿了,都會觸發(fā)永久代和老年代的垃圾收集。
不過,一個明顯的問題是,當JVM加載的類信息容量超過了參數(shù)-XX:MaxPermSize設(shè)定的值時,應用將會報OOM的錯誤
2. Metaspace(元空間)
jdk1.8中則把永久代給完全刪除了,取而代之的是 MetaSpace
heap in JAVA 8
2.1 metaspace的組成
metaspace其實由兩大部分組成
Klass Metaspace
NoKlass Metaspace
Klass Metaspace就是用來存klass的,klass是我們熟知的class文件在jvm里的運行時數(shù)據(jù)結(jié)構(gòu),不過有點要提的是我們看到的類似A.class其實是存在heap里的,是java.lang.Class的一個對象實例。
這塊內(nèi)存是緊接著Heap的,和我們之前的perm一樣,這塊內(nèi)存大小可通過-XX:CompressedClassSpaceSize參數(shù)來控制,這個參數(shù)前面提到了默認是1G,但是這塊內(nèi)存也可以沒有,假如沒有開啟壓縮指針就不會有這塊內(nèi)存,這種情況下klass都會存在NoKlass Metaspace里,另外如果我們把-Xmx設(shè)置大于32G的話,其實也是沒有這塊內(nèi)存的,因為這么大內(nèi)存會關(guān)閉壓縮指針開關(guān)。
還有就是這塊內(nèi)存最多只會存在一塊。
NoKlass Metaspace專門來存klass相關(guān)的其他的內(nèi)容,比如method,constantPool(常量池)等,這塊內(nèi)存是由多塊內(nèi)存組合起來的,所以可以認為是不連續(xù)的內(nèi)存塊組成的。
這塊內(nèi)存是必須的,雖然叫做NoKlass Metaspace,但是也其實可以存klass的內(nèi)容,上面已經(jīng)提到了對應場景。
Klass Metaspace和NoKlass Mestaspace都是所有classloader共享的,所以類加載器們要分配內(nèi)存,但是每個類加載器都有一個SpaceManager,來管理屬于這個類加載的內(nèi)存小塊。
如果Klass Metaspace用完了,那就會OOM了,不過一般情況下不會,NoKlass Mestaspace是由一塊塊內(nèi)存慢慢組合起來的,在沒有達到限制條件的情況下,會不斷加長這條鏈,讓它可以持續(xù)工作。
2.2 Metaspace的內(nèi)存分配與管理
Metaspace VM利用內(nèi)存管理技術(shù)來管理Metaspace。
這使得由不同的垃圾收集器來處理類元數(shù)據(jù)的工作,現(xiàn)在僅僅由Metaspace VM在Metaspace中通過C++來進行管理。
Metaspace背后的一個思想是,類和它的元數(shù)據(jù)的生命周期是和它的類加載器的生命周期一致的。
也就是說,只要類的類加載器是存活的,在Metaspace中的類元數(shù)據(jù)也是存活的,不能被釋放。
每個類加載器存儲區(qū)叫做“a metaspace”。
這些metaspaces一起總體稱為”the Metaspace”。
僅僅當類加載器不再存活,被垃圾收集器聲明死亡后,該類加載器對應的metaspace空間才可以回收。
Metaspace空間沒有遷移和壓縮。
但是元數(shù)據(jù)會被掃描是否存在Java引用。
Metaspace VM使用一個塊分配器(chunking allocator)來管理Metaspace空間的內(nèi)存分配。
塊的大小依賴于類加載器的類型。
其中有一個全局的可使用的塊列表(a global free list of chunks)。
當類加載器需要一個塊的時候,類加載器從全局塊列表中取出一個塊,添加到它自己維護的塊列表中。
當類加載器死亡,它的塊將會被釋放,歸還給全局的塊列表。
塊(chunk)會進一步被劃分成blocks,每個block存儲一個元數(shù)據(jù)單元(a unit of metadata)。
Chunk中Blocks的分配線性的(pointer bump)。
這些chunks被分配在內(nèi)存映射空間(memory mapped(mmapped) spaces)之外。
在一個全局的虛擬內(nèi)存映射空間(global virtual mmapped spaces)的鏈表,當任何虛擬空間變?yōu)榭諘r,就將該虛擬空間歸還回操作系統(tǒng)。
Metaspace的內(nèi)存分配與管理
2.3 Metaspace VM內(nèi)存碎片問題
先前提到的,Metaspace VM使用塊分配器(chunking allocator)。
chunk的大小取決于類加載器的類型。
由于類class并沒有一個固定的尺寸,這就存在這樣一種可能:
可分配的chunk的尺寸和需要的chunk的尺寸不相等,這就會導致內(nèi)存碎片。
內(nèi)存碎片的產(chǎn)生
Metaspace VM還沒有使用壓縮技術(shù),所以內(nèi)存碎片是現(xiàn)在的一個主要關(guān)注的問題。
2.4 Metaspace 總結(jié)
元空間的本質(zhì)和永久代類似,都是對JVM規(guī)范中方法區(qū)的實現(xiàn)。
不過元空間與永久代之間最大的區(qū)別在于:
元空間并不在虛擬機中,而是使用本地內(nèi)存。
因此,默認情況下,元空間的大小僅受本地內(nèi)存限制,但可以通過參數(shù)來指定元空間的大小。
java8內(nèi)存模型圖
2.5 MetaSpace應該掌握的知識
在 JDK 1.7 和 1.8 中將字符串常量池由永久代轉(zhuǎn)移到堆中
存放類相關(guān)信息的地方也不在heap(堆)中。在元空間里。
在jdk1.8中沒有永久代的概念
metaspace其實由兩大部分組成
Klass Metaspace
存放klass的,klass是我們熟知的class文件在jvm里的運行時數(shù)據(jù)結(jié)構(gòu),這個空間的默認大小是1G
NoKlass Metaspace
專門來存klass相關(guān)的其他的內(nèi)容,比如method,constantPool(常量池)等,這塊內(nèi)存是由多塊內(nèi)存組合起來的,所以可以認為是不連續(xù)的內(nèi)存塊組成的。這塊內(nèi)存是必須的
Klass Metaspace和NoKlass Mestaspace都是所有classloader共享的,所以類加載器們要分配內(nèi)存,但是每個類加載器都有一個SpaceManager,來管理屬于這個類加載的內(nèi)存小塊。
如果Klass Metaspace用完了,那就會OOM了,不過一般情況下不會,NoKlass Mestaspace是由一塊塊內(nèi)存慢慢組合起來的,在沒有達到限制條件的情況下,會不斷加長這條鏈,讓它可以持續(xù)工作。
5.metaspace主要相關(guān)參數(shù)
-XX:MetaspaceSize,初始空間大小,達到該值就會觸發(fā)垃圾收集進行類型卸載,同時GC會對該值進行調(diào)整:
如果釋放了大量的空間,就適當降低該值;
如果釋放了很少的空間,那么在不超過MaxMetaspaceSize時,適當提高該值。
-XX:MaxMetaspaceSize,最大空間,默認是沒有限制的。
-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空間容量的百分比,減少為分配空間所導致的垃圾收集
-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空間容量的百分比,減少為釋放空間所導致的垃圾收集
Metaspace的內(nèi)存分配與管理 都應該清楚
為什么要將永久代替換成Metaspace?
字符串存在永久代中,容易出現(xiàn)性能問題和內(nèi)存溢出。
類及方法的信息等比較難確定其大小,因此對于永久代的大小指定比較困難,太小容易出現(xiàn)永久代溢出,太大則容易導致老年代溢出。
永久代會為 GC 帶來不必要的復雜度,并且回收效率偏低。
Oracle 可能會將HotSpot 與 JRockit 合二為一。
總結(jié)
以上是生活随笔為你收集整理的java 1.8 vm_HotSpot虚拟机在java 1.8中的新实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java调试案例_Spring-boot
- 下一篇: 你还用信用卡吗?银保监会:信用卡资金不得