【问题标题】:How to set IntField from native jni to Java Android 10如何将 IntField 从本机 jni 设置为 Java Android 10
【发布时间】:2020-05-01 04:18:57
【问题描述】:

更新我的项目以支持 Android 10 后,在 JNI 级别产生了与 Android 10 中的非 SDK 接口限制相关的崩溃:

 JNI DETECTED ERROR IN APPLICATION: JNI SetIntField called with pending exception java.lang.NoSuchFieldError: no "I" field "value" in class "Ljava/lang/Integer;" or its superclasses

来自这部分代码:

jclass clazz = (*env)->GetObjectClass(env, outputObj);
jfieldID mi = (*env)->GetFieldID(env, clazz, "value", "I");
(*env)->SetIntField(env, outputObj, mi, pListLen);

为了解决这个问题,我将其替换为:

jclass clazz = (*env)->GetObjectClass(env, outputObj);
jmethodID intValueMethod = (*env)->GetMethodID(env, clazz, "intValue", "()I");
jint result = (*env)->CallIntMethod(env, outputObj,intValueMethod,pListLen);

之后我的应用程序不会崩溃并正确找到整数值,但我想使用相同的方法 SetIntField 在 Java 代码上设置结果整数。

能否请您给我一种在 Java 部分设置结果的方法或方法。

【问题讨论】:

  • 您不应该更改 Integer 对象的内部值,这会破坏各种不变量!请解释为什么你认为你需要这样做;也许我们可以找到其他方法。
  • 感谢您的回复, outputObj 稍后将在 java 部分中使用,但在 Android 10 更新之前,SetIntField 可以完美地工作,所以我想如果有另一种方法来设置我的outputObj 将其返回到 java 部分
  • 使用Integer#valueOf(int) 重载来构造一个新的Integer 对象。
  • “在 Android 10 更新之前,SetIntField 可以完美地工作” 之前工作的事实对我来说听起来像是一个错误。 Integers 应该是不可变的,因为例如如果您对 Integer.valueOf,则可以重复使用相同的 Integer 实例。
  • @Botje 我已经尝试过您的代码,但 outputObj 没有改变。这是我想做的:我想通过这个值设置 outputObj size_t pListLen = (size_t)(*env)->GetArrayLength(env, List);在这部分我将值设置为 java 部分: jclass clazz = (*env)->GetObjectClass(env, outputCidpuBufLen); jmethodID valueOfMethod = (*env)->GetStaticMethodID(env,clazz, "valueOf", "(I)Ljava/lang/Integer;"); (*env)->CallStaticObjectMethod(env,clazz, valueOfMethod, (jint)pListLen);最后在java部分没有出现新值,这真是奇怪的行为

标签: android java-native-interface android-10.0


【解决方案1】:

由于在JNI部分改变整数字段不是一个好习惯,所以我改变了方式而不是通过反射方法改变它

    jclass clazz = (*env)->GetObjectClass(env, outputBufLen);
    jmethodID value_of = (*env)->GetStaticMethodID(env,clazz, "valueOf", "(I)Ljava/lang/Integer;");
    jobject result = (*env)->CallStaticObjectMethod(env,clazz, value_of, pOutBufLen);

我将结果设置在一个 int 数组下并返回它:

int result = (*env)->CallStaticObjectMethod(env,clazz, value_of, pOutBufLen);

jintArray resultArray = (*env)->NewIntArray(env, 2);
jint fill[2];
fill[0] = result;
fill[1] = (jint) pOutBufLen;
(*env)->SetIntArrayRegion(env, result, 0, 2, fill);

return (resultArray);

【讨论】:

  • 因为我需要返回两个结果:
  • 给谁?你从未展示过调用代码,也从未解释过为什么要尝试更改 Integer 的内部值。请编辑您的问题以包含调用代码,然后我们可以为您制定答案。
  • 抱歉我的需求不清楚:因为我需要返回两个值:第一个返回内部方法的结果 `int ret = tlcGetCidpuList(virtualTabKey, virtualTabKeyLen, &param_t, pList, &pListLen) ; `
  • 我必须返回的第二个值也是pOutBufLen 所以最后改为返回一个整数并通过refelction方法设置另一个值` jclass clazz = (*env)->GetObjectClass(env,输出缓冲); jmethodID value_of = (*env)->GetStaticMethodID(env,clazz, "valueOf", "(I)Ljava/lang/Integer;"); jobject 结果 = (*env)->CallStaticObjectMethod(env,clazz, value_of, pOutBufLen); ` 我改变了返回两个整数的方式并在 java 部分进行了管理(请在 cmets 中保持礼貌!);)
  • 请使用调用代码和要求编辑您的问题或提出新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多