【问题标题】:JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x1JNI 检测到应用程序错误:使用已删除的本地引用 0x1
【发布时间】:2018-07-18 13:58:54
【问题描述】:

我有 Java 函数,声明如下:

public static void mathSendResults(final int kidId, final int points, final int correct, final int error, final float time,
                                       final String date, final long timestamp, final String description,
                                       final String settings, final int classNumber, final int level, final float percentage)

现在,我想通过 JNI 调用这个函数:

void NativeHelper::mathSendResults(int kidId, int points, int correct, int error, float time,
                            std::string date, long timestamp, std::string description,
                            std::string settings, int classNumber, int level, float percentage) {

    cocos2d::JniMethodInfo t;
    if (cocos2d::JniHelper::getStaticMethodInfo(t, AppActivityClassName, "mathSendResults",
                                                "(IIIIFLjava/lang/String;JLjava/lang/String;Ljava/lang/String;IIF)V")){

        jstring jdate = t.env->NewStringUTF(date.c_str());
        jstring jdescription = t.env->NewStringUTF(description.c_str());
        jstring jsettings = t.env->NewStringUTF(settings.c_str());

        t.env->CallStaticVoidMethod(t.classID, t.methodID, kidId, points, correct, error, time,
                                    jdate, timestamp, jdescription,
                                    jsettings, classNumber, level, percentage);

        t.env->DeleteLocalRef(t.classID);
        t.env->DeleteLocalRef(jdate);
        t.env->DeleteLocalRef(jdescription);
        t.env->DeleteLocalRef(jsettings);
    }
}

它应该可以工作,但应用程序崩溃并出现以下错误:

JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x1

这对我来说看起来很奇怪。我试过删除DeleteLocalRef 调用,但它仍然崩溃。我已经有其他方法,但参数较少。我不确定这是否是原因。无论如何,我尝试用整数替换字符串(仅用于测试),因此参数的数量没有改变并且它起作用了。所以这绝对是字符串对象的问题。我也试过发送空字符串,但结果是一样的(所以它与字符串内容无关)。我也尝试将字符串数量减少到只有一个,但它仍然崩溃。

【问题讨论】:

  • 你从哪里得到像t.classIDt.methodID这样的东西?
  • 这是一个标准的 cocos2d-x JNI 模板。

标签: java android c++ java-native-interface


【解决方案1】:

jmethodid 不是 jobject,不需要(不能)被删除。

【讨论】:

  • 好吧,FindClass 返回的 jclass 是一个本地引用。但是方法/字段 ID 不是。
  • 即使我不删除内容它仍然崩溃。
【解决方案2】:

经过多次尝试和错误,我终于修复了它。

我不知道为什么,但是当 jstrings 是第一个参数时它可以工作。如果我在任何字符串应用程序崩溃之前放置一些东西(如 int)。下面的代码是解决方案:

void NativeHelper::mathSendResults(int kidId, int points, int correct, int error, float time,
                            std::string date, long timestamp, std::string description,
                            std::string settings, int classNumber, int level, float percentage) {

//    final String date, final String description, final String settings,
//    final int kidId, final int points, final int correct, final int error, final int classNumber, final int level,
//    final float percentage, final float time,
//    final long timestamp

    cocos2d::JniMethodInfo t;
    if (cocos2d::JniHelper::getStaticMethodInfo(t, AppActivityClassName, "mathSendResults",
                                                "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIFFJ)V")){

        jstring jdate = t.env->NewStringUTF(date.c_str());
        jstring jdescription = t.env->NewStringUTF(description.c_str());
        jstring jsettings = t.env->NewStringUTF(settings.c_str());

        t.env->CallStaticVoidMethod(t.classID, t.methodID,
                                    jdate, jdescription, jsettings,
                                    kidId, points, correct, error, classNumber, level,
                                    percentage, time,
                                    timestamp);

        t.env->DeleteLocalRef(t.classID);
        t.env->DeleteLocalRef(jdate);
        t.env->DeleteLocalRef(jdescription);
        t.env->DeleteLocalRef(jsettings);
    }
}

Java:

public static void mathSendResults(final String date, final String description, final String settings,
                                   final int kidId, final int points, final int correct, final int error, final int classNumber, final int level,
                                   final float percentage, final float time,
                                   final long timestamp)

为什么顺序很重要对我来说仍然是个谜。

编辑:更新了代码。实际上第一个版本不能正常工作。一些 int 变量在 Java 代码中具有不正确的(随机)值。我必须通过类型对参数进行排序,然后它终于起作用了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    相关资源
    最近更新 更多