Java.lang.NoSuchFieldError:no"我"字段";值";在



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

需要注意的是,Xamarin中的问题仅在编译目标>10.否则,效果很好。我的猜测是,最新的非SDK接口更新破坏了应用程序。

库头:

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

堆叠竞赛:

---托管Java.Lang.IncompatibleClassChangeError堆栈跟踪结束---Java.Lang.NoSuchFieldError:no"我"字段";值";在课堂上";Ljava/lang/Integer"或其超类com.esong.lib.EPM002Lib.ReadParams(本机方法)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内部函数指针表的偏移量,更具体地说:

  • GetFieldID位于偏移752处
  • GetIntField处于偏移800
  • GetMethodID处于偏移264
  • CCD_ 8处于偏移392处

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

因此,总结一下,您需要执行以下操作:

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

祝你好运!

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

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

最新更新