java-native-access/jna · warning
JNA: Likely memory leak here
Error message
JNA: Likely memory leak here
What it means
When converting a callback's return value flagged as CVT_NATIVE_MAPPED_STRING or CVT_NATIVE_MAPPED_WSTRING, JNA prints this warning because the native string buffer allocated by getNativeString-style retrieval is not freed before toNative copies it, leaking memory per callback invocation. It is a known internal TODO, not a failure of the call itself.
Source
Thrown at native/callback.c:505
else switch(cb->rflag) {
case CVT_INTEGER_TYPE:
if (cb->cif.rtype->size > sizeof(ffi_arg)) {
*(jlong *)oldresp = getIntegerTypeValue(env, *(void **)resp);
}
else {
*(ffi_arg *)oldresp = (ffi_arg)getIntegerTypeValue(env, *(void **)resp);
}
break;
case CVT_POINTER_TYPE:
*(void **)resp = getPointerTypeAddress(env, *(void **)resp);
break;
case CVT_NATIVE_MAPPED:
toNative(env, *(void **)resp, oldresp, cb->cif.rtype->size, JNI_TRUE, cb->encoding);
break;
case CVT_NATIVE_MAPPED_STRING:
case CVT_NATIVE_MAPPED_WSTRING:
// TODO: getNativeString rather than allocated memory
fprintf(stderr, "JNA: Likely memory leak here\n");
toNative(env, *(void **)resp, oldresp, cb->cif.rtype->size, JNI_TRUE, cb->encoding);
break;
case CVT_POINTER:
*(void **)resp = getNativeAddress(env, *(void **)resp);
break;
case CVT_STRING:
*(void **)resp = getNativeString(env, *(void **)resp, JNI_FALSE);
break;
case CVT_WSTRING:
*(void **)resp = getNativeString(env, *(void **)resp, JNI_TRUE);
break;
case CVT_STRUCTURE:
writeStructure(env, *(void **)resp);
*(void **)resp = getStructureAddress(env, *(void **)resp);
break;
case CVT_STRUCTURE_BYVAL:
writeStructure(env, *(void **)resp);
memcpy(oldresp, getStructureAddress(env, *(void **)resp), cb->cif.rtype->size);View on GitHub (pinned to d036ad9781)
Solutions
- Avoid NativeMapped types that map to native strings as callback return types; return Pointer/byte[]/char[] or a primitive instead.
- Return a Java String/WString directly (CVT_STRING/CVT_WSTRING path) so JNA handles allocation/frees properly.
- Upgrade JNA — newer versions may address this TODO; monitor native memory usage in the interim.
Example fix
// before
public MyStringMappedType call() { ... } // NativeMapped over string -> leak
// after
public String call() { ... } // handled by native string conversion path Defensive patterns
Strategy: fallback
Prevention
- Avoid NativeMapped-over-string types as callback return types
- Return String/WString, byte[], char[], Pointer, or primitives from callbacks
- Upgrade JNA to pick up fixes for the string-conversion TODO
- Profile native memory if string-returning callbacks run at high frequency
When it happens
Trigger: A callback whose return type is a NativeMapped mapping to String/WString (e.g. a NativeMapped class whose native type is a wide/narrow string) returning to native code via invoke_callback.
Common situations: Long-running applications invoking such string-returning callbacks at high frequency, gradually leaking native memory; custom NativeMapped return types wrapping strings.
Related errors
- JNA: callback object has been garbage collected
- JNA: Unhandled arg conversion type %d
- JNA: error handling callback exception, continuing
- Win32Exception(rc)
- Win32Exception(Kernel32.INSTANCE.GetLastError())
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/fd7b24b01ad8fcc1.
Report an issue: GitHub.