Reputation: 1178
Didn't find similar question, so opening a new one.
I'm trying to pass a Java object to JNI layer in my program and extract Java String field in it. The extracted field is set in the C struct.
I'm seeing a strange behavior. I'm able to extract the required fields successfully and memcpy it in the struct field. But when my utility function returns, the field set in struct get corrupted. I suspected a memory leak and rechecked, but nothing looks suspicious (I'm not doing much dynamic memory stuff code..just one malloc and free.)
Here goes the code:
Header File:
typedef struct Job {
char* job_id;
} Job;
C File:
JNIEXPORT jint JNICALL Java_com.test.JobHandler__1submitJob(
JNIEnv *env, jobject this, jobject job) {
current_job = (Job *) malloc(sizeof(Job));
convert_job(env, job, current_job);
free(current_job);
}
void convert_job(JNIEnv *env, jobject javajob, Job *job) {
jclass cls = (*env)->GetObjectClass(env, javajob);
getVoidStringField(env, cls, javajob, job->job_id, "getJob_id");
//job->job_id gets corrupted here
}
void getVoidStringField(JNIEnv *env, jclass cls, jobject obj, char *jobStr, char *methodName) {
jmethodID mid = (*env)->GetMethodID(env, cls, methodName, "()Ljava/lang/String;");
jobject js = (*env)->CallObjectMethod(env, obj, mid);
const char *str = (*env)->GetStringUTFChars(env, js, 0);
int len = (*env)->GetStringUTFLength(env, js);
jobStr = (char*) malloc(len);
memcpy(jobStr, str, len);
jobStr[len] = '\0';
(*env)->ReleaseStringUTFChars(env, js, str);
//jobStr is fine till here.
}
I removed other stuff from my code and reduced to above version to simply debugging, still same issue.
If I pass modify getVoidStringField(...) a bit to accept Job object and then work on job->job_id, it works fine.
Curious to know. I doubt it has something to do with JNI.
Upvotes: 0
Views: 313
Reputation: 5034
Couple of things :
When you pass in job->job_id
, you are passing in the VALUE of that pointer, not the pointer itself. That means when you do the jobStr = (char*) malloc(len);
, you are not changing job->job_id
, but just that function's local variable.
So, what you need to pass in is &(job->job_id)
, and the parameter should be char **jobstr
Your malloc
would then be (not forgetting to allow for the null terminator):
*jobStr = (char*) malloc(len +1);
and, of course, the following statements should refer to *jobstr
Upvotes: 2