" />

最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java中使用mmap技術(shù)的實現(xiàn)示例

 更新時間:2026年01月28日 09:14:37   作者:Java編程愛好者  
本文主要介紹了java中使用mmap技術(shù)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

jdk21 之后,隨著 FFM 加入并穩(wěn)定,現(xiàn)在 java 中也可以直接使用 mmap 技術(shù)將文件直接映射進內(nèi)存并讀取了,并且沒有 nio 中 21 億的限制(Integer.MAX_VALUE)。

BIO時代

try (FileInputStream fis = new FileInputStream("file.txt")) {
    byte[] buffer = new byte[8192]; // 8KB 緩沖區(qū)
    int bytesRead;
    while ((bytesRead = fis.read(buffer)) != -1) {
        // 處理 buffer 中的前 bytesRead 字節(jié)
    }
}

最早讀取文件就是阻塞讀取,由于 byte[] 是jdk管理,自己傳入的,所以下標(biāo)最大就是21億,而且由于正常情況下由代碼傳入,所以不可能 new byte[Integer.MAX_VALUE],而且 byte[] 回收需要看 gc。

NIO時代(JDK 1.4+)

try (FileChannel channel = FileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ)) {
    MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
}

后來 java 推出了 NIO,但是作者本人實際工作接觸的需要如此優(yōu)化的場景太少,且 api 并不直觀,導(dǎo)致完全沒有用過幾次。返回的 MappedByteBuffer api 中下標(biāo)參數(shù)使用的是 int,這直接導(dǎo)致超過 4G 的文件必須分段映射,且 MappedByteBuffer 映射的內(nèi)存也需要 gc 回收。

屬于初代 mmap 技術(shù),雖然原理上是 mmap,但是限制頗多。

AIO時代(JDK 7+)

本質(zhì)上是 NIO.2,或者叫 new NIO,原則上屬于NIO的一部分

AsynchronousFileChannel

這個 api 更是查無此人,作者并不知道這個應(yīng)該怎么用/有什么性能。

FFM(JDK 22+)

try (var arena = Arena.ofConfined();
     var channel = FileChannel.open(path, StandardOpenOption.READ)) {
    var size = channel.size();
    var memorySegment = channel.map(FileChannel.MapMode.READ_ONLY,
            0,
            size,
            arena
    );

} catch (IOException e) {
    throw new RuntimeException(e);
}

隨著 FFM 穩(wěn)定,原本的 FileChannel api 中也加入了對 FFM 的支持,使用 Arena 配置接下來申請的內(nèi)存的生命周期管理,再將 arena 傳入 channel,返回 MemorySegment,使用 MemorySegment 即可對全文件進行隨機讀寫。arena 關(guān)閉后申請的所有內(nèi)存直接回收,沒有 gc 壓力。

由于調(diào)用的是底層的 mmap 返回的內(nèi)存段,所以直接讀寫 memorySegment 即可直接反應(yīng)到文件上,也可以調(diào)用 MemorySegment#force() 強制寫入。

更加接近底層的 mmap 技術(shù),可選擇是否有 gc 壓力。

讀取示例:

public class MemorySegmentFileTest {
    private static final Path path = Path.of("/home/bin-/Downloads/home/extraData.img");

    static void main() {
        try (var arena = Arena.ofConfined();
             var channel = FileChannel.open(path, StandardOpenOption.READ)) {
            var size = channel.size();
            var memorySegment = channel.map(FileChannel.MapMode.READ_ONLY,
                    0,
                    size,
                    arena
            );

            System.out.println("成功映射文件,大?。? + printSize(size));
            System.out.println("內(nèi)存段地址:" + memorySegment.address());
            System.out.println("內(nèi)存段大小:" + printSize(memorySegment.byteSize()));
            System.out.println("內(nèi)存段內(nèi)容前16字節(jié):");
            for (long i = 0; i < 16; i++) {
                byte b = memorySegment.get(ValueLayout.JAVA_BYTE, i);
                System.out.printf("0x%02X ", b);
            }
            System.out.println();
            System.out.println("內(nèi)存段內(nèi)容后16字節(jié):");
            for (long i = size - 16; i < size; i++) {
                byte b = memorySegment.get(ValueLayout.JAVA_BYTE, i);
                System.out.printf("0x%02X ", b);
            }
            System.out.println();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static String printSize(long size) {
        String[] units = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
        long s = size;
        var list = new ArrayList<String>();
        var builder = new StringBuilder();
        var formatter = new Formatter(builder);
        for (var unit : units) {
            int sub = (int) (s & ((1 << 10) - 1));
            formatter.format("%s %s", sub, unit);
            list.add(builder.toString());
            builder.setLength(0);
            if (s < 1024) {
                break;
            }
            s >>= 10;
        }
        return String.join(" ", list.reversed());
    }
}

原理說明

mmap 只是建立了虛擬內(nèi)存地址到磁盤文件的映射,并沒有真正加載數(shù)據(jù)(Lazy Loading)。只有真正讀取數(shù)據(jù)時,OS 才會發(fā)生缺頁中斷(Page Fault)去加載數(shù)據(jù)。

類似應(yīng)用

  • 數(shù)據(jù)庫系統(tǒng):SQLite、MySQL、Redis
  • Kafka
  • RocketMQ

已知缺點

  • 本質(zhì)是在借用 OS 的 Page Cache,如果同時運行數(shù)據(jù)庫(MySQL/Redis)等應(yīng)用,java 使用 mmap 瘋狂讀取大文件可能會把數(shù)據(jù)庫在 Page Cache 里的熱數(shù)據(jù)擠出去(Eviction)。

結(jié)尾

本文只是提出一種新版本 jdk 的全新 mmap 使用方式,與其他相對較老的方式相比,這種方式可以直接操縱堆外內(nèi)存,且性能更高,還支持隨機讀取,唯一缺點可能就是 api 太新,用起來可能需要重新研究寫法。

到此這篇關(guān)于java中使用mmap技術(shù)的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)java使用mmap技術(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Jenkins配置jdk、maven、git方式

    Jenkins配置jdk、maven、git方式

    為了在Jenkins中使用Java、Maven和Git,需要在系統(tǒng)管理的全局工具配置中設(shè)置這些工具,首先,確保Jenkins主機已經(jīng)安裝了JDK、Git、Maven以及Maven的settings文件,安裝完成后,按照提示配置各個工具
    2023-04-04
  • Java排列組合字符串的方法

    Java排列組合字符串的方法

    這篇文章主要介紹了Java排列組合字符串的方法
    2018-02-02
  • 從JVM分析Java的類的加載和卸載機制

    從JVM分析Java的類的加載和卸載機制

    這篇文章主要介紹了從JVM分析Java的類的加載和卸載機制,講解了Java類的聲明周期,需要的朋友可以參考下
    2015-11-11
  • SpringBoot配置文件注入值的簡單實現(xiàn)

    SpringBoot配置文件注入值的簡單實現(xiàn)

    本文主要介紹了SpringBoot配置文件注入值的簡單實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-11-11
  • Java泛型實現(xiàn)類型安全的通用類型轉(zhuǎn)換器

    Java泛型實現(xiàn)類型安全的通用類型轉(zhuǎn)換器

    在開發(fā)中,我們常常需要在不同類型之間進行轉(zhuǎn)換,為了提高代碼的可讀性與安全性,Java的泛型機制提供了強大的類型檢查能力,下面我們就來看看如何通過泛型實現(xiàn)類型安全的通用轉(zhuǎn)換器
    2024-11-11
  • springboot+thymeleaf+mybatis實現(xiàn)甘特圖的詳細(xì)過程

    springboot+thymeleaf+mybatis實現(xiàn)甘特圖的詳細(xì)過程

    這篇文章主要介紹了springboot+thymeleaf+mybatis實現(xiàn)甘特圖的詳細(xì)過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • 2022版IDEA創(chuàng)建一個maven項目的超詳細(xì)圖文教程

    2022版IDEA創(chuàng)建一個maven項目的超詳細(xì)圖文教程

    IDEA是用于java語言開發(fā)的集成環(huán)境,并且經(jīng)常用于maven、spring、MyBatis等項目的開發(fā),下面這篇文章主要給大家介紹了關(guān)于2022版IDEA創(chuàng)建一個maven項目的超詳細(xì)圖文教程,需要的朋友可以參考下
    2023-02-02
  • 關(guān)于Maven中pom.xml文件配置詳解

    關(guān)于Maven中pom.xml文件配置詳解

    pom.xml是Maven項目的核心配置文件,它描述了項目的結(jié)構(gòu)、依賴關(guān)系、構(gòu)建配置等信息,通過合理配置pom.xml,可以提高項目的可維護性和構(gòu)建效率
    2025-01-01
  • Java語言中&&與& ||與|的區(qū)別是什么

    Java語言中&&與& ||與|的區(qū)別是什么

    這篇文章主要介紹了Java語言中&&與& ||與|的區(qū)別是什么的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • spring多數(shù)據(jù)源配置實現(xiàn)方法實例分析

    spring多數(shù)據(jù)源配置實現(xiàn)方法實例分析

    這篇文章主要介紹了spring多數(shù)據(jù)源配置實現(xiàn)方法,結(jié)合實例形式分析了spring多數(shù)據(jù)源配置相關(guān)操作技巧與使用注意事項,需要的朋友可以參考下
    2019-12-12

最新評論

宁远县| 博客| 诸城市| 张家界市| 荆门市| 隆尧县| 会理县| 望江县| 宁陕县| 澜沧| 白朗县| 喀喇沁旗| 兰西县| 阳信县| 汨罗市| 新平| 隆林| 东台市| 榆林市| 丹凤县| 绵阳市| 自治县| 蒲江县| 余江县| 苍南县| 宁津县| 大连市| 墨江| 广州市| 宁化县| 宁海县| 澄城县| 新田县| 柳林县| 资源县| 南阳市| 镇坪县| 淳安县| 怀化市| 盐山县| 文登市|