色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

JAVA中NIO通過MappedByteBuffer操作大文件

汽車玩家 ? 來源:IT知識課堂 ? 作者:IT知識課堂 ? 2020-05-05 23:42 ? 次閱讀

java io操作中通常采用BufferedReader,BufferedInputStream等帶緩沖的IO類處理大文件,不過java nio中引入了一種基于MappedByteBuffer操作大文件的方式,其讀寫性能極高,本文會介紹其性能如此高的內部實現原理。

內存管理

在深入MappedByteBuffer之前,先看看計算機內存管理的幾個術語:

MMC:CPU的內存管理單元。

物理內存:即內存條的內存空間。

虛擬內存:計算機系統內存管理的一種技術。它使得應用程序認為它擁有連續的可用的內存(一個連續完整的地址空間),而實際上,它通常是被分隔成多個物理內存碎片,還有部分暫時存儲在外部磁盤存儲器上,在需要時進行數據交換。

頁面文件:操作系統反映構建并使用虛擬內存的硬盤空間大小而創建的文件,在windows下,即pagefile.sys文件,其存在意味著物理內存被占滿后,將暫時不用的數據移動到硬盤上。

缺頁中斷:當程序試圖訪問已映射在虛擬地址空間中但未被加載至物理內存的一個分頁時,由MMC發出的中斷。如果操作系統判斷此次訪問是有效的,則嘗試將相關的頁從虛擬內存文件中載入物理內存。

為什么會有虛擬內存和物理內存的區別?
如果正在運行的一個進程,它所需的內存是有可能大于內存條容量之和的,如內存條是256M,程序卻要創建一個2G的數據區,那么所有數據不可能都加載到內存(物理內存),必然有數據要放到其他介質中(比如硬盤),待進程需要訪問那部分數據時,再調度進入物理內存。

什么是虛擬內存地址和物理內存地址?
假設你的計算機是32位,那么它的地址總線是32位的,也就是它可以尋址00xFFFFFFFF(4G)的地址空間,但如果你的計算機只有256M的物理內存0x0x0FFFFFFF(256M),同時你的進程產生了一個不在這256M地址空間中的地址,那么計算機該如何處理呢?回答這個問題前,先說明計算機的內存分頁機制。

計算機會對虛擬內存地址空間(32位為4G)進行分頁產生頁(page),對物理內存地址空間(假設256M)進行分頁產生頁幀(page frame),頁和頁幀的大小一樣,所以虛擬內存頁的個數勢必要大于物理內存頁幀的個數。在計算機上有一個頁表(page table),就是映射虛擬內存頁到物理內存頁的,更確切的說是頁號到頁幀號的映射,而且是一對一的映射。
問題來了,虛擬內存頁的個數 > 物理內存頁幀的個數,豈不是有些虛擬內存頁的地址永遠沒有對應的物理內存地址空間?不是的,操作系統是這樣處理的。操作系統有個頁面失效(page fault)功能。操作系統找到一個最少使用的頁幀,使之失效,并把它寫入磁盤,隨后把需要訪問的頁放到頁幀中,并修改頁表中的映射,保證了所有的頁都會被調度。

現在來看看什么是虛擬內存地址和物理內存地址:

虛擬內存地址:由頁號(與頁表中的頁號關聯)和偏移量(頁的小大,即這個頁能存多少數據)組成。

舉個例子,有一個虛擬地址它的頁號是4,偏移量是20,那么他的尋址過程是這樣的:首先到頁表中找到頁號4對應的頁幀號(比如為8),如果頁不在內存中,則用失效機制調入頁,接著把頁幀號和偏移量傳給MMC組成一個物理上真正存在的地址,最后就是訪問物理內存的數據了。

MappedByteBuffer是什么

從繼承結構上看,MappedByteBuffer繼承自ByteBuffer,內部維護了一個邏輯地址address。

示例

通過MappedByteBuffer讀取文件

JAVA中NIO通過MappedByteBuffer操作大文件

map過程

FileChannel提供了map方法把文件映射到虛擬內存,通常情況可以映射整個文件,如果文件比較大,可以進行分段映射。

FileChannel中的幾個變量:MapMode mode:內存映像文件訪問的方式,共三種: MapMode.READ_ONLY:只讀,試圖修改得到的緩沖區將導致拋出異常。 MapMode.READ_WRITE:讀/寫,對得到的緩沖區的更改最終將寫入文件;但該更改對映射到同一文件的其他程序不一定是可見的。 MapMode.PRIVATE:私用,可讀可寫,但是修改的內容不會寫入文件,只是buffer自身的改變,這種能力稱之為”copy on write”。position:文件映射時的起始位置。allocationGranularity:Memory allocation size for mapping buffers,通過native函數initIDs初始化。

接下去通過分析源碼,了解一下map過程的內部實現。

通過RandomAccessFile獲取FileChannel。

JAVA中NIO通過MappedByteBuffer操作大文件

上述實現可以看出,由于synchronized ,只有一個線程能夠初始化FileChannel。

通過FileChannel.map方法,把文件映射到虛擬內存,并返回邏輯地址address,實現如下:

JAVA中NIO通過MappedByteBuffer操作大文件

上述代碼可以看出,最終map通過native函數map0完成文件的映射工作。
1. 如果第一次文件映射導致OOM,則手動觸發垃圾回收,休眠100ms后再次嘗試映射,如果失敗,則拋出異常。
2. 通過newMappedByteBuffer方法初始化MappedByteBuffer實例,不過其最終返回的是DirectByteBuffer的實例,實現如下:

JAVA中NIO通過MappedByteBuffer操作大文件

由于FileChannelImpl和DirectByteBuffer不在同一個包中,所以有權限訪問問題,通過AccessController類獲取DirectByteBuffer的構造器進行實例化。

DirectByteBuffer是MappedByteBuffer的一個子類,其實現了對內存的直接操作。

get過程

MappedByteBuffer的get方法最終通過DirectByteBuffer.get方法實現的。

JAVA中NIO通過MappedByteBuffer操作大文件

map0()函數返回一個地址address,這樣就無需調用read或write方法對文件進行讀寫,通過address就能夠操作文件。底層采用unsafe.getByte方法,通過(address + 偏移量)獲取指定內存的數據。

第一次訪問address所指向的內存區域,導致缺頁中斷,中斷響應函數會在交換區中查找相對應的頁面,如果找不到(也就是該文件從來沒有被讀入內存的情況),則從硬盤上將文件指定頁讀取到物理內存中(非jvm堆內存)。

如果在拷貝數據時,發現物理內存不夠用,則會通過虛擬內存機制(swap)將暫時不用的物理頁面交換到硬盤的虛擬內存中。

性能分析

從代碼層面上看,從硬盤上將文件讀入內存,都要經過文件系統進行數據拷貝,并且數據拷貝操作是由文件系統和硬件驅動實現的,理論上來說,拷貝數據的效率是一樣的。
但是通過內存映射的方法訪問硬盤上的文件,效率要比read和write系統調用高,這是為什么?

read()是系統調用,首先將文件從硬盤拷貝到內核空間的一個緩沖區,再將這些數據拷貝到用戶空間,實際上進行了兩次數據拷貝;

map()也是系統調用,但沒有進行數據拷貝,當缺頁中斷發生時,直接將文件從硬盤拷貝到用戶空間,只進行了一次數據拷貝。

所以,采用內存映射的讀寫效率要比傳統的read/write性能高。

總結

MappedByteBuffer使用虛擬內存,因此分配(map)的內存大小不受JVM的-Xmx參數限制,但是也是有大小限制的。

如果當文件超出1.5G限制時,可以通過position參數重新map文件后面的內容。

MappedByteBuffer在處理大文件時的確性能很高,但也存在一些問題,如內存占用、文件關閉不確定,被其打開的文件只有在垃圾回收的才會被關閉,而且這個時間點是不確定的。
javadoc中也提到:A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.*

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3081

    瀏覽量

    74604
  • JAVA
    +關注

    關注

    19

    文章

    2980

    瀏覽量

    105715
收藏 人收藏

    評論

    相關推薦

    鴻蒙文件傳輸三方庫上線開源鴻蒙社區 十行代碼實現大文件高速傳輸

    、斷點續下、分片上傳、斷點續傳、自動重試等多個特性的高性能文件傳輸解決方案,讓開發者開箱即用,輕松實現高效穩定的文件傳輸功能。 在應用開發過程,許多場景涉及到大文件的傳輸,尤其是在
    發表于 03-06 10:29

    hyper-v 文件,Hyper-V文件管理:高效操作指南

    在日常辦公,我們常常需要對大量文件或數據進行重復性操作,比如批量修改文件名、批量更新數據等。這些任務不僅耗時費力,還容易出錯。幸運的是,批量管理工具的出現為我們提供了一種高效的解決方
    的頭像 發表于 02-06 10:27 ?219次閱讀
    hyper-v <b class='flag-5'>文件</b>,Hyper-V<b class='flag-5'>文件</b>管理:高效<b class='flag-5'>操作</b>指南

    Spire.XLS for Android via Java組件說明

    Spire.XLS for Android via Java 是一款專業的 Android Excel 組件,用于在 Android 手機應用程序創建、操作和轉換 Excel 工作表,并且運行環境
    的頭像 發表于 01-24 12:16 ?186次閱讀
    Spire.XLS for Android via <b class='flag-5'>Java</b>組件說明

    SSM框架在Java開發的應用 如何使用SSM進行web開發

    SSM框架,即Spring、SpringMVC和MyBatis的整合,是Java Web開發中常用的技術棧。它通過分層架構,實現了視圖、控制、業務邏輯和數據訪問的分離,提高了代碼的可維護性和可擴展性
    的頭像 發表于 12-16 17:28 ?812次閱讀

    如何使用SFTP傳輸大文件

    在當今的數字化時代,大文件傳輸變得越來越常見。無論是企業數據遷移、遠程備份還是內容分發,都需要一種既安全又高效的文件傳輸方式。SFTP作為一種基于SSH的文件傳輸協議,提供了一種加密的傳輸方式,確保
    的頭像 發表于 11-13 14:11 ?1221次閱讀

    Windows連接P2Link的FTP服務——遠程操作文件

    FTP協議允許用戶通過客戶端軟件連接到FTP服務器,進行文件的上傳、下載、刪除、重命名等操作。P2Link可快速為本地文件目錄提供公網FTP服務地址,用于遠程
    的頭像 發表于 11-13 11:48 ?405次閱讀
    Windows連接P2Link的FTP服務——遠程<b class='flag-5'>操作文件</b>

    Java時間戳的使用

    Java時間戳的使用
    的頭像 發表于 11-06 16:04 ?315次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>中</b>時間戳的使用

    怎么在JAVA確定線性池大小

    JAVA確定線性池大小,分別介紹CPU密集型任務和I/O密集型任務及其處理方法。
    的頭像 發表于 10-24 14:02 ?276次閱讀

    java反編譯能拿到源碼嗎

    Java反編譯是一種將編譯后的Java字節碼(.class文件)轉換回Java源代碼的過程。雖然反編譯可以幫助理解代碼的邏輯和結構,但它并不總是能完美地還原原始源代碼。反編譯工具通常會
    的頭像 發表于 09-02 11:03 ?1348次閱讀

    如何修改buildroot和debian文件系統

    本文檔主要介紹在沒有編譯環境的情況下,如何修改buildroot和debian文件系統方法,如在buildroot文件系統添加文件、修改目錄等文件
    的頭像 發表于 07-22 17:46 ?646次閱讀
    如何修改buildroot和debian<b class='flag-5'>文件</b>系統

    如何實現Python復制文件操作

    Python 中有許多“開蓋即食”的模塊(比如 os,subprocess 和 shutil)以支持文件 I/O 操作。在這篇文章,你將會看到一些用 Python 實現文件復制的特殊
    的頭像 發表于 07-18 14:53 ?536次閱讀

    華納云:java web和java有什么區別java web和java有什么區別

    的平臺,Java可以用于開發桌面應用程序、移動應用程序、企業級應用程序等。 – Java Web是Java語言在Web開發領域的應用,它使用Java技術來構建動態的Web應用程序,這些
    的頭像 發表于 07-16 13:35 ?1119次閱讀
    華納云:<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別

    esp32如何一次性讀取大文件數據?

    esp32沒有提供數據庫讀寫的例子,最近有個大文件,無法一次性讀出,請問,怎么讀取,json中一部分json數組。然后修改完了以后,在寫入進去?
    發表于 06-25 06:52

    使用ESP32-S3開發板http post請求發送SD卡上的大文件,如何循環邊讀取文件邊分塊發送文件呢?

    您和,我準備使用ESP32-S3開發板http post請求發送SD卡上的大文件,但是使用esp_http_client_set_post_field的buffer太小,內存不能一次性申請太大,請問
    發表于 06-06 06:19

    java實現多線程的幾種方式

    Java實現多線程的幾種方式 多線程是指程序包含了兩個或以上的線程,每個線程都可以并行執行不同的任務或操作Java的多線程可以提高程序
    的頭像 發表于 03-14 16:55 ?858次閱讀
    主站蜘蛛池模板: 亚洲免费人成 久久 | 综合一区无套内射中文字幕 | www.精品视频 | 无套日出白浆在线播放 | 国产AV亚洲精品久久久久 | 2021国产精品久久久久精品免费网 | 国家产午夜精品无人区 | 精品一卡2卡三卡4卡乱码精品视频 | 琪琪色在线播放 | 337p欧洲亚大胆精品 | 性啪啪chinese东北女人 | 久久高清免费视频 | 国产精品看高国产精品不卡 | 国产69精品久久久久APP下载 | 吃奶啃奶玩乳漫画 | 一本之道高清在线观看免费 | 国产极品美女视频福利 | 亚洲国产精品嫩草影院久久 | 最近中文字幕在线看免费完整版 | 欧美日本高清动作片www网站 | 色一欲一性一乱一区二区三区 | 福利片福利一区二区三区 | 亚洲免费无l码中文在线视频 | 成人天堂婷婷青青视频在线观看 | 美女挑战50厘米长的黑人 | 国产精品97久久AV色婷婷 | 欧美一区二区三区激情视频 | 爱豆剧果冻传媒在线播放 | 猫咪av永久最新域名 | 鲁一鲁亚洲无线码 | 中文字幕一区二区三区在线观看 | 先锋影音 av | 亚洲精品影院久久久久久 | 午夜国产精品视频在线 | 男女做爽爽爽视频免费软件 | 国产人妻人伦精品无码.麻豆 | 久久久久久久网站 | 亚洲AV无码一区二区三区牛牛 | 国产精品国产三级国产AV麻豆 | 先锋影音av无码第1页 | 好大好爽好深舒服死了 |