DirectBuffer,释放

DirectBuffer, deallocation

我分配了一个直接缓冲区:

ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);

我读过:

Deallocating Direct Buffer Native Memory in Java for JOGL

但它没有直接回答。

总结一下:

  1. GC 将在启动 GC 并且未引用 directbuffer 时释放 directbuffer。在链接 post 中写道:

When you know that a direct NIO buffer has become useless for you, you have to release its native memory by using its sun.misc.Cleaner (StaxMan is right) and call clean() (except with Apache Harmony), call free() (with Apache Harmony) or use a better public API to do that (maybe in Java >= 1.9, AutoCleaning that extends AutoCloseable?).

但我没有看到如何显式释放内存块。好的,存在 sun.misc.Cleaner 什么?:

Cleaner c = new Cleaner()

  1. 用DirectBuffer代替Unsafe.allocateMemory的目的是什么


This solution (in this JEP, still a draft, probably not available in Java 1.9) is very promising, we won't need to use non public APIs.

public long memory(long index) {
    // The scope where the memory region is available
    // Implements AutoClosable but `close` can be called manually as well
    try (Scope scope = new NativeScope()) {
        // Allocate the actual memory area, in this case in the style of a "long-array"
        Pointer<Long> ptr = scope.allocate(
                    NativeLibrary.createLayout(long.class), numElements);

        // Get the reference to a certain element
        Reference<Long> ref = ptr.offset(index).deref();

        // Set a value to this element through the reference
        ref.set(Long.MAX_VALUE);

        // Read the value of an element
        return ref.get();
    }
}

它看起来像 C++ 中的智能指针,不是吗?

but I didn't see how to explicitly release of memory chunk.

目前你不能在 java 因为它不安全。它可能会导致释放后使用错误。 使其安全的方法,例如虚拟内存操作或安全点体操,很困难,可能会消耗一些性能或可能无法在所有平台上工作。

这并非不可能,但需要大量工作。请参阅 JDK-4724038、其副本和链接的邮件列表以了解多年来积累的提案。

What is the purpose of using DirectBuffer instead of Unsafe.allocateMemory.

安全访问可以传递给本机代码的稳定内存位置,无需复制,也无需对象固定(热点不支持)。

你确实可以,但代码很奇怪。

    // unmap the memory mapped buffer (wait gc cleans it up)
    ReferenceQueue rq = new ReferenceQueue();
    PhantomReference<ByteBuffer> ref = new PhantomReference<>(ref_out, rq);
    ref_out = null;
    while(rq.poll() == null) {
        System.gc();
    }

    // all finalizers are finished... only phantom references left.
    PhantomReference<PhantomReference> pref = new PhantomReference<>(ref, rq);
    ref.clear();
    ref = null;
    while(rq.poll() == null) {
        System.gc();
    }
    pref.clear();

干杯,

D.