如何在使用JNI时获取C ++中的Java异常的描述? [英] How to obtain a description of a Java exception in C++ when using JNI?

查看:142
本文介绍了如何在使用JNI时获取C ++中的Java异常的描述?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想确定在使用JNI从C ++代码调用该函数时,Java函数抛出了什么异常。我有以下代码捕获Java异常:

  JNIEnv * pEnv; //假设这个正确初始化
jclass javaClass; // ditto
jmethodID javaFunction; // ditto
pEnv-> CallStaticVoidMethod(javaClass,javaFunction);
jthrowable exc
if(exc = pEnv-> ExceptionOccurred())
{
pEnv-> ExceptionClear();
}



我不知道如何获取关于此C ++中的Java异常的描述性信息码。

解决方案

我已经省略了调用 ExceptionCheck()每个JNI调用查看是否有失败的尝试,以找到简洁的方法:你应该实施时添加这些



首先,存储异常,然后获得必要的Java方法获取有关 Throwable 的信息:

  //获取异常并清除as no 
//当存在异常时可以调用JNI。
jthrowable exception = pEnv-> ExceptionOccurred();
pEnv-> ExceptionClear();

jclass throwable_class = pEnv-> FindClass(java / lang / Throwable);
jmethodID mid_throwable_getCause =
pEnv-> GetMethodID(throwable_class,
getCause,
()Ljava / lang / Throwable;);
jmethodID mid_throwable_getStackTrace =
pEnv-> GetMethodID(throwable_class,
getStackTrace,
()[Ljava / lang / StackTraceElement;);
jmethodID mid_throwable_toString =
pEnv-> GetMethodID(throwable_class,
toString,
()Ljava / lang / String;);

jclass frame_class = pEnv-> FindClass(java / lang / StackTraceElement);
jmethodID mid_frame_toString =
pEnv-> GetMethodID(frame_class,
toString,
()Ljava / lang / String;);

其次,递归构造错误消息(您可能需要修改此):

  std :: string error_msg; //可以使用ostringstream代替。 

_append_exception_trace_messages(* pEnv,
ERROR_MSG,
例外,
mid_throwable_getCause,
mid_throwable_getStackTrace,
mid_throwable_toString,
mid_frame_toString);

无效_append_exception_trace_messages(
JNIEnv的&放大器; a_jni_env,
的std :: string的&放大器; a_error_msg,
jthrowable a_exception,
jmethodID a_mid_throwable_getCause,
jmethodID a_mid_throwable_getStackTrace ,
jmethodID a_mid_throwable_toString,
jmethodID a_mid_frame_toString)
{
//获取StackTraceElements的数组。
jobjectArray帧=
(jobjectArray)a_jni_env.CallObjectMethod(
a_exception,
a_mid_throwable_getStackTrace);
jsize frames_length = a_jni_env.GetArrayLength(frames);

//在下降
//之前添加Throwable.toString()堆栈跟踪消息。
如果(!0 =帧)
{
的jstring msg_obj =
(的jstring)a_jni_env.CallObjectMethod(a_exception,
a_mid_throwable_toString);
const char * msg_str = a_jni_env.GetStringUTFChars(msg_obj,0);

//如果这不是跟踪的顶部,那么
//这是一个原因。
if(!a_error_msg.empty())
{
a_error_msg + =\\\
Caused by:;
a_error_msg + = msg_str;
}
else
{
a_error_msg = msg_str;
}

a_jni_env.ReleaseStringUTFChars(msg_obj,msg_str);
a_jni_env.DeleteLocalRef(msg_obj);
}

//如果有任何附加栈跟踪消息。
if(frames_length> 0)
{
jsize i = 0;
for(i = 0; i {
//获取从'toString()'返回的字符串
//下一帧的方法并将其附加到
//错误消息。
jobject frame = a_jni_env.GetObjectArrayElement(frames,i);
jstring msg_obj =
(jstring)a_jni_env.CallObjectMethod(frame,
a_mid_frame_toString);

const char * msg_str = a_jni_env.GetStringUTFChars(msg_obj,0);

a_error_msg + =\\\
;
a_error_msg + = msg_str;

a_jni_env.ReleaseStringUTFChars(msg_obj,msg_str);
a_jni_env.DeleteLocalRef(msg_obj);
a_jni_env.DeleteLocalRef(frame);
}
}

//如果'a_exception'有原因,则从原因追加
//堆栈跟踪消息。
如果(!0 =帧)
{
jthrowable原因=
(jthrowable)a_jni_env.CallObjectMethod(
a_exception,
a_mid_throwable_getCause);
如果(0!=原因)
{
_append_exception_trace_messages(a_jni_env,
a_error_msg,
的原因,
a_mid_throwable_getCause,
a_mid_throwable_getStackTrace,
a_mid_throwable_toString,
a_mid_frame_toString);
}
}
}

写了几年前(修改为消除锅炉板 ExceptionCheck() s),但我没有编译我已经发布,但一般的方法是希望明确。 >

I would like to determine what exception has been thrown by a Java function when calling that function from C++ code using JNI. I have the following code that catches the Java exception:

JNIEnv * pEnv; // assume this is properly initialized
jclass javaClass; // ditto
jmethodID javaFunction; // ditto
pEnv->CallStaticVoidMethod(javaClass, javaFunction);
jthrowable exc;
if(exc = pEnv->ExceptionOccurred())
{
    pEnv->ExceptionClear();
}

I do not know how to obtain descriptive information about the Java exception within this C++ code. Can somebody help?

解决方案

I have omitted calling ExceptionCheck() after each JNI call and checking for any failed attempts to locate methods for brevity: you should add these when implementing.

First, store the exception and then acquire the Java methods necessary for obtaining information about the Throwable:

// Get the exception and clear as no
// JNI calls can be made while an exception exists.
jthrowable exception = pEnv->ExceptionOccurred();
pEnv->ExceptionClear();

jclass throwable_class = pEnv->FindClass("java/lang/Throwable");
jmethodID mid_throwable_getCause =
    pEnv->GetMethodID(throwable_class,
                      "getCause",
                      "()Ljava/lang/Throwable;");
jmethodID mid_throwable_getStackTrace =
    pEnv->GetMethodID(throwable_class,
                      "getStackTrace",
                      "()[Ljava/lang/StackTraceElement;");
jmethodID mid_throwable_toString =
    pEnv->GetMethodID(throwable_class,
                      "toString",
                      "()Ljava/lang/String;");

jclass frame_class = pEnv->FindClass("java/lang/StackTraceElement");
jmethodID mid_frame_toString =
    pEnv->GetMethodID(frame_class,
                      "toString",
                      "()Ljava/lang/String;");

Second, recursively construct the error message (you may want to modify this):

std::string error_msg; // Could use ostringstream instead.

_append_exception_trace_messages(*pEnv,
                                 error_msg,
                                 exception,
                                 mid_throwable_getCause,
                                 mid_throwable_getStackTrace,
                                 mid_throwable_toString,
                                 mid_frame_toString);

void _append_exception_trace_messages(
                        JNIEnv&      a_jni_env,
                        std::string& a_error_msg,
                        jthrowable   a_exception,
                        jmethodID    a_mid_throwable_getCause,
                        jmethodID    a_mid_throwable_getStackTrace,
                        jmethodID    a_mid_throwable_toString,
                        jmethodID    a_mid_frame_toString)
{
    // Get the array of StackTraceElements.
    jobjectArray frames =
        (jobjectArray) a_jni_env.CallObjectMethod(
                                        a_exception,
                                        a_mid_throwable_getStackTrace);
    jsize frames_length = a_jni_env.GetArrayLength(frames);

    // Add Throwable.toString() before descending
    // stack trace messages.
    if (0 != frames)
    {
        jstring msg_obj =
            (jstring) a_jni_env.CallObjectMethod(a_exception,
                                                 a_mid_throwable_toString);
        const char* msg_str = a_jni_env.GetStringUTFChars(msg_obj, 0);

        // If this is not the top-of-the-trace then
        // this is a cause.
        if (!a_error_msg.empty())
        {
            a_error_msg += "\nCaused by: ";
            a_error_msg += msg_str;
        }
        else
        {
            a_error_msg = msg_str;
        }

        a_jni_env.ReleaseStringUTFChars(msg_obj, msg_str);
        a_jni_env.DeleteLocalRef(msg_obj);
    }

    // Append stack trace messages if there are any.
    if (frames_length > 0)
    {
        jsize i = 0;
        for (i = 0; i < frames_length; i++)
        {
            // Get the string returned from the 'toString()'
            // method of the next frame and append it to
            // the error message.
            jobject frame = a_jni_env.GetObjectArrayElement(frames, i);
            jstring msg_obj =
                (jstring) a_jni_env.CallObjectMethod(frame,
                                                     a_mid_frame_toString);

            const char* msg_str = a_jni_env.GetStringUTFChars(msg_obj, 0);

            a_error_msg += "\n    ";
            a_error_msg += msg_str;

            a_jni_env.ReleaseStringUTFChars(msg_obj, msg_str);
            a_jni_env.DeleteLocalRef(msg_obj);
            a_jni_env.DeleteLocalRef(frame);
        }
    }

    // If 'a_exception' has a cause then append the
    // stack trace messages from the cause.
    if (0 != frames)
    {
        jthrowable cause = 
            (jthrowable) a_jni_env.CallObjectMethod(
                            a_exception,
                            a_mid_throwable_getCause);
        if (0 != cause)
        {
            _append_exception_trace_messages(a_jni_env,
                                             a_error_msg, 
                                             cause,
                                             a_mid_throwable_getCause,
                                             a_mid_throwable_getStackTrace,
                                             a_mid_throwable_toString,
                                             a_mid_frame_toString);
        }
    }
}

I copied this from code I wrote a few years ago (modified to eliminate boiler plate ExceptionCheck()s), but I did not compile what I have posted but the general approach is hopefully clear.

这篇关于如何在使用JNI时获取C ++中的Java异常的描述?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆