Tencent/tinker · error · IllegalStateException

Cannot query transaction code of performDexOptSecondary.

Error message

Cannot query transaction code of performDexOptSecondary.

What it means

To trigger secondary dex optimization on demand, Tinker reflects into the hidden android.content.pm.IPackageManager$Stub class to read the TRANSACTION_performDexOptSecondary constant (the binder transaction code). This error means the reflection chain (Class.getDeclaredField via a bootstrapped Method, then reading the static field) threw, so the transaction code could not be determined and the raw binder call cannot be built.

Source

Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerDexOptimizer.java:375

    }

    private static final int[] sPerformDexOptSecondaryTransactionCode = {-1};

    private static void performDexOptSecondaryByTransactionCode(Context context) throws IllegalStateException {
        synchronized (sPerformDexOptSecondaryTransactionCode) {
            if (sPerformDexOptSecondaryTransactionCode[0] == -1) {
                try {
                    final Method getDeclaredFieldMethod = ShareReflectUtil.findMethod(
                            Class.class, "getDeclaredField", String.class);
                    getDeclaredFieldMethod.setAccessible(true);
                    final Field cstField = (Field) getDeclaredFieldMethod.invoke(
                            Class.forName("android.content.pm.IPackageManager$Stub"),
                            "TRANSACTION_performDexOptSecondary"
                    );
                    cstField.setAccessible(true);
                    sPerformDexOptSecondaryTransactionCode[0] = (int) cstField.get(null);
                } catch (Throwable thr) {
                    throw new IllegalStateException("Cannot query transaction code of performDexOptSecondary.", thr);
                }
            }
        }

        ShareTinkerLog.i(TAG, "[+] performDexOptSecondaryByTransactionCode, code: %s",
                sPerformDexOptSecondaryTransactionCode[0]);

        final IBinder pmsBinder = getPMSBinderProxy(context);
        Parcel data = null;
        Parcel reply = null;
        try {
            data = Parcel.obtain();
            reply = Parcel.obtain();
            boolean result;
            try {
                data.writeInterfaceToken(pmsBinder.getInterfaceDescriptor());
                data.writeString(context.getPackageName());
                final String compileFilter = ShareTinkerInternals.isNewerOrEqualThanVersion(31 /* Android S */, true)

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Update Tinker to the latest release, which adapts the reflection for new API levels.
  2. Enable interpret mode so the dex-opt-by-binder path is never taken.
  3. As a last resort for a pinned old Tinker, catch this IllegalStateException around patch load and fall back to interpret-only loading.
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-flight: can we see the transaction constant at all?
try {
    Class<?> stub = Class.forName("android.content.pm.IPackageManager$Stub");
    Field f = stub.getDeclaredField("TRANSACTION_performDexOptSecondary");
} catch (Throwable t) {
    // binder-dexopt path unavailable: use interpret mode
}

Try / catch

try {
    performDexOptSecondaryByTransactionCode(context);
} catch (IllegalStateException e) {
    // reflection blocked on this ROM; degrade to interpret mode
    useInterpretMode = true;
}

Prevention

When it happens

Trigger: Running performDexOptSecondaryByTransactionCode on a ROM where IPackageManager$Stub no longer declares TRANSACTION_performDexOptSecondary, where the hidden-API greylist blocks access to it, or where an OEM renamed/obfuscated framework internals. Also on Android versions that changed the binder stub layout.

Common situations: Android 9+ hidden API restrictions (dark greylist); OEM frameworks (MIUI, EMUI) that alter AOSP internals; newer Android releases where the transaction constant was removed.

Related errors


AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14). Data as JSON: /api/errors/a4e0c203949110ad. Report an issue: GitHub.