在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

JAVA中NIO通過MappedByteBuffer操作大文件

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

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

內(nèi)存管理

在深入MappedByteBuffer之前,先看看計算機(jī)內(nèi)存管理的幾個術(shù)語:

MMC:CPU的內(nèi)存管理單元。

物理內(nèi)存:即內(nèi)存條的內(nèi)存空間。

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

頁面文件:操作系統(tǒng)反映構(gòu)建并使用虛擬內(nèi)存的硬盤空間大小而創(chuàng)建的文件,在windows下,即pagefile.sys文件,其存在意味著物理內(nèi)存被占滿后,將暫時不用的數(shù)據(jù)移動到硬盤上。

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

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

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

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

現(xiàn)在來看看什么是虛擬內(nèi)存地址和物理內(nèi)存地址:

虛擬內(nèi)存地址:由頁號(與頁表中的頁號關(guān)聯(lián))和偏移量(頁的小大,即這個頁能存多少數(shù)據(jù))組成。

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

MappedByteBuffer是什么

從繼承結(jié)構(gòu)上看,MappedByteBuffer繼承自ByteBuffer,內(nèi)部維護(hù)了一個邏輯地址address。

示例

通過MappedByteBuffer讀取文件

JAVA中NIO通過MappedByteBuffer操作大文件

map過程

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

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

接下去通過分析源碼,了解一下map過程的內(nèi)部實(shí)現(xiàn)。

通過RandomAccessFile獲取FileChannel。

JAVA中NIO通過MappedByteBuffer操作大文件

上述實(shí)現(xiàn)可以看出,由于synchronized ,只有一個線程能夠初始化FileChannel。

通過FileChannel.map方法,把文件映射到虛擬內(nèi)存,并返回邏輯地址address,實(shí)現(xiàn)如下:

JAVA中NIO通過MappedByteBuffer操作大文件

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

JAVA中NIO通過MappedByteBuffer操作大文件

由于FileChannelImpl和DirectByteBuffer不在同一個包中,所以有權(quán)限訪問問題,通過AccessController類獲取DirectByteBuffer的構(gòu)造器進(jìn)行實(shí)例化。

DirectByteBuffer是MappedByteBuffer的一個子類,其實(shí)現(xiàn)了對內(nèi)存的直接操作。

get過程

MappedByteBuffer的get方法最終通過DirectByteBuffer.get方法實(shí)現(xiàn)的。

JAVA中NIO通過MappedByteBuffer操作大文件

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

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

如果在拷貝數(shù)據(jù)時,發(fā)現(xiàn)物理內(nèi)存不夠用,則會通過虛擬內(nèi)存機(jī)制(swap)將暫時不用的物理頁面交換到硬盤的虛擬內(nèi)存中。

性能分析

從代碼層面上看,從硬盤上將文件讀入內(nèi)存,都要經(jīng)過文件系統(tǒng)進(jìn)行數(shù)據(jù)拷貝,并且數(shù)據(jù)拷貝操作是由文件系統(tǒng)和硬件驅(qū)動實(shí)現(xiàn)的,理論上來說,拷貝數(shù)據(jù)的效率是一樣的。
但是通過內(nèi)存映射的方法訪問硬盤上的文件,效率要比read和write系統(tǒng)調(diào)用高,這是為什么?

read()是系統(tǒng)調(diào)用,首先將文件從硬盤拷貝到內(nèi)核空間的一個緩沖區(qū),再將這些數(shù)據(jù)拷貝到用戶空間,實(shí)際上進(jìn)行了兩次數(shù)據(jù)拷貝;

map()也是系統(tǒng)調(diào)用,但沒有進(jìn)行數(shù)據(jù)拷貝,當(dāng)缺頁中斷發(fā)生時,直接將文件從硬盤拷貝到用戶空間,只進(jìn)行了一次數(shù)據(jù)拷貝。

所以,采用內(nèi)存映射的讀寫效率要比傳統(tǒng)的read/write性能高。

總結(jié)

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

如果當(dāng)文件超出1.5G限制時,可以通過position參數(shù)重新map文件后面的內(nèi)容。

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

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3109

    瀏覽量

    75003
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2985

    瀏覽量

    106936
收藏 人收藏

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    基于RK3576開發(fā)板的INI文件操作

    ”的表達(dá)方式為[Section1 Name],以括號“[]”包圍起來,它用來表示一個段落的開始,因INI文件可能是整個項目共用的,所以需要使用“節(jié)”來區(qū)分不同用途的參數(shù)區(qū)。“鍵”與“值”的組合表達(dá)方式為
    的頭像 發(fā)表于 05-12 14:47 ?830次閱讀
    基于RK3576開發(fā)板的INI<b class='flag-5'>文件</b><b class='flag-5'>操作</b>

    鴻蒙文件傳輸三方庫上線開源鴻蒙社區(qū) 十行代碼實(shí)現(xiàn)大文件高速傳輸

    、斷點(diǎn)續(xù)下、分片上傳、斷點(diǎn)續(xù)傳、自動重試等多個特性的高性能文件傳輸解決方案,讓開發(fā)者開箱即用,輕松實(shí)現(xiàn)高效穩(wěn)定的文件傳輸功能。 在應(yīng)用開發(fā)過程,許多場景涉及到大文件的傳輸,尤其是在
    發(fā)表于 03-06 10:29

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

    在日常辦公,我們常常需要對大量文件或數(shù)據(jù)進(jìn)行重復(fù)性操作,比如批量修改文件名、批量更新數(shù)據(jù)等。這些任務(wù)不僅耗時費(fèi)力,還容易出錯。幸運(yùn)的是,批量管理工具的出現(xiàn)為我們提供了一種高效的解決方
    的頭像 發(fā)表于 02-06 10:27 ?565次閱讀
    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 是一款專業(yè)的 Android Excel 組件,用于在 Android 手機(jī)應(yīng)用程序創(chuàng)建、操作和轉(zhuǎn)換 Excel 工作表,并且運(yùn)行環(huán)境
    的頭像 發(fā)表于 01-24 12:16 ?421次閱讀
    Spire.XLS for Android via <b class='flag-5'>Java</b>組件說明

    SSM框架在Java開發(fā)的應(yīng)用 如何使用SSM進(jìn)行web開發(fā)

    SSM框架,即Spring、SpringMVC和MyBatis的整合,是Java Web開發(fā)中常用的技術(shù)棧。它通過分層架構(gòu),實(shí)現(xiàn)了視圖、控制、業(yè)務(wù)邏輯和數(shù)據(jù)訪問的分離,提高了代碼的可維護(hù)性和可擴(kuò)展性
    的頭像 發(fā)表于 12-16 17:28 ?1456次閱讀

    如何使用SFTP傳輸大文件

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

    Windows連接P2Link的FTP服務(wù)——遠(yuǎn)程操作文件

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

    Java時間戳的使用

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

    P2Link是什么?——免費(fèi)讓你體驗高效智聯(lián)的新方式

    P2Link 是一個非常方便、簡單的工具,可以幫你直接傳輸大文件,或者讓別人訪問你內(nèi)網(wǎng)的服務(wù)。它不像傳統(tǒng)工具需要復(fù)雜的配置,也沒有上傳到云端的煩惱。特別適合那些臨時共享文件、傳大文件
    的頭像 發(fā)表于 10-31 14:11 ?602次閱讀

    怎么在JAVA確定線性池大小

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

    java反編譯能拿到源碼嗎

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

    如何修改buildroot和debian文件系統(tǒng)

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

    如何實(shí)現(xiàn)Python復(fù)制文件操作

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

    華納云:java web和java有什么區(qū)別java web和java有什么區(qū)別

    的平臺,Java可以用于開發(fā)桌面應(yīng)用程序、移動應(yīng)用程序、企業(yè)級應(yīng)用程序等。 – Java Web是Java語言在Web開發(fā)領(lǐng)域的應(yīng)用,它使用Java技術(shù)來構(gòu)建動態(tài)的Web應(yīng)用程序,這些
    的頭像 發(fā)表于 07-16 13:35 ?1369次閱讀
    華納云:<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區(qū)別<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區(qū)別

    esp32如何一次性讀取大文件數(shù)據(jù)?

    esp32沒有提供數(shù)據(jù)庫讀寫的例子,最近有個大文件,無法一次性讀出,請問,怎么讀取,json中一部分json數(shù)組。然后修改完了以后,在寫入進(jìn)去?
    發(fā)表于 06-25 06:52
    主站蜘蛛池模板: 久久久久无码国产精品一区 | 天堂中文在线最新版地址 | 大尺度在线播放 | 天天干夜夜夜 | 特级毛片永久久免费观看 | 亚洲va久久久噜噜噜久久天堂 | www.a级片| 亚洲综合在线观看一区www | 欧美成人免费夜夜黄啪啪 | 久久精品视频热 | 日本一区二区三区不卡在线视频 | 国产精品福利视频手机免费观看 | 99精品在免费线视频 | 天天谢天天干 | 国产一级做a爰大片免费久久 | 亚洲免费一级视频 | 国产成年网站v片在线观看 国产成人91青青草原精品 | haodiaose在线精品免费观看 | 二级黄色大片 | 一级一级女人18毛片 | 神马三级我不卡 | 4338×亚洲全国最大色成网站 | 中文字幕亚洲色图 | 久久狠狠色噜噜狠狠狠狠97 | 国内外精品免费视频 | 国产毛片一区二区三区精品 | 亚洲 另类色区 欧美日韩 | 国产午夜免费一区二区三区 | 亚洲影视久久 | 激情久久久久久久久久 | 午夜黄页网站在线播放 | 三级网址在线 | 一区二区三区欧美在线 | 婷婷在线免费观看 | 国内精品久久影视免费 | 四虎影视在线影院在线观看 | 成人午夜小视频手机在线看 | 操吧 | 美女扒开尿口让男生添 漫画 | 国产精品成人va在线观看入口 | 88影视在线观看污污 |