当前位置: 首页 > 面试题库 >

使用JNI时如何获取C ++中Java异常的描述?

党星鹏
2023-03-14
问题内容

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

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();
}

我不知道如何在此C ++代码中获取有关Java异常的描述性信息。有人可以帮忙吗?


问题答案:

ExceptionCheck()在每次JNI 调用之后,我都省略了调用,并没有检查任何为简便起见而定位失败的尝试:在实现时应添加这些方法。

首先,存储异常,然后获取获取有关的信息所必需的Java方法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;");

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

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);
        }
    }
}

我从几年前编写的代码(修改为消除样板代码)中复制了此代码ExceptionCheck(),但是我没有编译我发布的内容,但是希望通用的方法是明确的。



 类似资料:
  • 我在尝试运行此程序时遇到以下异常。我正在使用在线编译器。甚至在读取字符串后尝试使用nextLine(),但没有成功。 我得到了以下异常:输入客户名称:在线程“main”java中输入客户id异常。util。NoSuchElementException:在java中找不到行。util。扫描仪。nextLine(Scanner.java:1585)位于Main。main(main.java:12)

  • 我尝试使用Oracle SQLcl编写批处理文件。在这个文件中,我想插入一个带有的新表行。这只返回/,这是成功/失败的布尔返回。 我的问题是,我如何获取抛出的异常的错误消息,以便我可以找出我的插入语句有什么问题。 我所做的:首先,我连接到数据库服务器并启动脚本: 我的mybatchscript.js如下所示: 控制台输出如下: 脚本一直工作到util。执行insert语句。它返回false,因此i

  • 问题内容: JAVA代码 这是我用 JAVA 编写的代码的一部分,如您所见,这是一个有两个成员和的类。 这是我有本机方法的主类,从那里我调用了本机方法。 如您所见,我用一个对象创建数组并将其提供给我的函数。 JNI代码 我怎样才能得到这两个字符串,我已经从Java应用程序中设置并存储在? 问题答案: 以下代码应允许您访问字段 enrollmentID 。使用JNI String函数 来读取/操作它

  • 我使用下面的命令进行了mockito-junit测试。变量serviceTask是接口的实例,称为serviceTask。我在申报中使用了@Mock 声明: 命令行: 堆栈跟踪: Java语言lang.NullPointerException在sun。反映NativeMethodAccessorImpl。sun上的invoke0(本机方法)。反映NativeMethodAccessorImpl。在

  • 那么,为什么它要尝试将响应解析为JSON呢?我该如何解决呢? 谢谢!!

  • 我在POM中有以下依赖项 我在客户端请求中也注册了这个类,但当我启动JAVA应用程序尝试POST时,我得到了以下错误 在应用程序初始化期间,应用程序资源模型的验证失败。[[致命]未找到public com.rm类型参数的注入源 可能出了什么问题……有人能建议一下吗