Accessing Java class members from C
In the previous examples, we have been ignoring the second argument
that was automatically defined by javah for the C native
function. Here, we want to access a data member of the Java object
that calls the native method. This is where the second argument comes
in - it is the implicit this pointer of the calling Java
object (line 26).
Notice that the native method has been declared non-static (line 13).
This causes javah to assign a type of jobject
to the second argument (instead of the type jclass used
previously). This is so that the this pointer of the Java
object can be communicated to non-static native methods (the current
example), or, the type of the Java class can be communicated to static
native methods (the two previous examples).
To decouple JNI users from implementation details of JNI vendors, and
to support portability of user code, JNI has a reflection (or
meta-data) capability that must be exercised in order to access Java
data members and member functions. This meta-data feature is accessed
via JNI functions and JNI functions are called via the env
pointer. We'll need four new JNI functions for this example:
- GetObjectClass() - return a data structure that represents
the object's class
- GetFieldID() - return an offset into the class's data
structure
- GetXxxField() - return the current value of the specified
attribute
- SetXxxField() - set the value of the specified attribute
The Xxx above represents a Java data type (see
GetDoubleField() and SetDoubleField() at
lines 29, 31, and 33). The string "D" (lines 28 and 30) denotes the
type double. All Java types are mapped to their own code -
B | | byte
|
C | | char |
D | | double |
F | | float |
I | | int |
J | | long |
Lclassname; | | a class type |
S | | short |
V | | void |
Z | | boolean |
|
We'll see a lot more of this table in the next several examples as we
start working with the "signatures" of constructors and other member
functions.
[source: Horstmann98, pp594-595]