Java.lang.NoSuchFieldError: no "I" field "value" in class "Ljava/lang/Integer;" or its superclasses Android 10

Java.lang.NoSuchFieldError: no "I" field "value" in class "Ljava/lang/Integer;" or its superclasses Android 10

我从客户那里收到了一个 .so android 库,我必须将其集成到我的 Xamarin Forms 项目中。该库帮助应用程序连接到 IoT 设备。由于库方法具有以下签名,我决定编写一个 java 包装器来简化参数并创建一个 aar 文件。之后,我原生绑定aar并在我的项目中将其用作dll。

需要注意的是,Xamarin 中的问题仅在 Compile Target > 10 时出现。否则,它可以正常工作。我的猜测是 latest Updates to non-SDK interfaces broke the application.

图书馆header:

public static native int ReadParams(String token, StringBuilder serial, StringBuilder ssid, StringBuilder password, StringBuilder sensor, Integer keepAlive);

问题: 当从本机 android 应用程序中调用时,该方法工作正常,但因 Xamarin Forms 出现以下错误而崩溃。崩溃发生在 Java 包装器中的以下行。

崩溃线:

StringBuilder strSerial = new StringBuilder();
StringBuilder strssid = new StringBuilder();
StringBuilder strpassword = new StringBuilder();
StringBuilder strsensor = new StringBuilder();
Integer keepAlive = new Integer(0);
//Crash on below line
int response = EPM002Lib.ReadParams(token, strSerial, strssid, strpassword, strsensor, keepAlive);

堆栈跟踪:

--- End of managed Java.Lang.IncompatibleClassChangeError stack trace --- java.lang.NoSuchFieldError: no "I" field "value" in class "Ljava/lang/Integer;" or its superclasses at com.esong.lib.EPM002Lib.ReadParams(Native Method) at com.sensorwa.config.configdemo.SquareSdkhelper.ReadParams(SquareSdkhelper.java:32)

我知道有关 EPM002Lib.ReadParams 参数的内部功能的更多信息会有所帮助,但是,该库似乎可以与本机 android 应用程序一起使用(即使针对 Android 10).请随时询问更多信息或提供建议。感谢帮助

您依赖的是不应该依赖的实现细节。

现在它坏了,你可以保留两件。

我使用 Android Aarch64 编译器编译了这个文件:

#include <jni.h>

int access_field(JNIEnv *env, jobject obj) {
    jclass cls_Integer = (*env)->FindClass(env, "Ljava/lang/Integer;");
    jfieldID fid_Integer_value = (*env)->GetFieldID(env, cls_Integer, "value", "I");
    return (*env)->GetIntField(env, obj, fid_Integer_value);
}

int access_method(JNIEnv *env, jobject obj) {
    jclass cls_Integer = (*env)->FindClass(env, "Ljava/lang/Integer;");
    jmethodID mid_Integer_value = (*env)->GetMethodID(env, cls_Integer, "intValue", "()I");
    return (*env)->CallIntMethod(env, obj, mid_Integer_value);
}

这导致 access_field 的以下代码:

int access_field(JNIEnv *env, jobject obj) {
   0:   d10103ff    sub sp, sp, #0x40
   4:   a9037bfd    stp x29, x30, [sp,#48]
   8:   9100c3fd    add x29, sp, #0x30
   c:   90000008    adrp    x8, 0 <access_field>
  10:   91000108    add x8, x8, #0x0
  14:   90000002    adrp    x2, 0 <access_field>
  18:   91000042    add x2, x2, #0x0
  1c:   90000003    adrp    x3, 0 <access_field>
  20:   91000063    add x3, x3, #0x0
  24:   f81f83a0    stur    x0, [x29,#-8]
  28:   f81f03a1    stur    x1, [x29,#-16]
    jclass cls_Integer = (*env)->FindClass(env, "Ljava/lang/Integer;");
  2c:   f85f83a9    ldur    x9, [x29,#-8]
  30:   f9400129    ldr x9, [x9]
  34:   f9401929    ldr x9, [x9,#48]
  38:   f85f83a0    ldur    x0, [x29,#-8]
  3c:   aa0803e1    mov x1, x8
  40:   f90007e2    str x2, [sp,#8]
  44:   f90003e3    str x3, [sp]
  48:   d63f0120    blr x9
  4c:   f9000fe0    str x0, [sp,#24]
    jfieldID fid_Integer_value = (*env)->GetFieldID(env, cls_Integer, "value", "I");
  50:   f85f83a8    ldur    x8, [x29,#-8]
  54:   f9400108    ldr x8, [x8]
  58:   f9417908    ldr x8, [x8,#752]
  5c:   f85f83a0    ldur    x0, [x29,#-8]
  60:   f9400fe1    ldr x1, [sp,#24]
  64:   f94007e2    ldr x2, [sp,#8]
  68:   f94003e3    ldr x3, [sp]
  6c:   d63f0100    blr x8
  70:   f9000be0    str x0, [sp,#16]
    return (*env)->GetIntField(env, obj, fid_Integer_value);
  74:   f85f83a8    ldur    x8, [x29,#-8]
  78:   f9400108    ldr x8, [x8]
  7c:   f9419108    ldr x8, [x8,#800]
  80:   f85f83a0    ldur    x0, [x29,#-8]
  84:   f85f03a1    ldur    x1, [x29,#-16]
  88:   f9400be2    ldr x2, [sp,#16]
  8c:   d63f0100    blr x8
  90:   a9437bfd    ldp x29, x30, [sp,#48]
  94:   910103ff    add sp, sp, #0x40
  98:   d65f03c0    ret


}

access_method:

int access_method(JNIEnv *env, jobject obj) {
  9c:   d10103ff    sub sp, sp, #0x40
  a0:   a9037bfd    stp x29, x30, [sp,#48]
  a4:   9100c3fd    add x29, sp, #0x30
  a8:   90000008    adrp    x8, 0 <access_field>
  ac:   91000108    add x8, x8, #0x0
  b0:   90000002    adrp    x2, 0 <access_field>
  b4:   91000042    add x2, x2, #0x0
  b8:   90000003    adrp    x3, 0 <access_field>
  bc:   91000063    add x3, x3, #0x0
  c0:   f81f83a0    stur    x0, [x29,#-8]
  c4:   f81f03a1    stur    x1, [x29,#-16]
    jclass cls_Integer = (*env)->FindClass(env, "Ljava/lang/Integer;");
  c8:   f85f83a9    ldur    x9, [x29,#-8]
  cc:   f9400129    ldr x9, [x9]
  d0:   f9401929    ldr x9, [x9,#48]
  d4:   f85f83a0    ldur    x0, [x29,#-8]
  d8:   aa0803e1    mov x1, x8
  dc:   f90007e2    str x2, [sp,#8]
  e0:   f90003e3    str x3, [sp]
  e4:   d63f0120    blr x9
  e8:   f9000fe0    str x0, [sp,#24]
    jmethodID mid_Integer_value = (*env)->GetMethodID(env, cls_Integer, "intValue", "()I");
  ec:   f85f83a8    ldur    x8, [x29,#-8]
  f0:   f9400108    ldr x8, [x8]
  f4:   f9408508    ldr x8, [x8,#264]
  f8:   f85f83a0    ldur    x0, [x29,#-8]
  fc:   f9400fe1    ldr x1, [sp,#24]
 100:   f94007e2    ldr x2, [sp,#8]
 104:   f94003e3    ldr x3, [sp]
 108:   d63f0100    blr x8
 10c:   f9000be0    str x0, [sp,#16]
    return (*env)->CallIntMethod(env, obj, mid_Integer_value);
 110:   f85f83a8    ldur    x8, [x29,#-8]
 114:   f9400108    ldr x8, [x8]
 118:   f940c508    ldr x8, [x8,#392]
 11c:   f85f83a0    ldur    x0, [x29,#-8]
 120:   f85f03a1    ldur    x1, [x29,#-16]
 124:   f9400be2    ldr x2, [sp,#16]
 128:   d63f0100    blr x8
 12c:   a9437bfd    ldp x29, x30, [sp,#48]
 130:   910103ff    add sp, sp, #0x40
 134:   d65f03c0    ret

主要区别在于 ldr x8 调用中使用的偏移量。这些是 JNIEnv 内函数指针 table 的偏移量,更具体地说:

  • GetFieldID 位于偏移量 752
  • GetIntField 位于偏移量 800
  • GetMethodID 位于偏移量 264
  • CallIntMethod 位于偏移量 392。

另一个区别是传递给 GetIntFieldGetMethodID 的签名,它是在链接器时注入的。我转储的目标文件还没有链接,所以那里有伪指令。它是第四个参数,因此它在寄存器 x3.

中传递

因此,总而言之,您需要执行以下操作:

  • 在库中的某处找到字符串"()I"的地址或者添加到字符串table.
  • 您需要找到所有 java.lang.Integer#value 被访问的地方。
  • blr x8 调用之前替换 ldr x8 中的两个函数指针偏移量(752 -> 264;800 -> 392)。
  • 找到更改 x3 的代码并使其指向 "()I"

祝你好运!