堆外內(nèi)存——DirectByteBuffer

原文

https://www.cnblogs.com/moonandstar08/p/5107648.html

簡介

堆內(nèi)存完全由JVM負(fù)責(zé)分配和釋放,如果程序沒有缺陷代碼導(dǎo)致內(nèi)存泄露,那么就不會(huì)遇到j(luò)ava.lang.OutOfMemoryError這個(gè)錯(cuò)誤琳钉。
使用堆外內(nèi)存瓦糕,就是為了能直接分配和釋放內(nèi)存,提高效率苍息。JDK5.0之后,代碼中能直接操作本地內(nèi)存的方式有2種:使用未公開的Unsafe和NIO包下ByteBuffer。
關(guān)于Unsafe對象的簡介和獲取方式,可以參考:http://blog.csdn.net/aitangyong/article/details/38276681
使用ByteBuffer分配本地內(nèi)存則非常簡單屈藐,直接ByteBuffer.allocateDirect(10 * 1024 * 1024)即可。

ByteBuffer使用

package com.mergades.nio;

import java.nio.ByteBuffer;

public class TestByteBuffer {

    //運(yùn)行參數(shù)   -verbose:gc -XX:+PrintGCDetails -XX:DisableExplicitGC -XX:MaxDirectMemorySize=10M
    public static void main(String[] args) {
        while (true) {
            ByteBuffer bb = ByteBuffer.allocateDirect(10 * 1024 * 1024);
        }
    }
}

增加了-XX:+DisableExplicitGC熙尉,這個(gè)參數(shù)作用是禁止代碼中顯示調(diào)用GC联逻。代碼如何顯示調(diào)用GC呢,通過System.gc()函數(shù)調(diào)用检痰。如果加上了這個(gè)JVM啟動(dòng)參數(shù)包归,那么代碼中調(diào)用System.gc()沒有任何效果,相當(dāng)于是沒有這行代碼一樣铅歼。

顯然堆內(nèi)存(包括新生代和老年代)內(nèi)存很充足公壤,但是堆外內(nèi)存溢出了。也就是說NIO直接內(nèi)存的回收椎椰,需要依賴于System.gc()厦幅。如果我們的應(yīng)用中使用了java nio中的direct memory,那么使用-XX:+DisableExplicitGC一定要小心慨飘,存在潛在的內(nèi)存泄露風(fēng)險(xiǎn)慨削。
我們知道java代碼無法強(qiáng)制JVM何時(shí)進(jìn)行垃圾回收,也就是說垃圾回收這個(gè)動(dòng)作的觸發(fā)套媚,完全由JVM自己控制缚态,它會(huì)挑選合適的時(shí)機(jī)回收堆內(nèi)存中的無用java對象。代碼中顯示調(diào)用System.gc()堤瘤,只是建議JVM進(jìn)行垃圾回收玫芦,但是到底會(huì)不會(huì)執(zhí)行垃圾回收是不確定的,可能會(huì)進(jìn)行垃圾回收本辐,也可能不會(huì)桥帆。什么時(shí)候才是合適的時(shí)機(jī)呢医增?一般來說是,系統(tǒng)比較空閑的時(shí)候(比如JVM中活動(dòng)的線程很少的時(shí)候)老虫,還有就是內(nèi)存不足叶骨,不得不進(jìn)行垃圾回收。我們例子中的根本矛盾在于:堆內(nèi)存由JVM自己管理祈匙,堆外內(nèi)存必須要由我們自己釋放忽刽;堆內(nèi)存的消耗速度遠(yuǎn)遠(yuǎn)小于堆外內(nèi)存的消耗,但要命的是必須先釋放堆內(nèi)存中的對象夺欲,才能釋放堆外內(nèi)存跪帝,但是我們又不能強(qiáng)制JVM釋放堆內(nèi)存。

Direct Memory的回收機(jī)制:Direct Memory是受GC控制的些阅,例如ByteBuffer bb = ByteBuffer.allocateDirect(1024)伞剑,這段代碼的執(zhí)行會(huì)在堆外占用1k的內(nèi)存,Java堆內(nèi)只會(huì)占用一個(gè)對象的指針引用的大小市埋,堆外的這1k的空間只有當(dāng)bb對象被回收時(shí)黎泣,才會(huì)被回收,這里會(huì)發(fā)現(xiàn)一個(gè)明顯的不對稱現(xiàn)象缤谎,就是堆外可能占用了很多聘裁,而堆內(nèi)沒占用多少,導(dǎo)致還沒觸發(fā)GC弓千,那就很容易出現(xiàn)Direct Memory造成物理內(nèi)存耗光。

Direct ByteBuffer分配出去的內(nèi)存其實(shí)也是由GC負(fù)責(zé)回收的献起,而不像Unsafe是完全自行管理的洋访,Hotspot在GC時(shí)會(huì)掃描Direct ByteBuffer對象是否有引用,如沒有則同時(shí)也會(huì)回收其占用的堆外內(nèi)存谴餐。

參考:
http://blog.csdn.net/aitangyong/article/details/39403031
http://blog.csdn.net/aitangyong/article/category/2159887
http://blog.csdn.net/aitangyong/article/details/39323125
http://hellojava.info/?p=56
http://hellojava.info/?tag=maxdirectmemorysize
https://yq.aliyun.com/articles/2948

使用堆外內(nèi)存與對象池都能減少GC的暫停時(shí)間姻政,這是它們唯一的共同點(diǎn)。生命周期短的可變對象岂嗓,創(chuàng)建開銷大汁展,或者生命周期雖長但存在冗余的可變對象都比較適合使用對象池。生命周期適中厌殉,或者復(fù)雜的對象則比較適合由GC來進(jìn)行處理食绿。然而,中長生命周期的可變對象就比較棘手了公罕,堆外內(nèi)存則正是它們的菜器紧。

堆外內(nèi)存的好處是:

(1)可以擴(kuò)展至更大的內(nèi)存空間。比如超過1TB甚至比主存還大的空間;

(2)理論上能減少GC暫停時(shí)間;

(3)可以在進(jìn)程間共享楼眷,減少JVM間的對象復(fù)制铲汪,使得JVM的分割部署更容易實(shí)現(xiàn);

(4)它的持久化存儲(chǔ)可以支持快速重啟熊尉,同時(shí)還能夠在測試環(huán)境中重現(xiàn)生產(chǎn)數(shù)據(jù)

站在系統(tǒng)設(shè)計(jì)的角度來看,使用堆外內(nèi)存可以為你的設(shè)計(jì)提供更多可能掌腰。最重要的提升并不在于性能狰住,而是決定性的

堆外內(nèi)存說明請參見:http://ju.outofmemory.cn/entry/200574

http://blog.csdn.net/aitangyong/article/category/2159887

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市齿梁,隨后出現(xiàn)的幾起案子催植,更是在濱河造成了極大的恐慌,老刑警劉巖士飒,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件查邢,死亡現(xiàn)場離奇詭異,居然都是意外死亡酵幕,警方通過查閱死者的電腦和手機(jī)扰藕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芳撒,“玉大人邓深,你說我怎么就攤上這事”噬玻” “怎么了芥备?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舌菜。 經(jīng)常有香客問我萌壳,道長,這世上最難降的妖魔是什么日月? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任袱瓮,我火速辦了婚禮,結(jié)果婚禮上爱咬,老公的妹妹穿的比我還像新娘尺借。我一直安慰自己,他們只是感情好精拟,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布燎斩。 她就那樣靜靜地躺著,像睡著了一般蜂绎。 火紅的嫁衣襯著肌膚如雪栅表。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天师枣,我揣著相機(jī)與錄音谨读,去河邊找鬼。 笑死坛吁,一個(gè)胖子當(dāng)著我的面吹牛劳殖,可吹牛的內(nèi)容都是我干的铐尚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼哆姻,長吁一口氣:“原來是場噩夢啊……” “哼宣增!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起矛缨,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤爹脾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后箕昭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灵妨,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年落竹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泌霍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡述召,死狀恐怖朱转,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情积暖,我是刑警寧澤藤为,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站夺刑,受9級(jí)特大地震影響缅疟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜遍愿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一存淫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧错览,春花似錦、人聲如沸煌往。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刽脖。三九已至羞海,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曲管,已是汗流浹背却邓。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留院水,地道東北人腊徙。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓简十,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撬腾。 傳聞我的和親對象是個(gè)殘疾皇子螟蝙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359