didi/DoKit · error · NullPointerException

reflect failed.

Error message

reflect failed.

What it means

Utils.getApp() returns the cached Application (sApp), and when the cache is empty it obtains it via UtilsBridge.getApplicationByReflect(). If reflection cannot find the Application (returns null), a NullPointerException("reflect failed.") is thrown. Reflection is the fallback path used mainly in processes other than the main process, where the ContentProvider-based initialization (UtilsFileProvider) does not run.

Source

Thrown at Android/dokit-util/src/main/java/com/didichuxing/doraemonkit/util/Utils.java:72

            return;
        }
        if (sApp.equals(app)) return;
        UtilsBridge.unInit(sApp);
        sApp = app;
        UtilsBridge.init(sApp);
    }

    /**
     * Return the Application object.
     * <p>Main process get app by UtilsFileProvider,
     * and other process get app by reflect.</p>
     *
     * @return the Application object
     */
    public static Application getApp() {
        if (sApp != null) return sApp;
        init(UtilsBridge.getApplicationByReflect());
        if (sApp == null) throw new NullPointerException("reflect failed.");
        Log.i("Utils", UtilsBridge.getCurrentProcessName() + " reflect app success.");
        return sApp;
    }

    ///////////////////////////////////////////////////////////////////////////
    // interface
    ///////////////////////////////////////////////////////////////////////////

    public abstract static class Task<Result> extends ThreadUtils.SimpleTask<Result> {

        private Consumer<Result> mConsumer;

        public Task(final Consumer<Result> consumer) {
            mConsumer = consumer;
        }

        @Override
        public void onSuccess(Result result) {

View on GitHub (pinned to 626827cddb)

Solutions

  1. Call Utils.init(getApplicationContext()) in Application.attachBaseContext() so sApp is always populated before any Utils call.
  2. For non-main processes, initialize Utils explicitly in that process (e.g. in the service's onCreate) instead of relying on reflection.
  3. Check UtilsBridge.getApplicationByReflect() chain (ActivityThread -> mInitialApplication) works on the target device/ROM; avoid calling getApp() during very early process startup.

Example fix

// before
Context ctx = Utils.getApp(); // in :push process -> NPE reflect failed.

// after
public class MyApplication extends Application {
  @Override protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    Utils.init(base); // every process, including non-main
  }
}
Context ctx = Utils.getApp();
Defensive patterns

Strategy: validation

Validate before calling

if (Utils.getApp4Activity() == null) { /* fall back to passed Context */ }

Try / catch

try { app = Utils.getApp(); } catch (NullPointerException e) { app = yourContext.getApplicationContext(); } // last-resort only; prefer Utils.init in Application

Prevention

When it happens

Trigger: Calling Utils.getApp() in a non-main process (push service, web process, :remote service) before or without Utils.init(app); calling it in a process where the ActivityThread.currentActivityThread().getApplication() reflection chain fails; proguard/R8 stripping or OEM ROM differences breaking the reflection lookup.

Common situations: Library used inside a multiprocess app where UtilsFileProvider only initializes in the main process; an app class that never calls Utils.init(this) in attachBaseContext; aggressive obfuscation removing activity-thread internals on some devices.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/2541234339d6068d. Report an issue: GitHub.