- The jstring type represents strings in the Java virtual machine, and is different from the regular C string type (a pointer to characters, char *).
- We cannot use a jstring as a normal C string.
- We must use the appropriate JNI functions to convert jstring objects to C/C++ strings.
- The JNI supports conversion both to and from Unicode and UTF-8 strings.
- Unicode strings represent characters as 16-bit values, whereas UTF-8 strings use an encoding scheme that is upward compatible with 7-bit ASCII strings.
- UTF-8 strings act like NULL-terminated C strings.
Some JNI String Functions
- The GetStringUTFChars function is available through the JNIEnv interface pointer. It converts the jstring reference, typically represented by the Java virtual machine implementation as a Unicode sequence, into a C string represented in the UTF-8 format.
- The ReleaseStringUTFChars frees the memory used for native string resources. Therefore, calling this function will free the memory taken by the UTF-8 string. Failure to call ReleaseStringUTFChars would result in a memory leak.
- The NewStringUTF function constructs a new java.lang.String instance in the native method. The NewStringUTF function takes a C string with the UTF-8 format and constructs a java.lang.String instance. The newly constructed java.lang.String instance represents the same sequence of Unicode characters as the given UTF-8 C string.
To convert a jstring to a C-style string, you might write code like the following:
1 2 3 4 5 6 7 8 9 | JNIEXPORT void JNICALLJava_MyJavaClass_printName(JNIEnv *env, jobject obj, jstring name) { const char *str= (*env)->GetStringUTFChars(env,name,0); printf(“%s”, str); //need to release this string when done with it in //order to avoid memory leak (*env)->ReleaseStringUTFChars(env, name, str); } |
To convert a C-style string to a jstring , you can use the (*env)->NewStringUTF() function to create a new jstring from a C-style string. For example, a C function that needs to return a Java string could contain the following code:
1 2 3 4 | JNIEXPORT jstring JNICALLJava_MyJavaClass_getName(JNIEnv *env, jobject obj) { return (*env)->NewStringUTF(env, “My String”); } |
JNI String functions:
JNI Function | Description |
GetStringChars ReleaseStringChars |
Obtains or releases a pointer to the contents of a string in Unicode format. May return a copy of the string. |
GetStringUTFChars ReleaseStringUTFChars |
Obtains or releases a pointer to the contents of a string in UTF-8 format. |
GetStringLength | Returns the number of Unicode characters in the string. |
GetStringUTFLength | Returns the number of bytes needed to represent a string in the UTF-8 format. |
NewString | Creates a java.lang.String instance that contains the same sequence of characters as the given Unicode C string. |
NewStringUTF | Creates a java.lang.String instance that contains the same sequence of characters as the given UTF-8 encoded C string. |
GetStringCritical ReleaseStringCritical |
Obtains a pointer to the contents of a string in Unicode format. May return a copy of the string. Native code must not block between a pair of Get/ReleaseStringCritical calls. |
GetStringRegion SetStringRegion |
Copies the contents of a string to or from a preallocated C buffer in the Unicode format. |
GetStringUTFRegion SetStringUTFRegion |
Copies the content of a string to or from a preallocated C buffer in the UTF-8 format. |
JNI String Example:
Let’s write a JNI application that passes a prompt message to a native method, which method prints the prompt message, reads the user input and sends it back to the application.
The Java code will be(NativePrompt.java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class NativePrompt { private native String getInput(String prompt); //native method static //static initializer code { System.loadLibrary("NativePrompt"); } public static void main(String[] args) { NativePrompt NP = new NativePrompt(); String sName = NP.getInput("Enter your name: "); System.out.println("Hello " + sName); } } |
Compile NativePrompt.java (javac NativePrompt.java) and generate hedder file(javah -jni NativePrompt).
The generated with javah header file NativePrompt.h will be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* DO NOT EDIT THIS FILE - it is machine generated */ #include "jni.h" /* Header for class NativePrompt */ #ifndef _Included_NativePrompt #define _Included_NativePrompt #ifdef __cplusplus extern "C" { #endif /* * Class: NativePrompt * Method: getInput * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_NativePrompt_getInput (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif |
The C++ implementation file NativePrompt.cpp will be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include "NativePrompt.h" #include "jni.h" #include "string" #include "iostream" #include "vector" using namespace std; /* * Class: NativePrompt * Method: getInput * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_NativePrompt_getInput (JNIEnv *env, jobject obj, jstring prompt){ string sEntry; const char *str; str = env->GetStringUTFChars(prompt, NULL); if (str == NULL) { return env->NewStringUTF(""); } else{ cout << str; //Frees native string resources env->ReleaseStringUTFChars(prompt, str); //reads n-consecutive words from the //keyboard and store them in string getline(cin, sEntry); return env->NewStringUTF(sEntry.c_str()); } } |
Run the program (java NativePrompt) and verify the output.
When I try to compile its generate error regarding #include “vector” ??
1 JNIEXPORT void JNICALLJava_MyJavaClass_printName(…
I think you need a space here
1 JNIEXPORT void JNICALL Java_MyJavaClass_printName(…
No matter if some one searches for his essential thing, so
he/she wishes to be available that in detail, so that thing is maintained over
here.
Links in the article are broken.
How would one hand C++ string vectors? If i had to pass a C++ string vector, instead of a C++ string to java , how do we do this using the jni object?