【问题标题】:Calling back and forth between C and Java over JNI通过 JNI 在 C 和 Java 之间来回调用
【发布时间】:2019-04-15 03:37:40
【问题描述】:

当通过 JNI 在 C 和 Java 之间来回调用时,我遇到了一个奇怪的堆栈问题。

我们的代码是 C 和 Java 模块的混合体,它们可以使用 JNI 相互调用。

当以下情况发生时,我的问题似乎发生了;

C 模块 (CA.c) 调用 Java 模块 (JA.java),后者调用 C 模块 (CB.c),后者尝试调用 Java 模块 (JB.java),但失败。

CB 确实进行了一些成功运行的 Java 调用,但是一旦堆栈上有一定数量的函数,JNI 似乎开始失败:

CB.c

func1() {
   CallJavaViaJNI();  //Works fine
   func2();
   CallJavaViaJNI();  //Works fine
}

func2() {
   CallJavaViaJNI();  //Works fine
   func3();
   CallJavaViaJNI();  //Works fine
}

func3() {
   CallJavaViaJNI();  //Fails
}

在上面的例子中,从 func1() 和 func2() 调用 CallJavaViaJNI() 时会成功,但在 func3() 中调用会失败(jnienv->ExceptionCheck() 返回 true)。此外,在 func3() 之后发生的 func1() 和 func2() 中对 CallJavaViaJNI() 的调用起作用。

这只是一个例子,堆栈上的函数可能比这多得多。一旦堆栈上有这么多,JNI 似乎就会停止工作。函数从堆栈中弹出后,事情又开始工作了。

我尝试在 ExceptionCheck() 返回 true 后调用 ExceptionDescribe(),但我什么也没得到。清除异常并重试结果相同。

这与JNI的初始化有关吗?我需要指定堆栈大小或其他参数吗?

当从一个从 C 调用的 Java 模块回调到 C 时,有什么特别需要做的吗?文档对此不是很清楚。

如果有任何帮助或指点,我将不胜感激。

【问题讨论】:

  • CallJavaViaJNI 到底是做什么的?在所有这些情况下都是一样的吗?你说你从ExceptionDescribe 中一无所获。这是否意味着您没有发现输出有用,或者您根本没有得到任何输出?在后一种情况下,您确定您没有将 STDERR 重定向到 /dev/null 或类似的东西吗?
  • CallJavaViaJNI() 将使用类似 CallStaticVoidMethod() 的方式调用 Java 模块。在此调用之后,ExceptionCheck() 返回 true。至于 ExceptionDescribe(),它似乎返回一个空字符串。
  • 你尝试过扩展线程栈大小吗?
  • 我使用了ulimit -s unlimited,但没有效果。

标签: java c java-native-interface


【解决方案1】:

您的示例应该可以工作,但是它太简单了,我怀疑您遗漏了一些重要的内容,您能否发布更准确的问题说明?

如果没有更多上下文,我会犹豫猜测但是,我肯定遇到过类似的情况并且有一些想法。

我很想看看你是如何用 c++ 或 java 构造你的 java 对象的? func1()、func2()、func3()使用的对象实例化有区别吗?

【讨论】:

  • 很难给出更详细的答案,更接近我们的代码的工作原理。这是一个庞大的企业系统,拥有数千个模块和数百万行代码。我试图把它分解成一个尽可能简单的问题,然后在这里发布。有问题的代码适用于不同的场景,并且当堆栈中有很多内容时似乎开始失败。奇怪的是 C 执行得很好,只是 JNI 环境损坏了,一旦函数从堆栈中弹出,它甚至会恢复。
猜你喜欢
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多