HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

"Using the Java Native Interface Productively"
Vol. 7, Issue 6, p. 62

	


Listing 1: Passing an int to the JNI

package jni_article_;

public class IntegerAccess {
  static {
    System.loadLibrary("EasyJNI");
  }
  private native int accessInt(int value);
  // (1)
  private int value;
  public IntegerAccess() {value = 5;}

  public static void main(String[] args) {
   IntegerAccess integerAccess1 = new IntegerAccess();
System.out.println("Value sent and returned is " +
  integerAccess1.accessInt(integerAccess1.value));
  }
}  


Listing 2: Native code called in Listing 1

// Headers omitted...
JNIEXPORT jint JNICALL Java_jni_1article_1_IntegerAccess_accessInt
  (JNIEnv *, jobject, jint jInt)
{
  cout << "Value is " << jInt << endl;
	
  return (jInt);
}


Listing 3: Passing a string parameter from Java to C++ 

package jni_article_;

public class StringAccess {
  static {
    System.loadLibrary("EasyJNI");
  }
  private native String accessString(String stringValue);
  public StringAccess() {
  }

  public static void main(String[] args) {
    StringAccess stringAccess1 = new StringAccess();
    System.out.println("Value sent and returned is " +
      stringAccess1.accessString("Hello World"));
  }
}


Listing 4: Native code called in Listing 3

// Headers omitted...
JNIEXPORT jstring JNICALL Java_jni_1article_1_StringAccess_accessString
  (JNIEnv *env, jobject jo, jstring jStringValue)
{
  jstring jStr = 0;
  const char * str = 
    env->GetStringUTFChars(jStringValue, NULL);
	// (1)
  if (str) {
    cout << "Value is " << str << endl;
    jStr = env->NewStringUTF("Goodbye World");
    env->ReleaseStringUTFChars(jStringValue, str);
  }

  return (jStr);
}


Listing 5: Passing a class parameter from Java to C++.

package jni_article_;

public class ClassAccess {
  static {
    System.loadLibrary("EasyJNI");
  }
  private native int accessClass(Device1 devName);
  private native int accessClass(Device2 devName);
  public ClassAccess() {
  }

  public static void main(String[] args) {
    ClassAccess classAccess = new ClassAccess();
    Device2 dev2 = new Device2();
    classAccess.accessClass(dev2);
  }
}


// In device1.java
package jni_article_;

public class Device1 {
  public Device1 (int value) {
    intValue = value;
  }
  int intValue;
}

// In device2.java
package jni_article_;

public class Device2 {
  public Device2 () {
    intValue = 1;
    longValue = 11;
    stringValue = new String("Hello World");
    dev1Value = new Device1(5);
  }
  private int intValue;
  private long longValue;


  String stringValue;
  Device1 dev1Value;
}


Listing 6: Native code called in Listing 5

// Headers omitted...
// ClassAssign.AccessClass(Device2)
JNIEXPORT jint JNICALLJava_jni_1article_1_
ClassAccess_accessClass__Ljni_1article_1_Device2_2
  (JNIEnv *env, jobject jo, jobject jOutput)
{
// get the class of the object parameter
	jclass cls0 = env->GetObjectClass(jOutput);
// (1)
	               if (cls0) {
// get the field ID of the "intValue" field of this class
	jfieldID fidInt = env->GetFieldID(cls0, "intValue", "I");
// (2)
	               if (fidInt) {
// get the value of the field in this instance of the above class
	jint valInt = env->GetIntField(jOutput, fidInt);
	cout << "Value is " << valInt << endl;

// get the field ID of the "longValue" field of this class
	jfieldID fidLong = env->GetFieldID(cls0, "longValue", "J");
// (3)
	               if (fidLong) {
// get the value of the field in this instance of the above class
	jlong valLong = env->GetLongField(jOutput, fidLong);
	cout << "Value is " << (long) valLong << endl;
				
// get the field ID of the String field of this class
	jfieldID fidString = env->GetFieldID(cls0, 
	"stringValue", "Ljava/lang/String;");
// (4)
	                if (fidString) {
// get the value of the field in this instance of the above class
   jstring valString = (jstring) env->GetObjectField(jOutput, fidString);
	                if (valString) {
const char * str = env->GetStringUTFChars(valString, NULL);
	                if (str) {
cout << "Value is " << str << endl;
env->ReleaseStringUTFChars(valString, str);

// get the field ID of the Device1 object field of this class
    jfieldID fidObject = env->GetFieldID(cls0, 
	"dev1Value", "Ljni_article_/Device1;");
// (5)
	            if (fidObject) {
// get a reference to this field in this instance of the class
	jobject valObject = env->GetObjectField(jOutput, fidObject);
	           if (valObject) {
// get the class of the object parameter
	jclass clsObject = env->GetObjectClass(valObject);
	           if (clsObject) {
// get the field ID of the "intValue" field of this class
	jfieldID fidInt = env->GetFieldID(clsObject, "intValue", "I");
		       if (fidInt) {
// get the value of the field in this instance of the class
	jint valInt = env->GetIntField(valObject, fidInt);
// (6)
	cout << "Value is " << valInt << endl;
                     }
                   }
                 }
               }
             }
           }
         }
       }
     }
   }

	return (0);
}


Listing 7: Functions to handle fetching string and object members of a Java 
 

// class
void AccessString(JNIEnv *env, jclass clsContaining, 
jobject jContaining, LPCTSTR lpszFieldName, string & strOut)
{
	jfieldID fidString = env->GetFieldID(clsContaining, 
	lpszFieldName, "Ljava/lang/String;");	
// get the field ID of the field of this class
	             if (fidString) {
	jstring valString = (jstring) env->GetObjectField(jContaining, fidString);
// get the value of the field in this instance of the above class
		         if (valString) {
	const char * str = env->GetStringUTFChars(valString, NULL);
			     if (str) {
	strOut = str;
	env->ReleaseStringUTFChars(valString, str);
         }
       }
     }
   }

void AccessObject(JNIEnv *env, jclass clsContaining, 
jobject jContaining, LPCTSTR lpszFieldName, LPCTSTR lpszFieldSig, 
class *clsContained, jobject *oContained)
{
// Code defensively. Initialize with "failure" values for safety
	*clsContained = static_cast<jclass>(*oContained = 0);
// get the field ID of the field of this class
	jfieldID fidObject = env->GetFieldID(clsContaining, lpszFieldName, lpszFieldSig);
	             if (fidObject) {
// get the value of the object field in this instance of the above class
	*oContained = env->GetObjectField(jContaining, fidObject);
		         if (*oContained) {
// get the class of the object parameter
	*clsContained = env->GetObjectClass(*oContained);
     }
   }

	return;
}	


Listing 8: Listing 5 modified to use the access...

// functions
JNIEXPORT jint JNICALL Java_jni_1article_1_ClassAccess_
accessClass__Ljni_1article_1_Device2_2
  (JNIEnv *env, jobject jo, jobject jOutput)
{
// get the class of the object parameter
  jclass cls0 = env->GetObjectClass(jOutput);	
  if (cls0) {
// int and long code here...(omitted for clarity)
string sOut;
AccessString(env, cls0, jOutput, "stringValue", sOut);
cout << "Value is " << sOut.c_str() << endl;
	
    jclass clsContained;
    jobject oContained;
    AccessObject(env, cls0, jOutput, "dev1Value",
   "Ljni_article_/Device1;", &clsContained, &oContained);
                if (clsContained && oContained) {
// get the field ID of the intValue field of this
// class
 jfieldID fidInt = env->GetFieldID(clsContained, "intValue", "I");
                if (fidInt) {
// get the value of the int field in this instance
// of the above class
	jint valInt = env->GetIntField(oContained, fidInt);
	cout << "Value is " << valInt << endl;
       }
     }
   }

  return (0);
}


Listing 9: Assigning C structures to Java classes

package jni_article_;

public class ClassAssign {
  static {
    System.loadLibrary("EasyJNI");
  }
  private native int assignClass(Device3 devName);
  public ClassAssign() {
  }

  public static void main(String[] args) {
    ClassAssign classAssign = new ClassAssign();
    Device3 dev3 = new Device3();
    classAssign.assignClass(dev3);
    System.out.println("Integer value is "+ dev3.intValue);
    System.out.println("Long value is " + dev3.longValue);
    System.out.println("String value is " +
      dev3.stringValue);
    System.out.println("Integer value in Device 1 is " +
      dev3.dev1Value.intValue);
     }
   }


Listing 10: Functions to handle assignment of C++ data types to Java fields


// Get an object reference to a Java object type contained within a containing
// Java object.
jobject GetObjectReference(JNIEnv *env, 
jclass clsStruct, jobject joStruct, 
LPCSTR lpszJavaFieldName, LPCSTR lpszSignature)
{
// Get the field ID of the field in the Java object
	jfieldID fidField = env->GetFieldID(clsStruct, lpszJavaFieldName, lpszSignature);
	          if (fidField) {
// get a reference to the SymAPIDirector object
	jobject joField = env->GetObjectField(joStruct, fidField);
		return (joField);
	}
	return (0);
}

/*
Assign a C int value to a Java int field.
The Java class is cls0. 
The Java object is oOutput. 
The C int value is uiMember.
The Java class member name is lpszJavaFieldName.
Usage:
Return value:
	1 => success;
	0 => failure;
*/
int ParseIntField(JNIEnv *env, jclass cls0, 
jobject oOutput, unsigned uiMember, LPCSTR lpszJavaFieldName)
{
	int iRc = 0; // failure

// Get the field ID of the field in the Java object.
// Note the "I" JNI signature for an int.
	jfieldID fid0 = env->GetFieldID(cls0, lpszJavaFieldName, "I");
	         if (fid0) {
// assign the (C++) int field to the Java object
	env->SetIntField(oOutput, fid0, uiMember);
		iRc = 1; // success
	}

	return (iRc);
}

/*
Assign a C long value to a Java long field. 
The Java class is cls0. 
The Java object is oOutput. 
The C long value is lCMember.
The Java class member name is lpszJavaFieldName.
Return value:
	1 => success;
	0 => failure;
*/
int ParseLongField(JNIEnv *env, jclass cls0,
jobject oOutput, long lCMember, LPCSTR lpszJavaFieldName)
{
	int iRc = 0; // failure

// get the field ID of the field in the Java object
	jfieldID fid0 = env->GetFieldID(cls0, lpszJavaFieldName, "J");
	         if (fid0) {
// assign the (C++) long field to the Java object
	env->SetLongField(oOutput, fid0, lCMember);
		iRc = 1; // success
	}

	return (iRc);
}

/*
Assign a C single byte string value to a Java object field.
The Java class is cls0. 
The Java object is oOutput. 
The C string is lpszCMember.
The Java class member name is lpszJavaFieldName 
and it's signature is lpszSignature.
Return value:
	1 => success;
	0 => failure;
*/
int ParseStringField(JNIEnv *env, jclass cls0,
jobject oOutput, LPCSTR lpszCMember, LPCSTR lpszJavaFieldName)
{
	int iRc = 0; // failure
// convert C-string member to a java String object
	jstring str0 = env->NewStringUTF(lpszCMember);
	          if (str0) {
// get the field ID of the String field in the Java object
	jfieldID fid0 = env->GetFieldID(cls0, lpszJavaFieldName,"Ljava/lang/String;");
		      if (fid0) {
// assign the (C++) string field to the Java object
	env->SetObjectField(oOutput, fid0, str0);
		iRc = 1; 
// success
     }
   }

	return (iRc);
	
	

Additional Source Code Listings


Listing 11: Native code called in Listing 9

// Headers omitted…
JNIEXPORT jint JNICALL Java_jni_1article_1_ClassAssign_assignClass
  (JNIEnv *env, jobject jo, jobject jOutput)
{
	int iRc = 0;

// get the class of the object parameter
	jclass cls0 = env->GetObjectClass(jOutput);
// (1)
	            if (cls0) {
// get the field ID of the "intValue" field of this class
	jfieldID fidInt = env->GetFieldID(cls0, "intValue", "I");
// (2)
	        	if (fidInt) {
// assign the (C++) int member to the Java object
	env->SetIntField(jOutput, fidInt, dev3.intValue);

// get the field ID of the "longValue" field of this class
	jfieldID fidLong = env->GetFieldID(cls0, "longValue", "J");
// (3)
    			if (fidLong) {
// assign the (C++) long member to the Java object
	env->SetLongField(jOutput, fidLong, dev3.longValue);

// convert C-string member to a java String object
	jstring str0 = env->NewStringUTF(dev3.stringValue);
// (4)
				if (str0) {
// get the field ID of the String field in the Java object
	jfieldID fidString = env->GetFieldID(cls0, "stringValue", "Ljava/lang/String;"); 
				if (fidString) {
// assign the (C++) string field to the Java object
	env->SetObjectField(jOutput, fidString, str0);

// get the field ID of the object field in the Java object
	jfieldID fidObject = env->GetFieldID(cls0, "dev1Value", "Ljni_article_/Device1;");
// (5)
				if (fidObject) {
// get a reference to the object field in this instance of the class
	jobject joDevice1 = env->GetObjectField(jOutput, fidObject);
				if (joDevice1) {
// get the class of the object parameter
	jclass cls0 = env->GetObjectClass(joDevice1);
				if (cls0) {
// get the field ID of the "intValue" field of this class
	jfieldID fidInt = env->GetFieldID(cls0, "intValue", "I");
				if (fidInt) {
// assign the (C++) int member to the Java object
	env->SetIntField(joDevice1, fidInt, dev3.dev1Value.intValue);
		iRc = 1; // success
                     }
                   }
                 }
               }
             }
          }
        }
      }
    }
  }

	return (iRc);

Listing 12: Listing 11 modified to use the Parse… functions defined in Listing 10

JNIEXPORT jint JNICALL Java_jni_1article_1_ClassAssign_assignClass
  (JNIEnv *env, jobject jo, jobject jOutput)
{
  int iRc = 0;

  // get the class of the object parameter
  jclass cls0 = env->GetObjectClass(jOutput);	
  if (cls0) {
    iRc = ParseIntField(env, cls0, jOutput, dev3.intValue,
            "intValue");
    if (iRc) {
      iRc = ParseLongField(env, cls0, jOutput,
              dev3.longValue, "longValue");
      if (iRc) {
        iRc = ParseStringField(env, cls0, jOutput,
                dev3.stringValue, "stringValue");
        if (iRc) {
          jobject joDevice1 = GetObjectReference(env, cls0,
                                jOutput, "dev1Value", 
                                "Ljni_article_/Device1;");
          if (joDevice1) {
            // get the class of the object parameter
            jclass cls0 = env->GetObjectClass(joDevice1);
            if (cls0) {
              iRc = ParseIntField(env, cls0, joDevice1,
                      dev3.dev1Value.intValue,
                      "intValue");
              iRc = 1; // success
             }
           }
         }
       }
     }
   }

  return (iRc);
}

 

All Rights Reserved
Copyright © 2002 SYS-CON Media
E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.