Locating Android Native Memory Leakage Using Wrap Shell Script

Keywords: Android shell Linux Python

Prerequisite

  • Android version is over 8.0

Environmental configuration

  • cd to / src/main directory, create a new shell directory, and configure the directory of the same platform under the shell directory and libs directory. The hierarchical structure under app can be seen that the shell/lib directory has the same platform directory structure as libs directory.
── AndroidManifest.xml
├── java
├── libs
│   ├── arm64-v8a
│   └── armeabi-v7a
├── main.iml
├── res
└── shell
    └── lib
        ├── arm64-v8a
        └── armeabi-v7a
  • Create a wrap.sh script file in shell/lib / directory, edit the wrap.sh file and write the following contents
#!/system/bin/sh
LIBC_DEBUG_MALLOC_OPTIONS=backtrace $@

And grant scripts execution rights
chmod +x wrap.sh

Note that if your final generated apk only requires armeabi-v7a, do not place wrap.sh script files in arm64-v8a.

  • Open the / build.gradle file and add resource file paths to sourceSets.main, such as
sourceSets.main {
        jni.srcDirs = []
        jniLibs.srcDir "src/main/libs"
        resources.srcDir "src/main/shell"
    }
  • The environment configuration is completed, the compiled and packaged apk is compiled, and the apk is analyzed using Android Studio to ensure that wrap.sh script files exist in the corresponding platform.

Get Native memory allocation information

  • Install and run apk and get pid
  • A series of operations are performed on app, which may slow down because more operations are performed when memory is allocated.
  • The following commands are executed on the terminal: ADB shell am dumpheap-n < PID >/data/local/tmp/heap.txt
  • Pull / data / local / TMP / heap.txt locally and open heap.txt to see some information, as follows
Android Native Heap Dump v1.0

Total memory: 38937197
Allocation records: 42720
Backtrace size: 16

z 1  sz 20039040  num    1  bt edeff75a edeff654 edeff73e ee44d99a efda71f0 ee4487a4
z 1  sz  3908764  num    1  bt d2a28a38 d2a332b0 d290977a d28f9d96
z 1  sz   520192  num    1  bt cd30ca40 cd2b3ce8 cd2c307a cd2c2e50 cd2c2c24 cd2bca9e ee5cbdac ce546204 ce54d022 ce54f95c ce54ad92 ce53c1b4 ce53c1da ce5dab22 ee2ca8d6 ee29e340
......
  • Download files native_heapdump_viewer.py If your terminal can't access the addr2line and objdump commands directly, you need to replace the two commands in the python script with the path access of ndk, such as
<ndk path>toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objdump
<ndk path>toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line
  • Symbolic analysis of captured native memory allocation information using the following commands

python native_heapdump_viewer.py --symbols . heap.txt > heapinfo.txt

At this time, I take the memory allocation information of libQuCore.so library as an example, -- symbols is set to the script file path, note that opening heapinfo.txt at this time may not get the correct address and file matching information, such as the following information will be received

/data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so not found for symbol resolution

  2521990   6.72%  92.18%      409       ce5dab22 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so ??? ???
  2520966   6.72%  99.96%      408         ce53c1da /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so ??? ???
  2519574   6.71%  99.94%      381           ce53c1b4 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so ??? ???
  2519574   6.71% 100.00%      381             ce54ad92 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so ??? ???
  2519414   6.71%  99.99%      379               ce54f95c /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so ??? ???
  2517560   6.71%  99.93%      351                 ce54d022 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so ??? ???
  2500576   6.66%  99.33%      160                   ce546204 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so ??? ???

This is because android needs exactly the same symbolic file path as the mobile library path, so we create a new path locally and copy libQuCore.so to the new path, assuming that the path exists in the symbols directory, such as symbols/data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw=/lib/arm/libCore. To re-execute the above symbolic resolution command
python native_heapdump_viewer.py --symbols symbols heap.txt > heapinfo.txt

Open the heapinfo.txt file again to get the information about libQuCore.so symbols matching the number of files and rows. Here are some examples.


  2521990   6.72%  92.18%      409       ce5dab22 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so execute_native_thread_routine /Volumes/Android/buildbot/src/android/ndk-r14-release/toolchain/gcc/gcc-4.9/libstdc++-v3/src/c++11/thread.cc:84
  2520966   6.72%  99.96%      408         ce53c1da /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so std::thread::_Impl<std::_Bind_simple<void (*(alivc::ThreadService*))(alivc::ThreadService*)> >::_M_run() /Users/xunshan/Library/Android/sdk/android-ndk-r14b/sources/cxx-stl/gnu-libstdc++/4.9/include/functional:1700 (discriminator 2)
  2519574   6.71%  99.94%      381           ce53c1b4 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so alivc::ThreadWorker(alivc::ThreadService*) /Users/xunshan/Desktop/AliyunSVideo-product/sources/native/modules/alivc_framework/src/mdf/service/thread_service.cpp:18
  2519574   6.71% 100.00%      381             ce54ad92 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so alivc::RenderEngineService::OnInit() /Users/xunshan/Desktop/AliyunSVideo-product/sources/native/modules/alivc_framework/src/render_engine/render_engine_service.cpp:284
  2519414   6.71%  99.99%      379               ce54f95c /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so alivc::Canvas::Init() /Users/xunshan/Desktop/AliyunSVideo-product/sources/native/modules/alivc_framework/src/render_engine/canvas.cpp:36 (discriminator 1)
  2517560   6.71%  99.93%      351                 ce54d022 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so alivc::GraphicContext::Init(void*) /Users/xunshan/Desktop/AliyunSVideo-product/sources/native/modules/alivc_framework/src/render_engine/render_system/GL/graphic_context.cpp:36
  2500576   6.66%  99.33%      160                   ce546204 /data/app/com.aliyun.apsaravideo-e1DYx-Wua0VifW_TwlHhAw==/lib/arm/libQuCore.so alivc::AlivcEGLContext::Init(void*) /Users/xunshan/Desktop/AliyunSVideo-product/sources/native/modules/alivc_framework/src/render_engine/render_system/EGL/egl_context.cpp:59
  • According to the information of file and line number parsing for the memory allocation obtained above, we can analyze whether the memory allocation of native has leaked or not and where it has caused the memory leak.

Posted by rachelk on Wed, 20 Feb 2019 22:42:20 -0800