Deallocating Direct Buffer Native Memory in Java for JOGL

Viewed 9691

I am using direct buffers (java.nio) to store vertex information for JOGL. These buffers are large, and they are replaced several times during the application life. The memory is not deallocated in time and I am running out of memory after a few replacements.

It seems that there is not good way to deallocate using java.nio's buffer classes. My question is this:

Is there some method in JOGL to delete Direct Buffers? I am looking into glDeleteBuffer(), but it seems like this only deletes the buffer from the video card memory.

Thanks

6 Answers

Using information in gouessej's answer, I was able to put this utility class together for freeing the direct memory allocation of a given ByteBuffer. This, of course, should only be used as a last resort, and shouldn't really be used in production code.

Tested and working in Java SE version 10.0.2.

public final class BufferUtil {

    //various buffer creation utility functions etc. etc.

    protected static final sun.misc.Unsafe unsafe = AccessController.doPrivileged(new PrivilegedAction<sun.misc.Unsafe>() {
        @Override
        public Unsafe run() {
            try {
                Field f = Unsafe.class.getDeclaredField("theUnsafe");
                f.setAccessible(true);
                return (Unsafe) f.get(null);
            } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
                throw new RuntimeException(ex);
            }
        }
    });

    /** Frees the specified buffer's direct memory allocation.<br>
     * The buffer should not be used after calling this method; you should
     * instead allow it to be garbage-collected by removing all references of it
     * from your program.
     * 
     * @param directBuffer The direct buffer whose memory allocation will be
     *            freed
     * @return Whether or not the memory allocation was freed */
    public static final boolean freeDirectBufferMemory(ByteBuffer directBuffer) {
        if(!directBuffer.isDirect()) {
            return false;
        }
        try {
            unsafe.invokeCleaner(directBuffer);
            return true;
        } catch(IllegalArgumentException ex) {
            ex.printStackTrace();
            return false;
        }
    }

}
Related