Java Native Interface (JNI) 是不是受 C++ ABI 兼容性问题的影响?

Posted

技术标签:

【中文标题】Java Native Interface (JNI) 是不是受 C++ ABI 兼容性问题的影响?【英文标题】:Is the Java Native Interface (JNI) affected by C++ ABI compatibility issues?Java Native Interface (JNI) 是否受 C++ ABI 兼容性问题的影响? 【发布时间】:2012-01-04 05:15:11 【问题描述】:

Java 原生接口 (JNI) 是否受 C++ ABI 兼容性问题的影响?

我正在开发一个 Java 应用程序。我想使用 Java 本机接口 (JNI) 来调用 C++ 库中的函数。我可以访问 C++ 库的代码,并且可以根据需要重新构建它。 (例如,我可以静态链接 C++ 运行时。)

我可以要求我的用户拥有 JRE 6 或更高版本,但我不能要求他们拥有任何特定的 C++ 运行时。

一位同事向我推荐了这篇博客文章:http://www.trilithium.com/johan/2005/06/static-libstdc/,它建议不要使用动态加载的 C++ 代码。

另一位同事向我指出了这个错误报告:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590,其中详细说明了这些问题在 Java 1.4.2 中是如何解决的。

据我了解,问题的要点是 libstdc++ 的二进制接口经常发生变化。如果 C++ 应用程序加载使用不同编译器构建的 C++ 共享库,则会同时将两个不兼容的 libstdc++ 库加载到内存中。

错误报告解释了 Java 1.4.2 的解决方案:“我们在 JDK 中静态链接 C++ 运行时,并启用链接器脚本以隐藏 libstdc++ 和其他内部符号的符号。结果,这些符号对 JNI 代码不可见,并且当一些native代码需要调用到C++运行时,调用会用相应的libstdc++.so来解析。还有两个libstdc++.so同时被加载,但应该是良性的。”

我对此有几个问题。

首先,OpenJDK 是否继续采用这种方法?

[编辑:我在 OpenJDK 的 build-dev 邮件列表中提出了这个问题。答案是肯定的,HotSpot 仍然静态链接 libstdc++,但显然“大多数 Linux 发行版都对此进行了修补”。另一位开发人员指出,这甚至不需要补丁:“设置 STATIC_CXX=false 应该足够了(默认为 true)。"]

其次,即使在这种情况下,同时加载两个不兼容的 libstdc++.so 真的是良性的吗?

第三,这种方法(隐藏 JDK 中的符号)是否解决了所有的兼容性问题?

上面引用的博客文章警告说“针对不同 ABI 编译的代码根本不兼容二进制”。后来,“语言运行时支持通常依赖于共享的某些数据,例如访问某种锁或全局数据结构(类似于 C 程序需要共享 errno)。”

这听起来好像问题无法解决。

再一次,也许 ABI 不兼容不再是问题了。博客文章已有六年多的历史了。另一个 *** 问题 (GCC ABI compatibility) 的一个答案断言“自 gcc-3.4.0 以来,ABI 向前兼容”。成功了吗?

如果能就这些问题提供任何指导,我将不胜感激。 (嘿,感谢您阅读所有这些内容!)

编辑

我的问题很长,所以我没有提供所有细节。解决 Will 的 cmets:

    我只需要调用外部“C”函数。 (比如我用javah生成C头文件) 我不需要与 JVM 中的 C++ 运行时交互。 (我基本上只需要将字符串发送到 C++ 库。)

【问题讨论】:

【参考方案1】:

我不知道。但这并没有阻止我。

首先,这取决于你想做什么。 JDK静态链接背后的前提是提高实际JDK本身的可移植性。由于他们不能指望用户在他们的特定操作系统上重新编译 JDK,他们需要一种机制来使最终的二进制可移植。显然静态链接解决了这个问题。

接下来,关于 JNI,首先您将调用 C 函数而不是 C++,我不相信 JNI 具有任何类型的 C++ 绑定。因此,无论您想使用什么 C++,都需要封装在 C 例程中才能与 Java 对话。

接下来,您的 C++ .so 将动态链接到操作系统,就像我猜的一样。期望 JNI 例程不能与动态链接的 .so 一起使用似乎非常严厉,而 C++ .so 应该没有什么不同。而且,毫无疑问,C++ 与它一样受欢迎,但您无法动态链接到 C++ .so 似乎同样严厉。因此,无论需要采取什么恶作剧来促进这一点,都可以合理地假设他们(tm)已经完成了让这种情况发生的工作。

也就是说,当然不应该期望您使用的任何 C++ 都会与 Java 运行时中的 C++ 运行时发生任何交互。理想情况下,它们只会和平共处。

假设这完全可行,您的 C++ 肯定会遇到 ABI 可移植性问题,因为它将动态链接,并且受操作系统安装的 C++ 运行时的支配。

所以,最后,我只是试一试,看看会发生什么。

【讨论】:

JNI 确实有 C++ 绑定。但我怀疑它是 C 绑定的仅标头包装器,因此应该不受 ABI 问题的影响。

以上是关于Java Native Interface (JNI) 是不是受 C++ ABI 兼容性问题的影响?的主要内容,如果未能解决你的问题,请参考以下文章

Java固有接口JNI(Java Native Interface)之HelloWorld

Java Programming Tutorial Java Native Interface (JNI)

Mac下Java JNI (java native interface)调C

native

Java Native Interface加载dll文件

Java Native Interface(JNI)从零开始详细教程