直接 NIO バッファーは、管理されていないメモリを使用します。これは、Java ヒープではなく、ネイティブ ヒープに割り当てられることを意味します。結果として、JVM がネイティブ ヒープではなく Java ヒープでメモリ不足になった場合にのみ解放されます。言い換えれば、それは管理されていない = それらを管理するのはあなた次第です。ガベージ コレクションを強制することはお勧めできません。ほとんどの場合、この問題は解決しません。
直接の NIO バッファが役に立たなくなったことがわかったら、sun.misc.Cleaner (StaxMan が正しい) を使用してネイティブ メモリを解放し、clean() を呼び出し (Apache Harmony を除く)、free() を呼び出す必要があります。 (Apache Harmonyを使用)またはより良いパブリックAPIを使用してそれを行います(Java> 12では、AutoCloseableを拡張するAutoCleaningですか?)。
それを行うのはJOGLの仕事ではありません。プレーンなJavaコードを使用して自分で行うことができます。私の例は GPL v2 の下にあり、この例はより寛容なライセンスの下にあります。
編集:私の最新の例は、Java 1.9 でも動作し、OpenJDK、Oracle Java、Sun Java、Apache Harmony、GNU Classpath、および Android をサポートしています。Java < 1.7 (マルチキャッチ、ダイアモンド、およびジェネリック) で動作させるには、構文糖衣を削除する必要がある場合があります。
参照: http://www.ibm.com/developerworks/library/j-nativememory-linux/
Direct ByteBuffer オブジェクトは、ネイティブ バッファを自動的にクリーンアップしますが、これは Java ヒープ GC の一部としてのみ行うことができます。そのため、ネイティブ ヒープへの圧力に自動的に対応することはありません。GC は、Java ヒープがいっぱいになり、ヒープ割り当て要求を処理できない場合、または Java アプリケーションが明示的に要求した場合にのみ発生します (パフォーマンスの問題が発生するため、お勧めしません)。
参照: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#direct
ダイレクト バッファの内容は、通常のガベージ コレクション ヒープの外に存在する可能性があります
このソリューションは Java 14 に統合されています。
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
...
}
Java 16 では、 MemorySegment.ofByteBuffer(ByteBuffer)を呼び出してバイト バッファーをメモリ セグメントにラップし、そのメモリ アドレスを取得して解放できます (これは制限付きのメソッドです)。
CLinker.getInstance().freeMemoryRestricted(MemorySegment.ofByteBuffer(myByteBuffer).address());
通常、直接の NIO バッファーが ByteBuffer でない場合、割り当て解除できるバッファーを見つけるために、多くの重要なケースでリフレクションを使用する必要があることに注意してください。
注意: sun.misc.Cleaner は Java 1.9 のモジュール「java.base」のjdk.internal.ref.Cleanerに移動されました。後者は java.lang.Runnable を実装しました (その違いを思い出させてくれた Alan Bateman に感謝します)。短い時間ですが、もはやそうではありません。sun.misc.Unsafe.invokeCleaner() を呼び出す必要があります。これは JogAmp の Gluegen で行われます。私は、sun.misc.Unsafe に依存することを避けたので、Cleaner を Runnable として使用することを好みましたが、現在は機能しません。
私の最後の提案は、Java 9、10、11、および12で機能します。
私の最新の例では、インキュベーションされた機能 (Java >= 14 が必要) を使用する必要がありますが、非常に単純です。
Luceneには、より寛容なライセンスの下での良い例があります。