这是对Elliott Hughes' answer 的补充。我的回答提供了一个分步示例,解释了如何捕获异常以及如何使用JNI 层在 C++ 和 Java 单词之间转换它们。
简答
查看正确的Elliott Hughes' answer。
可重用示例
此答案和 sn-ps 位于公共领域或 CC0 中,以便于重用。这里所有的源代码都是C++03向后兼容的。
要重用上面的 sn-p,请执行以下操作:
- 用您自己的 C++ 异常替换
mypackage::Exception。
- 如果未定义对应的Java异常
my.group.mypackage.Exception,则将"my/group/mypackage/Exception"替换为"java/lang/RuntimeException"。
从 Java 中捕获异常
另请参阅snippet on coliru。
void rethrow_cpp_exception_as_java_exception()
{
try
{
throw; // This allows to determine the type of the exception
}
catch (const mypackage::Exception& e) {
jclass jc = env->FindClass("my/group/mypackage/Exception");
if(jc) env->ThrowNew (jc, e.what());
/* if null => NoClassDefFoundError already thrown */
}
catch (const std::bad_alloc& e) {
jclass jc = env->FindClass("java/lang/OutOfMemoryError");
if(jc) env->ThrowNew (jc, e.what());
}
catch (const std::ios_base::failure& e) {
jclass jc = env->FindClass("java/io/IOException");
if(jc) env->ThrowNew (jc, e.what());
}
catch (const std::exception& e) {
/* unknown exception (may derive from std::exception) */
jclass jc = env->FindClass("java/lang/Error");
if(jc) env->ThrowNew (jc, e.what());
}
catch (...) {
/* Oops I missed identifying this exception! */
jclass jc = env->FindClass("java/lang/Error");
if(jc) env->ThrowNew (jc, "Unidentified exception => "
"Improve rethrow_cpp_exception_as_java_exception()" );
}
}
感谢 Mooing Duck 对上述 C++ 代码的贡献。
改编JNI生成的源代码
下面的文件Java_my_group_mypackage_example.cpp使用上面的rethrow_cpp_exception_as_java_exception()函数:
JNIEXPORT jlong JNICALL Java_my_group_mypackage_example_function1
(JNIEnv *env, jobject object, jlong value)
{
try {
/* ... my processing ... */
return jlong(result);
} catch(...) {
rethrow_cpp_exception_as_java_exception();
return 0;
}
}
JNIEXPORT jstring JNICALL Java_my_group_mypackage_example_function2
(JNIEnv *env, jobject object, jlong value)
{
jstring jstr = 0
try {
/* ... my processing ... */
jstr = env->NewStringUTF("my result");
} catch(...) {
rethrow_cpp_exception_as_java_exception();
}
return jstr;
}
JNIEXPORT void JNICALL Java_my_group_mypackage_example_function3
(JNIEnv *env, jobject object, jlong value)
{
try {
/* ... my processing ... */
} catch(...) {
rethrow_cpp_exception_as_java_exception();
}
}
对应的Java代码
文件example.java
package my.group.mypackage;
public class Example {
static {
System.loadLibrary("my-DLL-name");
}
public Example() {
/* ... */
}
private native int function1(int); //declare DLL functions
private native String function2(int); //using the keyword
private native void function3(int); //'native'
public void dosomething(int value) {
int result = function1(value);
String str = function2(value); //call your DLL functions
function3(value); //as any other java function
}
}
注意:“my-DLL-name”是指上述C/C++代码编译生成的动态库。它可以是 Windows 上的 my-DLL-name.dll 或 GNU/Linux/Unix 上的 my-DLL-name.so。
步骤
从example.java 生成example.class(使用javac 或maven 或您最喜欢的IDE Eclipse/Netbeans/IntelliJ IDEA/...)
使用javah从example.class生成C/C++头文件Java_my_group_mypackage_example.h