Android - 加载库失败

时间:2010-09-02 20:56:33

标签: java android java-native-interface native

我遇到与this question类似的问题,但略有不同。我编译了一个.so库来与JNI一起使用。因为它很大(15 MB),所以我将它放在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

知道什么是错的吗?

我阅读了关于can android load dll's from sdcard in native mode的帖子,其中说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

4 个答案:

答案 0 :(得分:3)

我认为你的.so所依赖的图书馆可能更有可能找不到。但这只是在首先可以从SDCard加载.so文件的时候。

答案 1 :(得分:3)

libSample.so是否对您可能正在构建的其他共享库有依赖关系?如果是这样,您需要System.loadLibrarySystem.load其依赖项首先,确保在其他库之前加载最“基本”的库,就像它们是静态库一样。 NDK 7b至少似乎是这样。

例如,如果libSample.so取决于libfoo.so,您应该执行以下操作:

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

答案 2 :(得分:1)

请尝试遵循我为您在问题开头提到的问题提供的指导原则(我的意思是here)。祝你好运!

答案 3 :(得分:0)

好吧,我之前从未使用过Android,因此它可能是一个愚蠢的评论,但在JavaSE中它也不会起作用,因为你的库文件是“错误的”。 看,你用java编写程序,所以你不知道它会运行什么,对吧?你怎么知道你要加载的lib是在文件myLib.so还是myLib.dll或myLib.32TestNotHackerSufix? 嗯......你不要!这是java!它将根据您的SO解决lib的sufix。

尝试使用

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

没有“.so”。

(我想你在Android中没有像“LIBRARY_PATH”这样的东西,所以它会从你告诉他的路径加载你的lib ....如果在Android中存在这样的东西你应该加载你的lib像

System.load("libSampe"); 

并在启动你的app之前将你的目录放在LIBRARY_PATH中)