{"record":{"id":"db4387d4ce0cd492","repo":"asLody/VirtualApp","slug":"unable-to-retrieve-jnienv","errorCode":null,"errorMessage":"Unable to retrieve JNIEnv*.","messagePattern":"Unable to retrieve JNIEnv\\*\\.","errorType":"exception","errorClass":"std::runtime_error","httpStatus":null,"severity":"critical","filePath":"VirtualApp/lib/src/main/jni/fb/jni/fbjni.cpp","lineNumber":73,"sourceCode":"  return JNI_VERSION_1_6;\n}\n\nalias_ref<JClass> findClassStatic(const char* name) {\n  const auto env = internal::getEnv();\n  if (!env) {\n    throw std::runtime_error(\"Unable to retrieve JNIEnv*.\");\n  }\n  local_ref<jclass> cls = adopt_local(env->FindClass(name));\n  FACEBOOK_JNI_THROW_EXCEPTION_IF(!cls);\n  auto leaking_ref = (jclass)env->NewGlobalRef(cls.get());\n  FACEBOOK_JNI_THROW_EXCEPTION_IF(!leaking_ref);\n  return wrap_alias(leaking_ref);\n}\n\nlocal_ref<JClass> findClassLocal(const char* name) {\n  const auto env = internal::getEnv();\n  if (!env) {\n    throw std::runtime_error(\"Unable to retrieve JNIEnv*.\");\n  }\n  auto cls = env->FindClass(name);\n  FACEBOOK_JNI_THROW_EXCEPTION_IF(!cls);\n  return adopt_local(cls);\n}\n\n\n// jstring /////////////////////////////////////////////////////////////////////////////////////////\n\nstd::string JString::toStdString() const {\n  const auto env = internal::getEnv();\n  auto utf16String = JStringUtf16Extractor(env, self());\n  return detail::utf16toUTF8(utf16String.chars(), utf16String.length());\n}\n\nlocal_ref<JString> make_jstring(const char* utf8) {\n  if (!utf8) {\n    return {};","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/jni/fb/jni/fbjni.cpp#L55-L91","documentation":"facebook/jni (fbjni) requires a valid JNIEnv* for the calling thread, obtained via internal::getEnv(). findClassLocal calls FindClass to resolve a Java class as a local reference; if no JNIEnv can be retrieved (no JavaVM attached or thread not attached to the JVM), it throws std::runtime_error(\"Unable to retrieve JNIEnv*.\") before even attempting FindClass.","triggerScenarios":"Calling any fbjni-backed function (findClassLocal, JObject::toString, registerNatives, throwNewJavaException, JavaClass::javaClassLocal) from a native thread that was never attached to the JVM, after AndroidJNIHelper/Initialize was skipped (no JavaVM stored), or on a thread whose JNIEnv could not be fetched with GetEnv(JNI_VERSION_1_6).","commonSituations":"Using fbjni from a background pthread/std::thread without calling JavaVM::AttachCurrentThread; native code running before JNI_OnLoad/initialize stored the JavaVM; a detached thread invoking Java class lookups after its attachment was released.","solutions":["Attach the thread before calling fbjni: vm->AttachCurrentThread(&env, nullptr) (or fbjni's ThreadScope/attach helpers) at thread start","Ensure initialize()/JNI_OnLoad ran so fbjni stored the JavaVM (g_vm); verify the library containing the fbjni initialization is loaded before use","Use facebook::jni::ThreadScope RAII guard in worker-thread entry points to attach/detach around Java interop","If the error surfaces in throwNewJavaException during error handling, attach the thread first, then re-raise; check that GetEnv succeeds with JNI_VERSION_1_6"],"exampleFix":"// before\nvoid worker() {\n  auto cls = facebook::jni::findClassLocal(\"java/lang/String\"); // throws: no JNIEnv\n}\n// after\nvoid worker() {\n  JavaVM* vm = facebook::jni::Environment::current()->GetJavaVM(); // or stored g_vm\n  JNIEnv* env = nullptr;\n  vm->AttachCurrentThread(&env, nullptr);\n  facebook::jni::ThreadScope scope; // RAII attach/detach\n  auto cls = facebook::jni::findClassLocal(\"java/lang/String\");\n}","handlingStrategy":"type-guard","validationCode":"// C++: ensure the thread has a JNIEnv before fbjni calls\nJNIEnv* env = nullptr;\nif (g_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {\n    g_vm->AttachCurrentThread(&env, nullptr); // attach before fbjni usage\n}","typeGuard":"inline bool hasJniEnv() {\n  JNIEnv* env = nullptr;\n  return g_vm && g_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) == JNI_OK;\n}","tryCatchPattern":"try {\n  auto cls = facebook::jni::findClassLocal(name);\n} catch (const std::runtime_error& e) {\n  // \"Unable to retrieve JNIEnv*.\" — attach the thread and retry once\n  attachThreadToJvm();\n  auto cls = facebook::jni::findClassLocal(name);\n}","preventionTips":["Attach every native worker thread to the JVM before any fbjni call","Use facebook::jni::ThreadScope RAII guards at thread entry points","Ensure JNI_OnLoad / fbjni initialize() ran before first use","Never detach a thread while Java objects from it are still referenced","Verify GetEnv returns JNI_OK with JNI_VERSION_1_6 in debug builds"],"tags":["jni","native","android","threads","fbjni"],"backgroundTag":"missing-env-var","analyzedSha":"666fefcb5d3f39cc944001c3457c38ffd6544c87","analyzedAt":"2026-09-09T11:09:01.694Z","contentChangedAt":"2026-09-09T11:09:01.694Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}