{"record":{"id":"11affcc668c14d4a","repo":"java-native-access/jna","slug":"jna-can-t-attach-native-thread-to-vm-for-callback-d-check","errorCode":null,"errorMessage":"JNA: Can't attach native thread to VM for callback: %d (check stacksize for callbacks)\n","messagePattern":"JNA: Can't attach native thread to VM for callback: (.+?) \\(check stacksize for callbacks\\)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"native/callback.c","lineNumber":721,"sourceCode":"      options.detach = JNI_TRUE; // default detach behavior\n      options.name = NULL;\n      args.group = initializeThread(cb, &options);\n      daemon = options.daemon ? JNI_TRUE : JNI_FALSE;\n      needs_detach = options.detach ? JNI_TRUE : JNI_FALSE;\n      args.name = options.name;\n    }\n    if (daemon) {\n      attach_status = (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void*)&env, &args);\n    }\n    else {\n      attach_status = (*jvm)->AttachCurrentThread(jvm, (void *)&env, &args);\n    }\n    if (attach_status != JNI_OK) {\n      free((void *)args.name);\n      if (args.group) {\n        (*env)->DeleteWeakGlobalRef(env, args.group);\n      }\n      fprintf(stderr, \"JNA: Can't attach native thread to VM for callback: %d (check stacksize for callbacks)\\n\", attach_status);\n      return;\n    }\n    tls = get_thread_storage(env);\n    if (tls) {\n      snprintf(tls->name, sizeof(tls->name), \"%s\", args.name ? args.name : \"<unconfigured native thread>\");\n      tls->needs_detach = needs_detach;\n      tls->jvm_thread = JNI_FALSE;\n    }\n    // Dispose of allocated memory\n    free((void *)args.name);\n    if (args.group) {\n      (*env)->DeleteWeakGlobalRef(env, args.group);\n    }\n  }\n\n  if (!tls) {\n    fprintf(stderr, \"JNA: couldn't obtain thread-local storage\\n\");\n    return;","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/native/callback.c#L703-L739","documentation":"dispatch_callback must attach a native (non-Java) thread to the JVM before it can invoke the Java callback. If AttachCurrentThread fails, JNA frees the thread-name/group resources, prints this message including the JNI status code, and silently returns — the Java callback is never invoked and the native call proceeds without its result.","triggerScenarios":"A callback invoked on a native thread with insufficient stack space (JNI cannot create the attachment bookkeeping), or the JVM refusing attachment (shutting down, wrong JNI version), yielding attach_status != JNI_OK.","commonSituations":"Callbacks fired on deep native call stacks or tiny-stack threads (common on Windows with small default thread stacks, hence the 'check stacksize' hint), attaching during JVM shutdown, more attached threads than -Xss/native limits allow.","solutions":["Increase the native thread's stack size when creating it (e.g. pthread_attr_setstacksize / CreateThread dwStackSize), or raise -Xss.","Verify the JVM is still live and not shutting down when the native thread calls back.","Ensure jvm version passed to GetEnv/AttachCurrentThread matches (JNI_VERSION_1_4) and the JVM pointer is valid.","Reduce native stack depth before invoking the callback (invoke on a shallower stack)."],"exampleFix":"// before\npthread_create(&tid, NULL, native_worker, ctx); // 64KB stack, too small\n// after\npthread_attr_t a; pthread_attr_init(&a);\npthread_attr_setstacksize(&a, 1 << 20); // >= 1MB\npthread_create(&tid, &a, native_worker, ctx);","handlingStrategy":"validation","validationCode":"// Before registering a callback on a native thread, ensure adequate stack:\n// pthread: pthread_attr_setstacksize(&attr, 1<<20)\n// Windows: CreateThread(NULL, 1<<20, ...)\n// and confirm the JVM is up: JNIEnv via GetEnv != JNI_EDETACHED failure path","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create native threads with >= 1MB stack when they will invoke Java callbacks","Avoid deep native recursion before invoking callbacks","Never call callbacks during JVM shutdown","Raise -Xss if many threads attach with deep stacks"],"tags":["jni","attach","threading","stacksize"],"backgroundTag":"thread-attach-failed","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}