Im developing a plugin in eclipse which reads from a C++ file. I have const char * data in my C++ file and I have the following program to read into Java, but exception access violation error occurs while reading the string part in Java using Eclipse, while it works fine for long and integer. Can anybody point out what the mistake is?
JNIEXPORT void JNICALL Java_otf_OtfJni_otfjni_1set_1handler
(JNIEnv *env, jobject obj, jint type, jobject handler, jstring signature)
{
struct callback *cb;
jclass handler_class = (*env)->GetObjectClass(env, handler);
cb = (struct callback *)malloc(sizeof(struct callback));
printf("adding a handler\n");
cb->env = env;
cb->handler = (*env)->NewGlobalRef(env, handler);
cb->id = (*env)->GetMethodID(env, handler_class, "handle", "([Ljava/lang/Object;)V");
cb->signature_ref = (*env)->NewGlobalRef(env, signature);
cb->signature = (*env)->GetStringUTFChars(env, signature, NULL);
printf("Signature is: %s\n", cb->signature);
OTF_HandlerArray_setHandler(handlers, testhandler, type);
OTF_HandlerArray_setFirstHandlerArg(handlers, (void *)cb, type);
}
static int testhandler(void *arg, ...)
{
int i;
struct callback *cb = (struct callback *)arg;
JNIEnv *env = cb->env;
char *sig = cb->signature;
jint size = (jint) strlen(sig);
jint size1;
va_list arguments;
jobjectArray return_array;
jclass obj_class;
jbyteArray bytes;
jstring str;
obj_class = (*env)->FindClass(env, "java/lang/Object");
return_array = (*env)->NewObjectArray(env, size, obj_class, NULL);
va_start(arguments, arg);
for (i = 0; i < size; i++) {
jclass clazz;
jmethodID id;
jobject obj;
jobject encoding;
switch (sig[i]) {
case 'i': {
clazz = (*env)->FindClass(env, "java/lang/Integer");
id = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
obj = (*env)->NewObject(env, clazz, id, va_arg(arguments, uint32_t));
(*env)->SetObjectArrayElement(env, return_array, i, obj);
break;
}
case 'l': {
clazz = (*env)->FindClass(env, "java/lang/Long");
id = (*env)->GetMethodID(env, clazz, "<init>", "(J)V");
obj = (*env)->NewObject(env, clazz, id, va_arg(arguments, uint64_t));
(*env)->SetObjectArrayElement(env, return_array, i, obj);
break;
}
case 's': {
clazz = (*env)->FindClass(env, "java/lang/String");
size1 = (jint) strlen(va_arg(arguments, char *));
id = (*env)->GetMethodID(env, clazz, "<init>", "([BLjava/lang/String;)V");
encoding = (*env)->NewStringUTF(env, va_arg(arguments, uint64_t));
bytes = (*env)->NewByteArray(env, size1);
(*env)->SetByteArrayRegion(env, bytes, 0, size1, (jbyte *)(va_arg(arguments, char *)));
str = (jstring)(*env)->NewObject(env, clazz, id , bytes);
obj = (*env)->NewObject(env, clazz, id, str);
(*env)->SetObjectArrayElement(env, return_array, i, obj);
break;
}
default: {
printf("unknown signature char '%c'\n", sig[i]);
}
}
}
va_end(arguments);
(*env)->CallVoidMethod(env, cb->handler, cb->id, return_array);
return 0;
}
In Java, the testhandler is called as follows:
o.otfjni_set_handler(OtfJni.OTF_DEFFUNCTION_RECORD, newhandler, "iisii");
where 's' stands for the string part to be read from C++.