日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA NIO知识点总结(2)——直接缓冲区和非直接缓冲区

發(fā)布時(shí)間:2024/4/13 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA NIO知识点总结(2)——直接缓冲区和非直接缓冲区 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

? 前面我們一直說NIO能夠提高性能,那么到底如何提高效率。本篇就接著上一篇文章的緩沖區(qū),來看看直接緩沖區(qū)和非直接緩沖區(qū)。

非直接緩沖區(qū)

首先看看非直接緩沖區(qū)。我們之前說過NIO通過通道連接磁盤文件與應(yīng)用程序,通過緩沖區(qū)存取數(shù)據(jù)進(jìn)行雙向的數(shù)據(jù)傳輸。物理磁盤的存取是操作系統(tǒng)進(jìn)行管理的,與物理磁盤的數(shù)據(jù)操作需要經(jīng)過內(nèi)核地址空間;而我們的Java應(yīng)用程序是通過JVM分配的緩沖空間。有點(diǎn)雷同于一個(gè)屬于核心態(tài),一個(gè)屬于應(yīng)用態(tài)的意思,而數(shù)據(jù)需要在內(nèi)核地址空間和用戶地址空間,在操作系統(tǒng)和JVM之間進(jìn)行數(shù)據(jù)的來回拷貝,無形中增加的中間環(huán)節(jié)使得效率與后面要提的之間緩沖區(qū)相比偏低。


直接緩沖區(qū)

直接緩沖區(qū)則不再通過內(nèi)核地址空間和用戶地址空間的緩存數(shù)據(jù)的復(fù)制傳遞,而是在物理內(nèi)存中申請(qǐng)了一塊空間,這塊空間映射到內(nèi)核地址空間和用戶地址空間,應(yīng)用程序與磁盤之間的數(shù)據(jù)存取之間通過這塊直接申請(qǐng)的物理內(nèi)存進(jìn)行。

直接與非直接緩沖區(qū)的要點(diǎn)

? 字節(jié)緩沖區(qū)要么是直接的,要么是非直接的。如果為直接字節(jié)緩沖區(qū),則 Java 虛擬機(jī)會(huì)盡最大努力直接在此緩沖區(qū)上執(zhí)行本機(jī) I/O 操作。也就是說,在每次調(diào)用操作系統(tǒng)基礎(chǔ)的一個(gè)本機(jī) I/O 操作之前(或之后),虛擬機(jī)都會(huì)盡量避免將緩沖區(qū)的內(nèi)容復(fù)制到中間緩沖區(qū)中(或從中間緩沖區(qū)中復(fù)制內(nèi)容)。

? 直接字節(jié)緩沖區(qū)可以通過調(diào)用此類的 allocateDirect() 工廠方法來創(chuàng)建。此方法返回的緩沖區(qū)進(jìn)行分配和取消分配所需成本通常高于非直接緩沖區(qū)。直接緩沖區(qū)的內(nèi)容可以駐留在常規(guī)的垃圾回收堆之外,因此,它們對(duì)應(yīng)用程序的內(nèi)存需求量造成的影響可能并不明顯。所以,建議將直接緩沖區(qū)主要分配給那些易受基礎(chǔ)系統(tǒng)的本機(jī) I/O 操作影響的大型、持久的緩沖區(qū)。一般情況下,最好僅在 直接緩沖區(qū)能在程序性能方面帶來明顯好處時(shí) 分配它們。

? 直接字節(jié)緩沖區(qū)還可以通過 FileChannel 的 map() 方法 將文件區(qū)域直接映射到內(nèi)存中來創(chuàng)建。該方法返回MappedByteBuffer 。 Java 平臺(tái)的實(shí)現(xiàn)有助于通過 JNI 從本機(jī)代碼創(chuàng)建直接字節(jié)緩沖區(qū)。如果以上這些緩沖區(qū)中的某個(gè)緩沖區(qū)實(shí)例指的是不可訪問的內(nèi)存區(qū)域,則試圖訪問該區(qū)域不會(huì)更改該緩沖區(qū)的內(nèi)容,并且將會(huì)在訪問期間或稍后的某個(gè)時(shí)間導(dǎo)致拋出不確定的異常。

? 字節(jié)緩沖區(qū)是直接緩沖區(qū)還是非直接緩沖區(qū)可通過調(diào)用其 isDirect() 方法來確定。提供此方法是為了能夠在性能關(guān)鍵型代碼中執(zhí)行顯式緩沖區(qū)管理

(本文出自oschina博主happyBKs的博文:https://my.oschina.net/happyBKs/blog/1592329)

那么既然直接緩沖區(qū)的性能更高、效率更快,為什么還要存在兩種緩沖區(qū)呢?因?yàn)橹苯泳彌_區(qū)也存在著一些缺點(diǎn):

(1)不安全

(2)消耗更多,因?yàn)樗皇窃贘VM中直接開辟空間。這部分內(nèi)存的回收只能依賴于垃圾回收機(jī)制,垃圾什么時(shí)候回收不受我們控制。

(3)數(shù)據(jù)寫入物理內(nèi)存緩沖區(qū)中,程序就喪失了對(duì)這些數(shù)據(jù)的管理,即什么時(shí)候這些數(shù)據(jù)被最終寫入從磁盤只能由操作系統(tǒng)來決定,應(yīng)用程序無法再干涉。

?

選擇方法

直接緩沖區(qū)適合與數(shù)據(jù)長時(shí)間存在于內(nèi)存,或者大數(shù)據(jù)量的操作時(shí)更加適合

?

?

操作方法

@Testpublic void test3(){ByteBuffer dirBuf = ByteBuffer.allocateDirect(1024);if(dirBuf.isDirect()){System.out.println("dirBuf 是直接緩沖區(qū)");}else{System.out.println("dirBuf 是非直接緩沖區(qū)");}}

這是第一種建立直接緩沖區(qū)的方法。

之后我們介紹了通道之后,我們就有了第二種建立直接緩沖區(qū)的方式——建立內(nèi)存映射文件,來建立直接緩沖區(qū)。

?

源碼簡(jiǎn)析

我們可以看看直接緩沖區(qū)申請(qǐng)的源碼:

/*** Allocates a new direct byte buffer.** <p> The new buffer's position will be zero, its limit will be its* capacity, its mark will be undefined, and each of its elements will be* initialized to zero. Whether or not it has a* {@link #hasArray backing array} is unspecified.** @param capacity* The new buffer's capacity, in bytes** @return The new byte buffer** @throws IllegalArgumentException* If the <tt>capacity</tt> is a negative integer*/public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);}

我們?cè)倏碊irectByteBuffer的構(gòu)造實(shí)現(xiàn):

// Primary constructor//DirectByteBuffer(int cap) { // package-privatesuper(-1, 0, cap, cap);boolean pa = VM.isDirectMemoryPageAligned();int ps = Bits.pageSize();long size = Math.max(1L, (long)cap + (pa ? ps : 0));Bits.reserveMemory(size, cap);long base = 0;try {base = unsafe.allocateMemory(size);} catch (OutOfMemoryError x) {Bits.unreserveMemory(size, cap);throw x;}unsafe.setMemory(base, size, (byte) 0);if (pa && (base % ps != 0)) {// Round up to page boundaryaddress = base + ps - (base & (ps - 1));} else {address = base;}cleaner = Cleaner.create(this, new Deallocator(base, size, cap));att = null;}

可以看到unsafe.allocateMemory(size);已經(jīng)不能進(jìn)入源碼了,它已經(jīng)是操作系統(tǒng)層面的jni調(diào)用了。

我們?cè)倏纯捶侵苯泳彌_區(qū)的申請(qǐng)?jiān)创a:

它申請(qǐng)的是堆空間,即在JVM上的操作。

/*** Allocates a new byte buffer.** <p> The new buffer's position will be zero, its limit will be its* capacity, its mark will be undefined, and each of its elements will be* initialized to zero. It will have a {@link #array backing array},* and its {@link #arrayOffset array offset} will be zero.** @param capacity* The new buffer's capacity, in bytes** @return The new byte buffer** @throws IllegalArgumentException* If the <tt>capacity</tt> is a negative integer*/public static ByteBuffer allocate(int capacity) {if (capacity < 0)throw new IllegalArgumentException();return new HeapByteBuffer(capacity, capacity);}

再進(jìn)一層,我們已經(jīng)可以看到byte數(shù)組了。

HeapByteBuffer(int cap, int lim) { // package-privatesuper(-1, 0, lim, cap, new byte[cap], 0);/*hb = new byte[cap];offset = 0;*/}

?

?

轉(zhuǎn)載于:https://my.oschina.net/happyBKs/blog/1592329

總結(jié)

以上是生活随笔為你收集整理的JAVA NIO知识点总结(2)——直接缓冲区和非直接缓冲区的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。