Mobile Development 4 min read

Resolving Threading and FindClass Issues in Android NDK

The article explains how upgrading the Android NDK introduces threading pitfalls such as ANR and FindClass failures, and provides step‑by‑step solutions using main‑thread class lookup, global references, and thread attachment to safely execute JNI calls in background threads.

Hujiang Technology
Hujiang Technology
Hujiang Technology
Resolving Threading and FindClass Issues in Android NDK

After switching to a newer NDK version, the author encountered numerous threading problems that could cause ANR (Application Not Responding) even in seemingly harmless JNI calls.

It is recommended to move all potentially time‑consuming functions into background threads because the NDK may trigger ANR in unexpected places. The following code illustrates a typical JNI call that can lead to ANR:

clsContext := env^^.FindClass(env, 'android/content/Context'); getServiceContet := env^^.GetMethodID(env, clsContext, 'getSystemService', '(Ljava/lang/String;)Ljava/lang/Object;'); objActivityMgr := env^^.CallObjectMethodA(env, CONTEXT, getServiceContet, argsToJValues(env, ['activity']));

Running such code on a worker thread often results in FindClass returning nil because the JNIEnv in the child thread differs from the main thread’s environment, making the class unavailable.

One attempted fix is to perform FindClass on the main thread and store the result:

var clsContext: jclass; ... procedure ... clsContext := env^^.FindClass(env, 'android/content/Context'); ...

However, when the background thread later executes code such as:

thread { NativeAPI.run() }

the application still crashes with the JNI error accessed stale local reference , because the local reference is cleared after the function returns. Older NDK versions did not exhibit this problem.

The final solution is to create a global reference for the class before using it in a thread, or to attach the thread to the JVM. Using a global reference looks like this:

var clsContext: jclass; ... procedure ... clsContext := env^^.NewGlobalRef(env, env^^.FindClass(env, 'android/content/Context')); ...

With the global reference (or by calling AttachCurrentThread ), FindClass works correctly inside background threads, eliminating the ANR and crash issues.

AndroidthreadingJNINDKFindClass
Hujiang Technology
Written by

Hujiang Technology

We focus on the real-world challenges developers face, delivering authentic, practical content and a direct platform for technical networking among developers.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.