throw,catch,sigaction macosx

时间:2012-01-27 22:49:02

标签: java-native-interface jna

此处粘贴的代码是尝试将SIGSEGV映射到java异常。在任何人都兴奋之前,是的,我知道,这是各种标准中的各种陈述。这是一个完全临时的策略,可以追踪顽固的错误。

至少在Mac上,它不起作用。 sigaction函数中的C ++抛出会调用terminate。

我发布此问题,询问是否有人知道如何调整此工作。

#include <stdio.h>
#include <signal.h>
#include "com_github_bimargulies_jnisigsegv_Native.h"

static JavaVM* staticJvm;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
  staticJvm = jvm;
  return JNI_VERSION_1_6;
}

/* there has to be a catch. */
struct SomethingToThrow {};

void handler_function(int sig, struct __siginfo* si, void *) {
  JNIEnv *env = 0;
  staticJvm->GetEnv((void **)&env, JNI_VERSION_1_6);
  jclass newExcCls = env->FindClass("java/lang/RuntimeException");
  env->ThrowNew(newExcCls, "SIGSEGV");
  fprintf(stderr, "About to throw at the catch ... block\n");
  fflush(stderr);
  throw SomethingToThrow();
 }

JNIEXPORT void JNICALL Java_com_github_bimargulies_jnisigsegv_Native_setupHandler(JNIEnv *, jclass) {

  struct sigaction sa;
  struct sigaction oldsa;
  sa.sa_sigaction = handler_function;
  sa.sa_mask = 0;
  sa.sa_flags = SA_SIGINFO;
  int r = sigaction(SIGSEGV, &sa, &oldsa);
  fprintf(stderr, "Signaction returned %d\n", r);
  fflush(stderr);
}

JNIEXPORT void JNICALL Java_com_github_bimargulies_jnisigsegv_Native_getAnError
(JNIEnv *, jclass, jstring) {
  /* First experiment, just get a sigsegv */
  char * p = 0;
  try {
    *p = 1;
  } catch (...) {
    fprintf(stderr, "Caught something\n");
  }
  return;
}

1 个答案:

答案 0 :(得分:1)

查看JNA的本机位,它使用setjmp / longjmp将SIGSEGV转换为Java异常。

https://github.com/twall/jna/blob/master/native/protect.h

请注意,当您开始添加自己的信号处理程序时,您需要正确链接VM正常处理的信号(请参阅http://download.oracle.com/javase/6/docs/technotes/guides/vm/signal-chaining.html)。

您应该仔细阅读有关sigaction的手册页,以便在信号处理程序中查看您应该和不应该做的事情。只有少数系统调用是“安全的”,我不记得在信号处理程序的上下文中支持操作时抛出C ++异常。您的C ++异常堆栈展开信息很可能在信号处理程序的上下文中无效或无法访问。