为啥 DirectByteBuffer.array() 有额外的大小?
Posted
技术标签:
【中文标题】为啥 DirectByteBuffer.array() 有额外的大小?【英文标题】:Why does DirectByteBuffer.array() have extra size?为什么 DirectByteBuffer.array() 有额外的大小? 【发布时间】:2018-05-29 06:54:35 【问题描述】:我的代码是:
if (frameRGBABuffer == null)
frameRGBABuffer = ByteBuffer.allocateDirect(cameraHeight * cameraWidth * 4)
.order(ByteOrder.nativeOrder());
Log.d("tag",frameRGBABuffer.array().length)
我的相机分辨率是 1280×720,因此frameRGBABuffer
应该分配 3686400 字节的空间。
但奇怪的是frameRGBABuffer.array()
的长度是3686407,为什么多了7个字节的空格?
顺便说一句,frameRGBABuffer.array() 不抛出异常,返回一个带数据的 byte[]
Android 似乎分配了 7 个额外的空间来处理对齐。 源代码是:
MemoryRef(int capacity)
VMRuntime runtime = VMRuntime.getRuntime();
buffer = (byte[]) runtime.newNonMovableArray(byte.class, capacity + 7);
allocatedAddress = runtime.addressOf(buffer);
// Offset is set to handle the alignment: http://b/16449607
offset = (int) (((allocatedAddress + 7) & ~(long) 7) - allocatedAddress);
isAccessible = true;
isFreed = false;
【问题讨论】:
长度是属性而不是函数。 尝试使用capacity()
。您通常甚至不能保证array()
不会抛出UnsupportedOperationException
,因为您的ByteBuffer
往往没有可访问的byte[]
支持。
frameRGBABuffer.array() 不抛出异常,我可以通过“frameRGBABuffer.array()[0]”打印其中的数据
【参考方案1】:
这是它背后的代码(JVM,不是 android,但可能在 Android 上类似):
DirectByteBuffer(int cap) // package-private
super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0)); <----- HERE
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 boundary
address = base + ps - (base & (ps - 1));
else
address = base;
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
att = null;
VM.isDirectMemoryPageAligned()
// User-controllable flag that determines if direct buffers should be page
// aligned. The "-XX:+PageAlignDirectMemory" option can be used to force
// buffers, allocated by ByteBuffer.allocateDirect, to be page aligned.
这是用于性能的低级内容。
根据这位研究人员的说法,这对最近的英特尔 CPU 来说太过分了。 在这里阅读更多:https://lemire.me/blog/2012/05/31/data-alignment-for-speed-myth-or-reality/
【讨论】:
注意:我使用我的 IDE 快速浏览相关代码(+ JavaDocs)。我建议您配置您的 IDE 或编辑器,这样您就可以探索感兴趣的 JDK 代码,而无需通过 Google 或 *** 进行搜索。 得到,谢谢。看了Android的源码,逻辑类似以上是关于为啥 DirectByteBuffer.array() 有额外的大小?的主要内容,如果未能解决你的问题,请参考以下文章
为啥使用 glTranslatef?为啥不直接更改渲染坐标?
为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?