【问题标题】:Invoking Java from C++: how to catch/detect a fatal JVM error?从 C++ 调用 Java:如何捕获/检测致命的 JVM 错误?
【发布时间】:2013-02-04 05:11:10
【问题描述】:

我正在开发一个 C++ 程序(Win32,MS Visual Studio 2008),它通过 JNI 创建一个 Java VM,如here 所述。它在 Java 6 和 Java 7 上都可以正常运行很长时间了。

今天我安装了新版本的JRE;安装程序出现问题,JRE 损坏。我注意到我的 C++ 程序没有启动并且没有发出任何警告消息。调试程序显示运行成功,直到调用JNI_CreateJavaVM;但是调用JNI_CreateJavaVM 会导致程序立即终止。没有返回值,没有错误消息,什么都没有。

是的,我知道我只需要重新安装 JRE。但尽管如此,我希望我的 C++ 程序能够为这种情况做好准备。如果它无法创建 Java VM,它应该显示一条消息“请重新安装 JRE”。但我没有机会显示该消息,因为整个程序正在终止。

有没有办法在 JRE 中检测这种类型的错误,或者更一般地,在第三方库中检测到此类错误?我尝试使用 C++ try/catch 构造,我尝试使用 signal 函数 - 没有任何帮助;程序在没有调用任何 catch 或信号处理程序的情况下消失。

有没有办法检测这种 JRE 崩溃?或者:有没有办法可靠地检测第三方库中的崩溃或终止?

【问题讨论】:

  • 在什么环境下?有依赖于操作系统/依赖于编译器的方式..(如 MS c++ 上的 __try __except)
  • @dema80,是的,它是 Win32。感谢您的提示,我编辑了问题。
  • 我在 how to make a hook on ExitProcess 上找到了一个 über-hackerish 指令。虽然,在我的特定用例中,它有点矫枉过正。我将求助于在我们的技术支持数据库中写一篇文章:“如果应用程序无法启动,请重新安装 JRE”。 :-)

标签: java c++ java-native-interface jvm-crash catch-all


【解决方案1】:

如果您使用的是 Linux/Unix:这是我通常开始的:

struct sigaction sa;
sa.sa_handler = bt_sighandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;

sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);

如果您在 Windows 上使用 Microsoft C++:_try/_except 通常可以解决问题。它是一个 MSVC 扩展(你可以从双下划线看出),它扩展了标准的 try/catch。

Try/catch 捕获 C++ 异常,_try/_except 将捕获所有其他未处理的异常(COM、Win32、...)。例如,它将捕获 null 取消引用、内存访问问题,这些问题可能是您崩溃的原因。阅读here

否则,在寡妇中,尝试SetUnhandledExceptionFilter

编辑:由于使用 SEH 的方法似乎失败了,您可能会更上一层楼并使用向量异常处理。根据this blog post on msdn,VEH是按进程注册的,在SEH之前检查。

如果一切都失败了,请不要绝望 :) 您仍然可以将您的应用程序变成一对调试器/被调试者。这将使您完全控制被调试进程的事件、生死。通常不值得麻烦,但这是我过去不得不使用的另一个解决方案。它也没有看起来那么困难;如果还有其他问题,请告诉我,我会挖掘一些旧代码。

【讨论】:

  • 发生了一些奇怪的事情。 try/catch、__try/__except、signal、SetUnhandledExceptionFilter 都无法处理错误。但是,如果我在调用 JNI_CreateJavaVM 之前显示一个 MessageBox,所有这些结构都会开始工作;具体来说,信号报告一个 SIGSEGV 错误(内存访问冲突);然后程序能够继续运行。显然我不能每次都显示一个 MessageBox。也许显示一个不可见的窗口?呃,黑魔法……
  • 嗯.. 听起来像是线程问题.. 你能发布一些代码来展示你如何使用 SetUnhandledExceptionFilter 吗? (Win32 中的信号在下面使用 SetUnhandledExceptionFilter,IIRC)
  • 对不起,这不是 MessageBox。我没有直接调用 MessageBox,而是调用了我的错误报告函数,该函数也释放了我从中调用 CreateJavaVM 的库,因此访问冲突是由错误的函数指针引起的,而不是 Java 崩溃。所以,实际上似乎没有什么能够捕捉到崩溃。
  • @GoblinAlchemist 你也尝试过向量异常处理吗?
猜你喜欢
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 2019-11-16
  • 2019-04-20
  • 2013-07-30
  • 2017-02-09
  • 2018-09-10
  • 2016-10-28
相关资源
最近更新 更多