use*_*444 26 java-native-interface
我的应用程序中有一个JNI层.在某些情况下,Java会抛出异常.如何在JNI层中获取Java异常?我的代码如下所示.
if((*(pConnDA->penv))->ExceptionCheck(pConnDA->penv))
{
(*(pConnDA->penv))->ExceptionDescribe(pConnDA->penv);
(*(pConnDA->penv))->ExceptionClear(pConnDA->penv);
}
Run Code Online (Sandbox Code Playgroud)
这个代码块是否只捕获JNI异常?将在控制台(stderr)中记录异常描述的位置?如何将其插入缓冲区,以便将其传递给记录器模块?
Ell*_*hes 27
如果从 JNI 调用Java方法,则在Java抛出异常ExceptionCheck
后将返回调用JNI_TRUE
.
如果你只是调用一个JNI函数(例如FindClass
),ExceptionCheck
它将告诉你是否以一种留下挂起异常的方式失败(就像FindClass
在出错时一样).
ExceptionDescribe
输出到stderr.没有方便的方法让它去其他任何地方,但是如果你想玩它就ExceptionOccurred
给你一个jthrowable
,或者你可以让它去Java并在那里处理它.这是通常的风格:
jclass c = env->FindClass("class/does/not/Exist");
if (env->ExceptionCheck()) {
return;
}
// otherwise do something with 'c'...
Run Code Online (Sandbox Code Playgroud)
请注意,返回的价值无关紧要; 调用Java代码永远不会看到它 - 它会看到挂起的异常.
oli*_*bre 14
这是Elliott Hughes回答的补充.我的回答提供了一个分步示例,说明如何捕获异常以及如何使用JNI层在C++和Java单词之间进行转换.
看到正确的Elliott Hughes的回答.
这个答案和片段在公共领域或CC0中,以便于重用.这里的所有源代码都是C++ 03向后兼容的.
要重复使用上述代码段,请执行以下操作:
mypackage::Exception
为您自己的C++异常.my.group.mypackage.Exception
未定义相应的Java异常,则替换"my/group/mypackage/Exception"
为"java/lang/RuntimeException"
.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()" );
}
}
Run Code Online (Sandbox Code Playgroud)
我感谢Mooing Duck对上述C++代码的贡献.
以下文件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();
}
}
Run Code Online (Sandbox Code Playgroud)
文件 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
}
}
Run Code Online (Sandbox Code Playgroud)
注意:" my-DLL-name
"是指从上面编译的C/C++代码生成的动态库.它可以my-DLL-name.dll
在Windows上或my-DLL-name.so
在GNU/Linux/Unix上.
生成example.class
的example.java
(使用javac
或Maven或者您喜欢的IDE的Eclipse/Netbeans的/的IntelliJ IDEA/...)
生成C/C++头文件Java_my_group_mypackage_example.h
从example.class
使用javah
归档时间: |
|
查看次数: |
38115 次 |
最近记录: |