JNI在应用程序中检测到错误:错误的论点& JNI ERROR(app bug):访问陈旧的全局引用

时间:2017-04-27 13:08:08

标签: java android c++ android-ndk

最近,我正在学习Android JNI。我写了一个演示并尝试使用JNI调用一些Android SDK方法,然后发生了一些奇怪的崩溃。 1.使用JNI调用IActivityManager.getLaunchedFromUid(IBinder令牌),在某些设备上失败! 2.使用JNI调用IPackageManager.getLaunchedFromUid(String packageName,int flags),几乎在所有设备上都失败了!

这是我的Java代码。

public class HelloJni extends Activity {

    private static final String TAG = "HelloJni";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hello_jni);
        TextView tv = (TextView) findViewById(R.id.hello_textview);

        try {
            Class<?> activityManagerNativeClass = Class.forName("android.app.ActivityManagerNative");
            Field gDefaultField = activityManagerNativeClass.getDeclaredField("gDefault");
            gDefaultField.setAccessible(true);
            Object gDefault = gDefaultField.get(null);
            // gDefault is an android.util.Singleton Object
            Class<?> singleton = Class.forName("android.util.Singleton");
            // get the mInstance from ActivityManagerNative.gDefault. The mInstance implements IActivityManager
            Field mInstanceField = singleton.getDeclaredField("mInstance");
            mInstanceField.setAccessible(true);
            Object rawIActivityManager = mInstanceField.get(gDefault);

            // get ActivityToken
            Class<?> activityClazz = Class.forName("android.app.Activity");
            Method getActivityTokenMethod = activityClazz.getDeclaredMethod("getActivityToken");
            getActivityTokenMethod.setAccessible(true);
            Object activityToken = getActivityTokenMethod.invoke(this);

            Class<?> iActivityManagerClazz = Class.forName("android.app.IActivityManager");
            Method getLaunchedFromUidMethod = iActivityManagerClazz.getDeclaredMethod("getLaunchedFromUid", IBinder.class);
            getLaunchedFromUidMethod.setAccessible(true);
            // Call IActivityManager.getLaunchedFromUid(IBinder token) using reflection, success!
            int uid = (int) getLaunchedFromUidMethod.invoke(rawIActivityManager, activityToken);
            Log.d(TAG, "uid=" + uid);

            Class<?> iPackageManagerClazz = Class.forName("android.content.pm.IPackageManager");
            Method getPackageUidMethod = iPackageManagerClazz.getDeclaredMethod("getPackageUid", String.class, int.class);
            getPackageUidMethod.setAccessible(true);
            Class<?> activityThreadClazz = Class.forName("android.app.ActivityThread");
            Field sPackageManagerFiled = activityThreadClazz.getDeclaredField("sPackageManager");
            sPackageManagerFiled.setAccessible(true);
            Method method = activityThreadClazz.getDeclaredMethod("currentActivityThread");
            method.setAccessible(true);
            Object activityThread = method.invoke(null);
            Object sPackageManager = sPackageManagerFiled.get(activityThread);
            // Call IPackageManager.getLaunchedFromUid(IBinder token) using reflection, success!
            int packageUid = (int) getPackageUidMethod.invoke(sPackageManager, "com.example.hellojni", 0);
            Log.d(TAG, "packageUid=" + packageUid);

            // Call IActivityManager.getLaunchedFromUid(IBinder token) using JNI, fail on some devices!
            // Call IPackageManager.getLaunchedFromUid(String packageName, int flags) using JNI, almost fail on all devices!
            packageUid = getPackageUid(sPackageManager);
            tv.setText("uid=" + getLaunchedFromUid(rawIActivityManager, activityToken) + " packageUid=" + packageUid);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public native int getPackageUid(Object iPackageManager);

    public native int getLaunchedFromUid(Object iActivityManager, Object activityToken);

    static {
        System.loadLibrary("hello-jni");
    }
}

这是我的C ++代码。

extern "C" {
    JNIEXPORT jint JNICALL Java_com_example_hellojni_HelloJni_getPackageUid(JNIEnv * env, jobject thisObject, jobject iPackageManager);
    JNIEXPORT jint JNICALL Java_com_example_hellojni_HelloJni_getLaunchedFromUid(JNIEnv * env, jobject thisObject, jobject iActivityManager, jobject activityToken);
};

JNIEXPORT jint JNICALL Java_com_example_hellojni_HelloJni_getPackageUid(JNIEnv * env, jobject thisObject, jobject iPackageManager) {
    jclass IPackageManagerClazz = env->FindClass("android/content/pm/IPackageManager");
    jmethodID mid = env->GetMethodID(IPackageManagerClazz, "getPackageUid", "(Ljava/lang/String;I)I");
    jint uid = env->CallIntMethod(iPackageManager, mid, "com.example.hellojn", 0);
    return uid;
}

JNIEXPORT jint JNICALL Java_com_example_hellojni_HelloJni_getLaunchedFromUid(JNIEnv * env, jobject thisObject, jobject iActivityManager, jobject activityToken) {
    jclass IActivityManagerClazz = env->FindClass("android/app/IActivityManager");
    jmethodID midGetLaunchedFromUid = env->GetMethodID(IActivityManagerClazz, "getLaunchedFromUid", "(Landroid/os/IBinder;)I");
    int uid = env->CallIntMethod(iActivityManager, midGetLaunchedFromUid, activityToken);
    return uid;
}

使用JNI调用IActivityManager.getLaunchedFromUid(IBinder令牌)时的崩溃日志

E/art: JNI ERROR (app bug): attempt to pass an instance of android.app.IActivityManager as argument 1 to int android.app.IActivityManager.getLaunchedFromUid(android.os.IBinder)
E/art: JNI DETECTED ERROR IN APPLICATION: bad arguments passed to int android.app.IActivityManager.getLaunchedFromUid(android.os.IBinder) (see above for details)
E/art:     from int com.example.hellojni.HelloJni.getLaunchedFromUid(java.lang.Object, java.lang.Object)
E/art: "main" prio=5 tid=1 Runnable
E/art:   | group="main" sCount=0 dsCount=0 obj=0x755b12a0 self=0xf4bf6a00
E/art:   | sysTid=23997 nice=-1 cgrp=default sched=0/0 handle=0xf75f7de4
E/art:   | state=R schedstat=( 172765773 2780770 100 ) utm=12 stm=5 core=9 HZ=100
E/art:   | stack=0xff370000-0xff372000 stackSize=8MB
E/art:   | held mutexes= "mutator lock"(shared held)
E/art:     at com.example.hellojni.HelloJni.getLaunchedFromUid(Native method)
E/art:     at com.example.hellojni.HelloJni.onCreate(HelloJni.java:64)
E/art:     at android.app.Activity.performCreate(Activity.java:6288)
E/art:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113)
使用JNI调用IPackageManager.getLaunchedFromUid(String packageName,int flags)时出现崩溃日志

E/art: JNI ERROR (app bug): accessed stale global reference 0xf392b302 (index 44224 in a table of size 300)
E/art: JNI DETECTED ERROR IN APPLICATION: use of deleted global reference 0xf392b302
E/art:     from int com.example.hellojni.HelloJni.getPackageUid(java.lang.Object)
E/art: "main" prio=5 tid=1 Runnable
E/art:   | group="main" sCount=0 dsCount=0 obj=0x755b12a0 self=0xf4bf6a00
E/art:   | sysTid=24310 nice=-1 cgrp=default sched=0/0 handle=0xf75f7de4
E/art:   | state=R schedstat=( 48943077 1340463 65 ) utm=1 stm=3 core=9 HZ=100
E/art:   | stack=0xff370000-0xff372000 stackSize=8MB
E/art:   | held mutexes= "mutator lock"(shared held)
E/art:     at com.example.hellojni.HelloJni.getPackageUid(Native method)
E/art:     at com.example.hellojni.HelloJni.onCreate(HelloJni.java:63)
E/art:     at android.app.Activity.performCreate(Activity.java:6288)
E/art:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113)
E/art:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2500)
E/art:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2613)
E/art:     at android.app.ActivityThread.access$900(ActivityThread.java:180)
E/art:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1473)
E/art:     at android.os.Handler.dispatchMessage(Handler.java:111)
E/art:     at android.os.Looper.loop(Looper.java:207)
E/art:     at android.app.ActivityThread.main(ActivityThread.java:5710)
E/art:     at java.lang.reflect.Method.invoke!(Native method)
E/art:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:900)

虽然我们可能不会在实际应用中做这些事情,但我很好奇为什么会发生这些崩溃。

感谢您的帮助!

0 个答案:

没有答案