代码之家  ›  专栏  ›  技术社区  ›  solotim

Java JNI:本地代码中的全局变量冲突

  •  2
  • solotim  · 技术社区  · 14 年前

    今天好,大师们。假设我有一个Java类A:

    class A {
        public A() {}
        public native void setValue(String value);
        public native String getValue();
    }
    

    在实现本机C代码时,使用全局char[]变量来存储仅由本机设置的值。 setValue 方法。这个 getValue 方法只返回全局char[]变量。

    我的问题是:我创建了几个A对象,并调用了它们各自的set/get方法,我发现它们最终会写入和读取同一块内存!实际上,C本机代码中的全局char[]变量完全由所有对象共享。

    有人能给我一些关于这种行为的深入解释吗?我知道我对JNI的工作方式有一个基本的误解。谢谢!

    1 回复  |  直到 14 年前
        1
  •  7
  •   David Sauter    14 年前

    问题是,一方面有面向对象的Java,另一方面有程序C。当加载Java类A时,JNI没有在C世界中创建某种对象(这是C -非C++),没有对象到对象映射。所以jni在C世界中加载相应的cpp文件 一旦 进入内存(这在C中是完全正常的行为)。编译器看到一堆函数和一个全局引用,不需要以某种方式创建多个实例。在加载Java类时,所有JNI编译器都是将C文件添加到要编译的文件列表中。

    您想要的是Java对象和C对象之间的映射。这可以通过几种方式实现,我建议您阅读JNI中的代理模式。

    很快解释一下,您有两种基本的方法来实现这一点。您可以在C端或Java端进行。当在C世界中存储关系时,您将在C中保持一个哈希表,其中C对象映射到Java对象。反过来说,在Java对象中有一个int对象,它实际上是指向内存中C对象的指针。然后,在C代码中,您将取消对该指针的引用(通过getIntfield())并转换为所需的C对象。

    当然要加

    private String value;
    

    对于Java类A,的确非常有效。Java有对象的概念,所以你可以从C世界中访问这些字符串。

    env->GetObjectField(obj, "value", "Ljava/lang/String;")
    

    环境是JNI环境。