【问题标题】:C++ signal handler can't notify Java sideC++ 信号处理程序无法通知 Java 端
【发布时间】:2018-08-14 12:40:34
【问题描述】:

我有以下 CPP 代码。我想要做的是,当我的本地端发生错误时,我会通知 Java 错误。我使用How can I catch SIGSEGV (segmentation fault) and get a stack trace under JNI on Android? 作为参考。

static JavaVM* g_JVM = NULL;
static jobject  g_thejavaobject  = NULL;

void InitializeNativeSide(JNIEnv *env, jclass, jobject object)
{
    env->GetJavaVM(&g_JVM);
    g_thejavaobject = env->NewGlobalRef(object);
}

// this executes in another thread running in parallel with UI thread
void StartExecuting(JNIEnv *_env, jclass) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = SignalErrorHandler;
    sa.sa_flags   = SA_SIGINFO;
    sigaction(SIGSEGV, &sa, NULL);

    // native starts executing here. after a while, a SEGFAULT is encountered
    // triggering SignalErrorHandler()
    ...
}

void SignalErrorHandler(int signal, siginfo_t *si, void *arg)
{
    JNIEnv *env;
    g_JVM->GetEnv((void**)&env, JNI_VERSION_1_6);

    jclass myClass = env->FindClass("com/company/MyClass");
    jmethodID myMethod = env->GetMethodID(myClass, "nativeCrashed", "()V" );
    env->CallVoidMethod(g_thejavaobject, myMethod);

    env->DeleteLocalRef(myClass);
}

一切正常,但对 myClass.nativeCrashed() 的调用不起作用。我做错了什么?

【问题讨论】:

标签: android c++ java-native-interface


【解决方案1】:

你不能这样做:

void SignalErrorHandler(int signal, siginfo_t *si, void *arg)
{
    JNIEnv *env;
    g_JVM->GetEnv((void**)&env, JNI_VERSION_1_6);

    jclass myClass = env->FindClass("com/company/MyClass");
    jmethodID myMethod = env->GetMethodID(myClass, "nativeCrashed", "()V" );
    env->CallVoidMethod(g_thejavaobject, myMethod);

    env->DeleteLocalRef(myClass);
}

这至少有两个根本原因是行不通的。

首先,只能从信号处理程序中调用异步信号安全函数。可以在http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03 找到 POSIX 指定的列表。

没有 Java JNI 调用是异步信号安全的。

其次,the Java JVM uses SIGSEGV internally - 获得SIGSEGV 不一定是致命的:

Oracle Solaris、Linux 和 macOS 中使用的信号

...

SIGSEGV, SIGBUS, SIGFPE, SIGPIPE, SIGILL 这些信号用于 隐式空值检查的实现,等等。

【讨论】:

  • 感谢您的链接。我很感激。顺便说一句,我帖子中的链接声称他能够从他的信号处理程序中调用 java。现在我很困惑。
  • @user1506104 阅读我链接的 POSIX 文档:“当信号中断不安全函数或等效函数时......并且信号捕获函数调用不安全函数时,行为未定义。”问题仅指定在特定时间发生,然后结果是“未定义的行为”。简而言之,它可以看起来工作 - 直到它失败。它类似于超出数组 - 它可能“工作”,但它仍然是错误的。它可能会失败。
  • 你太棒了!谢谢!
  • @user1506104 谢谢。我也必须以艰难的方式学习这一点。这个问题也很相关,因为提问者正在做类似的事情:stackoverflow.com/questions/34547199/…
猜你喜欢
  • 2017-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 2017-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多