I'm trying to load obj models using assimp but I get a memory leak
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3EE50000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileCloseProc.<init>(AIFileCloseProc.java:51)
at com.eldev.engine.loader.MeshLoader$2.<init>(MeshLoader.java:80)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:80)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3EE40000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileOpenProc.<init>(AIFileOpenProc.java:52)
at com.eldev.engine.loader.MeshLoader$1.<init>(MeshLoader.java:40)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:40)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D40490000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileReadProc.<init>(AIFileReadProc.java:53)
at com.eldev.engine.loader.MeshLoader$1$1.<init>(MeshLoader.java:50)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:50)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D404B0000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileTellProc.<init>(AIFileTellProc.java:50)
at com.eldev.engine.loader.MeshLoader$1$3.<init>(MeshLoader.java:69)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:69)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D404A0000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileSeek.<init>(AIFileSeek.java:52)
at com.eldev.engine.loader.MeshLoader$1$2.<init>(MeshLoader.java:57)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:57)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3F5D0000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileTellProc.<init>(AIFileTellProc.java:50)
at com.eldev.engine.loader.MeshLoader$1$3.<init>(MeshLoader.java:69)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:69)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3F5C0000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileSeek.<init>(AIFileSeek.java:52)
at com.eldev.engine.loader.MeshLoader$1$2.<init>(MeshLoader.java:57)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:57)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3F5B0000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileReadProc.<init>(AIFileReadProc.java:53)
at com.eldev.engine.loader.MeshLoader$1$1.<init>(MeshLoader.java:50)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:50)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3FD40000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileTellProc.<init>(AIFileTellProc.java:50)
at com.eldev.engine.loader.MeshLoader$1$3.<init>(MeshLoader.java:69)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:69)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3FD30000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileSeek.<init>(AIFileSeek.java:52)
at com.eldev.engine.loader.MeshLoader$1$2.<init>(MeshLoader.java:57)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:57)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3FD20000
at org.lwjgl.system.Callback.create(Callback.java:136)
at org.lwjgl.system.Callback.<init>(Callback.java:86)
at org.lwjgl.assimp.AIFileReadProc.<init>(AIFileReadProc.java:53)
at com.eldev.engine.loader.MeshLoader$1$1.<init>(MeshLoader.java:50)
at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:50)
at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
at org.lwjgl.system.JNI.invokePPP(Native Method)
at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
at com.eldev.game.Game.main(Game.java:26)
LWJGL callback function objects must be manually freed to avoid memory leaks.
When I free the callback function objects i get an exception
Exception in thread "Render Thread" java.lang.IllegalStateException: The memory address specified is not being tracked: 0x15D01D9A4F0
at org.lwjgl.system.MemoryManage$DebugAllocator.untrack(MemoryManage.java:259)
at org.lwjgl.system.MemoryManage$DebugAllocator.free(MemoryManage.java:220)
at org.lwjgl.system.MemoryUtil.nmemFree(MemoryUtil.java:336)
Which LWJGL version do you use?
LWJGL 3.2.3 Build 13
I think the issue is that AIFileIO's OpenProc and CloseProc are invoked multiple times (3 in my testing) within a single aiImportFileEx call. If OpenProc creates a new AIFile each time, then you need to make sure that the corresponding CloseProc invocation is freeing those callbacks.
This is a bit wasteful of course. Depending on how your code is structured, you may be able to reuse the callback instances and avoid the overhead.
I got the same memory leak when I tested this demo
https://github.com/LWJGL/lwjgl3-demos/blob/main/src/org/lwjgl/demo/opengl/assimp/WavefrontObjDemo.java
WavefrontObjDemo has been fixed (https://github.com/LWJGL/lwjgl3-demos/commit/1b31a5f7b9e48ca8531445b3921a30c3fe3e611e) to properly cleanup the AIFileIO & AIFile callbacks.