ByteBuffers and Memory

Hi guys,

I just want to make sure that I am using Java Buffer objects in the correct way. Through most of my code, I have used the following method to fill a Buffer object from an array of data:


private FloatBuffer getFloatBuffer(float[] data)
{
    FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
    buffer.put(data);
    buffer.flip();
    return buffer;
}

However, I found a tutorial that describes how to use LWJGL’s STB binding to load a texture into openGL. I have included the code below which shows the process of creating and filling a byte buffer with image data via STB.


public void loadTexture(String filepath)
{
    ByteBuffer imageData;

    try (MemoryStack stack = MemoryStack.stackPush())
    {
        IntBuffer w = stack.mallocInt(1);
        IntBuffer h = stack.mallocInt(1);
        IntBuffer comp = stack.mallocInt(1);

        imageData = stbi_load(filepath, w, h, comp, 4);
    }

   // do openGL texure stuff
    
    MemoryUtil.memFree(imageData);
}

At the end of this function, the LWJGL memory util class is used to free the image data from memory, which is what causes confusion. Why does this Buffer’s memory need to be freed manually? Should I also be doing this with the Buffer objects being created in my first code sample?

Also, why use the MemoryStack class in the try statement? What would be the consequences of creating standard IntBuffers without the aid of this utility?

First of all, please read the Memory FAQ.

[quote=“unlight,post:1,topic:58288”]
It needs to be freed manually because its an allocation made by the native library, not by the JVM. More specifically, the only buffer instances that are automatically garbage collected are instances allocated via [icode]ByteBuffer.allocateDirect[/icode]. Most LWJGL bindings create resources that similarly need to be cleaned up manually.

Also, the above code should not be calling memFree(). The stb_image library has a dedicated function for freeing images, stbi_image_free(). It happens to work correctly because stbi_image_free() is a simple call to free() and the stb bindings are configured to use the same memory allocator as LWJGL.

[quote=“unlight,post:1,topic:58288”]
No. It entirely depends on how the buffer object has been allocated (see the FAQ above).

Most buffers returned by API calls are allocated externally and should not be freed by the user. They are usually freed by the library, automatically or with another API call. When that’s not the case, there’s usually documentation that mentions it.

[quote=“unlight,post:1,topic:58288”]
The MemoryStack class is a performance optimization. The FAQ has more details. There’s no actual allocation made, so it’s much faster for short lived buffers. The drawback is that you have limited stack space (configured statically with Configuration.STACK_SIZE, defaults to 64kb) and the allocation is not available after the stack has been popped (done automatically at the end of the try-with-resources block).

Thank you for the reply Spasi, very clear explanations. I’ll have a good read of the FAQ.