【问题标题】:How to use NDK-compiled JNI library in a normal non-Android Java application?如何在普通的非 Android Java 应用程序中使用 NDK 编译的 JNI 库?
【发布时间】:2016-09-21 22:56:11
【问题描述】:

我有一个 JNI 库,供 Android 应用程序与 NDK 一起使用。 我没有源代码,只为某些拱门编译了 .so 文件。

我想在 64 位 x86 linux PC 上的简单控制台 Java 应用程序中调用此库中的函数。

我做了什么:

  1. 我从 x86_64 文件夹中取出库并使用 System.loadLibrary 将其加载到我的 Java 程序中
  2. 尝试启动程序并得到 UnsatisfiedLinkError 详细信息liblog.so: cannot open shared object file: No such file or directory
  3. 所以我从官方 NDK 获取了 x86_64 架构的 liblog.so 并加载了它,然后遇到了与 libstdc++.so: cannot open shared object file: No such file or directory 相同的错误
  4. 为 libstdc++.so 库做了同样的事情,得到了这个/usr/lib/x86_64-linux-gnu/libc.so: invalid ELF header
  5. 打开 libc.so,它似乎只是一个文本文件...用正确的 libc.so 文件替换它
  6. 我的图书馆终于得到了 UnsatisfiedLinkError 的 undefined symbol: __stack_chk_guard 评论。看起来我的库与 Android 的东西紧密相关

我应该怎么做才能在我的正常程序中使用这个库,而没有任何 Android 特定的东西?

【问题讨论】:

  • 您可以编写自己的 liblog.so ——您不需要 Android 的。理论上,您可以替换 .so 文件中的库名称和函数名称(前提是您对它们进行了 demangle/mangle)。但就你目前的情况而言,我会使用 libc 编写一个简单的 .so 库,让它工作,然后看看有什么区别。 “无效的精灵头”很可能意味着您有一个用于不同架构的库。曾经有一个 Linux 实用程序可以将 ELF 标头打印到控制台。 (另外,在 ARM 上,v7 和 pre-v7 的库不能合并,可能你也有类似的问题。)
  • @18446744073709551615 谢谢!我检查了 libc.so 的类型,它似乎只是一个文本文件:D 打开它,发现里面有一些正常库的路径。复制它并...在我的问题中查找第 6 步。
  • __stack_chk_guard -- 看起来与malloc() 实现有关。只需将需要__stack_chk_guard 的功能替换为适用于您的架构的功能即可。最后,您应该能够从源代码为您的架构构建 libc。 (好吧,如果您对此非常感兴趣,那么您一定有非常特殊的客户......)
  • 嗨@AnnaProsvetova,你做到了吗?我的客户有同样的要求,我尝试使用 python 导入它,但我卡在你的第 4 步,你从哪里得到proper libc.so file

标签: java android android-ndk java-native-interface


【解决方案1】:

简而言之 - Android 和桌面 Linux 二进制文件不兼容,即使它们针对相同的 CPU 架构。

【讨论】:

  • 这是否意味着我绝对没有机会在我的 Linux x86_64 上使用这些 Android x86_64 库?即使我使用 Android ARM 库并尝试使用 Raspberry Pi(在 ARM 上)?
  • @AndreyStartsev 有时它可能会起作用(如果没有 android 特定的依赖项并且您可以以某种方式加载 ELF 文件)。但是运行时肯定会有惊喜。即使您已经从 android 获取了所有用户模式模块 - 内核也有些不同且不兼容。当然,您可以在桌面 linux 上使用 android 二进制文件,但不要考虑在生产中使用这种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-11
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
相关资源
最近更新 更多