在Android的JNI库中,我能否使用C++异常?

4
是否有办法在Android上的JNI(Java Native Interface)库中使用C++异常?
编辑:我说的是JNI库完全内部使用的C++异常处理。也就是说,异常在库内抛出和捕获,从未逃逸出库。
根据Android文档(docs/CPLUSPLUS-SUPPORT.html)所述,只有在使用“GNU libstdc ++”作为C ++运行时而不是默认值时才支持异常。
问题是文档还指出,程序的所有部分必须使用相同的C ++运行时:
“您只能选择单个C ++运行时,所有代码都将依赖于它。不可能混合使用针对不同C ++运行时编译的共享库。”
据我理解,这意味着我被迫使用与Dalvik(Android上的Java VM)相同的C ++运行时。
因此,如果Dalvik没有使用“GNU libstdc ++”,那么我是否仍然可以在我的JNI库中使用异常?
Dalvik使用哪个C ++运行时?
编辑:我必须假设使用我的JNI库的任何Java应用程序也可能想要使用其他我无法控制的JNI库。这是否以任何方式限制了我的选项?

您尚未定义“使用异常”的含义。如果您希望仅在同一库内使用异常(即在同一库中使用try/catch),则请使用GNU libstdc++运行时,它将起作用。另一方面,如果您希望从JNI库中抛出异常并在Java代码中捕获它,则无法实现。 - CadentOrange
@CadentOrange 我已经有了 - 谢谢。 - Kristian Spangsege
一般而言,是的,你可以在JNI中使用C++异常。但是,你必须确保C++异常不会跨越语言屏障(即从JNI公开的函数中逃逸出来)。如果C++异常逃逸到JNI中,你的应用程序很可能会终止或中止。 - Nathan Ernst
@CadentOrange:请注意,JNI定义了从本地代码抛出Java异常的函数。但是这些与C++异常不等价。 - Alex Cohn
1个回答

3

是的,您可以在IT技术中使用异常处理。

APP_STL := gnustl_static

或者 gnustl_shared。文档使用了有点令人生畏的语言,但他们只是想要你不要在应用程序中混合使用带有不同STL实现的库。这就是为什么设置具有 APP_ 前缀而不是 LOCAL_ 的原因。

Dalvik VM完全支持文档中列出的任何STL实现。

通常情况下,您可以控制JNI的双方,并确保所有本地组件都编译为 gnustl_shared。这是首选方案。

如果您的业务是提供一个黑盒子库,可能会被其他人使用,并且他们可能还决定包含其他库,则更安全的选择是选择 gnustl_static,以支持您代码中的C++异常。这样您就不会依赖于他人的好意。您应该小心设计API,以使您的本地对象(特别是异常)永远不会暴露给其他组件。


假设另一个JNI库也使用APP_STL:= gnustl_static。那么,我似乎违反了同一文档文件中的以下规则:“另一方面,如果您的项目中有两个共享库(例如libfoo.so和libbar.so),它们都链接到相同的静态运行时,则它们每个都将在其最终二进制映像中包含运行时代码的副本。这是有问题的,因为运行时内部使用/提供的某些全局变量会被复制。”文档继续提到了几个关键问题。 - Kristian Spangsege
两个问题都是基本正确的。当您在应用程序中有多个本地库时,我建议使用相同的**_shared** STL实现。但实际上,如果这两个JNI库从未相互交互,则全局变量的重复和其他问题对您提到的次要相关性。 - Alex Cohn
好的,听起来不错。你自己有这样的设置经验吗? - Kristian Spangsege
是的,我个人混合使用了 gnustl_staticsystem。但让这个秘密保持小小的吧 ;-) - Alex Cohn
通常情况下,您可以控制JNI的双方,并确保所有本地组件都编译为“gnustl_shared”。这是首选方案。如果您的业务是提供一个“黑盒子”库,可能会被其他人使用,他们可能决定还包括其他库,那么选择“gnustl_static”更安全。这样,您就不依赖于他人的意愿。您应该小心设计您的API,以使您的本地对象永远不会暴露给其他组件。 - Alex Cohn
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接