安卓中本地共享库加载速度过慢

4

我有一个共享库放置在libs / armeabi文件夹中。它是使用以下方式加载的:

System.loadLibrary("library_name.so");

图书馆的大小约为3MB。加载时间非常长。有时会持续近20秒钟。它阻碍了我的GUI。我试图将System.loadLibrary("library_name.so");放入不同的线程中,但我的GUI仍然被阻塞。我知道其他应用程序使用更大的.so文件,但加载时间并不那么长。问题可能是什么?
编辑
3MB是调试版本的大小。发布版本约为800KB,但问题仍然存在。一些额外的信息:
- .so包含我的两个相互连接的C++库 - 运行arm-linux-androideabi-nm -D -C -g library_name.so会显示许多函数和变量 - 我不再使用LOCAL_WHOLE_STATIC_LIBRARIES - 这里是使用arm-linux-androideabi-readelf-tool得到的节头表:
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .dynsym           DYNSYM          00000114 000114 00b400 10   A  2   1  4

  [ 2] .dynstr           STRTAB          0000b514 00b514 015b0c 00   A  0   0  1

  [ 3] .hash             HASH            00021020 021020 004d1c 04   A  1   0  4

  [ 4] .rel.dyn          REL             00025d3c 025d3c 006e98 08   A  1   0  4

  [ 5] .rel.plt          REL             0002cbd4 02cbd4 000468 08   A  1   6  4

  [ 6] .plt              PROGBITS        0002d03c 02d03c 0006b0 00  AX  0   0  4

  [ 7] .text             PROGBITS        0002d6f0 02d6f0 08e6e0 00  AX  0   0  8

  [ 8] .ARM.extab        PROGBITS        000bbdd0 0bbdd0 00bad0 00   A  0   0  4

  [ 9] .ARM.exidx        ARM_EXIDX       000c78a0 0c78a0 005b80 08  AL  7   0  4

  [10] .rodata           PROGBITS        000cd420 0cd420 005cc0 00   A  0   0  4

  [11] .data.rel.ro.loca PROGBITS        000d46d8 0d36d8 0006e4 00  WA  0   0  4

  [12] .fini_array       FINI_ARRAY      000d4dbc 0d3dbc 000008 00  WA  0   0  4

  [13] .init_array       INIT_ARRAY      000d4dc4 0d3dc4 00009c 00  WA  0   0  4

  [14] .data.rel.ro      PROGBITS        000d4e60 0d3e60 00384c 00  WA  0   0  8

  [15] .dynamic          DYNAMIC         000d86ac 0d76ac 000100 08  WA  2   0  4

  [16] .got              PROGBITS        000d87ac 0d77ac 000854 00  WA  0   0  4

  [17] .data             PROGBITS        000d9000 0d8000 000648 00  WA  0   0  8

  [18] .bss              NOBITS          000d9648 0d8648 047271 00  WA  0   0  8

  [19] .comment          PROGBITS        00000000 0d8648 000026 01  MS  0   0  1

  [20] .note.gnu.gold-ve NOTE            00000000 0d8670 00001c 00      0   0  4

  [21] .ARM.attributes   ARM_ATTRIBUTES  00000000 0d868c 00002d 00      0   0  1

  [22] .shstrtab         STRTAB          00000000 0d86b9 0000d8 00      0   0  1

这个库中有多少个方法?你是通过RegisterNatives还是给它们命名为Java_来在JNI中注册它们的? - fadden
@fadden 我有5个导出函数。它们是使用RegisterNatives()注册的。这些方法使用我C++库中的函数。也许问题在于整个C++库都包含在我的.so文件中? - sinisha
@fadden 我使用了_auseln_答案中建议的工具。它显示有很多函数被注册了。我认为问题出现在我使用了LOCAL_WHOLE_STATIC_LIBRARIES,而且没有它就无法构建我的项目。 - sinisha
2个回答

1
问题在于某些构造函数中的静态初始化需要太长时间才能完成。

1
尝试减少共享库中导出函数的数量。您可以使用
arm-linux-androideabi-nm -D -C -g library_name.so

检查列表是否过长,并删除您不使用的内容(将它们声明为静态)。您可以通过$man nm查找nm手册并了解如何使用和解释它。

如果需要使用大量函数,请使用RegisterNatives()注册您的函数,而不是依赖于名称混淆和查找 - 这就是当您给函数命名为Java_your_path_YourClass_yourFunction时所做的事情。

如果库中有符号,则可以尝试strip(arm-linux-androideabi-strip)库。

为避免阻塞UI,可以尝试在不同的线程中尽早加载共享库并等待它。

如果最终不想公开静态库,则不建议使用LOCAL_WHOLE_STATIC_LIBRARIES。

LOCAL_WHOLE_STATIC_LIBRARIES

  • 这些是您想在模块中包含的静态库,而不允许链接器从中删除死代码。
  • 如果您想将一个静态库添加到共享库并从共享库中公开静态库的内容,则这通常很有用。

尝试解决问题而不是绕过构建问题。


我有5个导出函数。它们是使用RegisterNatives()注册的。我应该在哪里使用arm-linux-androideabi-nm -D -C -g library_name.so - sinisha
如果你没有运行它,你怎么知道有多少个导出函数? - auselen
1
你可以在 NDK 中找到 nm。 - auselen
不,你应该使用nm命令检查so文件。 - auselen
@sinisha 更新了我的答案。我认为除此之外我无法再帮助你了。 - auselen
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接