You are on page 1of 36

Java Native Interface (Java Field)

Lecture 8

JNI Field: https://www.youtube.com/watch?v=XNZOD_ODf8Q


Instance and Static Field (Revision)
Java Field
A Java field is a variable inside a class

Instance Field Static Field

Instance field is in Object scope Static field is in Class scope


• It is declared in a class, but • It is declared with the
outside a method. static keyword in a class, but
• It is created when an object is outside a method.
created and destroyed when • It is created when a program
the object is destroyed. starts and destroyed when the
• Each object has its own copy program stops.
of the instance field of the • All object of a class shares
class. the static fields of the class.
Instance and Static Field (Revision)
Instance Field Static Field

• Instance field locates in the objects • A static field belongs to the class.
of the class. • There is one copy of each static
• Each object of the class have its filed per class, regardless of how
own values for these fields. many objects are created from it.

public class Test { Test p = Test(); public class Test { Test.field1 = “mmu”;
String field1; p.field1 = “mmu”; static String field1; System.out.println(Test.field1);
} System.out.println(p.field1); }

Source: http://tutorials.jenkov.com/java/fields.html
Instance Field
Accessing Instance Field
To access the Java field in JNI:
1. Find class reference of the object
GetObjectClass( )

2. Find field id of the instance field


GetFieldID( )

3A. Read the correct instance field


Get<Type>Field( )

3B. Modify the value of instance field


Set<Type>Field( )

Type refers to data type used in Java


Accessing Instance Field (Primitive Type)
Java source code: Book.java C++ native code: CBook.cpp

field/method declaration: input parameters:


instance field: int code interface pointer: env
native method: void read( ) object reference: obj

Static block: 1. GetObjectClass( )


load CBook.dll => Book class of object p
2. GetFieldID( )
main function: => fieldID of code
Book object: p 3. GetIntField( )
p.code = 3356789 => read value of code
p.read( ) 4. SetIntField( )
=> change value of code
to 1112998

p.code = 1112998

GetIntField and SetIntField because field code is a int data type.


Accessing Instance Field (Primitive Type)
#include <iostream> C++ native code: CBook.cpp
#include "Book.h"

JNIEXPORT void JNICALL Java_Book_read(JNIEnv *env, jobject obj) {


jint num;

jclass cls = env->GetObjectClass(obj); // get the class reference


jfieldID fid = env->GetFieldID(cls, "code", "I"); // search field id in cls
if (fid == NULL) return; // if failed to find the field id

Java source code: num = env->GetIntField(obj, fid); // read the instance field
std::cout<<"code received = "<<num<<"\n";
Book.java
class Book {
private int code; std::cout<<"Please enter new code: ";
private native void read(); std::cin>>num;
env->SetIntField(obj, fid, num); // set the instance field into new value
static { }
System.loadLibrary("CBook");
}

public static void main(String args[]) {


Book p = new Book();
p.code = 3356789;
p.read();
System.out.println("latest code = " + p.code);
}
}
Accessing Instance Field (Primitive Type)
Compilation Process of JNI
// Step 2: compile Java source code

// Step 4: build shared library file (CBook.dll)

// Step 5: execute the JNI program

Step 1: write Java source code (Book.java)


Step 3: write C++ native code (CBook.cpp)
Accessing Instance Field
Assume: JNIEXPORT void JNICALL Java_Book_read(JNIEnv *env, jobject obj)

Step 1: Obtain the class reference using GetObjectClass() function


JNI interface pointer object reference

jclass cls = env->GetObjectClass(obj); It returns the class reference


(class of an object).
class reference

Step 2: Obtain the field ID using GetFieldID() function


name of the instance field in the Java class
It returns the field ID for an
jfieldID fid = env->GetFieldID(cls, "code", "l"); instance field of a class. It
return NULL if operation fails.
field id field descriptor
code is an integer instance field in Java class
Accessing Instance Field
Assume: JNIEXPORT void JNICALL Java_Book_read(JNIEnv *env, jobject obj)

<Type> refers to data type used in Java

Step 3A: Obtain the value of instance field using Get<Type>Field() functio
JNI interface pointer object reference field id

jint num = env->Get<Type>Field(obj, fid);


The field to access is specified
by field ID. It returns the value
of an instance field.
jint num = env->GetIntField(obj, fid);

temporary storage

instance field(code) in the Java class is int type


Accessing Instance Field
Assume: JNIEXPORT void JNICALL Java_Book_read(JNIEnv *env, jobject obj)

<Type> refers to data type used in Java

Step 3B: Change the value of instance field using Set<Type>Field() functi
jint num = 10; the updated value
object reference
field id

env->Set<Type>Field(obj, fid, num);


It set the value of an
instance field of an object
env->SetIntField(obj, fid, num);

num consists of the updated int value


Accessing Instance Field
 For Primitive data types:
Type Get<Type>Field() Set<Type>Field()
jboolean GetBooleanField() SetBooleanField()
jbyte GetByteField() SetByteField()
jchar GetCharField() SetCharField()
jshort GetShortField() SetShortField()
jint GetIntField() SetIntField()
jlong GetLongField() SetLongField()
jfloat GetFloatField() SetFloatField()
jdouble GetDoubleField() SetDoubleField()

 For Class data types:


Type Get<Type>Field() Set<Type>Field()
String
GetObjectField() SetObjectField()
Array
Field Signature/Descriptor
 The field signature/descriptor is the encoded symbol
for data type of the field in JNI. field descriptor
jfieldID fid = env->GetFieldID(cls, "code", "l");

 It is used to identify the data type of the field passed


from Java code into the shared library.
Field Signature/Descriptor cont..
Java Type Field Signature/Descriptor
boolean Z
byte B
char C

Primitive short S
data type int I
long J
float F
double D
String Ljava/lang/String;
Class Object Ljava/lang/Object;
data type int[] [I
Example of Field Signature/Descriptor
List the field signature below:

1. int ; I

2. boolean door; Z

3. String name; Ljava/lang/String;

4. float [] price; [F
Accessing Instance Field (String Type)
Java source code: Pen.java C native code: CPen.cpp

field/method declaration: input parameters:


instance field: String brand interface pointer: env
native method: void read( ) object reference: obj

Static block: 1. GetObjectClass( )


load CPen.dll => Pen class of object b
2. GetFieldID( )
main function: => fieldID of brand
Pen object: b 3. GetObjectField( )
b.brand = "Faber-castell" => access value of brand
b.read( ) 4. SetObjectField( )
=> change value of brand
to "Sheaffer"

b.brand = "Sheaffer"

GetObjectField and SetObjectField because field brand is a String data type.


Accessing Instance Field (String Type)
#include <iostream> C++ native code: CPen.cpp
#include "Pen.h"
using namespace std;

JNIEXPORT void JNICALL Java_Pen_read(JNIEnv *env, jobject obj) {


jstring jstr;
const char *str;
string content;

jclass cls = env->GetObjectClass(obj); // get class reference


jfieldID fid = env->GetFieldID(cls, "brand", "Ljava/lang/String;"); // search the field id
if (fid == NULL) return;

jstr = (jstring)env->GetObjectField(obj, fid); // read the instance field (jstring)


str = env->GetStringUTFChars(jstr, NULL); // convert jsting to C-style string
Java source code: Pen.java if (str == NULL) return;
cout << "The received brand = " << str;
class Pen { env->ReleaseStringUTFChars(jstr, str);
private String brand;
private native void read(); cout << "\nPlease enter new brand: ";
getline(cin, content);
static { jstr = env->NewStringUTF(content.c_str()); // create new string to store the user's input
System.loadLibrary("CPen"); env->SetObjectField(obj, fid, jstr); // set the instance field into new value
} }

public static void main(String args[]) {


Pen b = new Pen();
b.brand = "Faber-castell";
b.read();
System.out.println("latest brand = " + b.brand);
}
}
Accessing Instance Field (String Type)
Compilation Process of JNI
// Step 2: compile Java source code

// Step 4: build shared library file (CPen.dll)


// Step 5: execute Java program

Step 1: write Java source code (Pen.java)


Step 3: write C++ native code (CPen.cpp)
Java class:
• private String brand;
Java main function:
• Pen b = new Pen();
• b.brand = “Faber-castell”;

jclass cls = env->GetObjectClass(obj);


To access the value
of an instance field
(brand) and the fid = env->GetFieldID(cls, “brand", "Ljava/lang/String;");
value is stored in jstr
jstr = (jstring)env->GetObjectField(obj, fid);

To convert the value str = env->GetStringUTFChars(jstr, NULL);


from jstr (jstring) to
str (C-style string)
env->ReleaseStringUTFChars(jstr, str);

To get user’s input,


getline(cin, content);
store the user’s value
into new string and
update the instance jstr = env->NewStringUTF(content.c_str());
field (brand) with the
new string env->SetObjectField(obj, fid, jstr);
Static Field
Accessing Static Field
To access the Java static field in JNI:
1. Find class reference of the object
GetObjectClass()

2. Find field id of the static field


GetStaticFieldID()

3A. Read the correct static field


GetStatic<Type>Field()

3B. Modify the value of the static field


SetStatic<Type>Field()

Type refers to data type used in Java


Accessing Static Field
Assume: JNIEXPORT void JNICALL Java_ Java_Box_check(JNIEnv *env, jobject obj)

Step 1: Obtain the class reference using GetObjectClass() function


JNI interface pointer object reference

jclass cls = env->GetObjectClass(obj); It returns the class reference


(class of an object).
class reference

Step 2: Obtain the field ID using GetStaticFieldID() function


name of the static field in the Java class field descriptor
It returns the field ID
jfieldID fid = env->GetStaticFieldID(cls, "size", "C"); for a static field of a
class. It return NULL
field id if operation fails.
size is char static field in Java class
Accessing Static Field
Assume: JNIEXPORT void JNICALL Java_ Java_Box_check(JNIEnv *env, jobject obj)

<Type> refers to data type used in Java

Step 3A: Obtain the value of static field using GetStatic<Type>Field() function
JNI interface pointer class reference field id
It returns the value of a static
jint si = env->GetStaticCharField(cls, fid); field of a class. The field to
access is specified by field ID.
temporary storage static field(size) in the Java class is char type

Step 3B: Update the value of static field using SetStatic<Type>Field()


function class reference field id the updated value
jchar unit = 'M';
env->SetStaticCharField(cls, fid, unit); It set the value for a static
field of a class.
unit consists of the updated char value
Accessing Static Field (Primitive Type)
Java source code: Box.java C++ native code: CBox.cpp

field/method declaration: input parameters:


static field: char size interface pointer: env
native method: void check( ) object reference: obj

Static block: 1. GetObjectClass( )


load CBox.dll => Box class of object k
2. GetStaticFieldID( )
main function: => fieldID of size
Box object: k 3. GetStaticCharField( )
Box.size = ‘S’ => read value of size
k.check( ) 4. SetStaticCharField( )
=> change value of size to
‘M’

Box.size = ‘M’

GetStaticCharField and SetStaticCharField because the static field size is a char data type.
Accessing Static Field (Primitive Type)
#include <iostream> C++ native code: CBox.cpp
#include "Box.h"
using namespace std;

JNIEXPORT void JNICALL Java_Box_check(JNIEnv *env, jobject obj) {


jchar unit;
char temp;

jclass cls = env->GetObjectClass(obj); // get the class reference


jfieldID fid = env->GetStaticFieldID(cls, "size", "C"); // search field id in cls
if (fid == NULL) return;

unit = env->GetStaticCharField(cls, fid); // read the static field


Java source code: Box.java cout << "box size received = " << char(unit);

class Box { cout << "\nPlease enter new size: ";


private static char size; cin>>temp;
private native void check(); cout << "new size = " << temp<< "\n";
unit = char(temp);
static { env->SetStaticCharField(cls, fid, unit); // set the static field into new value
System.loadLibrary("CBox"); }
}

public static void main(String args[]) {


Box.size = 'S';
Box k = new Box();
k.check();
System.out.println("Box size is changed to " + Box.size);
}
}
Accessing Static Field (Primitive Type)
Compilation Process of JNI

// Step 2: compile Java source code

// Step 4: build shared library file (CBox.dll)

// Step 5: execute Java program

Step 1: write Java source code (Box.java)


Step 3: write C++ native code (CBox.cpp)
Accessing Static Field
 For Primitive data types:
Type GetStatic<Type>Field() SetStatic<Type>Field()
jboolean GetStaticBooleanField() SetStaticBooleanField()
jbyte GetStaticByteField() SetStaticByteField()
jchar GetStaticCharField() SetStaticCharField()
jshort GetStaticShortField() SetStaticShortField()
jint GetStaticIntField() SetStaticIntField()
jlong GetStaticLongField() SetStaticLongField()
jfloat GetStaticFloatField() SetStaticFloatField()
jdouble GetStaticDoubleField() SetStaticDoubleField()

 For Class data types:


Type GetStatic<Type>Field() SetStatic<Type>Field()
String
GetStaticObjectField() SetStaticObjectField()
Array
Extra Exercise (Q1)
import java.util.Scanner;

class Q3{
public native void printTest(int num);

static {
System.loadLibrary("CQ3");
}

public static void main(String[] args) {


Scanner ab = new Scanner(System.in);
System.out.printf("Please enter your magic number: ");
int num = ab.nextInt();

Q3 ww = new Q3();
ww.printTest(num);
}
}
Extra Exercise (Q1)
#include "Q3.h"
#include <iostream>
using namespace std;

JNIEXPORT void JNICALL Java_Q3_printTest(JNIEnv *env, jobject obj, jint nn)


{

if (nn > 0 && nn <= 50)


cout<<"Your magic number is equal or less than 50"<<"\n";
else if (nn > 50 && nn <= 100)
cout<<"Your magic number is larger than 50 and less or equal to 100"<<"\n";
else
cout<<"You magic number is not in the range";

return;
}
Extra Exercise (Q1)
Extra Exercise (Q2)
import java.util.Scanner;

class Q4 {
public native int printResult(int num);

static {
System.loadLibrary("CQ4");
}

public static void main(String[] args) {


Scanner ab = new Scanner(System.in);
System.out.printf("Please enter your magic number: ");
int num = ab.nextInt();

Q4 ww = new Q4();
System.out.printf("The result is " + ww.printResult(num));
}
}
Extra Exercise (Q2)
#include "Q4.h"

JNIEXPORT jint JNICALL Java_Q4_printResult(JNIEnv *env, jobject obj, jint nn)


{

jint temp;

if (nn > 0 && nn <= 50)


temp = 10*nn;
else if (nn > 50 && nn <= 100)
temp = 5*nn;
else
temp = nn*2;

return temp;
}
Extra Exercise (Q2)
Extra Exercise (Q1)
import java.util.Scanner;

class Q5{
public native void printLength(String name);

static {
System.loadLibrary("CQ5");
}

public static void main(String[] args) {


Scanner ab = new Scanner(System.in);
System.out.printf("Please enter your name: ");
String name = ab.nextLine();

Q5 ww = new Q5();
ww.printLength(name);
}
}
Extra Exercise (Q1)
#include "Q5.h"
#include <iostream>
using namespace std;

JNIEXPORT void JNICALL Java_Q5_printLength(JNIEnv *env, jobject obj, jstring


text) {

const char *str = env->GetStringUTFChars(text, NULL);


cout<< "Hi " << str << "\n";

jint length = env->GetStringLength(text);


cout << "Length of your name (include whitespace): " << length;

env->ReleaseStringUTFChars(text, str);

return;
}
Extra Exercise (Q1)

You might also like