trouble handling java objects from inside java methods via C

B

badduck

I am trying to use the invocation API to load the JVM from C. Java
method calls from C seem to work only when the objects being manipuated
within Java are simple data-types like "int". The moment I try to use
int[] I always get a return value of "0" from my method calls.. Also,
the System.outt.printlnl() doesn't execute if I have the first
statement as "int retval = this.i[this.k++];". If I put the printtln()
before this statement, I am able to see the output of the println. It
doesn't crash the JVM but the "state" in the Java object doesn't update
either! I've even tested this code on two separate machines. What am I
doing wrong?

----My Java Code----


public class Prog {
public int[] i;
public int k;

public void Prog() {
this.i = new int[10];
for(int j=0;j<10;j++) {
this.i[j]=j;
}
this.k=0;
}

public int foolMain() {
int retval = this.i[this.k++];
System.out.println("this is a silly printtln.....");
return retval;
}
}



-----My C Code----


#include <jni.h>
#include "./Prog.h"

void main() {
JNIEnv *env;
JavaVM *jvm;

JavaVMInitArgs vm_args;
JavaVMOption *options;
long result;
int i,j;

jclass cls;
jmethodID mid;
jstring jstr;
jobject obj;
jclass stringClass;
jobjectArray args;

options = (void *)malloc(sizeof(JavaVMOption));
/* load the vm_arg options... */
options[0].optionString="-Djava.class.path=.";

vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;

/* Create the Java VM */
result = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);


if (result = JNI_ERR) {
fprintf(stderr, "Can't create Java VM inside 1.2\n");
exit(1);
}

/*-------------here is where the core of the calls are handledd */

/* get the required class.. */
cls = (*env)->FindClass(env, "Prog");
if (cls == NULL) {
goto destroy;
}
printf("here-1\n");

/* get a handle to the constructor method */
mid = (*env)->GetMethodID(env, cls, "<init>","()V");
if (mid == NULL) {
goto destroy;
}
printf("here-2\n");

/* create an object of the class */
obj = (*env)->NewObject(env, cls, mid, "");
if (obj == NULL) {
goto destroy;
}
printf("here-3\n");

/* get a handle to the method */
mid = (*env)->GetMethodID(env, cls, "foolMain","()I");
if (mid == NULL) {
goto destroy;
}
printf("here-4\n");

/* call the method a bunch of times... */
for(i=0;i<10;i++) {
j = (*env)->CallIntMethod(env, obj, mid, "");
printf("j=%d\n",j);
}

printf("here-5\n");
destroy:
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}

/* destroy the VM */
(*jvm)->DestroyJavaVM(jvm);
}
 
D

Denis

Problem is in your Java code. Replace "public void Prog() {" with
"public Prog() {". In your original code, you define a void method
named "Prog", instead of difnining a constructor. So, default
constructor is used, fields "i" and "k" are not initialized. Guess what
happens? Right, NullPointerException is thrown.

Besides that, there is a misprint in your C code: add the second "=" to
this line: "if (result = JNI_ERR) {".

A pair of tips:
1. Before calling any Java code from C, write a java main() and invoke
your Java code from it. This way, you check that Java code is OK, and
then you can concentrate on C=>Java invocation.

2. Always check for exceptions after each JNI call. In your C code,
there is only one exception check, and it happens after ten calls to
"foolMain". This is not good. You should add check into each loop
iteration.

Hope this helps,
Denis.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,701
Latest member
XavierQ83

Latest Threads

Top