4

Is there any way that I can use C++ exceptions in a JNI (Java Native Interface) library on Android?

EDIT: I am talking about C++ exception handling that is entirely internal to the JNI library. That is, the exception is both thrown and catched within the library, and it never escapes the library.

According to the Android documentation (docs/CPLUSPLUS-SUPPORT.html), exceptions are only supported if I use 'GNU libstdc++' as the C++ runtime instead of the default.

The problem is that the documentation also states that all parts of a program must use the same C++ runtime:

"You can only select a single C++ runtime that all your code will depend on. It is not possible to mix shared libraries compiled against different C++ runtimes."

According to my interpretation, this means that I am forced to use the same C++ runtime as Dalvik (Java VM on Android).

So, if Dalvik does not use 'GNU libstdc++', is there still a way that I can use exceptions in my JNI lib?

What C++ runtime is Dalvik compiled against?

EDIT: I have to assume that whichever Java app is using my JNI library, may also want to use other JNI libraries, that I have no control over. Does that in any way limit my options?

Kristian Spangsege
  • 2,903
  • 1
  • 20
  • 43
  • You haven't defined what you mean by "use exceptions". Do you want to use exceptions only within the same library (i.e. try/catch within the same library), then use the GNU libstdc++ runtime and it'll work. On the other hand, if you're hoping to throw an exception from your JNI library and catch it in your Java code then this is not going to work. – CadentOrange Nov 28 '12 at 16:53
  • @CadentOrange I have now - thanks. – Kristian Spangsege Nov 28 '12 at 17:43
  • In general, yes, you can use C++ exceptions inside of JNI. HOWEVER, you must make sure that C++ exceptions do not cross the language barrier (i.e. escape from your JNI exposed functions). If a C++ exception escapes into JNI, your app will most likely terminate or abort. – Nathan Ernst Nov 28 '12 at 18:32
  • @CadentOrange: note that JNI defines functions to throw Java exceptions from native code. These are not equivalent to C++ exceptions, though. – Alex Cohn Nov 28 '12 at 18:45

1 Answers1

3

Yes you can use exceptions with

APP_STL := gnustl_static

or gnustl_shared. The doc uses kindof intimidating language but they only want you not to mix libraries that expect different STL implementations in your app. That's why the setting has APP_ prefix, not LOCAL_.

Dalvik VM fully supports any of the STL implementations listed in the doc.

Usually you control both sides of your JNI, and can make sure that all native components are compiled for gnustl_shared. This is the preferred scenario.

If your business is to provide a black box library that may be used by other people who could decide to also include other libraries, it's safer to choose gnustl_static to support C++ exceptions in your code. This way you don't depend on others' good will. You should be careful to design your API so that your native objects (and especially exceptions) never get exposed to other components.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Alright, that sounds encouraging. But suppose that a Java application uses both my JNI library and some other JNI library. Suppose further that that other JNI library uses, say APP_STL := stlport_static. Would such a mixing of C++ runtimes still work? Is that still not a violation of the 'no mixing' rule? – Kristian Spangsege Nov 29 '12 at 11:36
  • Suppose instead that the other JNI library also uses APP_STL := gnustl_static. Then it seems I have a violation of the following rule from the same documentation file: "On the other hand, if you have two shared libraries in your project (e.g. libfoo.so and libbar.so) which both link against the same static runtime, each one of them will include a copy of the runtime's code in its final binary image. This is problematic because certain global variables used/provided internally by the runtime are duplicated." The documentation goes on to mention several critical issues. – Kristian Spangsege Nov 29 '12 at 11:40
  • Both concerns are essentially correct. When you have more than one native library in your app, I'd recommend to use the same **_shared** STL implementation. But in reality, if the two JNI libraries never interact with each other, the duplication of global variables and other troubles you mention is of minor relevance. – Alex Cohn Nov 29 '12 at 13:28
  • You say that it will likely work if the two JNI libraries never interact. If a Java app calls one JNI lib, and then the other, is that interaction? Still, what are the remaining issues, that I need to be aware of? – Kristian Spangsege Nov 29 '12 at 14:28
  • 'Interact' could be that one JNI library creates an std::string, or std::list, and passes a handle to it to Java, and Java gives this handle to another JNI library. Duplication of global variables may effect performance and memory consumption of the app. – Alex Cohn Nov 29 '12 at 14:52
  • Ok, sounds good. Do you have any experience yourself with such a setup? – Kristian Spangsege Nov 29 '12 at 15:17
  • So is 'gnustl_static' my only option, or could I also use 'gnustl_shared'. According to my understanding, if I use 'gnustl_shared', then the Java process might have to load multiple shared libraries for different C++ runtimes. Would that really work? The doc seems to explicitly disallow it. – Kristian Spangsege Nov 29 '12 at 15:22
  • Yes, I have personally mixed `gnustl_static` with `system`. But let this remain our tiny secret ;-) – Alex Cohn Nov 29 '12 at 15:24
  • Usually you control both sides of your JNI, and can make sure that all native components are compiled for `gnustl_shared`. This is the preferred scenario. If your business is to provide a _black box_ library that may be used by other people who could decide to also include other libraries, it's safer to choose `gnustl_static`. This way you don't depend on others' good will. You should be careful to design your API so that your native objects never get exposed to other components. – Alex Cohn Nov 29 '12 at 15:30
  • Thanks. Could you expand you answer with this important caveat? Note that I have now stated in my question, that indeed I must be able to coexist with other unknown JNI libraries. – Kristian Spangsege Nov 29 '12 at 15:40