Java 本机接口 (JNI) 是否受C++ ABI 兼容性问题的影响?
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 代码变得不可见,当某些本机代码需要调用C++运行时时,将使用适当的 libstdc++.so 解析调用。仍然有两个libstdc++.所以同时加载,但它应该是良性的。
我对此有几个问题。
首先,OpenJDK是否继续采用这种方法?
[编辑:我在OpenJDK的构建开发邮件列表中问了这个问题。答案是肯定的,HotSpot仍然静态链接libstdc ++,但显然“大多数Linux发行版都对此进行了修补”。另一位开发人员指出,这甚至不需要补丁:“设置STATIC_CXX=false应该足够了(它默认为true)。
其次,即使在这种情况下,同时加载两个不兼容的libstdc++..真的是良性的吗?
第三,这种方法(隐藏JDK中的符号)是否解决了所有的兼容性问题?
上面引用的博客文章警告说,“针对不同ABI编译的代码根本不兼容二进制。后来,“语言运行时支持通常依赖于共享的一些数据,例如访问某种锁或全局数据结构(类似于C程序需要共享errno的方式)。
这听起来像是问题无法解决。
话又说回来,也许ABI不兼容不再是问题。这篇博客文章已有六年多的历史了。另一个堆栈溢出问题(GCC ABI兼容性)的一个答案断言“由于gcc-3.4.0,ABI是向前兼容的。成功了吗?
我非常感谢有关这些问题的任何指导。(嘿,感谢您阅读所有这些内容!
编辑
我的问题很长,所以我没有给出所有的细节。为了解决Will的评论:
- 我只需要调用外部“C”函数。(例如,我使用javah来生成C头文件。
- 我不需要在JVM中与C++运行时进行交互。(我基本上只需要将字符串发送到C++库。