JNI起步问题

4
我开始研究JNI,据我所知,如果加载的dll出现问题,则JVM可能会立即终止。
也就是说,进程无法受到保护,例如捕获异常时的情况。
因此,如果我的理解是正确的,那么我的问题是,在使用JNI时,是否存在标准的方法/模式来处理这种情况。
或者换句话说,使用JNI的进程是否设计为避免这些问题?
或者不会出现这样的问题吗?

谢谢。

3个回答

3
是的,JVM将会突然终止,这也是JNI代码难以调试的原因之一。如果您使用C++代码,可以使用异常,然后将它们映射到Java异常,这至少会提供一定程度的安全性,但对于诸如错误内存访问等问题并没有帮助。
从架构角度来看,建议您尽可能地将代码与JNI解耦。创建一个完全可从C++/ C进行测试的类/过程结构,并让JNI代码只执行所有的转换操作。如果JVM崩溃,则您至少知道需要查找哪里。

我最初想到的方法是在发布文章时,生成一个新进程来访问dll。这样原始进程就可以继续运行。但我不确定这是否被用作一种方法。 - Cratylus
嗯,在那种情况下,您可能干脆不使用JNI,转而使用另一种进程间通信方式。我只会在速度是最大问题的情况下使用JNI(然后将其放入自己的进程中就没有意义了)。这是速度和安全之间的权衡。 - Daff

1

这些原则与任何多线程C应用程序没有区别:

  1. 始终彻底检查所有输入。
  2. 始终释放您分配的临时内存。
  3. 确保您的函数是可重入的。
  4. 不要依赖于未定义的行为。

如果本地代码失败或泄漏,Java虚拟机对其没有额外的保护,您的VM将会失败或泄漏。


@Daff: 我最初想到的一个方法是将这个post放进去,也就是生成一个新的进程来访问这个dll。这样原始进程就能够继续存在下去。但我不确定这种方法是否被广泛采用。 - Cratylus
@user384706 生成一个新进程并非没有风险,而且对于大多数用途来说速度太慢是无法接受的。此外,如果您已经要启动一个外部进程,为什么不直接使用纯Java呢? - biziclop
我想到的想法是,在Java无法完成特定情况下,使用本地代码。原始进程生成一个新进程来访问dll,任何结果/消息都将发送到父进程。如果发生了什么事情,第二个进程就会死亡,但可以执行更多功能(访问dll)的原始进程仍然存在。我不确定这是否是一种常用方法。也许有点过分了? - Cratylus
@user384706 听起来有点过于复杂,但我不知道具体情况。将那个进程编译成exe文件,然后从Java中启动它不是更容易吗? - biziclop

0

在JNI库中,您可以像在其他任何地方一样拥有完全相同的错误处理谱系。

您可以使用try/catch。如果您在Windows上,则可以使用SEH。如果您在Linux上,则可以调用sigaction。

尽管如此,如果出现SIGSEGV并且您搞砸了,无论您是否尝试捕获该信号,您的JVM可能都会崩溃。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接