了解Java缓冲池
了解Java緩沖池
緩沖池空間位于垃圾收集器管理的內存之外。 這是分配本地堆外內存的一種方法。 使用緩沖池有什么好處? 為了回答這個問題,讓我們首先了解什么是字節緩沖區。
字節緩沖區
非直接緩沖區
ByteBuffer類附帶了java.nio包。 它允許我們分配直接和非直接字節緩沖區。 非直接字節緩沖區沒有什么特別的-它們是由ByteBuffer.allocate()和ByteBuffer.wrap()工廠方法創建的HeapByteBuffer的實現。 就像該類的名稱所暗示的那樣,它們是堆上字節緩沖區。 那么,在Java堆空間上分配所有緩沖區會不會更容易? 為什么有人需要在本機內存中分配某些內容? 要回答這個問題,我們需要了解操作系統如何執行I / O操作。 任何讀或寫指令都在連續的字節序列存儲區上執行。 那么byte[]是否在堆上占據了連續的空間? 從技術上講這很有意義,但是JVM規范沒有這樣的保證。 更有趣的是, 規范甚至不能保證堆空間本身是連續的! 盡管JVM不太可能將一維原語數組放置在內存中的不同位置,但是Java堆空間中的字節數組不能直接用于本機I / O操作。 必須在每次I / O之前將其復制到本機內存,這當然會導致明顯的低效率。 因此,引入了直接緩沖區。
直接緩沖
直接緩沖區是與Java共享的本機內存塊,您可以從中執行直接讀取。 可以使用ByteBuffer.allocateDirect()工廠方法創建DirectByteBuffer的實例。 字節緩沖區是執行I / O操作的最有效方法,因此,它們在許多庫和框架中使用,例如在Netty中。
內存映射緩沖區
直接字節緩沖區也可以通過將文件區域直接映射到內存中來創建。 換句話說,我們可以將文件的區域加載到可以稍后訪問的特定本機內存區域。 您可以想象,如果我們需要多次讀取文件內容,它可以顯著提高性能。 借助內存映射文件,后續讀取將使用內存中文件的內容,而不是每次需要時都從光盤加載數據。 MappedByteBuffer可以通過創建FileChannel.map()方法。
內存映射文件的另一個優點是,操作系統可以在系統關閉時直接將緩沖區刷新到磁盤。 而且,操作系統可以鎖定文件的映射部分,使其免受計算機上其他進程的影響。
分配很貴
直接緩沖區的問題之一是分配它們很昂貴。 無論緩沖區的大小如何,調用ByteBuffer.allocateDirect()都是一個相對較慢的操作。 因此,對于大型和長壽命的緩沖區使用直接緩沖區,或者創建一個大型緩沖區,按需分割部分,并在不再需要它們時將它們返回以重新使用,效率更高。 當切片的大小不總是相同時,可能會出現切片問題。 當分配和釋放不同大小的對象時,初始的大字節緩沖區可能會變得碎片化。 與Java堆不同,直接字節緩沖區無法壓縮,因為它不是垃圾收集器的目標。
監視緩沖池的使用
如果您對應用程序使用的直接或映射的字節緩沖區的數量感興趣,則可以使用許多工具(包括VisualVM(帶有BufferMonitor插件)和FusionReactor)輕松監視它們。 Java將根據需要增加緩沖池,因此“已使用的直接內存”涵蓋了下圖的“直接容量”這一事實,這意味著到目前為止分配的所有緩沖內存都在使用中。
請注意–您可以使用-XX:MaxDirectMemorySize=N標志來限制應用程序可以分配的直接字節緩沖區空間量。 盡管這是可能的,但是您將需要一個很好的理由。
翻譯自: https://www.javacodegeeks.com/2018/03/understanding-java-buffer-pool.html
總結
- 上一篇: 小米的自研系统真的要来了 手机汽车共享
- 下一篇: java queue使用_使用Java使