{"record":{"id":"1a4d9410e15fc4fb","repo":"apache/hadoop","slug":"hdfsthreaddestructor-getjavavm-failed-with-error","errorCode":null,"errorMessage":"hdfsThreadDestructor: GetJavaVM failed with error %d\n","messagePattern":"hdfsThreadDestructor: GetJavaVM failed with error (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/os/posix/thread_local_storage.c","lineNumber":60,"sourceCode":" * is destroyed.\n *\n * @param v         The thread-local data\n */\nvoid hdfsThreadDestructor(void *v)\n{\n  JavaVM *vm;\n  struct ThreadLocalState *state = (struct ThreadLocalState*)v;\n  JNIEnv *env = state->env;;\n  jint ret;\n  jthrowable jthr;\n  char thr_name[MAXTHRID];\n\n  /* Detach the current thread from the JVM */\n  if ((env != NULL) && (*env != NULL)) {\n    ret = (*env)->GetJavaVM(env, &vm);\n\n    if (ret != 0) {\n      fprintf(stderr, \"hdfsThreadDestructor: GetJavaVM failed with error %d\\n\",\n        ret);\n      jthr = (*env)->ExceptionOccurred(env);\n      if (jthr) {\n        (*env)->ExceptionDescribe(env);\n        (*env)->ExceptionClear(env);\n      }\n    } else {\n      ret = (*vm)->DetachCurrentThread(vm);\n\n      if (ret != JNI_OK) {\n        jthr = (*env)->ExceptionOccurred(env);\n        if (jthr) {\n          (*env)->ExceptionDescribe(env);\n          (*env)->ExceptionClear(env);\n        }\n        get_current_thread_id(env, thr_name, MAXTHRID);\n\n        fprintf(stderr, \"hdfsThreadDestructor: Unable to detach thread %s \"","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/os/posix/thread_local_storage.c#L42-L78","documentation":"At thread exit, the TLS destructor libhdfs registered via pthread_key_create tries to detach the thread from the embedded JVM. It first resolves the VM with GetJavaVM on the thread's JNIEnv; a non-zero return (e.g. JNI_EDETACHED, or the env is already invalid during teardown) prints this warning, describes any pending exception, and continues. The state is still freed, so impact is limited to a leaked attachment.","triggerScenarios":"Thread exit during JVM shutdown; the thread already detached by another native library that manages JNI attachment itself, leaving GetJavaVM unable to resolve the VM.","commonSituations":"Mixing libhdfs with other JNI libraries that also call DetachCurrentThread; exit-time ordering races; harmless but noisy lines in production logs during shutdown.","solutions":["If seen only at process shutdown with no functional failure, treat as benign log noise","If seen mid-run, audit other in-process JNI components for double-detach of the same thread","Ensure HDFS work on the thread completes before triggering JVM teardown"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Let libhdfs' TLS destructor be the only code detaching threads it created state for","Finish HDFS work on a thread before that thread exits","Filter these lines out of shutdown log alerts unless a real failure accompanies them"],"tags":["libhdfs","jni","thread-exit","tls-destructor","getjavavm"],"backgroundTag":"jni-getjavavm-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}