JVM无法与包含名为“ Node”的类的JNI C ++代码一起使用

汤姆:

我本人和一些队友无法理解为什么使用JVM版本1.6u23至1.6u31(本文发布时的最新信息)时,以下代码片段无法提供正确的输出。此代码段表示一个较大问题的简化:

更新:稍微修改了该示例,以将重点放在“ virtual_function()”似乎没有被调用的问题上。

更新:根据迄今为止的评论,该示例更加简化。

NodeTester.cpp:

#include <iostream>
#include <jni.h>

class Node {
  public:
    Node () :m_counter(0) {}
    virtual ~Node () {}

    virtual void virtual_function () {
      m_counter += 10;
    }

    void non_virtual_function () {
      m_counter += 1;
    }

    int get_counter () {
      return m_counter;
    }

  private:
    int m_counter;

};

extern "C" {
  JNIEXPORT void JNICALL Java_NodeTester_testNode (JNIEnv *jni_env_rptr, 
                                                   jclass java_class) {
    Node *node_rptr = new Node();
    node_rptr->non_virtual_function();
    node_rptr->virtual_function();

    std::cout << node_rptr->get_counter() << std::endl;

    delete node_rptr;
  }
}

NodeTester.java:

public class NodeTester {
  public static native void testNode ();

  static {
    System.loadLibrary("nodetester");
  }

  public static final void main (String[] args) {
    NodeTester.testNode();
  }
}

预期输出:

11

JVM 1.6u23到1.6u31的实际输出:

1

看来JVM在JNI中错误地构造了“ Node”对象。尽管此代码可能与JNI的使用不符。当类“节点”被添加了更多的功能(例如,更多的属性,附加的虚拟和非虚拟操作)时,我们会导致分段错误,而不仅仅是错误的输出。我们正在使用g ++将cpp代码编译到RedHat linux 64位共享对象库中,并在64位Server VM上运行Java代码。请注意,在JVM 1.6u20至1.6u22上,这会产生预期的输出。我没有尝试过任何早期版本。

我们已决定悬赏这个问题!以下是有关我们已经知道的更多信息:

  • JVM 1.6u22(及更高版本)产生预期结果
  • 重命名“节点”或将其放在命名空间中会产生预期的结果
  • 在堆栈上分配“ Node”对象而不是JNI函数中的堆会产生预期的结果
  • 类“节点”的非虚拟组件没有问题

对于我们来说不幸的是,这些项目都没有一个可行的解决方案-我提到的“更大的问题”是,我们正在处理一个名为“ Node”的C ++类的现有代码库,需要通过JNI访问。我们还尝试了几种g ++和javac编译器选项,以及几种JVM选项,但无济于事(尽管如果有人偶然发现了一个实际会产生预期结果的选项,这将是一个可接受的解决方案)。

塞缪尔·奥德(Samuel Audet):

好的,这不是一个完美的答案,但是如果我们没有更好的选择,那么以下内容可能会有所帮助。正如其他注释中所解释的那样,问题的症结在于两个不同的C ++类,它们都Node在全局名称空间中命名,一个来自OpenJDK或SunJDK 1.6u23,在RedHat Linux上(至少),另一个在另一个库中,两者其中需要与其他库共享其符号。为了在JDK之前加载符号,我们可以LD_PRELOAD通过调用以下命令来设置环境变量:

LD_PRELOAD=libTheNodeTester.so java ...

但这可能会使JDK崩溃,如果它实际上开始使用我们的符号,就好像它来自其库中的符号一样...

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Selenium C#-为什么Chrome的详细日志记录无法与此代码一起使用?

从C ++使用JNI时JVM找不到类

C# 如何使用隐藏的代码将类的 observableCollection 与可观察的集合绑定在一起

无法将 DefineClass (JNI) 与 Qt 资源一起使用

我的与任务计划程序一起使用的应用程序无法在我的C#代码中创建目录

具有ostream运算符的C ++类可与VS一起使用,并且无法使用gcc进行编译

在C#中将“ this”与类名一起使用

如何将c ++类与ctypes一起使用?

uniq -c无法与awk一起使用?

为什么C ++ Map的operator <无法与<=一起使用

C ++无法使用枚举并一起切换

有类无法与父级一起使用jQuery

无法将Tuple类与本机查询一起使用

对象类在 Swift 中无法与 RLMSupport 一起使用

Node.js无法与Intellij Idea一起使用

Mongodb无法与Node.js一起使用

setTimeout无法与node.js一起使用

jQuery无法与Node.js一起使用

Mongo无法与Node.js一起使用

AngularJS代码无法与NodeJS一起使用

Tree JavaScript代码无法与Internet Explorer一起使用

保存JSON无法与代码一起使用

jQuery无法与Ajax返回的代码一起使用

简单的std :: regex_search()代码无法与Apple clang ++一起编译-std = c ++ 14

为什么这个简单的C ++代码无法与clang ++一起编译?

C、代码一起运行

C# 强制一组类一起使用

在C ++中将模板与类一起使用时,类成员函数的答案错误?

无法在JNI中将GetMethodID与字节数组参数一起使用