<@UE0E6UWAJ> I haven't done JNI in a while but you...
# tornadofx
c
@alex I haven't done JNI in a while but you had to free up memory since you were out from under the JVM's memory management.
a
@carlw I can't find any documentation clarification. Some claim memory freed automatically when variable is GC'ed, others -- that you need to free it. I've run simple infinite loop to see if memory is leaking:
Copy code
while (true) {
            val ptr = PointerByReference()            Shell32.INSTANCE.SHGetKnownFolderPath(KnownFolders.FOLDERID_Desktop, 0, null, ptr)
            val sliced = ptr.value.getCharArray(0, WinDef.MAX_PATH).takeWhile { it != '\u0000' }.toCharArray()
            val pathStr = String(sliced)
            // free memory ???
            println(pathStr)
        }
Without freeing it ended up with
Caused by: java.lang.Error: Invalid memory access
after 1-2 seconds at the line with
sliced
. If I add
Ole32.INSTANCE.CoTaskMemFree(ptr.value)
at the end of the loop, there is no exception. I suppose freeing is necessary, but I wonder why documentation is so unclear about it (or at least why I can not find the right page).
No idea which function for freeing memory to use though, it seems like there are quite a few of them.
Native.free(Pointer.nativeValue(ptr.value))
this one seems like correct one
And it seems only the instances of class: https://java-native-access.github.io/jna/4.2.0/com/sun/jna/Memory.html are GC'ed automatically, can't find similar statements for other memory-related classes.
Also as Luis mentioned in another thread, it's better to free memory in finalize section, so complete code example looks like this:
Copy code
val ptr = PointerByReference()
try {            Shell32.INSTANCE.SHGetKnownFolderPath(KnownFolders.FOLDERID_Desktop, 0, null, ptr)
	val sliced = ptr.value.getCharArray(0, WinDef.MAX_PATH).takeWhile { it != '\u0000' }.toCharArray()
	val pathStr = String(sliced)
	return Paths.get(pathStr)
} finally {
	Native.free(Pointer.nativeValue(ptr.value))
}