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。
另一个区别是传递给 GetIntField
或 GetMethodID
的签名,它是在链接器时注入的。我转储的目标文件还没有链接,所以那里有伪指令。它是第四个参数,因此它在寄存器 x3
.
中传递
因此,总而言之,您需要执行以下操作:
- 在库中的某处找到字符串
"()I"
的地址或者添加到字符串table.
- 您需要找到所有
java.lang.Integer#value
被访问的地方。
- 在
blr x8
调用之前替换 ldr x8
中的两个函数指针偏移量(752 -> 264;800 -> 392)。
- 找到更改
x3
的代码并使其指向 "()I"
。
祝你好运!
我从客户那里收到了一个 .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
位于偏移量 752GetIntField
位于偏移量 800GetMethodID
位于偏移量 264CallIntMethod
位于偏移量 392。
另一个区别是传递给 GetIntField
或 GetMethodID
的签名,它是在链接器时注入的。我转储的目标文件还没有链接,所以那里有伪指令。它是第四个参数,因此它在寄存器 x3
.
因此,总而言之,您需要执行以下操作:
- 在库中的某处找到字符串
"()I"
的地址或者添加到字符串table. - 您需要找到所有
java.lang.Integer#value
被访问的地方。 - 在
blr x8
调用之前替换ldr x8
中的两个函数指针偏移量(752 -> 264;800 -> 392)。 - 找到更改
x3
的代码并使其指向"()I"
。
祝你好运!