DirectByteBuffer实现原理分析
Posted kenny.wmh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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并不会提高性能
以上是关于DirectByteBuffer实现原理分析的主要内容,如果未能解决你的问题,请参考以下文章