如何避免制作 ByteBuffer 的防御性副本?

发布于 2024-12-07 23:26:35 字数 153 浏览 1 评论 0原文

我有一个类,它采用 ByteBuffer 作为构造函数参数。有没有办法避免制作防御性副本,以确保缓冲区不会在该点之后被修改?

ByteBuffer.isReadOnly() 不保证原始所有者不会修改缓冲区。更糟糕的是,似乎没有办法子类化 ByteBuffer。有什么想法吗?

I've got a class that takes a ByteBuffer as a constructor argument. Is there a way to avoid making defensive copies in order to ensure that the buffer doesn't get modified past that point?

ByteBuffer.isReadOnly() doesn't guarantee that the original owner won't modifying the buffer. To make matters worse, there doesn't seem to be a way to subclass ByteBuffer. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

π浅易 2024-12-14 23:26:35

正如您所说,唯一真正的方法是 buf.asReadOnlyBuffer(),然后将其传递到构造函数中。除此之外没有其他选择,尽管您可以将内容复制到新的 ByteBuffer 中,然后将其传递。

The only real way is, as you say, buf.asReadOnlyBuffer(), then pass this into the constructor. There's no other option apart from this, although you could do a copy of the contents into a new ByteBuffer, then pass that.

枉心 2024-12-14 23:26:35

这是我目前能做的最好的事情:

/**
 * Helper functions for java.nio.Buffer.
 * <p/>
 * @author Gili Tzabari
 */
public final class Buffers
{
    /**
     * Returns a ByteBuffer that is identical but distinct from the original buffer.
     * <p/>
     * @param original the buffer to copy
     * @return an independent copy of original
     * @throws NullPointerException if original is null
     */
    public static ByteBuffer clone(ByteBuffer original)
    {
        Preconditions.checkNotNull(original, "original may not be null");

        ByteBuffer result = ByteBuffer.allocate(original.capacity());
        ByteBuffer source = original.duplicate();
        source.rewind();
        result.put(source);

        try
        {
            source.reset();
            result.position(source.position());
            result.mark();
        }
        catch (InvalidMarkException unused)
        {
            // Mark is unset, ignore.
        }
        result.position(original.position());
        result.limit(original.limit());
        return result;
    }

    /**
     * Returns an array representation of a buffer. The returned buffer may, or may not, be tied to
     * the underlying buffer's contents (so it should not be modified).
     * <p/>
     * @param buffer the buffer
     * @return the remaining bytes
     */
    public static byte[] toArray(ByteBuffer buffer)
    {
        if (buffer.hasArray() && !buffer.isReadOnly() && buffer.position() == 0
            && buffer.remaining() == buffer.limit())
        {
            return buffer.array();
        }
        ByteBuffer copy = buffer.duplicate();
        byte[] result = new byte[copy.remaining()];
        copy.get(result);
        return result;
    }

    /**
     * Prevent construction.
     */
    private Buffers()
    {
    }
}

我还向 Oracle 提交了功能请求: https://bugs.java.com/bugdatabase/view_bug?bug_id=7130631

This is the best I could do for now:

/**
 * Helper functions for java.nio.Buffer.
 * <p/>
 * @author Gili Tzabari
 */
public final class Buffers
{
    /**
     * Returns a ByteBuffer that is identical but distinct from the original buffer.
     * <p/>
     * @param original the buffer to copy
     * @return an independent copy of original
     * @throws NullPointerException if original is null
     */
    public static ByteBuffer clone(ByteBuffer original)
    {
        Preconditions.checkNotNull(original, "original may not be null");

        ByteBuffer result = ByteBuffer.allocate(original.capacity());
        ByteBuffer source = original.duplicate();
        source.rewind();
        result.put(source);

        try
        {
            source.reset();
            result.position(source.position());
            result.mark();
        }
        catch (InvalidMarkException unused)
        {
            // Mark is unset, ignore.
        }
        result.position(original.position());
        result.limit(original.limit());
        return result;
    }

    /**
     * Returns an array representation of a buffer. The returned buffer may, or may not, be tied to
     * the underlying buffer's contents (so it should not be modified).
     * <p/>
     * @param buffer the buffer
     * @return the remaining bytes
     */
    public static byte[] toArray(ByteBuffer buffer)
    {
        if (buffer.hasArray() && !buffer.isReadOnly() && buffer.position() == 0
            && buffer.remaining() == buffer.limit())
        {
            return buffer.array();
        }
        ByteBuffer copy = buffer.duplicate();
        byte[] result = new byte[copy.remaining()];
        copy.get(result);
        return result;
    }

    /**
     * Prevent construction.
     */
    private Buffers()
    {
    }
}

I've also filed a feature request with Oracle: https://bugs.java.com/bugdatabase/view_bug?bug_id=7130631

寂寞花火° 2024-12-14 23:26:35

不避免复制,但也许:

  1. 的预填充池
  2. 使用预分配的ByteBuffer
    作者类的构造函数允许传入的“副本”
    ByteBuffer,但让类使用池中的 ByteBuffer 进行移动
    应用程序启动/关闭的分配/释放成本。这样只需要支付内存复制成本。

Doesn't avoid a copy, but perhaps:

  1. Use a pre-filled pool of pre-allocated ByteBuffers
  2. Allow the
    constructor of Author's class to allow a 'copy' of incoming
    ByteBuffer, but have class use a ByteBuffer from the pool to move
    Alloc/Dealloc costs to app startup/shutdown. Only pay a memcopy cost this way.
猥︴琐丶欲为 2024-12-14 23:26:35

这并不能完全回答问题,但是,对于某些用途(例如,如果您主要试图强制执行“按合同设计”),它可能足够好并且更高效。对于其他用途,它将不起作用并且效率可能会低得多。

在构造函数期间,保存 ByteBuffer 的 hashCode

Final int OriginalBBHashCode = byteBuffer.hashCode();

然后,在代码中要验证 ByteBuffer 是否未更改的几个关键位置,验证 byteBuffer.hashCode() == OriginalBBHashCode。如果不是,则抛出异常。坦率地说,我很想抛出 ConcurrentModificationException,因为这是您正在模仿的行为,但是 YMMV。

This doesn't quite answer the question, but, for some usages (e.g. if you are mainly trying to enforce "design by contract") it may be good enough and more efficient. For other usages it will not work and may be far less efficient.

During your constructor, save away the hashCode of the ByteBuffer

final int originalBBHashCode = byteBuffer.hashCode();

Then, at the few critical places in your code where you want to verify that the ByteBuffer hasn't changed, verify that the byteBuffer.hashCode() == originalBBHashCode. If not, throw an exception. Frankly, I'd be tempted to throw a ConcurrentModificationException, since that is the behavior you are mimicking, but YMMV.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文