In order to minimize JNI marshalling, I want to store some strings on the C++ side as static variables via a setup method, use them in a different JNI method call rather than passing them each time, and then release the strings later with yet another JNI method call. For example,
C++ code:
static const char *stringValue1;
extern "C" JNIEXPORT void JNICALL
Java_mypackage_myclass_setValue1(JNIEnv* env, jclass jobj, jstring javaString) {
jboolean isCopy;
if(!env->IsSameObject(javaString, NULL)) {
const char *stringValue1= env->GetStringUTFChars(javaString, &isCopy);
}
}
extern "C" JNIEXPORT void JNICALL
Java_mypackage_myclass_execute(JNIEnv* env, jclass jobj, jint javaInt) {
// ... use the stringValue1 static variable - otherwise, this method would need another jstring argument.
}
extern "C" JNIEXPORT void JNICALL
Java_mypackage_myclass_releaseValue1(JNIEnv* env, jclass jobj, jstring javaString) {
if(stringValue1 != 0) {
env->ReleaseStringUTFChars(javaString, stringValue1);
}
}
Java code:
myclass.setValue1("hello")
for(int i = 0; i < 10; i++) {
myclass.execute(i); // execute needs the "hello" string, but we try to store it in the C++ side rather than pass it in each loop iteration.
}
myclass.releaseValue1("hello");
Is this a valid JNI pattern? In all of the JNI examples I have seen, both calls to GetStringUTFChars
and ReleaseStringUTFChars
occur in the same method/scope. In this example, they do not occur in the same scope, and the jstring argument could possibly not be the same Java String either.
Yes, the documentation states
This array is valid until it is released by ReleaseStringUTFChars().
This is corroborated by the implementation in Hotspot, which just allocates off-heap memory for a copy.