where's the bug in my little program?

I'm a fresh jni coder

I try to use native code to print the contents of integer array data in an converse object

after successfully compiling,I run it

Oops!

JVM crash buginfos fill in all my screen!!!

Help me find the bug,thank you

Test.java

publicclass Test{

publicstaticvoid main(String args[]){

Converse conv=new Converse();

conv.print();

}

}

Converse.java

publicclass Converse{

privateint[] data;

public Converse()

{

data =newint[10];

for (int i = 0; i < 10; i++)

{

data[i] = i;

}

}

publicnativevoid print();

static

{

System.loadLibrary("Converse");

}

}

#include"Converse.h"

#include <stdio.h>

JNIEXPORTvoid JNICALL Java_Converse_print(JNIEnv *env, jobject object)

{

jclass system_class;

jclass print_class;

jclass conv_class;

jclass string_class;

jfieldID out_ID;

jfieldID data_ID;

jmethodID println_ID;

jmethodID valueOf_ID;

jobject out_obj;

jarray data_array;

int length;

int *data;

int i;

system_class=(*env)->FindClass(env,"java/lang/System");

out_ID=(*env)->GetFieldID(env,system_class,"out","java/io/PrintStream");

out_obj=(*env)->GetObjectField(env,system_class,out_ID);

print_class=(*env)->GetObjectClass(env,out_obj);

println_ID=(*env)->GetStaticMethodID(env,print_class,"println","(Ljava/lang/String;)V");

conv_class=(*env)->GetObjectClass(env,object);

data_ID=(*env)->GetFieldID(env,conv_class,"data","[I");

data_array=(*env)->GetObjectField(env,object,data_ID);

length=(*env)->GetArrayLength(env,data_array);

data=(*env)->GetIntArrayElements(env,data_array,NULL);

string_class=(*env)->FindClass(env,"java/lang/String");

valueOf_ID=(*env)->GetStaticMethodID(env,string_class,"valueOf","(I)Ljava/lang/String;");

for(i=0;i<length;i++)

{

jstring datai=(*env)->CallStaticObjectMethod(env,string_class,valueOf_ID,data[i]);

(*env)->CallVoidMethod(env,out_obj,println_ID,datai);

}

}

[3759 byte] By [purebeggera] at [2007-10-3 10:49:36]
# 1

I think I forgot some comments

In the following jni codes,

I use

System.out.println(data);

to print the contents

so I need "java.lang.System" class

and then the "out" static field,

then "java.io.PrintStream"class because it's the type of "out" field

then we get the println(String) method needed to print

and then we use String.valueOf(int) static method to tranlate the data of int type to a short string

so we must get extra classid and methodid,

firstthe "java.lang.String" class

second the "valueOf(int)" method

then we translate it

finally we use the out.println() to print the result to the console...

JNIEXPORT void JNICALL Java_Converse_print(JNIEnv *env, jobject object)

{

jclass system_class;

jclass print_class;

jclass conv_class;

jclass string_class;

jfieldID out_ID;

jfieldID data_ID;

jmethodID println_ID;

jmethodID valueOf_ID;

jobject out_obj;

jarray data_array;

int length;

int *data;

int i;

system_class=(*env)->FindClass(env,"java/lang/System");

out_ID=(*env)->GetFieldID(env,system_class,"out","java/io/PrintStream");

out_obj=(*env)->GetObjectField(env,system_class,out_ID);

print_class=(*env)->GetObjectClass(env,out_obj);

println_ID=(*env)->GetStaticMethodID(env,print_class,"println","(Ljava/lang/String;)V");

conv_class=(*env)->GetObjectClass(env,object);

data_ID=(*env)->GetFieldID(env,conv_class,"data","[I");

data_array=(*env)->GetObjectField(env,object,data_ID);

length=(*env)->GetArrayLength(env,data_array);

data=(*env)->GetIntArrayElements(env,data_array,NULL);

string_class=(*env)->FindClass(env,"java/lang/String");

valueOf_ID=(*env)->GetStaticMethodID(env,string_class,"valueOf","(I)Ljava/lang/String;");

for(i=0;i<length;i++)

{

jstring datai=(*env)->CallStaticObjectMethod(env,string_class,valueOf_ID,data);

(*env)->CallVoidMethod(env,out_obj,println_ID,datai);

}

}

purebeggera at 2007-7-15 6:14:30 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 2

There are too many errors!

☆the instance field "out" of PrintStream is static and the signature of it is "Ljava/io/PrintStream;"

☆if you want to get the value of an instance field, you should pass a object parameter, not a class parameter, and to get value of a static instance field, you should use GetStaticObjectField with a class parameter.

☆the method "println" is not a static method of PrintStream, if you are not sure about the signature of field or method, you can use javap command to see it, like javap -s java.lang.System

☆the most import thing, you should check every return value and catch possible exception use ExceptionCheck()

☆you should delete local reference

☆recommend to read the JNI specification of sun.

the corrent codes look like:

#include "Converse.h"

#include <stdio.h>

#include <jni.h>

JNIEXPORT void JNICALL Java_Converse_print(JNIEnv *env, jobject object)

{

jclass system_class;

jclass print_class;

jclass conv_class;

jclass string_class;

jfieldID out_ID;

jfieldID data_ID;

jmethodID println_ID;

jmethodID valueOf_ID;

jobject out_obj;

jarray data_array;

int length;

int *data;

int i;

system_class = (*env)->FindClass(env, "java/lang/System");

if(system_class)

{

printf("1 OK\n");

out_ID = (*env)->GetStaticFieldID(env,system_class, "out", "Ljava/io/PrintStream;");

if(out_ID)

{

printf("2 OK\n");

out_obj = (*env)->GetStaticObjectField(env, system_class, out_ID);

print_class = (*env)->GetObjectClass(env, out_obj);

if(print_class)

{

printf("3 OK\n");

println_ID = (*env)->GetMethodID(env, print_class, "println", "(Ljava/lang/String;)V");

}

}

}

conv_class = (*env)->GetObjectClass(env, object);

if(conv_class)

{

printf("4 OK\n");

data_ID = (*env)->GetFieldID(env, conv_class, "data", "[I");

if(data_ID)

{

printf("5 OK\n");

data_array = (*env)->GetObjectField(env, object, data_ID);

if(data_array)

{

printf("6 OK\n");

length = (*env)->GetArrayLength(env, data_array);

data = (*env)->GetIntArrayElements(env, data_array, JNI_FALSE);

}

}

}

angelswingadama at 2007-7-15 6:14:30 > top of Java-index,Java HotSpot Virtual Machine,Specifications...