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

  1. Avoid NativeMapped types that map to native strings as callback return types; return Pointer/byte[]/char[] or a primitive instead.
  2. Return a Java String/WString directly (CVT_STRING/CVT_WSTRING path) so JNA handles allocation/frees properly.
  3. 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

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


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/fd7b24b01ad8fcc1. Report an issue: GitHub.