问题
Is the Java Native Interface (JNI) affected by C++ ABI compatibility issues?
I am developing a Java application. I would like to use the Java Native Interface (JNI) to call functions in a C++ library. I have access to the code for the C++ library, and I can rebuild it however I may need to. (For example, I can statically link the C++ runtime.)
I can require my users to have JRE 6 or greater, but I can't require them to have any particular C++ runtime.
A coworker pointed me to this blog article: http://www.trilithium.com/johan/2005/06/static-libstdc/ which advises against using dynamically loaded C++ code.
Another coworker pointed me to this bug report: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590 which details how these issues were addressed back in Java 1.4.2.
The gist of the problem, as I understand it, is that the binary interface of libstdc++ often changes. If a C++ application loads a C++ shared library that was built with a different compiler, two incompatible libstdc++ libraries will be loaded into memory at the same time.
The bug report explains the solution for Java 1.4.2: "We statically link the C++ runtime in JDK and enabled linker script to hide symbols from libstdc++ and other internal symbols. As the result, those symbols become invisible to JNI code, and when some native code needs to call into C++ runtime, the call will be resolved with the appropriate libstdc++.so. There are still two libstdc++.so being loaded at the same time, but it should be benign."
I have a few questions about this.
First, does OpenJDK continue to take this approach?
[EDIT: I asked this question on OpenJDK's build-dev mailing list. The answer is yes, HotSpot still statically links libstdc++, but apparently "most Linux distros patch this out". Another developer notes that this doesn't even require a patch: "Setting STATIC_CXX=false should be enough (it defaults to true)."]
Second, even in this case, is it truly benign to have two incompatible libstdc++.so loaded at the same time?
Third, does this approach (to hide the symbols in the JDK) address all of the compatibility issues?
The blog article referenced above warns that "code compiled against different ABIs is simply not binary compatible." And later that, "the language runtime support typically rely on some data being shared, e.g. to access some kind of lock or global data structure (similar to how C programs need a shared errno)."
This makes it sound like the problem cannot be solved.
Then again, maybe ABI incompatibility isn't a problem anymore. The blog article is over six years old. One answer for another stackoverflow question ( GCC ABI compatibility ) asserts that "Since gcc-3.4.0, the ABI is forward compatible." Has that been successful?
I'd appreciate any guidance on these issues. (And hey, thanks for reading all of this!)
EDITS
My question was getting pretty long, so I didn't give all the specifics. To address Will's comments:
- I only need to call extern "C" functions. (For example, I use javah to generate the C header file.)
- I don't need to interact with the C++ runtime in the JVM. (I basically just need to send strings to a C++ library.)
回答1:
I don't know. But that never stopped me.
First, it depends on what you want to do. The premise behind the static linking of the JDK is to improve portability of the actual JDK itself. Since they can't expect users to recompile the JDK on their particular OS, they needed a mechanism to make the final binary portable. Apparently static linking fixed this problem.
Next, regarding JNI, first you'll be calling C functions and not C++, I don't believe JNI has any kind of C++ binding. So, whatever C++ you'll want to use will need to be wrapped in a C routine to talk to Java.
Next, your C++ .so will dynamically link against the OS pretty much like normal I'm guessing. It's seems pretty draconian to expect a JNI routine to not work with a dynamic linked .so, and a C++ .so should be no different. And, no doubt C++ being as popular as it is, it seems similarly draconian that you would not be able to dynamically link against a C++ .so. So, whatever shenanigans that need to have taken place to facilitate this, it's a reasonable assumption that They(tm) have done the work to allow this to happen.
That said, there should certainly be no expectation that whatever C++ you're using will have any interaction whatsoever with the C++ runtime in the Java runtime. Ideally, they'll simply peacefully co-exist.
Given that, assuming this works at all, your C++ will most certainly have the ABI portability issue, since it will be dynamically linking, and will be at the mercy of the OS'es installed C++ runtime.
So, in the end, I'd just give it a rip and see what happens.
来源:https://stackoverflow.com/questions/8722320/is-the-java-native-interface-jni-affected-by-c-abi-compatibility-issues