Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the Java Native Interface (JNI) affected by C++ ABI compatibility issues?

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:

  1. I only need to call extern "C" functions. (For example, I use javah to generate the C header file.)
  2. I don't need to interact with the C++ runtime in the JVM. (I basically just need to send strings to a C++ library.)
like image 744
John V. Avatar asked Jan 04 '12 05:01

John V.


People also ask

What is the use of Java Native Interface JNI?

JNI is the Java Native Interface. It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++).

Which software is used to run the JNI programming?

The JNI is a native programming interface. It allows Java code that runs inside a Java Virtual Machine (VM) to interoperate with applications and libraries written in other programming languages, such as C, C++, and assembly.

What is JNA vs JNI?

Java Native Access (JNA) is a community-developed library that provides Java programs easy access to native shared libraries without using the Java Native Interface (JNI). JNA's design aims to provide native access in a natural way with a minimum of effort. Unlike JNI, no boilerplate or generated glue code is required.

Which of the following are appropriate reasons why you might want to define a native method in Java?

To improve the performance of the system. To achieve machine level/memory level communication. To use already existing legacy non-java code.


1 Answers

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.

like image 148
Will Hartung Avatar answered Sep 20 '22 16:09

Will Hartung