dimanche 7 mai 2023

How to safely share String between JNI thread and native thread

Situation:

I am working on a Java application where I need to pass a String variable to native code using JNI. The native code will store the reference of the String variable as a global variable and use it to access the value of the variable in an IPC context.

Problem:

The issue I am facing is that the memory location pointed by the global variable and the memory location referred when we access the information variable is different. This causes the program to crash as it tries to access invalid memory locations. It’s worth noting that the Java side is set by one thread, and the native side is accessed by another thread in an IPC context.

I have tried using the GetCharArrayElements() and ReleaseCharArrayElements() methods to access the character array of the string, but it didn’t help. I also tried using the GetStringUTFChars() and ReleaseStringUTFChars() methods, but they also didn’t solve the issue.

I added log lines to print the address of the pointer to the jstring before and after accessing the value of the information string, and it looks like the pointer to the jstring is changing between the Java and native threads.

Pseudo code:

Java side:

/ Create a string variable
String information = "This is the information string";

// Pass the string variable to native code using JNI
nativeMethod(information);

// Native method declaration
public static native void nativeMethod(String information);

Native side:

jstring globalInformation;

JNIEXPORT void JNICALL Java_className_nativeMethod(JNIEnv* env, jobject obj, jstring information) {
    globalInformation = static_cast<jstring>(env->NewGlobalRef(information));
    printf("Set globalInformation address: %p\n", (void*)&globalInformation);
}

void printInformation() {
    printf("Read globalInformation address: %p\n", (void*)&globalInformation);
    const char* informationValue = (*env)->GetStringUTFChars(env, globalInformation, NULL);
    if (informationValue == NULL) {
        printf("Unable to access information value\n");
    } else {
        printf("%s\n", informationValue);
        (*env)->ReleaseStringUTFChars(env, globalInformation, informationValue);
    }
}

Output:

Set globalInformation address: 0xb45deb78
Read globalInformation address: 0xb1f3e250
Unable to access information value

I would appreciate any guidance on how to resolve this issue.

Aucun commentaire:

Enregistrer un commentaire