前言:原來(lái)的文章不是md形式,寫(xiě)的也比較亂,現(xiàn)在看看 有點(diǎn)不好意思,就重新修正下。
今天群里分享這個(gè)圖片,又這個(gè)圖片引起了一系列討論,我們隊(duì)jvm的理解都是局限于知其然不知其所以然的階段啊。

類似的問(wèn)題:
metaspace在不在堆中?
directory memory和native memory關(guān)系?
討論了一堆,記錄下自己的理解,不一定正確。。。
metaspace在不在堆中? 不在。
可以參考這篇文章:深入探究 JVM | 探秘 Metaspace ---雖然年代寫(xiě)的比較久遠(yuǎn),但作者的理解我感覺(jué)哈 是比較準(zhǔn)的。
這個(gè)是jdk1.8的新特性,1.8以前呢,HotSpot JVM堆上有個(gè)永久代,存放類和方法的元數(shù)據(jù)以及常量池。1.8以后呢把永久代移除了,方法區(qū)移至 Metaspace,字符串常量移至 Java Heap。
為啥要這么干?
1 由于 PermGen 內(nèi)存經(jīng)常會(huì)溢出,引發(fā)惱人的 java.lang.OutOfMemoryError: PermGen,因此 JVM 的開(kāi)發(fā)者希望這一塊內(nèi)存可以更靈活地被管理,不要再經(jīng)常出現(xiàn)這樣的 OOM。
我覺(jué)得這個(gè)原因比較實(shí)在,現(xiàn)在比較流行的框架都喜歡用反射,比如spring的aop,一般這種動(dòng)態(tài)代理的類都會(huì)占用方法區(qū)的資源的。
2 移除 PermGen 可以促進(jìn) HotSpot JVM 與 JRockit VM 的融合,因?yàn)?JRockit 沒(méi)有永久代。
一般情況下:設(shè)置Metaspace的參數(shù)-XX:MetaspaceSize -XX:MaxMetaspaceSize 這兩個(gè)參數(shù)的值最好一致,值的大小可以根據(jù)監(jiān)控情況動(dòng)態(tài)的調(diào)整一下。 如果Metaspace由于空間不足引起動(dòng)態(tài)擴(kuò)容,會(huì)引發(fā)FULL GC。
其他兩篇文章參考:
由「Metaspace容量不足觸發(fā)CMS GC」從而引發(fā)的思考
JVM參數(shù)MetaspaceSize的誤解
directory memory和native memory關(guān)系? 可以理解為directory memory是native memory的一部分。
可以參考這篇文章:
JVM的Heap Memory和Native Memory 這篇文章可以先熟悉下概念。

一次堆外OOM問(wèn)題排查 這篇文章詳細(xì)的說(shuō)了下堆外內(nèi)存OOM及回收方式 而且有樣例,值得一看。
native memory中文叫本地內(nèi)存,狹義的理解下,對(duì)jvm來(lái)說(shuō),就是不受jvm垃圾回收機(jī)制主動(dòng)管理的內(nèi)存就是本地內(nèi)存。
directory memory指的是NIO direct buffer操作的本地內(nèi)存。
需要注意的是DirectBuffer這個(gè)引用是分配在堆上,受gc控制的,而且記錄分配了多少堆外內(nèi)存的參數(shù)在java.nio.Bits類中,如下圖:

我還讀過(guò)一篇因?yàn)檫@個(gè)參數(shù)造成OOM,其實(shí)本地內(nèi)存并沒(méi)有超限,可惜當(dāng)時(shí)沒(méi)存。
還讀了一篇JVM進(jìn)程無(wú)緣無(wú)故的掛了,后來(lái)看linux日志是本地內(nèi)存用的太多,被操作系統(tǒng)殺死了,可惜也沒(méi)存。
他的回收機(jī)制叫Cleaner機(jī)制,Cleaner實(shí)現(xiàn)了PhantomReference,具體研究下代碼吧,就是如果DirectBuffer被垃圾回收器回收的話,會(huì)通過(guò)通知機(jī)制回收directory memory。
一般給的建議是自己申請(qǐng)的堆外內(nèi)存,不用的時(shí)候最好自己回收下。DirectBuffer接口有個(gè)cleaner()方法可以獲得Cleaner ,調(diào)用Cleaner.clean方法就可以回收堆外內(nèi)存。
2018-12-14補(bǔ)充
最新理解,full gc可以看看gc日志,如果發(fā)生full gc 就會(huì)回收對(duì)yung old permanent區(qū)都進(jìn)行回收
2018-12-26補(bǔ)充 nio buffer用的是內(nèi)核內(nèi)存,主要目的是減少一次從內(nèi)核態(tài)到用戶態(tài)的內(nèi)存拷貝。
