Interacting with Java from the Native Side |
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 variablesi
and an instance string member variables
. The example program calls the native methodaccessFields
, 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:
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.
- 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 variablesi
as follows:and we get the identifier for the instance string member variablefid = (*env)->GetStaticFieldID(env, cls, "si", "I");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 useGetStaticIntField
to get the value of the class integer member variablesi
, as follows:We use the functionsi = (*env)->GetStaticIntField(env, cls, fid);GetObjectField
to get the value of the instance string member variables
:jstr = (*env)->GetObjectField(env, obj, fid);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 letterL
, followed by the fully-qualified class for the object, and terminated by a semicolon (;). Thus, you form the member variable signature for aString
variable, such asc.s
inFieldAccess.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:This gives you output containing the following two member variable signatures:javap -s -p FieldAccess... static si I s Ljava/lang/String; ...
Interacting with Java from the Native Side |