Trail: Java Native Interface
|
Lesson: Interacting with Java from the Native Side
|
|
Accessing Java Member Variables
The JNI provides functions that native methods use to get and set
Java member variables. You can get and set both instance and class member variables. Similar to accessing methods, you use one set of
JNI functions to access instance member variables and another set of JNI functions to access class member variables.
Our example program, FieldAccess.java, contains a
class with one class integer member variable si and an instance
string member variable s. The example program calls the native method
accessFields, which prints out the value of these two
member variables and then sets the member variables to new values. To verify the member variables
have indeed changed, we print out their values again in the Java application after
returning from the native method.
Procedure for Accessing a Java Member Variable
To get and set Java member variables from a native language method, you must do the following:
- Obtain the identifier for that member variable from its class, name,
and type signature. For example, in
FieldAccess.c, we get the identifier for the class integer member variable si as follows:
fid = (*env)->GetStaticFieldID(env, cls, "si", "I");
and we get the identifier for the instance string member variable s as follows:
fid = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
- Use one of several JNI functions to either get or set the member variable
specified by the member variable identifier. To get the value of a class member variable, pass the class to one of the appropriate class member variable
access functions. To get the value of an instance member variable, pass the object to the appropriate instance member variable access
function. For example, in
FieldAccess.c, we use GetStaticIntField to get the value of the class integer member variable si, as follows:
si = (*env)->GetStaticIntField(env, cls, fid);
We use the function GetObjectField to get the value of the instance string member variable s:
jstr = (*env)->GetObjectField(env, obj, fid);
Just as we did when calling a Java method, we factor out the cost of member variable lookup
using a two-step process. First we obtain the member variable ID, then use the member variable ID to access the member variable itself. The member variable ID uniquely identifies a member variable in
a given class. Similar to method IDs, a member variable ID remains valid until
the class from which it is derived is unloaded.
Member Variable Signatures
Specify member variable signatures following the same
encoding scheme as method signatures. The general form of a member variable
signature is:
"member variable type"
The member variable signature is the encoded symbol for the type of the
member variable, enclosed in double quotes (""). The member variable symbols are the same
as the argument symbols in the method signature. That is, you
represent an integer member variable with "I", a float member variable with "F", a double
member variable with "D", a boolean member variable with "Z", and so on.
The signature for a Java object, such as a String,
begins with the letter L, followed by the fully-qualified class for
the object, and terminated by a semicolon (;). Thus, you form the
member variable signature for a String variable, such as c.s
in FieldAccess.java, as follows:
"Ljava/lang/String;"
To indicate an array, use a leading square bracket ([) followed by
the type of the array. For example, you designate an integer array as
follows:
"[I"
Refer to the table in the previous section
that summarizes the encoding for the Java type signatures and their
matching Java types.
You can use the Java class disassembler tool javap with option "-s" to generate the member variable
signatures from class files. For example, run:
javap -s -p FieldAccess
This gives you output containing the following two member variable signatures:
...
static si I
s Ljava/lang/String;
...
|