Good day, masters. Suppose I have a java class A:
class A {
public A() {}
public native void setValue(String value);
public native String getValue();
}
When implementing the native C code, a global char[] variable is used to store the value just be set by native setValue
method. The getValue
method just return that global char[] variable.
Here comes my ques开发者_开发问答tion: I create several A objects, and invoke their respective set/get method, I found that they end up writting and readding the same block of memory! Actually the global char[] variable in C native code is totally shared by all A object.
Can anybody give me some in-depth explaination of this behavior? I knew I had a fundmental misunderstanding in terms of the way JNI works. Thanks!
The problem is that you have the object oriented java on the one side, and the procedural C on the other side. When a java class A is loaded, JNI does not somehow create an object in the C world (this is C - not C++), there is no object-to-object mapping. So JNI loads the corresponding CPP file in the C world once into memory (this is completely normal behavior in C). The compiler sees a bunch of functions and a global reference, there is no need to create multiple instances somehow. When loading a Java class, all the JNI compiler does is to add the C file to the list of files to be compiled.
What you would like to have is a mapping between Java objects and C objects. This can be achieved in several ways, I suggest you read about the proxy pattern in JNI.
To explain very shortly, you have two fundamental ways to achieve this. You can either do it on the C side or on the Java side. When storing the relationship in the C world, you would maintain a hashtable in C where C objects map to Java objects. The other way around, you would have an int object in a Java object that is actually a pointer to a C object in memory. In the C code you would then dereference this pointer (through GetIntField()) and cast to the C object you require.
Of course adding
private String value;
to your Java class A, would indeed work very smootly. Java has a notion of objects, so you could access those Strings from the C world with
env->GetObjectField(obj, "value", "Ljava/lang/String;")
with env being the JNI environment.
精彩评论