DirectByteBuffer實現原理分析


1.創建DirectByteBuffer

  Direct ByteBuffer是通過JNI在Java虛擬機外的內存中分配了一塊(所以即使在運行時通過-Xmx指定了Java虛擬機的最大堆內存,還是可能實例化超出該大小的Direct ByteBuffer),該內存塊並不直接由Java虛擬機負責垃圾收集.

使用allocateDirect()靜態方法創建對象分配內存

  ByteBuffer buffer=ByteBuffer.allocateDirect(256);

 1 /**
 2  * Allocates a new direct byte buffer.
 3  *
 4  * <p> The new buffer's position will be zero, its limit will be its
 5  * capacity, its mark will be undefined, and each of its elements will be
 6  * initialized to zero.  Whether or not it has a
 7  * {@link #hasArray </code>backing array<code>} is unspecified.
 8  *
 9  * @param capacity The new buffer's capacity, in bytes
10  * @return The new byte buffer
11  * @throws IllegalArgumentException If the <tt>capacity</tt> is a negative integer
12  */
13 public static ByteBuffer allocateDirect(int capacity) {
14     if (capacity < 0) {
15         throw new IllegalArgumentException("capacity < 0: " + capacity);
16     }
17 
18     DirectByteBuffer.MemoryRef memoryRef = new DirectByteBuffer.MemoryRef(capacity);
19     return new DirectByteBuffer(capacity, memoryRef);
20 }
21 //
22 public MemoryRef(int capacity) {
23     VMRuntime runtime = VMRuntime.getRuntime();
24     buffer = (byte[]) runtime.newNonMovableArray(byte.class, capacity + 7);
25     allocatedAddress = runtime.addressOf(buffer);
26     // Offset is set to handle the alignment: http://b/16449607
27     offset = (int) (((allocatedAddress + 7) & ~(long) 7) - allocatedAddress);
28     isAccessible = true;
29     isFreed = false;
30 }

 

  以上方法將創建一個容量為256字節的DirectByteBuffer,如果發現創建的緩沖區容量太小,唯一的選擇就是重新創建一個大小合適的緩沖區.

DirectByteBuffer主要應用在android數據傳遞過程.減少數據與JNI數據拷貝轉換操作

DirectByteBuffer.putInt(value);
下面分析一下當執行putInt后,DirectByteBuffer都執行了什么操作
 1     //計算寫數據的位置
 2     @Override
 3     public final ByteBuffer putInt(int x) {
 4         if (!memoryRef.isAccessible) {
 5             throw new IllegalStateException("buffer is inaccessible");
 6         }
 7         if (isReadOnly) {
 8             throw new ReadOnlyBufferException();
 9         }
10         putInt(ix(nextPutIndex(SizeOf.INT)), x);
11         return this;
12     }
13     //調用Memory來完成Int數據存儲
14     private ByteBuffer putInt(long a, int x) {
15         Memory.pokeInt(a, x, !nativeByteOrder);
16         return this;
17     }
18 
19     private long ix(int i) {
20         return address + i;
21     }
22     

再往下看Memory做了什么

1 public static void pokeInt(long address, int value, boolean swap) { 
2        if (swap) {
3             value = Integer.reverseBytes(value);
4         }
5         pokeIntNative(address, value);
6     }
7 //因為最后執行到JNI層.這塊就不涉及到字節序的問題
8 private static native void pokeIntNative(long address, int value);

 

當執行 DirectByteBuffer.getInt();都執行了哪些操作

 1 public int getInt() {
 2     if (!memoryRef.isAccessible) {
 3        throw new IllegalStateException("buffer is inaccessible");
 4     }
 5     return getInt(ix(nextGetIndex(SizeOf.INT)));
 6 }
 7 
 8 //最后執行Memory 的JNI方法
 9 private int getInt(long a) {
10         return Memory.peekInt(a, !nativeByteOrder);
11 }
12 //Memory 執行的操作
13 public static int peekInt(long address, boolean swap) {
14     int result = peekIntNative(address);
15     if (swap) {
16         result = Integer.reverseBytes(result);
17     }
18     return result;
19 }
20 private static native int peekIntNative(long address);

所以得出結論就本身在Java中引入DirectByteBuffer並不會提高性能

 

      


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM