java Android - 加载库失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3631201/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:44:15  来源:igfitidea点击:

Android - failure on loading library

javaandroidjava-native-interfacenative

提问by I82Much

I have a similar problem to this question, but slightly different. I have compiled a .so library to use with JNI. Because it is large (15 MB), I am putting it on the SDCard instead of in the standard application place.

我有一个与此问题类似的问题,但略有不同。我编译了一个 .so 库以与 JNI 一起使用。因为它很大(15 MB),所以我把它放在 SDCard 上而不是放在标准的应用程序位置。

The file is called libSample.so and it's located at /data/library/libSample.so

该文件名为 libSample.so,位于 /data/library/libSample.so

I load it in a static initialization block:

我将它加载到静态初始化块中:

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());
    }

Here's the relevant logcat output:

这是相关的 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

Any idea what's wrong?

知道出了什么问题吗?

I read the post about can android load dll's from sdcard in native modewhich said that the sdcard cannot be used to load libraries, so I moved the .so into /data/data/com.example.hellojni/lib/libSample.so (the private app data storage location). No change:

我阅读了关于android 是否可以在本机模式下从 sdcard 加载 dll 的帖子,其中说 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

What I don't understand is that clearly the library exists, and the OS is trying to load it ... so what would make it fail?

我不明白的是,库显然存在,并且操作系统正在尝试加载它......那么什么会导致它失败?

Following the advice of one of the commentors, I tried attaching via strace to get more detailed error information. The log can be found as a github gist.

按照其中一位评论者的建议,我尝试通过 strace 附加以获得更详细的错误信息。该日志可以作为github gist找到。

The error appears to be on lines 47-51:

错误似乎在第 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

Here's the readelf of the library:

这是图书馆的readelf:

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

回答by Paul Gregtheitroade

I think it may be more likely that a library that your .so depends upon is not being found. But that is only if .so files can be loaded from an SDCard in the first place.

我认为更有可能找不到您的 .so 所依赖的库。但前提是 .so 文件可以首先从 SDCard 加载。

回答by ldav1s

Does libSample.sohave any dependencies on other shared libs that you may be building? If so, you'll need to System.loadLibraryor System.loadits dependencies first, making sure to load the most "basic" libraries before others, as if they were static libs. At least it seems to be this way with NDK 7b.

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

For example, if libSample.sodepends on libfoo.soyou should do something like:

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

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

回答by Maciej Pigulski

Please try following guidelines I have provided for the problem you were refering to in the beginning of your question (I mean here). Good luck!

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

回答by Plínio Pantale?o

Ok, i never used Android before, so its may be a stupid comment, but in JavaSE it will not work too, because your library file is "wrong". See, you write a program in java, so you dont know in what SO it will run, right? How could you know if the lib you want to load is in file myLib.so or myLib.dll or myLib.32TestNotHackerSufix? Well... you dont! It's java! It will solve the sufix of the lib for you based on your SO.

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

Try use

尝试使用

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

without ".so".

没有“.so”。

(I suppose you dont have something like "LIBRARY_PATH" in Android, so it will load your lib from the path you tell him.... If such thing exists in Android you shoul load your lib like

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

System.load("libSampe"); 

and put your directory in LIBRARY_PATH before start your app)

并在启动您的应用程序之前将您的目录放在 LIBRARY_PATH 中)