|
[ This exercise
| Solution
| Course Notes
| Exercises page
]
|
|
Help: Exercise 3 |
Compile JavaFields.java and Main.java using javac:
javac JavaFields.java javac Main.javaThis produces JavaFields.class and Main.class.
Using javah, create the C/C++ header file that represents the JavaFields class. Be sure to include the -jni switch so that the resulting header file is a JNI-compatible file. Also, don't include the .class extension:javah -jni JavaFieldsThis creates a file called JavaFields.h in the same directory as JavaFields.class:/* DO NOT EDIT THIS FILE - it is machine generated */ #include < jni.h > /* Header for class JavaFields */ #ifndef _Included_JavaFields #define _Included_JavaFields #ifdef __cplusplus extern "C" { #endif /* * Class: JavaFields * Method: manipulateFields * Signature: ()V */ JNIEXPORT void JNICALL Java_JavaFields_manipulateFields (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endifIt is important that you compile JavaFields.java in the previous step so that the .class file is available to javah in this step.
As with all native methods, first be sure that you have done the following correctly:
#include the header file that was created in the previous step. Make sure that you prepend Java_JavaFields_ to the name of the method. Check that the return type and argument types match the declaration in JavaFields.h. If they don't match, you won't get any warnings from the compiler, but at run-time, when java calls the method, it will fail. Don't forget the first two parameters to the function. They are required and we will use them in this exercise. If you have problems at run-time, they are likely to be caused by this function signature. The safest thing to do to ensure that you won't have any problems is to copy the declaration of the function from the header file generated by javah. Once the function name and signature are correct you will implement the body by making several calls to the API:
- Get the object's class by calling GetObjectClass. This will return a reference to the class JavaFields that you implemented earlier. You only need to call this once, although you will use cls multiple times.
jclass cls = env->GetObjectClass(obj);- Call the API function GetFieldID to get the non-static fields' IDs. There are three arguments to the function. The first is the class that you obtained in the previous call. The second argument is the literal name of the field. The third argument is the field's signature or data type.At runtime, the GetFieldID function will look for the field by name. You will need to call this function once for each non-static field that you want to access. In this exercise, you will call it three times.
For the static field, you need to call this function:jfieldID fid_i = env->GetFieldID(cls, "i", "I"); jfieldID fid_f = env->GetFieldID(cls, "f", "F"); jfieldID fid_pi = env->GetFieldID(cls, "pi", "I");jfieldID fid_si = env->GetStaticFieldID(cls, "y", "I");- Once you have the field ID's, you can get the values of the non-static fields by calling these functions:
For the static field, you need to call this function:int i = env->GetIntField(obj, fid_i); float f = env->GetFloatField(obj, fid_f); int pi = env->GetIntField(obj, fid_pi);int si = env->GetStaticIntField(cls, fid_si);- To set the non-static fields, you call these functions: (the values are arbitrary)
For the static field, you need to call this function (the value is arbitrary):env->SetIntField(obj, fid_i, 100); env->SetFloatField(obj, fid_f, 123.45); env->SetIntField(obj, fid_pi, 300);env->SetStaticIntField(cls, fid_si, 200);Task 4
This is the step where the actual creation of the shared library happens. It is important that the name matches what the JavaFields class is expecting when it loads the shared library in its static initialization:This code is taken from JavaFields.java:
static { // The name of our shared library must match what // the class is loading at initialization time: System.loadLibrary("JavaFieldsImp"); }Here is an example of how to make a shared library under Unix:
# This works on sirius.cs.pdx.edu # The -o option allows you to name the shared library. Note that # you must provide the 'lib' prefix and '.so' suffix here. gcc -G -I/pkgs/jdk1.1.1/include -I/pkgs/jdk1.1.1/include/solaris JavaFieldsImp.cpp -o libJavaFieldsImp.soHere is an example of how to make a shared library under Windows NT:
: This works under NT. Replace the include paths to match your environment : and be sure to include Sun's JDK not Microsoft's! : Note that you must provide the .dll extension (case insensitive) cl -Im:\jdk1.1.5\include -Im:\jdk1.1.5\include\win32 -LD JavaFieldsImp.cpp -FeJavaFieldsImp.dllTask 5
To execute the program, run Main with the java interpreter:java MainThe output should look something like this:From native code: public int i = 1 public float f = 2.450000 static public int si = 3 private int pi = 5 After native call: public int i = 100 public float f = 123.45 static public int si = 200 private int pi = 300If you receive an error message such as either of these:java.lang.UnsatisfiedLinkError: no JavaFieldsImp in shared library path java.lang.UnsatisfiedLinkError: manipulateFieldsrefer to the common mistakes in the detailed example.
If you get a SIGSEGV error under Solaris, you'll probably get a message like: (buried in about 30 lines of text)lang.NoSuchFieldError *current thread*It is probably because of this line of code (or similar line):jfieldID fid = env->GetFieldID(cls, "i", "I");There are two likely reasons for this error message.Under Windows NT, you will get a "java.exe - Application Error" dialog box saying something useful like:
- You have supplied a non-existent field name. This field name is looked-up at runtime so the compiler has no way of verifying that the field you specified really exists.
- The signature (data type) is incorrect. If the field is an integer, then you must specify that type in the third argument.
The instruction at "0x1001280e" referenced memory at "0x00000014". The memory could not be "read". Blah, blah, blahThis is a SIGSEGV under Windows NT.
Copyright © 1998 Sergio Antoy. All Rights Reserved
February 99, version 020199