java-native-access/jna · warning

JNA: could not detach native thread (automatic)

Error message

JNA: could not detach native thread (automatic)

What it means

dispose_thread_data runs during native thread teardown (DllMain on Windows) and tries to detach a thread that JNA automatically attached to the JVM. If DetachCurrentThread returns nonzero, this warning is printed and the thread's termination flag is not set, potentially leaking the thread's TLS entry and leaving the thread attached at process exit.

Source

Thrown at native/callback.c:604

      else if (!TLS_SET(tls_thread_data_key, tls)) {
        free(tls);
        throwByName(env, EOutOfMemory, "JNA: Internal TLS error");
        tls = NULL;
      }
    }
  }
  return tls;
}

static void dispose_thread_data(void* data) {
  thread_storage* tls = (thread_storage*)data;
  JavaVM* jvm = tls->jvm;
  JNIEnv* env;
  int is_attached = (*jvm)->GetEnv(jvm, (void*)&env, JNI_VERSION_1_4) == JNI_OK;
  jboolean detached = JNI_TRUE;
  if (is_attached) {
    if ((*jvm)->DetachCurrentThread(jvm) != 0) {
      fprintf(stderr, "JNA: could not detach native thread (automatic)\n");
      detached = JNI_FALSE;
    }
  }
  if (tls->termination_flag && detached) {
    *(tls->termination_flag) = JNI_TRUE;
  }
  free(data);
}

#ifdef _WIN32

BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD fdwReason, LPVOID lpvReserved) {
  switch (fdwReason) {
  case DLL_PROCESS_ATTACH:
    tls_thread_data_key = TlsAlloc();
    if (tls_thread_data_key == TLS_OUT_OF_INDEXES) {
      return FALSE;
    }

View on GitHub (pinned to d036ad9781)

Solutions

  1. Explicitly dispose callbacks (CallbackReference disposal / dropping all Callback references) and ensure native threads finish before JVM shutdown.
  2. Avoid invoking Java callbacks from native threads that outlive the JVM (e.g. during DllMain/process exit).
  3. Unregister threads via JNA's native thread cleanup APIs instead of relying on automatic detach at exit.
  4. Treat as benign if it only appears at process exit; otherwise investigate JVM/native library unload ordering.
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: A native thread that JNA auto-attached (via dispatch_callback or thread initialization) exits while DetachCurrentThread fails — typically during DLL_PROCESS_DETACH when the JVM no longer permits attachment operations.

Common situations: Windows process shutdown with callbacks still registered, native threads created by third-party DLLs invoking Java callbacks, JVM already destroyed/unloading before the native thread detaches.

Related errors


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