结合 OpenCore 分析安卓应用程序 Crash 问题

关于 OpenCoreSDK

详情可参考上一篇文章 Android 应用程序如何抓取 Coredump

配置 Coredump

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码public class App extends Application {

@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);

Coredump.getInstance().init();
Coredump.getInstance().setCoreDir(getExternalFilesDir(null).getAbsolutePath());
Coredump.getInstance().setCoreMode(Coredump.MODE_COPY | Coredump.MODE_PTRACE);
//Coredump.getInstance().setCoreMode(Coredump.MODE_COPY);
//Coredump.getInstance().setCoreMode(Coredump.MODE_PTRACE);
Coredump.getInstance().enable(Coredump.JAVA);
Coredump.getInstance().enable(Coredump.NATIVE);
}
}

测试 Java OOM 场景

1
2
3
4
5
6
7
8
9
java复制代码public class LeakMemory {
private byte[] data = new byte[65536];

public LeakMemory() {
for (int i = 0; i < data.length; i++) {
data[i] = (byte) 0xaa;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
java复制代码void doOOM(View view) {
ArrayList<LeakMemory> array = new ArrayList<LeakMemory>();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
array.add(new LeakMemory());
}
}
}).start();
}

当我们点击 “doOOM” 的按钮时,程序会不停的创建一个 LeakMemory 对象,直到程序发生 OOM Crash,当发生 Java Crash 时,会被 Opencore 拦截触发抓取 Coredump。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
java复制代码AndroidRuntime: java.lang.OutOfMemoryError: Failed to allocate a 65552 byte allocation with 63712 free bytes and 62KB until OOM, target footprint 268435456, growth limit 268435456
AndroidRuntime: at penguin.opencore.coretester.LeakMemory.<init>(LeakMemory.java:4)
AndroidRuntime: at penguin.opencore.coretester.MainActivity$2.run(MainActivity.java:55)
AndroidRuntime: at java.lang.Thread.run(Thread.java:1012)

Opencore-arm64: Wait (19990) coredump
Opencore-arm64: Coredump /storage/emulated/0/Android/data/penguin.opencore.coretester/files/core.19935 ...
Opencore-arm64: WriteCoreLoadSegment Mode(3)
Opencore-arm64: [0x5ffff08000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff1b000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff2e000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff41000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff54000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x7c98a00000] /memfd:jit-cache (deleted) Not in self.
Opencore-arm64: [0x7c9dde0000] /memfd:jit-cache (deleted) Not in self.
Opencore-arm64: Coredump Done.
Opencore: /storage/emulated/0/Android/data/penguin.opencore.coretester/files/core.19935

我们即可拿个到该 OOM 问题的内存现场,那么我们可以进行离线内存分析,对于 ART 虚拟机的应用程序,我们有专门的分析工具可以辅助。类似的也可用 GDB、LLDB 来完成。

解析 Java 堆栈定位 Execption 类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
java复制代码art-parser> bt 19987
"Thread-4" prio=0 tid=2 Waiting
| group="" sCount=0 ucsCount=0 flags=0 obj=0x12c80f10 self=0x7d57f78400
| sysTid=19987 nice=<unknown> cgrp=<unknown> sched=<unknown> handle=0x7c9dbdfcb0
| stack=0x7c9dadc000-0x7c9dade000 stackSize=0x103cb0
| held mutexes=
x0 0x0000007c185a5db0 x1 0x0000000000000080 x2 0x0000000000000000 x3 0x0000000000000000
x4 0x0000000000000000 x5 0x0000000000000000 x6 0x0000000000000000 x7 0x0000007c9dbddf60
x8 0x0000000000000062 x9 0x4a022fd738159c35 x10 0x0000000000000003 x11 0x0000000000000002
x12 0x0000007c185ad9fc x13 0x000000004cec4ec5 x14 0x0000007c9dbde7d0 x15 0x0000000000000004
x16 0x0000007cb360f7c8 x17 0x0000007d4a94b200 x18 0x0000007c39c64000 x19 0x0000007c185a5da0
x20 0x0000007d57f78400 x21 0x0000007c185a5db0 x22 0x0000000000000000 x23 0x0000000000000000
x24 0x0000007c187f1040 x25 0x0000007c9dbe0000 x26 0x0000000000000001 x27 0x0000007d57feec20
x28 0x0000007d57feebe0 x29 0x0000007c9dbde5a0
lr 0x0000007cb3081f6c sp 0x0000007c9dbde590 pc 0x0000007d4a94b21c pst 0x0000000060001000
FP[0x7c9dbde5a0] PC[0x7d4a94b21c] native: #00 (syscall+0x1c) /apex/com.android.runtime/lib64/bionic/libc.so
FP[0x7c9dbde5a0] PC[0x7cb3081f6c] native: #01 (art::ConditionVariable::WaitHoldingLocks(art::Thread*)+0x8c) /apex/com.android.art/lib64/libart.so
FP[0x7c9dbde630] PC[0x7cb3372eb4] native: #02 (art::Monitor::Wait(art::Thread*, long, int, bool, art::ThreadState)+0x274) /apex/com.android.art/lib64/libart.so
FP[0x7c9dbde6d0] PC[0x7cb33746ac] native: #03 (art::Monitor::Wait(art::Thread*, art::ObjPtr<art::mirror::Object>, long, int, bool, art::ThreadState)+0x12c) /apex/com.android.art/lib64/libart.so
QF[0x7c9dbde720] PC[0x0000000000] at dex-pc 0x0000000000 java.lang.Object.wait(Native method) //AM[0x706f1370]
- waiting on <0x12e52f78> (java.lang.Object)
QF[0x7c9dbde7d0] PC[0x7cb300a914] at dex-pc 0x7caeea69f2 java.lang.Object.wait //AM[0x706f1350]
QF[0x7c9dbde8c0] PC[0x7cb300a258] at dex-pc 0x7caeea69d8 java.lang.Object.wait //AM[0x706f1330]
QF[0x7c9dbde9a0] PC[0x7cb300a258] at dex-pc 0x7c9bac1d1a penguin.opencore.sdk.Coredump.waitCore //AM[0x7c9c5584e0]
QF[0x7c9dbdea80] PC[0x7cb300a258] at dex-pc 0x7c9bac1bf4 penguin.opencore.sdk.Coredump.doCoredump //AM[0x7c9c558400]
QF[0x7c9dbdeb50] PC[0x7cb300a258] at dex-pc 0x7c9bac1ace penguin.opencore.sdk.Coredump$JavaCrashHandler.uncaughtException //AM[0x7c9c5585a0]
QF[0x7c9dbdec30] PC[0x7cb300b078] at dex-pc 0x7caeeb1714 java.lang.ThreadGroup.uncaughtException //AM[0x70676b78]
QF[0x7c9dbded30] PC[0x7cb300a258] at dex-pc 0x7caeeb1700 java.lang.ThreadGroup.uncaughtException //AM[0x70676b78]
QF[0x7c9dbdee30] PC[0x7cb300b078] at dex-pc 0x7caeeb287e java.lang.Thread.dispatchUncaughtException //AM[0x707001e0]

展开寄存器查看 Java 函数调用参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
java复制代码...
QF[0x7c9dbdee30] PC[0x7cb300b078] at dex-pc 0x7caeeb287e java.lang.Thread.dispatchUncaughtException //AM[0x707001e0]
{
Virtual registers
{
v0 = 0x12c811f0 v1 = 0x70517d70 v2 = 0x12c80f10 v3 = 0x12cc0000
}
Physical registers
{
x19 = 0x7d57f78400 x20 = 0x0 x21 = 0x0 x22 = 0x7caeeb287e
x23 = 0x3072 x24 = 0x7cb3000880 x25 = 0x7c9dbdee58 x26 = 0x7064c9a0
x27 = 0x8 x28 = 0x7c9dbdee80 x29 = 0x7c9dbdee68 x30 = 0x7cb300b078
}
}

字节码反编译确定 Throwable 对象所在寄存器。

1
2
3
4
java复制代码art-parser> disassemble 0x707001e0 -i 0x7caeeb287e
void java.lang.Thread.dispatchUncaughtException(java.lang.Throwable) [dex_method_idx=3796]
DEX CODE:
0x7caeeb287e: 3072 0eba 0321 | invoke-interface {v1, v2, v3}, void java.lang.Thread$UncaughtExceptionHandler.uncaughtException(java.lang.Thread, java.lang.Throwable) // method@3770

解析 Throwable 错误信息。

1
2
3
4
5
6
7
8
9
10
11
12
java复制代码art-parser> dumpjava 0x12cc0000
Throwable java.lang.OutOfMemoryError
Failed to allocate a 65552 byte allocation with 63712 free bytes and 62KB until OOM, target footprint 268435456, growth limit 268435456
penguin.opencore.coretester.LeakMemory.<init>(LeakMemory.java:4)
penguin.opencore.coretester.MainActivity$2.run(MainActivity.java:55)
java.lang.Thread.run(Thread.java:1012)
Caused by:
Throwable java.lang.OutOfMemoryError
Failed to allocate a 65552 byte allocation with 63712 free bytes and 62KB until OOM, target footprint 268435456, growth limit 268435456
penguin.opencore.coretester.LeakMemory.<init>(LeakMemory.java:4)
penguin.opencore.coretester.MainActivity$2.run(MainActivity.java:55)
java.lang.Thread.run(Thread.java:1012)

统计 Java 堆内存对象占用的 ShallowSize 大小以及分配数量,可见 byte[] 数组占用了 200+M 内存。并与 LeakMemory 对象分配的数量高度吻合。

1
2
3
4
5
6
7
8
9
10
11
12
java复制代码art-parser> top 10 -a -d
Address Allocations ShallowSize NativeSize ClassName
0x705050f8 3820 249731739 0 byte[]
0x12c80f88 3805 45660 0 penguin.opencore.coretester.LeakMemory
0x70566f78 1753 561064 0 java.lang.String
0x705052b8 1029 60360 0 java.lang.Object[]
0x705bf568 761 15220 0 java.util.ArrayList
0x70507aa0 741 26676 0 sun.misc.Cleaner
0x7079f8e0 736 17664 0 libcore.util.NativeAllocationRegistry$CleanerThunk
0x70547510 681 608344 0 int[]
0x70547828 650 162232 0 long[]
0x70cac990 422 10128 0 android.graphics.Rect

解析每一个 LeakMemory 内存分布, 可确定 LeakMemory 对象均持有一个 byte[] 数组,并且每一个 byte[] 大小为 65552 字节, 因此 LeakMemory 对象存在泄露。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
java复制代码art-parser> p 0x12f69ec8 -r
Size: 0x10
Padding: 0x4
Object Name: penguin.opencore.coretester.LeakMemory
iFields of penguin.opencore.coretester.LeakMemory
[0x8] byte[] data = 0x86907000
iFields of java.lang.Object
[0x0] java.lang.Class shadow$_klass_ = 0x12c80f88
[0x4] int shadow$_monitor_ = 0x0
References:
>> 0x12f57108 java.lang.Object[]

art-parser> p 0x86907000
Size: 0x10010
Padding: 0x4
Array Name: byte[]
[0] 0xaa
[1] 0xaa
[2] 0xaa
...
[65535] 0xaa

由于 LeakMemory 被线程的局部变量 java.util.ArrayList 所持有,无法 GC 回收,因此造成 OOM。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
java复制代码art-parser> p 0x12f57108
Size: 0x4120
Padding: 0x4
Array Name: java.lang.Object[]
[0] 0x12f5b228
[1] 0x12f5b238
...
[4163] 0x0
References:
>> 0x12c81078 java.util.ArrayList

art-parser> p 0x12c81078 -r
Size: 0x18
Padding: 0x4
Object Name: java.util.ArrayList
iFields of java.util.ArrayList
[0xc] java.lang.Object[] elementData = 0x12f57108
[0x10] int size = 0xedd
iFields of java.util.AbstractList
[0x8] int modCount = 0xedd
iFields of java.util.AbstractCollection
iFields of java.lang.Object
[0x0] java.lang.Class shadow$_klass_ = 0x705bf568
[0x4] int shadow$_monitor_ = 0x0
References:
>> 0x12c81090 penguin.opencore.coretester.MainActivity$2

art-parser> p 0x12c81090 -r
Size: 0x10
Object Name: penguin.opencore.coretester.MainActivity$2
iFields of penguin.opencore.coretester.MainActivity$2
[0x8] penguin.opencore.coretester.MainActivity this$0 = 0x12cac780
[0xc] java.util.ArrayList val$array = 0x12c81078
iFields of java.lang.Object
[0x0] java.lang.Class shadow$_klass_ = 0x12de6d50
[0x4] int shadow$_monitor_ = 0x0
References:
>> 0x12c80f10 java.lang.Thread

测试 Native Crash 场景

该测试用例在 Android12~Android13 之间使用,要看到这个 Native Crash 问题编译 apk 注意 debuggable 的条件,当 debuggable 为 false,此问题必现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码public class NterpTester {

class Entry {}

private List<Entry> mList;

public void setList() {
mList = new ArrayList<>();
}

@Override
public String toString() {
return "Penguin." + mList;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
java复制代码void doTest(View view) {
Log.i("Opencore", "test");
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
nterpTester.toString();
}
}
}).start();

new Thread(new Runnable() {
@Override
public void run() {
while (true) {
nterpTester.setList();
}
}
}).start();
}

当 debuggable 为 true 时,需做一些小小的 HOOK 处理才能复现,我们需要将 setList 这个 Java 函数运行方式修改为 Nterp 解析运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码void doHook(View view) {
Log.i("Opencore", "doHook");
try {
Method setListMethod = NterpTester.class.getMethod("setList", null);
Field artMethodField = Executable.class.getDeclaredField("artMethod");
artMethodField.setAccessible(true);
long artMethod = artMethodField.getLong(setListMethod);
Log.i("Opencore", artMethodField.getName() + " = 0x" + Long.toHexString(artMethod));
native_call(artMethod);
} catch (Exception e) {
e.printStackTrace();
}
}

强行修改 entry_point_from_quick_compiled_code_ 让其跳转函数到 ExecuteNterpImpl。

1
2
3
4
5
6
7
8
9
10
11
12
c++复制代码extern "C"
JNIEXPORT void JNICALL
Java_penguin_opencore_coretester_MainActivity_native_1call(JNIEnv *env, jobject thiz, jlong art_method_ptr) {
#if defined (__aarch64__) || defined (__arm64__)
ArtMethod *method = reinterpret_cast<ArtMethod *>(art_method_ptr);
void *art_load = read_module_address("/apex/com.android.art/lib64/libart.so");
int nterp_offset = read_symb_offset("/apex/com.android.art/lib64/libart.so", "ExecuteNterpImpl", STT_FUNC);
void* ExecuteNterpImpl = reinterpret_cast<void *>((uint64_t)art_load + nterp_offset);
LOGI("%p %p %p", method, art_load, ExecuteNterpImpl);
method->ptr_sized_fields_.entry_point_from_quick_compiled_code_ = ExecuteNterpImpl;
#endif
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
java复制代码Opencore-SDK: Init opencore environment..
Opencore: test
Opencore: doHook
Opencore: artMethod = 0x7c9c56ded0
Opencore: 57, 0000000000200090, 000000000005d34f, ExecuteNterpImpl, 0x7c9da1a82a, 0x7c9d10e000
Opencore: 0x7c9c56ded0 0x7cb2e00000 0x7cb3000090
Opencore-arm64: Wait (20399) coredump
Opencore-arm64: Coredump /storage/emulated/0/Android/data/penguin.opencore.coretester/files/core.20356 ...
Opencore-arm64: WriteCoreLoadSegment Mode(3)
Opencore-arm64: [0x5ffff08000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff1b000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff2e000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff41000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x5ffff54000] /mali csf (deleted) Not in self.
Opencore-arm64: [0x7c98a00000] /memfd:jit-cache (deleted) Not in self.
Opencore-arm64: [0x7c9d940000] [anon:dalvik-CompilerMetadata] Not in self.
Opencore-arm64: [0x7c9dde0000] /memfd:jit-cache (deleted) Not in self.
Opencore-arm64: Coredump Done.

可看到堆栈在 java 函数 java.lang.String.valueOf 处发生 Native Crash。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
java复制代码art-parser> bt 20397 -adj
"Thread-4" prio=0 tid=29 Unknown
| group="" sCount=0 ucsCount=0 flags=4 obj=0x17200d10 self=0x7c162dac00
| sysTid=20397 nice=<unknown> cgrp=<unknown> sched=<unknown> handle=0x7c16fcacb0
| stack=0x7c16ec7000-0x7c16ec9000 stackSize=0x103cb0
| held mutexes= "mutator lock"
x0 0x00000000ffffffff x1 0x0000007d474c9b98 x2 0x0000000000000000 x3 0x0000000000000000
x4 0x0000007d474c82a0 x5 0x0000000000b0863a x6 0x0000007d474c9708 x7 0x706d756465726f63
x8 0x0000000000000104 x9 0x4a022fd738159c35 x10 0x0000000000000002 x11 0xfffffffffffffffd
x12 0x0000007d474c83c0 x13 0x0000000000000016 x14 0x0000007d474c9708 x15 0x000000ce9c37561b
x16 0x0000007d4a9cf298 x17 0x0000007d4a9a9010 x18 0x0000007c123ae000 x19 0x0000007d580029c0
x20 0x000000000000000b x21 0x0000007d474c9da0 x22 0x0000007d474c9e48 x23 0x0000007d572e86f8
x24 0x0000007c16fcb000 x25 0x0000007c16fcb000 x26 0x000000000000000b x27 0x0000007d572e8318
x28 0x0000000000000000 x29 0x0000007d474c9ca0
lr 0x0000007c9b084f80 sp 0x0000007d474c9b60 pc 0x0000007d4a9a9014 pst 0x0000000060001000
FP[0x7d474c9ca0] PC[0x7d4a9a9014] native: #00 (wait4+0x4) /apex/com.android.runtime/lib64/bionic/libc.so
FP[0x7d474c9ca0] PC[0x7c9b084f80] native: #01 (OpencoreImpl::DoCoreDump()+0x64) /data/app/~~AeyWfgE18eFG7ZKpLRTTqw==/penguin.opencore.coretester-7NCCv5-T4UIf09uA5DJyVA==/base.apk!/lib/arm64-v8a/libopencore.so
FP[0x7d474c9cf0] PC[0x7c9b082aa8] native: #02 (Opencore::HandleSignal(int)+0x88) /data/app/~~AeyWfgE18eFG7ZKpLRTTqw==/penguin.opencore.coretester-7NCCv5-T4UIf09uA5DJyVA==/base.apk!/lib/arm64-v8a/libopencore.so
FP[0x7d474c9d40] PC[0x7d572e31fc] native: #03 (art::SignalChain::Handler(int, siginfo*, void*)+0x14c) /apex/com.android.art/lib64/libsigchain.so
FP[0x7d474caff0] PC[0x7d594dd84c] native: #04 () [vdso]
<<maybe handle signal>>
x0 0x0000000000000000 x1 0x000000001409fec0 x2 0x000000001409fec0 x3 0x00000000172012be
x4 0x0000000014166e20 x5 0x0000000000000000 x6 0x00000000000011e0 x7 0x0000000000000010
x8 0x4a022fd738159c35 x9 0x4a022fd738159c35 x10 0x0000000000000000 x11 0x000000000000000b
x12 0x0000000014166d9c x13 0x0000000000000001 x14 0xfffffffffc000000 x15 0x0000000000000030
x16 0x0000007d5802af28 x17 0x0000000000000000 x18 0x0000007c123ae000 x19 0x0000007c162dac00
x20 0x0000000000000001 x21 0x0000000000000000 x22 0x000000001409fec0 x23 0x000000001409fec0
x24 0x000000001409fec0 x25 0x0000007c16fca940 x26 0x000000007064c218 x27 0x0000000000000004
x28 0x0000007c16fca950 x29 0x000000009cb5f9b0
lr 0x000000009cb5bd80 sp 0x0000007c16fca7b0 pc 0x000000009cb60ffc pst 0x0000000040001000
QF[0x7c16fca7b0] PC[0x009cb60ffc] at dex-pc 0x7caeeaebe0 java.lang.String.valueOf //AM[0x706ff3b8]
QF[0x7c16fca7e0] PC[0x009cb5bd80] at dex-pc 0x7caeeacb80 java.lang.StringBuilder.append //AM[0x706a2198]
QF[0x7c16fca830] PC[0x009cb6130c] at dex-pc 0x7c9be8cf22 penguin.opencore.coretester.NterpTester.toString //AM[0x7c9c56def0]
QF[0x7c16fca870] PC[0x009cb5f95c] at dex-pc 0x7c9be8cb94 penguin.opencore.coretester.MainActivity$3.run //AM[0x7c9c56e118]
QF[0x7c16fca920] PC[0x7cb300b078] at dex-pc 0x7caeeb2b60 java.lang.Thread.run //AM[0x70700400]

解析机器码可看到在指令 ldr x0,[x0, #192] 上发生段错误。此时 x0 实际上是 x1 对象的 klass_ 成员变量的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
asm复制代码(gdb) x /32i 0x9cb60fb0
0x9cb60fb0: sub x16, sp, #0x2, lsl #12
0x9cb60fb4: ldr wzr, [x16]
0x9cb60fb8: str x0, [sp, #-48]!
0x9cb60fbc: stp x22, x30, [sp, #32]
0x9cb60fc0: str wzr, [sp, #28]
0x9cb60fc4: ldr w16, [x19]
0x9cb60fc8: tst w16, #0x7
0x9cb60fcc: b.ne 0x9cb61030 // b.any
0x9cb60fd0: mov x16, #0xaf28 // #44840
0x9cb60fd4: movk x16, #0x5802, lsl #16
0x9cb60fd8: movk x16, #0x7d, lsl #32
0x9cb60fdc: ldrb w17, [x16]
0x9cb60fe0: cbnz w17, 0x9cb6103c
0x9cb60fe4: cbnz w1, 0x9cb60ff4
0x9cb60fe8: ldr w0, 0x9cb61068
0x9cb60fec: mov x22, x1
0x9cb60ff0: b 0x9cb61008
0x9cb60ff4: mov x22, x1
0x9cb60ff8: ldr w0, [x1]
0x9cb60ffc: ldr x0, [x0, #192]
0x9cb61000: ldr x30, [x0, #24]
0x9cb61004: blr x30
0x9cb61008: mov x1, x0

而 x1 对象为 java.util.ArrayList, 并且最终内存转储后,klass_ = 0x705bf568,并非空指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码art-parser> p 0x000000001409fec0   
Size: 0x18
Padding: 0x4
Object Name: java.util.ArrayList
iFields of java.util.ArrayList
[0xc] java.lang.Object[] elementData = 0x7053e720
[0x10] int size = 0x0
iFields of java.util.AbstractList
[0x8] int modCount = 0x0
iFields of java.util.AbstractCollection
iFields of java.lang.Object
[0x0] java.lang.Class shadow$_klass_ = 0x705bf568
[0x4] int shadow$_monitor_ = 0x20000000

该问题这里不进行详细解答,感兴趣的可以私信我,该问主要原因在于 mList = new ArrayList<>(); 该代码为 Nterp 解释运行下的 new-instance 这条字节码身上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码art-parser> disassemble 0x7c9c56ded0 --full
void penguin.opencore.coretester.NterpTester.setList() [dex_method_idx=325]
DEX CODE:
0x7c9be8cf5c: 0022 0113 | new-instance v0, java.util.ArrayList // type@TypeIndex[275]
0x7c9be8cf60: 1070 0127 0000 | invoke-direct {v0}, void java.util.ArrayList.<init>() // method@295
0x7c9be8cf66: 105b 3261 | iput-object v0, v1, Ljava/util/List; penguin.opencore.coretester.NterpTester.mList // field@12897
0x7c9be8cf6a: 000e | return-void
OatQuickMethodHeader(0x7cb300008c)
code_offset: 0x7cb3000090
code_size: 0xf0b4
NterpMethodFrameInfo
frame_size_in_bytes: 0xd0
core_spill_mask: 0x7ff80000 (x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30)
fp_spill_mask: 0xff00 (x8, x9, x10, x11, x12, x13, x14, x15)
OAT CODE:
[0x7cb3000090-0x7cb300f144]

具体修复可对 mList 成员对象添加 volatile 修饰来避免,只有 Android14 之后才修复。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
asm复制代码// https://android-review.googlesource.com/c/platform/art/+/2583193

%def op_new_instance():
EXPORT_PC
// Fast-path which gets the class from thread-local cache.
% fetch_from_thread_cache("x0", miss_label="2f")
TEST_IF_MARKING 3f
4:
ldr lr, [xSELF, #THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET]
blr lr
dmb ishst // need fence for making object's class visible
1:
lsr w1, wINST, #8 // w1 <- A
SET_VREG_OBJECT w0, w1 // fp[A] <- value
FETCH_ADVANCE_INST 2
GET_INST_OPCODE ip
GOTO_OPCODE ip
2:
mov x0, xSELF
ldr x1, [sp]
mov x2, xPC

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%