日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本文介紹了直接緩沖存儲器的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我需要從Web請求返回一個相當大的文件。該文件的大小約為670MB。在大多數情況下,這可以很好地工作,但一段時間后會拋出以下錯誤:

java.lang.OutOfMemoryError: Direct buffer memory
    at java.nio.Bits.reserveMemory(Bits.java:694) ~[na:1.8.0_162]
    at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123) ~[na:1.8.0_162]
    at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311) ~[na:1.8.0_162]
    at sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:241) ~[na:1.8.0_162]
    at sun.nio.ch.IOUtil.read(IOUtil.java:195) ~[na:1.8.0_162]
    at sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:159) ~[na:1.8.0_162]
    at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:65) ~[na:1.8.0_162]
    at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:109) ~[na:1.8.0_162]
    at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:103) ~[na:1.8.0_162]
    at java.nio.file.Files.read(Files.java:3105) ~[na:1.8.0_162]
    at java.nio.file.Files.readAllBytes(Files.java:3158) ~[na:1.8.0_162]

我已將堆大小設置為4096MB,我認為該大小應該足以處理此類文件。此外,當這個錯誤發生時,我使用jmap獲取堆轉儲來分析當前狀態。我發現了兩個相當大的字節[],這應該是我想要返回的文件。但是堆的大小只有1.6 GB左右,還沒有達到配置的4 GB大小。

根據其他一些答案(https://stackoverflow.com/a/39984276/5126654),在一個類似的問題中,我嘗試在返回此文件之前運行手動GC。問題仍然存在,但現在只是零星的。問題在一段時間后出現,但當我再次厭倦運行相同的請求時,似乎垃圾收集已經解決了導致問題的問題,但這是不夠的,因為問題顯然仍然可能發生。是否有其他方法可以避免此內存問題?

推薦答案

DirectByteBuffer管理的實際內存緩沖區不在堆中分配。它們是使用UnSafe.allocateMemory分配的,它分配本機內存和。因此,增加或減少堆大小無濟于事。

當GC檢測到DirectByteBuffer不再被引用時,將使用Cleaner釋放本機內存。但是,這種情況發生在收集后階段,因此如果對直接緩沖區的需求/周轉太大,收集器可能跟不上。如果發生這種情況,您將獲得OOME。


您能對此做些什么?

AFAIK,您唯一可以做的就是強制更頻繁的垃圾回收。但這可能會對性能產生影響。我不認為這是一個有保證的解決方案。

真正的解決方案是采取不同的方法。

您看到您正在從Web服務器提供大量非常大的文件,堆棧跟蹤顯示您正在使用Files::readAllBytes將它們加載到內存中,然后(假設)使用單個write發送它們。想必您這樣做是為了盡可能獲得最快的下載時間。這是一個錯誤:

您占用了大量內存(是垃圾收集器的倍數,給垃圾收集器帶來了壓力。這導致了更多的GC運行和偶爾的OOME。它還可能以各種方式影響服務器上的其他應用程序。

傳輸文件的瓶頸可能是而不是從磁盤讀取數據的過程。(真正的瓶頸是通常通過網絡上的TCP流發送數據,或將數據寫入客戶端的文件系統。)

如果您按順序讀取一個大文件,現代Linux操作系統通常會使用預讀大量磁盤塊,并將這些塊保存在(OS)緩沖區緩存中。這將減少您的應用程序進行的read系統調用的延遲。

因此,對于這種大小的文件,更好的方法是對文件進行流式處理。要么分配一個大的(幾兆字節)ByteBuffer并循環讀寫,使用Files::copy(...)(javadoc)復制文件,這應該會為您負責緩沖。

(也可以選擇使用映射到Linux系統調用的內容。這會將數據從一個文件描述符復制到另一個文件描述符,而不會將其寫入用戶空間緩沖區。)

這篇關于直接緩沖存儲器的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,

分享到:
標簽:緩沖存儲器
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定