JNI Part 4: JNI Strings

  1. The jstring type represents strings in the Java virtual machine, and is different from the regular C string type (a pointer to characters, char *).
  2. We cannot use a jstring as a normal C string.
  3. We must use the appropriate JNI functions to convert jstring objects to C/C++ strings.
  4. The JNI supports conversion both to and from Unicode and UTF-8 strings.
  5. 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.
  6. UTF-8 strings act like NULL-terminated C strings.

Some JNI String Functions

  1. 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.
  2. 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.
  3. 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.

Start exploring endless computing possibilities with your own Raspberry Pi computer and accessories. Perfect for beginners and students.

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.


5 Responses to “JNI Part 4: JNI Strings”

  1. dhardy

    Sorry, but Unicode is a standard, not an encoding. Do you mean UTF-16 when you say Unicode? It’s also worth pointing out that even in UTF-16 glyphs may be encoded using more than one 2-byte “element”.

    Reply
  2. patel

    When I try to compile its generate error regarding #include “vector” ??

    Reply
  3. 1 JNIEXPORT void JNICALLJava_MyJavaClass_printName(…

    I think you need a space here

    1 JNIEXPORT void JNICALL Java_MyJavaClass_printName(…

    Reply
  4. 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?

    Reply

Leave a Reply