堆外內存

什么是堆外內存

堆外內存也叫直接內存(Direct Memory)赊堪,并不是JVM內存區(qū)域的一部分祝旷,也不是《Java虛擬機規(guī)范》中定義的內存區(qū)域履澳。
JDK1.4引入了NIO包(new input/output),引入了一種基于通道(Channel)和緩沖區(qū)(Buffer)的IO方式怀跛,可以使用native函數直接分配堆外內存距贷,然后通過一個存儲在Java堆里的DirectByteBuffer對象作為這塊內存的引用進行操作。在一些場景中可以顯著提高性能吻谋,因為避免了在Java對和Native堆中來回復制數據忠蝗。
申請堆外內存時,如果空間不足漓拾,會拋出java.lang.OutOfMemoryError: Direct buffer memory

堆外內存的優(yōu)勢

  1. 堆外內存受操作系統(tǒng)管理阁最,不受JVM管理,可以減少JVM GC壓力骇两,減輕JVM垃圾回收對程序性能的影響速种。
  2. 提高IO效率
  3. 堆內內存屬于用戶態(tài)的緩沖區(qū),堆外內存屬于內核態(tài)的緩沖區(qū)
  4. 如果從堆向磁盤/網卡寫數據低千,需要CPU把數據復制從用戶態(tài)復制到內核態(tài)配阵,再由操作系統(tǒng)DMA從內核態(tài)復制到磁盤/網卡。
  5. 如果直接從堆外內存向磁盤/網卡寫數據,可以省略掉用戶態(tài)到內核態(tài)的復制


    image.png

堆外內存的缺點

  1. 需要自行分配和回收內存闸餐,增加了復雜度
  2. 如果回收內存處理不當饱亮,容易引發(fā)內存泄漏,并且難以排查
    堆外內存引發(fā)內存泄漏排查: https://mp.weixin.qq.com/s/55slokngVRgqEav6c3TxOA

堆外內存的使用

  1. 調用java.nio.ByteBuffer的allocateDirect方法舍沙,最終會調用sun.misc.Unsafe#allocateMemory近上,相當于C++的malloc函數
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
  1. 可以通過設置-XX:MaxDirectMemorySize=10M控制堆外內存的使用上限

使用場景

  1. 常駐在本地內存的本地緩存,比如國家拂铡、省份壹无、城市信息等,長期駐扎在老年代感帅。

堆外內存的回收

  1. 等到full gc的時候垃圾回收
    堆外內存對應的Java對象引用在堆里斗锭,受JVM垃圾回收的管理,一旦該對象引用被回收失球,JVM會釋放對應的堆外內存
  2. 程序手動回收
private void clean (ByteBuffer byteBuffer) {
    if (byteBuffer.isDirect()) {
        ((DirectBuffer)byteBuffer).cleaner().clean();
    }
}

堆外內存緩存框架

https://mp.weixin.qq.com/s/YYMnXRFyozHpsmRwN-vvGQ

  1. 引入依賴
<dependency>
    <groupId>org.caffinitas.ohc</groupId>
    <artifactId>ohc-core</artifactId>
    <version>0.7.4</version>
</dependency>
  1. 自定義序列化岖是、反序列器,調用put实苞、get方法進行寫入和讀取豺撑,操作類似HashMap
import org.apache.commons.io.Charsets;
import org.caffinitas.ohc.CacheSerializer;
import org.caffinitas.ohc.OHCache;
import org.caffinitas.ohc.OHCacheBuilder;

import java.nio.ByteBuffer;

public class OhcDemo {
    public static void main(String[] args) {
        OHCache ohCache = OHCacheBuilder.<String, String>newBuilder()
                .keySerializer(OhcDemo.stringSerializer)
                .valueSerializer(OhcDemo.stringSerializer)
                .build();
        ohCache.put("hello","why");
        System.out.println("ohCache.get(hello) = " + ohCache.get("hello"));
    }

    public static final CacheSerializer<String> stringSerializer = new CacheSerializer<String>() {
        public void serialize(String s, ByteBuffer buf) {
            // 得到字符串對象UTF-8編碼的字節(jié)數組
            byte[] bytes = s.getBytes(Charsets.UTF_8);
            // 用前16位記錄數組長度
            buf.put((byte) ((bytes.length >>> 8) & 0xFF));
            buf.put((byte) ((bytes.length) & 0xFF));
            buf.put(bytes);
        }

        public String deserialize(ByteBuffer buf) {
            // 獲取字節(jié)數組的長度
            int length = (((buf.get() & 0xff) << 8) + ((buf.get() & 0xff)));
            byte[] bytes = new byte[length];
            // 讀取字節(jié)數組
            buf.get(bytes);
            // 返回字符串對象
            return new String(bytes, Charsets.UTF_8);
        }

        public int serializedSize(String s) {
            byte[] bytes = s.getBytes(Charsets.UTF_8);
            // 設置字符串長度限制,2^16 = 65536
            if (bytes.length > 65535)
                throw new RuntimeException("encoded string too long: " + bytes.length + " bytes");

            return bytes.length + 2;
        }
    };
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末黔牵,一起剝皮案震驚了整個濱河市聪轿,隨后出現的幾起案子,更是在濱河造成了極大的恐慌猾浦,老刑警劉巖陆错,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異金赦,居然都是意外死亡音瓷,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門夹抗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來外莲,“玉大人,你說我怎么就攤上這事兔朦。” “怎么了磨确?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵沽甥,是天一觀的道長。 經常有香客問我乏奥,道長摆舟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮恨诱,結果婚禮上媳瞪,老公的妹妹穿的比我還像新娘。我一直安慰自己照宝,他們只是感情好蛇受,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厕鹃,像睡著了一般兢仰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剂碴,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天把将,我揣著相機與錄音,去河邊找鬼忆矛。 笑死察蹲,一個胖子當著我的面吹牛,可吹牛的內容都是我干的催训。 我是一名探鬼主播洽议,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瞳腌!你這毒婦竟也來了绞铃?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤嫂侍,失蹤者是張志新(化名)和其女友劉穎儿捧,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體挑宠,經...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡菲盾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了各淀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片懒鉴。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碎浇,靈堂內的尸體忽然破棺而出临谱,到底是詐尸還是另有隱情,我是刑警寧澤奴璃,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布悉默,位于F島的核電站,受9級特大地震影響苟穆,放射性物質發(fā)生泄漏抄课。R本人自食惡果不足惜唱星,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跟磨。 院中可真熱鬧间聊,春花似錦、人聲如沸抵拘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仑濒。三九已至叹话,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間墩瞳,已是汗流浹背驼壶。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留喉酌,地道東北人热凹。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像泪电,于是被迫代替她去往敵國和親般妙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容