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. One more important piece of information is that, all the processes read from the same memory pointer (only one process sets the global variable for itself not for others to read it). Not sure how different processes are being allowed to read from the same memory address.
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:
// Global Information Variable (static/non-static both doesnt help)
char * globalInformation;
JNIEXPORT void JNICALL Java_className_nativeMethod(JNIEnv* env, jobject obj, jstring information) {
ALOGI("Pointer to magicdata is %p\n", &globalInformation);
// Get a pointer to the string representation of the information string
const char* temp = env->GetStringUTFChars(information, nullptr);
// Allocate memory for the globalInformation char array
globalInformation = new char[strlen(temp) + 1];
// Copy the information string into globalInformation
strcpy(globalInformation, temp);
// Release the informationChars pointer
env->ReleaseStringUTFChars(information, temp);
}
void printInformation() {
ALOGI("Read globalInformation address: %p\n", (void*)&globalInformation);
if (globalInformation == NULL) {
printf("Unable to access information value\n");
} else {
printf("%s\n", globalInformation);
}
}
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.
Some more information why I mention about IPC context: The above piece of code will serve as a framework for different processes in my system. From the java side, fwk will set some value in native jni file. The value set will be read in native context when the systems server will initiate an IPC call to all the processes to get their respective the data. So different processes should have its own copy of the variable.