Advanced JNI Problems on ARM

Miriam Busch kaffe@rufus.w3.org
Thu, 12 Jul 2001 14:43:20 +0200



--rwEMma7ioTxnRzrJ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

I'm having advanced JNI problems which only occur on StrongARM (Linux),
not on x86.

If native code calls Java via CallStaticObjectMethod and a Java object is
returned to the native side, it is somehow broken arriving at the native side.

A small test programm which reproduces the Bug is attached.

My KaffeVM is (almost) current CVS version, jit3, unix-pthreads.

Any idea what might be the problem?

Thank you,
      Miriam Busch

--rwEMma7ioTxnRzrJ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="JNISandwich.java"

package jni;

/** Java calls native code who calls Java code
 */
public class JNISandwich{

    static{
	System.loadLibrary("sandwich");
    }

    private String anything;
    public static int aStaticField = 1;
    public int aField = 2;

    public JNISandwich(){
	anything="Done";
	System.out.println("JNISandwich constructed.");
    }

    public String toString(){
	return "JNISandwich "+anything;
    }

    public void touch(){
	System.out.println("JNISandwich is touched.");
    }

    public static native JNISandwich getSandwichNative();

    // to be called via native
    public static JNISandwich createSandwich(){
	JNISandwich s =  new JNISandwich();
	System.out.println("Java is going to return "+s+" to the native side."); 
	return s;
    }

    public static void main(String[] argv){
	System.out.println("Before native call.");
	JNISandwich s = getSandwichNative();
	if (s!=null){
	    System.out.println("Got Sandwich: ");
	    System.out.println(s.toString()); 
	    System.out.println("If you see this, everything went fine.");
	} else{
	    System.out.println("getSandwichNative returned null.");
	}
    }

}

--rwEMma7ioTxnRzrJ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sandwich.c"

#include <jni.h>
#include <stdio.h>

JNIEXPORT jobject JNICALL
Java_jni_JNISandwich_getSandwichNative(JNIEnv* env, jclass clazz) {

  jmethodID  methodId;
  jobject obj;
  jfieldID fieldId, staticFieldId;

  methodId = (*env)->GetStaticMethodID(env, clazz, "createSandwich", "()Ljni/JNISandwich;");
  if (!methodId)
    printf("Method not found\n");

  printf("Performing native call...\n");
  obj = (*env)->CallStaticObjectMethod( env, 
					 clazz,
					 methodId
					 );
  printf("Native side: Touching the Java object: \n");

  staticFieldId = (*env)->GetStaticFieldID(env, clazz, "aStaticField", "I");
  if (!staticFieldId)
    printf("Field not found!\n");
  printf("Accessing static field: %d\n", (*env)->GetStaticIntField(env, clazz, staticFieldId));

  fieldId = (*env)->GetFieldID(env, clazz, "aField", "I");
  if (!fieldId)
    printf("Field not found!\n");
  printf("Accessing field: %d\n", (*env)->GetIntField(env, obj, fieldId));

  methodId = (*env)->GetMethodID(env, clazz, "touch", "()V");
  if (!methodId)
    printf("Method not found\n");

  (*env)->CallVoidMethod(env, obj, methodId);


  return obj;
}

--rwEMma7ioTxnRzrJ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="jnisandwich.out"

Output x86
----------
Before native call.
Performing native call...
JNISandwich constructed.
Java is going to return JNISandwich Done to the native side.
Native side: Touching the Java object:
Accessing static field: 1
Accessing field: 2
JNISandwich is touched.
Got Sandwich:
JNISandwich Done
If you see this, everything went fine.


Output ARM
----------
Before native call.
Performing native call...
JNISandwich constructed.
Java is going to return JNISandwich Done to the native side.
Native side: Touching the Java object:
Accessing static field: 1
Accessing field: 0
java.lang.NullPointerException
        at jni.JNISandwich.getSandwichNative(JNISandwich.java:native)
        at jni.JNISandwich.main(JNISandwich.java:39)

--rwEMma7ioTxnRzrJ--