简体   繁体   English

Java.lang.NoSuchFieldError:类“Ljava/lang/Integer”中没有“I”字段“value”; 或其超类 Android 10

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

I have received a .so android library from a client and I have to integrate that in my Xamarin Forms project.我从客户端收到了一个 .so android 库,我必须将它集成到我的 Xamarin Forms 项目中。 The library helps the app connect to an IoT device.该库可帮助应用程序连接到 IoT 设备。 As the library methods are of the following signature, I decided to write a java wrapper to simplify the parameters and create an aar file.由于库方法具有以下签名,我决定编写一个 java 包装器来简化参数并创建一个 aar 文件。 Afterwards, I natively bind the aar and use it as a dll in my project.之后,我本地绑定了 aar 并将其用作我的项目中的 dll。

It is important to note that the problem in Xamarin only occurs when the Compile Target is > 10. Otherwise, it works fine.需要注意的是,Xamarin 中的问题仅在 Compile Target > 10 时出现。否则,它工作正常。 My guess is that the latest Updates to non-SDK interfaces broke the application .我的猜测是非 SDK 接口最新更新破坏了应用程序

Library header:库头:

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

The problem: The method works fine when called from within a native android application however crashes with the following error from Xamarin Forms.问题:该方法在从本机 android 应用程序中调用时工作正常,但因 Xamarin Forms 的以下错误而崩溃。 The crash is on the following line in the Java wrapper.崩溃发生在 Java 包装器的下一行。

Crash line:崩溃线:

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);

The stacktrace:堆栈跟踪:

--- End of managed Java.Lang.IncompatibleClassChangeError stack trace --- java.lang.NoSuchFieldError: no "I" field "value" in class "Ljava/lang/Integer;" --- 托管 Java.Lang.IncompatibleClassChangeError 堆栈跟踪结束 --- java.lang.NoSuchFieldError:在类“Ljava/lang/Integer;”中没有“I”字段“value”; or its superclasses at com.esong.lib.EPM002Lib.ReadParams(Native Method) at com.sensorwa.config.configdemo.SquareSdkhelper.ReadParams(SquareSdkhelper.java:32)或其超类 com.esong.lib.EPM002Lib.ReadParams(Native Method) at com.sensorwa.config.configdemo.SquareSdkhelper.ReadParams(SquareSdkhelper.java:32)

I understand that more information regarding the internal functionality of the EPM002Lib.ReadParams params would help, however, the library seems to work with a native android application (even when compiled against Android 10).我知道有关 EPM002Lib.ReadParams 参数的内部功能的更多信息会有所帮助,但是,该库似乎适用于本机 Android 应用程序(即使针对 Android 10 进行编译)。 Please feel free to ask for more information or provide suggestions.请随时询问更多信息或提供建议。 Thanks for the help 😄谢谢帮忙😄

You're relying on an implementation detail that was not supposed to be relied on.您正在依赖不应该依赖的实现细节。

Now it broke and you get to keep both pieces.现在它坏了,你可以保留这两部分。

I compiled this file using the Android Aarch64 compiler:我使用 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);
}

which results in the following code for access_field :这导致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


}

and for access_method :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

The main differences are the offsets used in the ldr x8 calls.主要区别在于ldr x8调用中使用的偏移量。 These are offsets into the function pointer table inside the JNIEnv , more specifically:这些是JNIEnv内函数指针表的偏移量,更具体地说:

  • GetFieldID is at offset 752 GetFieldID位于偏移量 752
  • GetIntField is at offset 800 GetIntField位于偏移量 800
  • GetMethodID is at offset 264 GetMethodID位于偏移量 264
  • CallIntMethod is at offset 392. CallIntMethod位于偏移量 392 处。

The other difference is the signature passed to the GetIntField or GetMethodID , which is injected at linker time.另一个区别是传递给GetIntFieldGetMethodID的签名,它是在链接器时注入的。 The object file I dumped is not linked yet, so there are dummy instructions there.我转储的目标文件还没有链接,所以那里有虚拟指令。 It is the fourth argument so it is passed in register x3 .它是第四个参数,因此它在寄存器x3传递。

So, to summarize, you need to do the following:因此,总而言之,您需要执行以下操作:

  • Find the address of the string "()I" somewhere in the library or add it to the string table.在库中某处找到字符串"()I"的地址或将其添加到字符串表中。
  • You need to find all places where java.lang.Integer#value is accessed.您需要找到所有访问java.lang.Integer#value地方。
  • Replace the two function pointer offsets (752 -> 264; 800 -> 392) in the ldr x8 right before the blr x8 call.blr x8调用之前blr x8 ldr x8的两个函数指针偏移量 (752 -> 264; 800 -> 392)。
  • Find the code that changes x3 and make it point to "()I" instead.找到更改x3的代码并使其指向"()I"

Good luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 [Android]:java.lang.NoSuchFieldError:无字段error_color_material - [Android]: java.lang.NoSuchFieldError: No field error_color_material java.lang.NoSuchFieldError:类Lcom / google / android / gms / R $ styleable中没有类型I的静态字段MapAttrs_liteMode; - java.lang.NoSuchFieldError: No static field MapAttrs_liteMode of type I in class Lcom/google/android/gms/R$styleable; 为什么我得到一个Enum值上的java.lang.NoSuchFieldError :? - Why do I get a java.lang.NoSuchFieldError: on an Enum value? 更改类后的java.lang.NoSuchFieldError - java.lang.NoSuchFieldError after changing class java.lang.NoSuchFieldError dynamoDB android 时间偏移 - java.lang.NoSuchFieldError dynamoDB android timeoffset 在 RamlValidationService 中获取 java.lang.NoSuchFieldError: VALUE - Getting java.lang.NoSuchFieldError: VALUE in RamlValidationService java.lang.NoSuchFieldError:sqlResultSetMappings - java.lang.NoSuchFieldError: sqlResultSetMappings java.lang.NoSuchFieldError:句柄 - java.lang.NoSuchFieldError: handle java.lang.NoSuchFieldError: DEFAULT - java.lang.NoSuchFieldError: DEFAULT java.lang.NoSuchFieldError:INSTANCE - java.lang.NoSuchFieldError: INSTANCE
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM