【问题标题】: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]”打印其中的数据

标签: java android bytebuffer


【解决方案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 或 StackOverflow 进行搜索。
  • 得到,谢谢。看了Android的源码,逻辑类似
猜你喜欢
  • 2015-02-04
  • 2011-08-14
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多