Android – сбой при загрузке библиотеки

У меня есть аналогичная проблема с этим вопросом , но немного другая. Я скомпилировал библиотеку .so для использования с JNI. Поскольку он большой (15 МБ), я помещаю его в SDCard вместо стандартного приложения.

Файл называется libSample.so, и он находится в /data/library/libSample.so

Я загружаю его в статический блок инициализации:

 try { File sdcard = Environment.getExternalStorageDirectory(); File libraryLoc = new File(sdcard.getAbsolutePath() + "/library/libSample.so"); Log.i("Library", "Does the library exist?" + libraryLoc.exists()); System.load(libraryLoc.getAbsolutePath()); } catch (UnsatisfiedLinkError e) { Log.e("Translator", e.getMessage()); Log.e("Translator", e.toString()); } 

Вот соответствующий вывод logcat:

 09-02 16:42:58.882: DEBUG/dalvikvm(4185): Trying to load lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 09-02 16:42:58.892: DEBUG/dalvikvm(4185): Added shared lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 09-02 16:42:58.892: DEBUG/dalvikvm(4185): No JNI_OnLoad found in /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 09-02 16:42:58.892: INFO/Library(4185): Library exists: true 09-02 16:42:58.902: INFO/Library(4185): Library can be read: true 09-02 16:42:58.902: DEBUG/dalvikvm(4185): Trying to load lib /sdcard/library/libSample.so 0x434fb6f8 09-02 16:42:58.902: INFO/dalvikvm(4185): Unable to dlopen(/sdcard/library/libSample.so): Cannot find library 09-02 16:42:58.912: ERROR/Translator(4185): Library /sdcard/library/libSample.so not found 09-02 16:42:58.912: ERROR/Translator(4185): java.lang.UnsatisfiedLinkError: Library /sdcard/library/libSample.so not found 

Любая идея, что не так?

Я прочитал сообщение о том, может ли dll s android загрузить с sdcard в собственном режиме, который сказал, что sdcard не может использоваться для загрузки библиотек, поэтому я переместил .so в /data/data/com.example.hellojni/lib/libSample.so ( Хранилище данных для частного приложения). Без изменений:

 09-02 16:53:18.332: DEBUG/dalvikvm(4515): Trying to load lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 09-02 16:53:18.342: DEBUG/dalvikvm(4515): Added shared lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 09-02 16:53:18.342: DEBUG/dalvikvm(4515): No JNI_OnLoad found in /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 09-02 16:53:18.352: INFO/Library(4515): Library exists: true 09-02 16:53:18.352: INFO/Library(4515): Library can be read: true 09-02 16:53:18.352: DEBUG/dalvikvm(4515): Trying to load lib /data/data/com.example.hellojni/lib/libSample.so 0x434fb6f8 09-02 16:53:18.482: INFO/dalvikvm(4515): Unable to dlopen(/data/data/com.example.hellojni/lib/libSample.so): Cannot find library 09-02 16:53:18.492: ERROR/Translator(4515): Library /data/data/com.example.hellojni/lib/libSample.so not found 09-02 16:53:18.492: ERROR/Translator(4515): java.lang.UnsatisfiedLinkError: Library /data/data/com.example.hellojni/lib/libSample.so not found 

Что я не понимаю, так это то, что библиотека явно существует, и ОС пытается ее загрузить … так что это может привести к ее провалу?

Следуя советам одного из комментаторов, я попытался подключиться через strace, чтобы получить более подробную информацию об ошибках. Журнал можно найти как github gist .

Ошибка отображается в строках 47-51:

 mprotect(0x4235d000, 4096, PROT_READ) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbeb58080) = -1 ENOTTY (Not a typewriter) write(1, "bionic/linker/linker.c:1243| ERROR: 34 unknown reloc type 3 @ 0x811a854c (2441)\n", 83) = 83 write(1, "bionic/linker/linker.c:1641| ERROR: failed to link /data/data/com.example.hellojni/lib/libSample.so\n", 100) = 100 munmap(0x81000000, 8839168) = 0 

Вот читатель библиотеки:

 arm-eabi-readelf -d libSample.so Dynamic section at offset 0x80b648 contains 17 entries: Tag Type Name/Value 0x00000019 (INIT_ARRAY) 0x7ff234 0x0000001b (INIT_ARRAYSZ) 76 (bytes) 0x00000004 (HASH) 0xd4 0x00000005 (STRTAB) 0x7f41c 0x00000006 (SYMTAB) 0x2650c 0x0000000a (STRSZ) 1197287 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000003 (PLTGOT) 0x80c6f0 0x00000002 (PLTRELSZ) 76480 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0x1ccb84 0x00000011 (REL) 0x1a3904 0x00000012 (RELSZ) 168576 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x00000016 (TEXTREL) 0x0 0x6ffffffa (RELCOUNT) 2412 0x00000000 (NULL) 0x0 

Solutions Collecting From Web of "Android – сбой при загрузке библиотеки"

Я думаю, что более вероятно, что библиотека, от которой зависит ваш .so, не найдена. Но это только если .so файлы могут быть загружены из SDCard в первую очередь.

Имеет ли libSample.so какие-либо зависимости от других общих библиотек, которые вы можете создавать? Если это так, сначала вам нужно сначала установить System.loadLibrary или System.load , чтобы загружать большинство «базовых» библиотек перед другими, как если бы они были статическими libs. По крайней мере, это похоже на NDK 7b.

Например, если libSample.so зависит от libfoo.so вы должны сделать что-то вроде:

 System.loadLibrary("foo"); System.loadLibrary("Sample"); 

Пожалуйста, попробуйте следовать рекомендациям, которые я представил для проблемы, о которой вы говорили в начале вашего вопроса (я имею в виду здесь ). Удачи!

Хорошо, я никогда не использовал Android раньше, поэтому его может быть глупым комментарием, но в JavaSE он тоже не будет работать, потому что ваш файл библиотеки «неправильный». Видите, вы пишете программу в java, так что вы не знаете, в какой степени она будет работать, не так ли? Как узнать, есть ли библиотека, которую вы хотите загрузить, в файле myLib.so или myLib.dll или myLib.32TestNotHackerSufix? Ну … ты не хочешь! Это java! Он решит sufix lib для вас на основе вашего SO.

Попробуйте использовать

  File libraryLoc = new File(sdcard.getAbsolutePath() + "/library/libSample"); 

Без ".so".

(Полагаю, у вас в Android нет чего-то типа «LIBRARY_PATH», поэтому он будет загружать вашу библиотеку с того пути, о котором вы ему рассказываете …. Если такая вещь существует в Android, вы можете загружать свою библиотеку как

 System.load("libSampe"); 

И поместите свой каталог в LIBRARY_PATH, прежде чем запускать приложение)