fix DeleteGlobalRef missing argument for IdentityHashMap.put
[cacao.git] / src / native / jni.c
index bd32d530682c78797d55ef4e7278fd4da91c810b..651649e9ff2e57833775844a1ddedfcc5f89b220 100644 (file)
             Martin Platter
             Christian Thalinger
 
-   $Id: jni.c 2427 2005-05-01 12:27:54Z jowenn $
+   $Id: jni.c 3095 2005-07-21 13:51:36Z motse $
 
 */
 
 
+#include <assert.h>
 #include <string.h>
 
 #include "config.h"
 #include "native/include/java_lang_VMClass.h"
 #include "native/include/java_lang_VMClassLoader.h"
 
+#if defined(ENABLE_JVMTI)
+# include "native/jvmti/jvmti.h"
+#endif
+
 #if defined(USE_THREADS)
 # if defined(NATIVE_THREADS)
 #  include "threads/native/threads.h"
 #include "vm/jit/jit.h"
 #include "vm/statistics.h"
 
+
 /* XXX TWISTI hack: define it extern so they can be found in this file */
+
 extern const struct JNIInvokeInterface JNI_JavaVMTable;
 extern struct JNINativeInterface JNI_JNIEnvTable;
 
 /* pointers to VM and the environment needed by GetJavaVM and GetEnv */
+
 static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable;
-static void* ptr_env = (void*) &JNI_JNIEnvTable;
+void* ptr_env = (void*) &JNI_JNIEnvTable;
 
 
 #define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
@@ -115,193 +123,224 @@ static jmethodID removemid = NULL;
 
 #define setField(obj,typ,var,val) *((typ*) ((long int) obj + (long int) var->offset))=val;  
 #define getField(obj,typ,var)     *((typ*) ((long int) obj + (long int) var->offset))
-#define setfield_critical(clazz,obj,name,sig,jdatatype,val) setField(obj,jdatatype,getFieldID_critical(env,clazz,name,sig),val); 
+#define setfield_critical(clazz,obj,name,sig,jdatatype,val) \
+    setField(obj, jdatatype, getFieldID_critical(env,clazz,name,sig), val);
+
 
-static void fill_callblock(void *obj, methoddesc *descr, jni_callblock blk[], va_list data, int rettype)
+static void fill_callblock_from_vargs(void *obj, methoddesc *descr,
+                                                                         jni_callblock blk[], va_list data,
+                                                                         s4 rettype)
 {
-    int cnt;
-    u4 dummy;
-       int i;
-       typedesc *paramtype;
+       typedesc *paramtypes;
+       s4        i;
+
+       paramtypes = descr->paramtypes;
+
+       /* if method is non-static fill first block and skip `this' pointer */
+
+       i = 0;
 
        if (obj) {
-               /* the this pointer */
+               /* the `this' pointer */
                blk[0].itemtype = TYPE_ADR;
                blk[0].item = PTR_TO_ITEM(obj);
-               cnt = 1;
+
+               paramtypes++;
+               i++;
        } 
-       else 
-               cnt = 0;
 
-       paramtype = descr->paramtypes;
-       for (i=0; i<descr->paramcount; ++i,++cnt,++paramtype) {
-               switch (paramtype->decltype) {
-                       /* primitive types */
+       for (; i < descr->paramcount; i++, paramtypes++) {
+               switch (paramtypes->decltype) {
+               /* primitive types */
                case PRIMITIVETYPE_BYTE:
                case PRIMITIVETYPE_CHAR:
                case PRIMITIVETYPE_SHORT: 
                case PRIMITIVETYPE_BOOLEAN: 
-                       blk[cnt].itemtype = TYPE_INT;
-                       blk[cnt].item = (u8) va_arg(data, int);
+                       blk[i].itemtype = TYPE_INT;
+                       blk[i].item = (s8) va_arg(data, s4);
                        break;
 
                case PRIMITIVETYPE_INT:
-                       blk[cnt].itemtype = TYPE_INT;
-                       dummy = va_arg(data, u4);
-                       /*printf("fill_callblock: pos:%d, value:%d\n",cnt,dummy);*/
-                       blk[cnt].item = (u8) dummy;
+                       blk[i].itemtype = TYPE_INT;
+                       blk[i].item = (s8) va_arg(data, s4);
                        break;
 
                case PRIMITIVETYPE_LONG:
-                       blk[cnt].itemtype = TYPE_LNG;
-                       blk[cnt].item = (u8) va_arg(data, jlong);
+                       blk[i].itemtype = TYPE_LNG;
+                       blk[i].item = (s8) va_arg(data, s8);
                        break;
 
                case PRIMITIVETYPE_FLOAT:
-                       blk[cnt].itemtype = TYPE_FLT;
-                       *((jfloat *) (&blk[cnt].item)) = (jfloat) va_arg(data, jdouble);
+                       blk[i].itemtype = TYPE_FLT;
+#if defined(__ALPHA__)
+                       /* this keeps the assembler function much simpler */
+
+                       *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
+#else
+                       *((jfloat *) (&blk[i].item)) = (jfloat) va_arg(data, jdouble);
+#endif
                        break;
 
                case PRIMITIVETYPE_DOUBLE:
-                       blk[cnt].itemtype = TYPE_DBL;
-                       *((jdouble *) (&blk[cnt].item)) = (jdouble) va_arg(data, jdouble);
+                       blk[i].itemtype = TYPE_DBL;
+                       *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
                        break;
 
                case TYPE_ADR: 
-                       blk[cnt].itemtype = TYPE_ADR;
-                       blk[cnt].item = PTR_TO_ITEM(va_arg(data, void*));
+                       blk[i].itemtype = TYPE_ADR;
+                       blk[i].item = PTR_TO_ITEM(va_arg(data, void*));
                        break;
                }
        }
 
-       /*the standard doesn't say anything about return value checking, but it appears to be usefull*/
+       /* The standard doesn't say anything about return value checking, but it  */
+       /* appears to be useful.                                                  */
+
        if (rettype != descr->returntype.decltype)
                log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
 }
 
+
 /* XXX it could be considered if we should do typechecking here in the future */
-static bool fill_callblock_objA(void *obj, methoddesc *descr, jni_callblock blk[], java_objectarray* params,
-                                                               int *rettype)
+
+static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
+                                                                                       jni_callblock blk[],
+                                                                                       java_objectarray *params)
 {
-    jobject param;
-    int cnt;
-    int cnts;
-       typedesc *paramtype;
+    jobject    param;
+       s4         paramcount;
+       typedesc  *paramtypes;
+       classinfo *c;
+    s4         i;
+       s4         j;
+
+       paramcount = descr->paramcount;
+       paramtypes = descr->paramtypes;
+
+       /* if method is non-static fill first block and skip `this' pointer */
+
+       i = 0;
 
-    /* determine number of parameters */
        if (obj) {
                /* this pointer */
                blk[0].itemtype = TYPE_ADR;
                blk[0].item = PTR_TO_ITEM(obj);
-               cnt=1;
-       } else {
-               cnt = 0;
+
+               paramtypes++;
+               paramcount--;
+               i++;
        }
 
-       paramtype = descr->paramtypes;
-       for (cnts=0; cnts < descr->paramcount; ++cnts,++cnt,++paramtype) {
-               switch (paramtype->type) {
-                       /* primitive types */
-                       case TYPE_INT:
-                       case TYPE_LONG:
-                       case TYPE_FLOAT:
-                       case TYPE_DOUBLE:
-                       
-                               param = params->data[cnts];
-                               if (!param)
+       for (j = 0; j < paramcount; i++, j++, paramtypes++) {
+               switch (paramtypes->type) {
+               /* primitive types */
+               case TYPE_INT:
+               case TYPE_LONG:
+               case TYPE_FLOAT:
+               case TYPE_DOUBLE:
+                       param = params->data[j];
+                       if (!param)
+                               goto illegal_arg;
+
+                       /* internally used data type */
+                       blk[i].itemtype = paramtypes->type;
+
+                       /* convert the value according to its declared type */
+
+                       c = param->vftbl->class;
+
+                       switch (paramtypes->decltype) {
+                       case PRIMITIVETYPE_BOOLEAN:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Boolean *) param)->value;
+                               else
                                        goto illegal_arg;
+                               break;
 
-                               /* internally used data type */
-                               blk[cnt].itemtype = paramtype->type;
-
-                               /* convert the value according to its declared type */
-                               switch (paramtype->decltype) {
-                                               case PRIMITIVETYPE_BOOLEAN:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Boolean *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               case PRIMITIVETYPE_BYTE:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               case PRIMITIVETYPE_CHAR:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Character *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               case PRIMITIVETYPE_SHORT:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
-                                                       else if (param->vftbl->class == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               case PRIMITIVETYPE_INT:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
-                                                       else if (param->vftbl->class == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
-                                                       else if (param->vftbl->class == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               case PRIMITIVETYPE_LONG:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Long *) param)->value;
-                                                       else if (param->vftbl->class == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
-                                                       else if (param->vftbl->class == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
-                                                       else if (param->vftbl->class == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               case PRIMITIVETYPE_FLOAT:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               case PRIMITIVETYPE_DOUBLE:
-                                                       if (param->vftbl->class == primitivetype_table[paramtype->decltype].class_wrap)
-                                                               *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
-                                                       else if (param->vftbl->class == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
-                                                               *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value;
-                                                       else
-                                                               goto illegal_arg;
-                                                       break;
-                                               default:
-                                                       goto illegal_arg;
-                               } /* end declared type switch */
+                       case PRIMITIVETYPE_BYTE:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                               else
+                                       goto illegal_arg;
                                break;
+
+                       case PRIMITIVETYPE_CHAR:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Character *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_SHORT:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_INT:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_LONG:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Long *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
+                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_FLOAT:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_DOUBLE:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       *((jdouble *) (&blk[i].item)) = (jdouble) ((java_lang_Float *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
+                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       default:
+                               goto illegal_arg;
+                       } /* end declared type switch */
+                       break;
                
                        case TYPE_ADDRESS:
-                               {
-                                       classinfo *cls;
-                                  
-                                       if (!resolve_class_from_typedesc(paramtype,true,&cls))
-                                               return false; /* exception */
-                                       if (params->data[cnts] != 0) {
-                                               if (paramtype->arraydim > 0) {
-                                                       if (!builtin_arrayinstanceof(params->data[cnts], cls->vftbl))
-                                                               goto illegal_arg;
-                                               }
-                                               else {
-                                                       if (!builtin_instanceof(params->data[cnts], cls))
-                                                               goto illegal_arg;
-                                               }
+                               if (!resolve_class_from_typedesc(paramtypes, true, true, &c))
+                                       return false;
+
+                               if (params->data[j] != 0) {
+                                       if (paramtypes->arraydim > 0) {
+                                               if (!builtin_arrayinstanceof(params->data[j], c->vftbl))
+                                                       goto illegal_arg;
+
+                                       } else {
+                                               if (!builtin_instanceof(params->data[j], c))
+                                                       goto illegal_arg;
                                        }
-                                       blk[cnt].itemtype = TYPE_ADR;
-                                       blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
                                }
+                               blk[i].itemtype = TYPE_ADR;
+                               blk[i].item = PTR_TO_ITEM(params->data[j]);
                                break;                  
 
                        default:
@@ -310,8 +349,9 @@ static bool fill_callblock_objA(void *obj, methoddesc *descr, jni_callblock blk[
 
        } /* end param loop */
 
-       if (rettype)
-               *rettype = descr->returntype.decltype;
+/*     if (rettype) */
+/*             *rettype = descr->returntype.decltype; */
+
        return true;
 
 illegal_arg:
@@ -320,20 +360,27 @@ illegal_arg:
 }
 
 
-static jmethodID get_virtual(jobject obj,jmethodID methodID) {
-       if (obj->vftbl->class==methodID->class) return methodID;
-       return class_resolvemethod (obj->vftbl->class, methodID->name, methodID->descriptor);
+static jmethodID get_virtual(jobject obj, jmethodID methodID)
+{
+       if (obj->vftbl->class == methodID->class)
+               return methodID;
+
+       return class_resolvemethod(obj->vftbl->class, methodID->name,
+                                                          methodID->descriptor);
 }
 
 
-static jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) {
-       if (clazz==methodID->class) return methodID;
-/*class_resolvemethod -> classfindmethod? (JOWENN)*/
-       return class_resolvemethod (clazz, methodID->name, methodID->descriptor);
+static jmethodID get_nonvirtual(jclass clazz, jmethodID methodID)
+{
+       if (clazz == methodID->class)
+               return methodID;
+
+       /* class_resolvemethod -> classfindmethod? (JOWENN) */
+       return class_resolvemethod(clazz, methodID->name, methodID->descriptor);
 }
 
 
-static jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
+static jobject callObjectMethod(jobject obj, jmethodID methodID, va_list args)
 {      
        int argcount;
        jni_callblock *blk;
@@ -370,7 +417,7 @@ static jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
 
        blk = MNEW(jni_callblock, /*4 */argcount+2);
 
-       fill_callblock(obj, methodID->parseddesc, blk, args, TYPE_ADR);
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_ADR);
        /*      printf("parameter: obj: %p",blk[0].item); */
        STATS(jnicallXmethodnvokation();)
        ret = asm_calljavafunction2(methodID,
@@ -432,7 +479,7 @@ static jint callIntegerMethod(jobject obj, jmethodID methodID, int retType, va_l
 
        blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
-       fill_callblock(obj, methodID->parseddesc, blk, args, retType);
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType);
 
        /*      printf("parameter: obj: %p",blk[0].item); */
        STATS(jnicallXmethodnvokation();)
@@ -493,7 +540,7 @@ static jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
 
        blk = MNEW(jni_callblock,/* 4 */argcount+2);
 
-       fill_callblock(obj, methodID->parseddesc, blk, args, TYPE_LNG);
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_LNG);
 
        /*      printf("parameter: obj: %p",blk[0].item); */
        STATS(jnicallXmethodnvokation();)
@@ -537,7 +584,7 @@ static jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,int
 
        blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
-       fill_callblock(obj, methodID->parseddesc, blk, args, retType);
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType);
 
        /*      printf("parameter: obj: %p",blk[0].item); */
        STATS(jnicallXmethodnvokation();)
@@ -591,9 +638,11 @@ static fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
 
 jint GetVersion(JNIEnv *env)
 {
-       /* GNU classpath currently supports JNI 1.2 */
        STATS(jniinvokation();)
-       return JNI_VERSION_1_2;
+
+       /* just say we support JNI 1.4 */
+
+       return JNI_VERSION_1_4;
 }
 
 
@@ -607,19 +656,22 @@ jint GetVersion(JNIEnv *env)
 
 *******************************************************************************/
 
-jclass DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen)
+jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
+                                  const jbyte *buf, jsize bufLen)
 {
-       jclass c;
+       java_lang_ClassLoader *cl;
+       java_lang_String      *s;
+       java_bytearray        *ba;
+       jclass                 c;
+
        STATS(jniinvokation();)
 
-       c = (jclass) Java_java_lang_VMClassLoader_defineClass(env,
-                                                                                                                 NULL,
-                                                                                                                 (java_lang_ClassLoader *) loader,
-                                                                                                                 javastring_new_char(name),
-                                                                                                                 (java_bytearray *) buf,
-                                                                                                                 0,
-                                                                                                                 bufLen,
-                                                                                                                 NULL);
+       cl = (java_lang_ClassLoader *) loader;
+       s = javastring_new_char(name);
+       ba = (java_bytearray *) buf;
+
+       c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
+                                                                                                                 0, bufLen, NULL);
 
        return c;
 }
@@ -635,12 +687,28 @@ jclass DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *b
 
 jclass FindClass(JNIEnv *env, const char *name)
 {
-       classinfo *c = NULL;  
+       utf               *u;
+       classinfo         *c;
+       java_objectheader *cl;
+
        STATS(jniinvokation();)
-  
-       if (!load_class_bootstrap(utf_new_char_classname((char *) name),&c) || !link_class(c)) {
+
+       u = utf_new_char_classname((char *) name);
+
+       /* check stacktrace for classloader, if one found use it, otherwise use */
+       /* the system classloader */
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__)
+       cl = cacao_currentClassLoader();
+#else
+       cl = NULL;
+#endif
+
+       if (!(c = load_class_from_classloader(u, cl)))
+               return NULL;
+
+       if (!link_class(c))
                return NULL;
-       }
 
        use_class_as_object(c);
 
@@ -648,45 +716,50 @@ jclass FindClass(JNIEnv *env, const char *name)
 }
   
 
-/*******************************************************************************
+/* FromReflectedMethod *********************************************************
 
-       converts java.lang.reflect.Method or 
-       java.lang.reflect.Constructor object to a method ID  
+   Converts java.lang.reflect.Method or java.lang.reflect.Constructor
+   object to a method ID.
   
 *******************************************************************************/
   
-jmethodID FromReflectedMethod(JNIEnv* env, jobject method_or_constr)
+jmethodID FromReflectedMethod(JNIEnv *env, jobject method)
 {
-        struct methodinfo *mi;
-        classinfo *c;
-       s4 slot;
+       methodinfo *mi;
+       classinfo  *c;
+       s4          slot;
 
        STATS(jniinvokation();)
 
-       if (method_or_constr==0) return 0;
+       if (method == NULL)
+               return NULL;
        
-       if (builtin_instanceof(method_or_constr, class_java_lang_reflect_Method))
-       {
-               java_lang_reflect_Method *rm=(java_lang_reflect_Method*) method_or_constr;
-               slot=rm->slot;
-               c= (classinfo *) (rm->declaringClass);  
-       }
-       else if (builtin_instanceof(method_or_constr, class_java_lang_reflect_Constructor))
-       {
-               java_lang_reflect_Constructor *rc=(java_lang_reflect_Constructor*) method_or_constr;
-               slot=rc->slot;
-               c= (classinfo*) (rc->clazz);
+       if (builtin_instanceof(method, class_java_lang_reflect_Method)) {
+               java_lang_reflect_Method *rm;
+
+               rm = (java_lang_reflect_Method *) method;
+               c = (classinfo *) (rm->declaringClass);
+               slot = rm->slot;
+
+       } else if (builtin_instanceof(method, class_java_lang_reflect_Constructor)) {
+               java_lang_reflect_Constructor *rc;
+
+               rc = (java_lang_reflect_Constructor *) method;
+               c = (classinfo *) (rc->clazz);
+               slot = rc->slot;
+
+       } else
+               return NULL;
+
+       if ((slot < 0) || (slot >= c->methodscount)) {
+               /* this usually means a severe internal cacao error or somebody
+                  tempered around with the reflected method */
+               log_text("error illegal slot for method in class(FromReflectedMethod)");
+               assert(0);
        }
-       else return 0;
 
+       mi = &(c->methods[slot]);
 
-       printf ("slot %d,methodscount %d\n",slot,c->methodscount);
-        if ((slot < 0) || (slot >= c->methodscount)) {
-               /*this usually means a severe internal cacao error or somebody
-               tempered around with the reflected method*/
-                panic("error illegal slot for method in class(FromReflectedMethod)");
-        }
-        mi = &(c->methods[slot]);
        return mi;
 }
 
@@ -898,9 +971,9 @@ jobject PopLocalFrame(JNIEnv* env, jobject result)
 
 void DeleteLocalRef(JNIEnv *env, jobject localRef)
 {
-       log_text("JNI-Call: DeleteLocalRef: IMPLEMENT ME!");
        STATS(jniinvokation();)
 
+       log_text("JNI-Call: DeleteLocalRef: IMPLEMENT ME!");
 }
 
 
@@ -1102,7 +1175,8 @@ jfieldID FromReflectedField(JNIEnv* env, jobject field)
        if ( (f->slot<0) || (f->slot>=c->fieldscount)) {
                /*this usually means a severe internal cacao error or somebody
                tempered around with the reflected method*/
-                panic("error illegal slot for field in class(FromReflectedField)");
+               log_text("error illegal slot for field in class(FromReflectedField)");
+               assert(0);
        }
        fid=&(c->fields[f->slot]);
        return fid;
@@ -1144,7 +1218,7 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *s
                *exceptionptr =
                        new_exception_message(string_java_lang_NoSuchMethodError, name);
 
-               return 0;
+               return NULL;
        }
 
        return m;
@@ -1802,6 +1876,7 @@ void CallNonvirtualVoidMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodI
 jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) 
 {
        jfieldID f;
+
        STATS(jniinvokation();)
 
 /*     log_text("========================= searching for:");
@@ -1836,7 +1911,8 @@ jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig)
        log_text("sig:");
        log_text(sig);
 
-       panic("setfield_critical failed"); 
+       log_text("setfield_critical failed");
+          assert(0);
     }
     return id;
 }
@@ -2586,6 +2662,8 @@ void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble v
 }
 
 
+/* String Operations **********************************************************/
+
 /* NewString *******************************************************************
 
    Create new java.lang.String object from an array of Unicode
@@ -2598,6 +2676,7 @@ jstring NewString(JNIEnv *env, const jchar *buf, jsize len)
        java_lang_String *s;
        java_chararray   *a;
        u4                i;
+
        STATS(jniinvokation();)
        
        s = (java_lang_String *) builtin_new(class_java_lang_String);
@@ -2619,66 +2698,104 @@ jstring NewString(JNIEnv *env, const jchar *buf, jsize len)
 }
 
 
-static char emptyString[]="";
 static jchar emptyStringJ[]={0,0};
 
-/******************* returns the length of a Java string ***************************/
+/* GetStringLength *************************************************************
+
+   Returns the length (the count of Unicode characters) of a Java
+   string.
+
+*******************************************************************************/
 
-jsize GetStringLength (JNIEnv *env, jstring str)
+jsize GetStringLength(JNIEnv *env, jstring str)
 {
-       return ((java_lang_String*) str)->count;
+       return ((java_lang_String *) str)->count;
 }
 
 
 /********************  convertes javastring to u2-array ****************************/
        
-u2 *javastring_tou2 (jstring so) 
+u2 *javastring_tou2(jstring so) 
 {
-       java_lang_String *s = (java_lang_String*) so;
-       java_chararray *a;
-       u4 i;
-       u2 *stringbuffer;
+       java_lang_String *s;
+       java_chararray   *a;
+       u2               *stringbuffer;
+       u4                i;
+
        STATS(jniinvokation();)
        
-       if (!s) return NULL;
+       s = (java_lang_String *) so;
+
+       if (!s)
+               return NULL;
 
        a = s->value;
-       if (!a) return NULL;
+
+       if (!a)
+               return NULL;
 
        /* allocate memory */
-       stringbuffer = MNEW( u2 , s->count + 1 );
+
+       stringbuffer = MNEW(u2, s->count + 1);
 
        /* copy text */
-       for (i=0; i<s->count; i++) stringbuffer[i] = a->data[s->offset+i];
+
+       for (i = 0; i < s->count; i++)
+               stringbuffer[i] = a->data[s->offset + i];
        
        /* terminate string */
+
        stringbuffer[i] = '\0';
 
        return stringbuffer;
 }
 
-/********* returns a pointer to an array of Unicode characters of the string *******/
 
-const jchar *GetStringChars (JNIEnv *env, jstring str, jboolean *isCopy)
+/* GetStringChars **************************************************************
+
+   Returns a pointer to the array of Unicode characters of the
+   string. This pointer is valid until ReleaseStringchars() is called.
+
+*******************************************************************************/
+
+const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
 {      
-       jchar *jc=javastring_tou2(str);
+       jchar *jc;
+
        STATS(jniinvokation();)
 
+       jc = javastring_tou2(str);
+
        if (jc) {
-               if (isCopy) *isCopy=JNI_TRUE;
+               if (isCopy)
+                       *isCopy = JNI_TRUE;
+
                return jc;
        }
-       if (isCopy) *isCopy=JNI_TRUE;
+
+       if (isCopy)
+               *isCopy = JNI_TRUE;
+
        return emptyStringJ;
 }
 
-/**************** native code no longer needs access to chars **********************/
 
-void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars)
+/* ReleaseStringChars **********************************************************
+
+   Informs the VM that the native code no longer needs access to
+   chars. The chars argument is a pointer obtained from string using
+   GetStringChars().
+
+*******************************************************************************/
+
+void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
 {
        STATS(jniinvokation();)
-       if (chars==emptyStringJ) return;
-       MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1);
+
+       if (chars == emptyStringJ)
+               return;
+
+       MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1);
 }
 
 
@@ -2706,47 +2823,65 @@ jsize GetStringUTFLength (JNIEnv *env, jstring string)
 }
 
 
-/************ converts a Javastring to an array of UTF-8 characters ****************/
+/* GetStringUTFChars ***********************************************************
 
-const char* GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)
+   Returns a pointer to an array of UTF-8 characters of the
+   string. This array is valid until it is released by
+   ReleaseStringUTFChars().
+
+*******************************************************************************/
+
+const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)
 {
-    utf *u;
+       utf *u;
        STATS(jniinvokation();)
 
-    u = javastring_toutf((java_lang_String *) string, false);
+       if (!string)
+               return "";
 
-    if (isCopy)
-               *isCopy = JNI_FALSE;
+       if (isCopy)
+               *isCopy = JNI_TRUE;
        
-    if (u)
+       u = javastring_toutf((java_lang_String *) string, false);
+
+       if (u)
                return u->text;
 
-    return emptyString;
-       
+       return "";
 }
 
 
-/***************** native code no longer needs access to utf ***********************/
+/* ReleaseStringUTFChars *******************************************************
 
-void ReleaseStringUTFChars (JNIEnv *env, jstring str, const char* chars)
+   Informs the VM that the native code no longer needs access to
+   utf. The utf argument is a pointer derived from string using
+   GetStringUTFChars().
+
+*******************************************************************************/
+
+void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
 {
        STATS(jniinvokation();)
 
-    /*we don't release utf chars right now, perhaps that should be done later. Since there is always one reference
-       the garbage collector will never get them*/
-       /*
-    log_text("JNI-Call: ReleaseStringUTFChars");
-    utf_display(utf_new_char(chars));
-       */
+    /* XXX we don't release utf chars right now, perhaps that should be done 
+          later. Since there is always one reference the garbage collector will
+          never get them */
 }
 
-/************************** array operations ***************************************/
+
+/* Array Operations ***********************************************************/
+
+/* GetArrayLength **************************************************************
+
+   Returns the number of elements in the array.
+
+*******************************************************************************/
 
 jsize GetArrayLength(JNIEnv *env, jarray array)
 {
        STATS(jniinvokation();)
 
-    return array->size;
+       return array->size;
 }
 
 
@@ -2942,318 +3077,574 @@ jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
 }
 
 
-jboolean * GetBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *isCopy)
+/* Get<PrimitiveType>ArrayElements *********************************************
+
+   A family of functions that returns the body of the primitive array.
+
+*******************************************************************************/
+
+jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array,
+                                                                 jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jbyte * GetByteArrayElements (JNIEnv *env, jbyteArray array, jboolean *isCopy)
+jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jchar * GetCharArrayElements (JNIEnv *env, jcharArray array, jboolean *isCopy)
+jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jshort * GetShortArrayElements (JNIEnv *env, jshortArray array, jboolean *isCopy)
+jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jint * GetIntArrayElements (JNIEnv *env, jintArray array, jboolean *isCopy)
+jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jlong * GetLongArrayElements (JNIEnv *env, jlongArray array, jboolean *isCopy)
+jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jfloat * GetFloatArrayElements (JNIEnv *env, jfloatArray array, jboolean *isCopy)
+jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jdouble * GetDoubleArrayElements (JNIEnv *env, jdoubleArray array, jboolean *isCopy)
+jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+                                                               jboolean *isCopy)
 {
        STATS(jniinvokation();)
-    if (isCopy) *isCopy = JNI_FALSE;
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
+/* Release<PrimitiveType>ArrayElements *****************************************
+
+   A family of functions that informs the VM that the native code no
+   longer needs access to elems. The elems argument is a pointer
+   derived from array using the corresponding
+   Get<PrimitiveType>ArrayElements() function. If necessary, this
+   function copies back all changes made to elems to the original
+   array.
 
-void ReleaseBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode)
+*******************************************************************************/
+
+void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
+                                                                jboolean *elems, jint mode)
 {
        STATS(jniinvokation();)
-    /* empty */
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void ReleaseByteArrayElements (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode)
+void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems,
+                                                         jint mode)
 {
        STATS(jniinvokation();)
-    /* empty */
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void ReleaseCharArrayElements (JNIEnv *env, jcharArray array, jchar *elems, jint mode)
+void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems,
+                                                         jint mode)
 {
-    /* empty */
+       STATS(jniinvokation();)
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void ReleaseShortArrayElements (JNIEnv *env, jshortArray array, jshort *elems, jint mode)
+void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems,
+                                                          jint mode)
 {
        STATS(jniinvokation();)
-    /* empty */
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void ReleaseIntArrayElements (JNIEnv *env, jintArray array, jint *elems, jint mode)
+void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
+                                                        jint mode)
 {
        STATS(jniinvokation();)
-    /* empty */
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void ReleaseLongArrayElements (JNIEnv *env, jlongArray array, jlong *elems, jint mode)
+void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems,
+                                                         jint mode)
 {
        STATS(jniinvokation();)
-    /* empty */
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void ReleaseFloatArrayElements (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode)
+void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems,
+                                                          jint mode)
 {
        STATS(jniinvokation();)
-    /* empty */
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode)
+void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+                                                               jdouble *elems, jint mode)
 {
        STATS(jniinvokation();)
-    /* empty */
+
+       if (elems != array->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       break;
+               case 0:
+                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf)
+/*  Get<PrimitiveType>ArrayRegion **********************************************
+
+       A family of functions that copies a region of a primitive array
+       into a buffer.
+
+*******************************************************************************/
+
+void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
+                                                  jsize len, jboolean *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jboolean, len);
 }
 
 
-void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
+void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
+                                               jbyte *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size) 
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jbyte, len);
 }
 
 
-void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
+void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
+                                               jchar *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jchar, len);
 }
 
 
-void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
+void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
+                                                jsize len, jshort *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else       
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jshort, len);
 }
 
 
-void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
+void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
+                                          jint *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jint, len);
 }
 
 
-void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
+void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len,
+                                               jlong *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jlong, len);
 }
 
 
-void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
+void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
+                                                jsize len, jfloat *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jfloat, len);
 }
 
 
-void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
+void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
+                                                 jsize len, jdouble *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start+len>array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+               MCOPY(buf, &array->data[start], jdouble, len);
 }
 
 
-void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf)
+/*  Set<PrimitiveType>ArrayRegion **********************************************
+
+       A family of functions that copies back a region of a primitive
+       array from a buffer.
+
+*******************************************************************************/
+
+void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
+                                                  jsize len, jboolean *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jboolean, len);
 }
 
 
-void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
+void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
+                                               jbyte *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jbyte, len);
 }
 
 
-void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
+void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
+                                               jchar *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jchar, len);
 
 }
 
 
-void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
+void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
+                                                jsize len, jshort *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jshort, len);
 }
 
 
-void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
+void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
+                                          jint *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jint, len);
 
 }
 
 
-void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
+void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len,
+                                               jlong *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jlong, len);
 
 }
 
 
-void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
+void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
+                                                jsize len, jfloat *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jfloat, len);
 
 }
 
 
-void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
+void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
+                                                 jsize len, jdouble *buf)
 {
        STATS(jniinvokation();)
+
     if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+               *exceptionptr =
+                       new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
     else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+               MCOPY(&array->data[start], buf, jdouble, len);
 }
 
 
-jint RegisterNatives (JNIEnv* env, jclass clazz, const JNINativeMethod *methods, jint nMethods)
+/* Registering Native Methods *************************************************/
+
+/* RegisterNatives *************************************************************
+
+   Registers native methods with the class specified by the clazz
+   argument. The methods parameter specifies an array of
+   JNINativeMethod structures that contain the names, signatures, and
+   function pointers of the native methods. The nMethods parameter
+   specifies the number of native methods in the array.
+
+*******************************************************************************/
+
+jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+                                        jint nMethods)
 {
        STATS(jniinvokation();)
-    log_text("JNI-Call: RegisterNatives");
+
+    log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!");
+
     return 0;
 }
 
 
-jint UnregisterNatives (JNIEnv* env, jclass clazz)
+/* UnregisterNatives ***********************************************************
+
+   Unregisters native methods of a class. The class goes back to the
+   state before it was linked or registered with its native method
+   functions.
+
+   This function should not be used in normal native code. Instead, it
+   provides special programs a way to reload and relink native
+   libraries.
+
+*******************************************************************************/
+
+jint UnregisterNatives(JNIEnv *env, jclass clazz)
 {
        STATS(jniinvokation();)
-    log_text("JNI-Call: UnregisterNatives");
+
+       /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
+
+    log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
+
     return 0;
 }
 
@@ -3342,46 +3733,71 @@ void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char
 }
 
 
-/************** obtain direct pointer to array elements ***********************/
+/* GetPrimitiveArrayCritical ***************************************************
+
+   Obtain a direct pointer to array elements.
+
+*******************************************************************************/
 
-void * GetPrimitiveArrayCritical (JNIEnv* env, jarray array, jboolean *isCopy)
+void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
 {
+       java_objectheader *s;
+       arraydescriptor   *desc;
+
        STATS(jniinvokation();)
-       java_objectheader *s = (java_objectheader*) array;
-       arraydescriptor *desc = s->vftbl->arraydesc;
 
-       if (!desc) return NULL;
+       s = (java_objectheader *) array;
+       desc = s->vftbl->arraydesc;
+
+       if (!desc)
+               return NULL;
 
-       return ((u1*)s) + desc->dataoffset;
+       if (isCopy)
+               *isCopy = JNI_FALSE;
+
+       /* TODO add to global refs */
+
+       return ((u1 *) s) + desc->dataoffset;
 }
 
 
-void ReleasePrimitiveArrayCritical (JNIEnv* env, jarray array, void *carray, jint mode)
+/* ReleasePrimitiveArrayCritical ***********************************************
+
+   No specific documentation.
+
+*******************************************************************************/
+
+void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray,
+                                                                  jint mode)
 {
        STATS(jniinvokation();)
-       log_text("JNI-Call: ReleasePrimitiveArrayCritical");
 
-       /* empty */
+       log_text("JNI-Call: ReleasePrimitiveArrayCritical: IMPLEMENT ME!!!");
+
+       /* TODO remove from global refs */
 }
 
-/**** returns a pointer to an array of Unicode characters of the string *******/
 
-const jchar * GetStringCritical (JNIEnv* env, jstring string, jboolean *isCopy)
+/* GetStringCritical ***********************************************************
+
+   The semantics of these two functions are similar to the existing
+   Get/ReleaseStringChars functions.
+
+*******************************************************************************/
+
+const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)
 {
        STATS(jniinvokation();)
-       log_text("JNI-Call: GetStringCritical");
 
-       return GetStringChars(env,string,isCopy);
+       return GetStringChars(env, string, isCopy);
 }
 
-/*********** native code no longer needs access to chars **********************/
 
-void ReleaseStringCritical (JNIEnv* env, jstring string, const jchar *cstring)
+void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring)
 {
        STATS(jniinvokation();)
-       log_text("JNI-Call: ReleaseStringCritical");
 
-       ReleaseStringChars(env,string,cstring);
+       ReleaseStringChars(env, string, cstring);
 }
 
 
@@ -3456,7 +3872,7 @@ void DeleteGlobalRef(JNIEnv* env, jobject gref)
                jobject newval = NewObject(env, intclass, newint, val);
 
                if (newval != NULL) {
-                       CallObjectMethod(env,*global_ref_table, putmid,newval);
+                       CallObjectMethod(env,*global_ref_table, putmid, gref, newval);
 
                } else {
                        log_text("JNI-DeleteGlobalRef: unable to create new java.lang.Integer");
@@ -3485,8 +3901,9 @@ jboolean ExceptionCheck(JNIEnv *env)
 
 /* NewDirectByteBuffer *********************************************************
 
-   Allocates and returns a direct java.nio.ByteBuffer referring to the block of
-   memory starting at the memory address address and extending capacity bytes.
+   Allocates and returns a direct java.nio.ByteBuffer referring to the
+   block of memory starting at the memory address address and
+   extending capacity bytes.
 
 *******************************************************************************/
 
@@ -3501,8 +3918,8 @@ jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 
 /* GetDirectBufferAddress ******************************************************
 
-   Fetches and returns the starting address of the memory region referenced by
-   the given direct java.nio.Buffer.
+   Fetches and returns the starting address of the memory region
+   referenced by the given direct java.nio.Buffer.
 
 *******************************************************************************/
 
@@ -3517,8 +3934,8 @@ void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
 
 /* GetDirectBufferCapacity *****************************************************
 
-   Fetches and returns the capacity in bytes of the memory region referenced by
-   the given direct java.nio.Buffer.
+   Fetches and returns the capacity in bytes of the memory region
+   referenced by the given direct java.nio.Buffer.
 
 *******************************************************************************/
 
@@ -3540,9 +3957,24 @@ jint DestroyJavaVM(JavaVM *vm)
 }
 
 
+/* AttachCurrentThread *********************************************************
+
+   Attaches the current thread to a Java VM. Returns a JNI interface
+   pointer in the JNIEnv argument.
+
+   Trying to attach a thread that is already attached is a no-op.
+
+   A native thread cannot be attached simultaneously to two Java VMs.
+
+   When a thread is attached to the VM, the context class loader is
+   the bootstrap loader.
+
+*******************************************************************************/
+
 jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args)
 {
        STATS(jniinvokation();)
+
        log_text("AttachCurrentThread called");
 
 #if !defined(HAVE___THREAD)
@@ -3552,6 +3984,7 @@ jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args)
 #endif
 
        *env = &ptr_env;
+
        return 0;
 }
 
@@ -3565,29 +3998,50 @@ jint DetachCurrentThread(JavaVM *vm)
 }
 
 
+/* GetEnv **********************************************************************
+
+   If the current thread is not attached to the VM, sets *env to NULL,
+   and returns JNI_EDETACHED. If the specified version is not
+   supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
+   sets *env to the appropriate interface, and returns JNI_OK.
+
+*******************************************************************************/
+
 jint GetEnv(JavaVM *vm, void **env, jint version)
 {
        STATS(jniinvokation();)
-       if ((version != JNI_VERSION_1_1) && (version != JNI_VERSION_1_2) &&
-               (version != JNI_VERSION_1_4)) {
-               *env = NULL;
-               return JNI_EVERSION;
-       }
 
-       /*
-         TODO: If the current thread is not attached to the VM...
-       if (0) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       if (thread_getself() == NULL) {
                *env = NULL;
+
                return JNI_EDETACHED;
        }
-       */
+#endif
 
-       *env = &ptr_env;
+       if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) ||
+               (version == JNI_VERSION_1_4)) {
+               *env = &ptr_env;
 
-       return JNI_OK;
+               return JNI_OK;
+       }
+
+#if defined(ENABLE_JVMTI)
+       if (version == JVMTI_VERSION_1_0) {
+               *env = (void *) new_jvmtienv();
+
+               if (env != NULL)
+                       return JNI_OK;
+       }
+#endif
+       
+       *env = NULL;
+
+       return JNI_EVERSION;
 }
 
 
+
 jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
 {
        STATS(jniinvokation();)
@@ -3632,11 +4086,13 @@ void jni_init2(JNIEnv* env, jobject gref) {
        DeleteGlobalRef(env, gref); 
 }
 
-void jni_init(){
+
+void jni_init(void)
+{
        jmethodID mid;
 
        initrunning = true;
-       log_text("JNI-Init: initialize global_ref_table");
+
        /* initalize global reference table */
        ihmclass = FindClass(NULL, "java/util/IdentityHashMap");
        
@@ -4035,19 +4491,25 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 
 jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args)
 {
-       *p_vm = (JavaVM *) &JNI_JavaVMTable;
-       *p_env = (JNIEnv *) &JNI_JNIEnvTable;
+       const struct JNIInvokeInterface *vm;
+       struct JNINativeInterface *env;
+
+       vm = &JNI_JavaVMTable;
+       env = &JNI_JNIEnvTable;
+
+       *p_vm = (JavaVM *) vm;
+       *p_env = (JNIEnv *) env;
 
        return 0;
 }
 
 
-jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, jobject obj, java_objectarray *params)
+jobject *jni_method_invokeNativeHelper(JNIEnv *env, methodinfo *methodID,
+                                                                          jobject obj, java_objectarray *params)
 {
-       int argcount;
        jni_callblock *blk;
-       int retT;
-       jobject retVal;
+       jobject        o;
+       s4             argcount;
 
        if (methodID == 0) {
                *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
@@ -4056,14 +4518,21 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
 
        argcount = methodID->parseddesc->paramcount;
 
+       /* if method is non-static, remove the `this' pointer */
+
+       if (!(methodID->flags & ACC_STATIC))
+               argcount--;
+
        /* the method is an instance method the obj has to be an instance of the 
           class the method belongs to. For static methods the obj parameter
           is ignored. */
+
        if (!(methodID->flags & ACC_STATIC) && obj &&
                (!builtin_instanceof((java_objectheader *) obj, methodID->class))) {
-               *exceptionptr = new_exception_message(string_java_lang_IllegalArgumentException,
+               *exceptionptr =
+                       new_exception_message(string_java_lang_IllegalArgumentException,
                                                                                          "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
-               return 0;
+               return NULL;
        }
 
 
@@ -4071,73 +4540,73 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
        if (argcount > 3) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. invokeNativeHelper does not support that");
-               return 0;
+               return NULL;
        }
 #endif
-       if (((params==0) && (argcount != 0)) || (params && (params->header.size != argcount))) {
-               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
-               return 0;
+
+       if (((params == NULL) && (argcount != 0)) ||
+               (params && (params->header.size != argcount))) {
+               *exceptionptr =
+                       new_exception(string_java_lang_IllegalArgumentException);
+               return NULL;
        }
 
 
-       if (((methodID->flags & ACC_STATIC)==0) && (0==obj))  {
+       if (!(methodID->flags & ACC_STATIC) && !obj)  {
                *exceptionptr =
                        new_exception_message(string_java_lang_NullPointerException,
                                                                  "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
-               return 0;
+               return NULL;
        }
 
-       if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0;
+       if ((methodID->flags & ACC_STATIC) && (obj))
+               obj = NULL;
 
        if (obj) {
-               if ( (methodID->flags & ACC_ABSTRACT) || (methodID->class->flags & ACC_INTERFACE) ) {
-                       methodID=get_virtual(obj,methodID);
+               if ((methodID->flags & ACC_ABSTRACT) ||
+                       (methodID->class->flags & ACC_INTERFACE)) {
+                       methodID = get_virtual(obj, methodID);
                }
        }
 
-       blk = MNEW(jni_callblock, /*4 */argcount+2);
+       blk = MNEW(jni_callblock, /*4 */argcount + 2);
 
-       if (!fill_callblock_objA(obj, methodID->parseddesc, blk, params,&retT))
-               return 0; /* exception */
+       if (!fill_callblock_from_objectarray(obj, methodID->parseddesc, blk,
+                                                                                params))
+               return NULL;
 
-       switch (retT) {
+       switch (methodID->parseddesc->returntype.decltype) {
        case TYPE_VOID:
-               (void) asm_calljavafunction2(methodID,
-                                                                        argcount + 1,
+               (void) asm_calljavafunction2(methodID, argcount + 1,
                                                                         (argcount + 1) * sizeof(jni_callblock),
                                                                         blk);
-               retVal = NULL; /*native_new_and_init(loader_load(utf_new_char("java/lang/Void")));*/
+               o = NULL; /*native_new_and_init(loader_load(utf_new_char("java/lang/Void")));*/
                break;
 
        case PRIMITIVETYPE_INT: {
-               s4 intVal;
-               intVal = asm_calljavafunction2int(methodID,
-                                                                                 argcount + 1,
-                                                                                 (argcount + 1) * sizeof(jni_callblock),
-                                                                                 blk);
-               retVal = builtin_new(class_java_lang_Integer);
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_int__void),
-                                          intVal);
+               s4 i;
+               i = asm_calljavafunction2int(methodID, argcount + 1,
+                                                                        (argcount + 1) * sizeof(jni_callblock),
+                                                                        blk);
+
+               o = native_new_and_init_int(class_java_lang_Integer, i);
        }
        break;
 
        case PRIMITIVETYPE_BYTE: {
-               s4 intVal;
-               intVal = asm_calljavafunction2int(methodID,
-                                                                                 argcount + 1,
-                                                                                 (argcount + 1) * sizeof(jni_callblock),
-                                                                                 blk);
-               retVal = builtin_new(class_java_lang_Byte);
+               s4 i;
+               i = asm_calljavafunction2int(methodID, argcount + 1,
+                                                                        (argcount + 1) * sizeof(jni_callblock),
+                                                                        blk);
+
+/*             o = native_new_and_init_int(class_java_lang_Byte, i); */
+               o = builtin_new(class_java_lang_Byte);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
                                                                                   utf_init,
                                                                                   utf_byte__void),
-                                          intVal);
+                                          i);
        }
        break;
 
@@ -4147,10 +4616,10 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                  argcount + 1,
                                                                                  (argcount + 1) * sizeof(jni_callblock),
                                                                                  blk);
-               retVal = builtin_new(class_java_lang_Character);
+               o = builtin_new(class_java_lang_Character);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
                                                                                   utf_init,
                                                                                   utf_char__void),
                                           intVal);
@@ -4163,10 +4632,10 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                  argcount + 1,
                                                                                  (argcount + 1) * sizeof(jni_callblock),
                                                                                  blk);
-               retVal = builtin_new(class_java_lang_Short);
+               o = builtin_new(class_java_lang_Short);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
                                                                                   utf_init,
                                                                                   utf_short__void),
                                           intVal);
@@ -4179,10 +4648,10 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                  argcount + 1,
                                                                                  (argcount + 1) * sizeof(jni_callblock),
                                                                                  blk);
-               retVal = builtin_new(class_java_lang_Boolean);
+               o = builtin_new(class_java_lang_Boolean);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
                                                                                   utf_init,
                                                                                   utf_boolean__void),
                                           intVal);
@@ -4195,10 +4664,10 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                        argcount + 1,
                                                                                        (argcount + 1) * sizeof(jni_callblock),
                                                                                        blk);
-               retVal = builtin_new(class_java_lang_Long);
+               o = builtin_new(class_java_lang_Long);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
                                                                                   utf_init,
                                                                                   utf_long__void),
                                           longVal);
@@ -4211,10 +4680,10 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                          argcount + 1,
                                                                                          (argcount + 1) * sizeof(jni_callblock),
                                                                                          blk);
-               retVal = builtin_new(class_java_lang_Float);
+               o = builtin_new(class_java_lang_Float);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
                                                                                   utf_init,
                                                                                   utf_float__void),
                                           floatVal);
@@ -4227,10 +4696,10 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                                argcount + 1,
                                                                                                (argcount + 1) * sizeof(jni_callblock),
                                                                                                blk);
-               retVal = builtin_new(class_java_lang_Double);
+               o = builtin_new(class_java_lang_Double);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
                                                                                   utf_init,
                                                                                   utf_double__void),
                                           doubleVal);
@@ -4238,14 +4707,14 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
        break;
 
        case TYPE_ADR:
-               retVal = asm_calljavafunction2(methodID,
-                                                                          argcount + 1,
-                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                          blk);
+               o = asm_calljavafunction2(methodID, argcount + 1,
+                                                                 (argcount + 1) * sizeof(jni_callblock), blk);
                break;
 
        default:
-               /* if this happens the acception has already been set by fill_callblock_objA*/
+               /* if this happens the exception has already been set by              */
+               /* fill_callblock_from_objectarray                                    */
+
                MFREE(blk, jni_callblock, /*4 */ argcount+2);
                return (jobject *) 0;
        }
@@ -4253,36 +4722,23 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
        MFREE(blk, jni_callblock, /* 4 */ argcount+2);
 
        if (*exceptionptr) {
-               java_objectheader *exceptionToWrap = *exceptionptr;
-               classinfo *ivtec;
-               java_objectheader *ivte;
+               java_objectheader *cause;
 
-               *exceptionptr = NULL;
-               if (load_class_bootstrap(utf_new_char("java/lang/reflect/InvocationTargetException"),
-                                                                &ivtec)) 
-               {
-                       ivte = builtin_new(ivtec);
-                       asm_calljavafunction(class_resolvemethod(ivtec,
-                                                                                                        utf_new_char("<init>"),
-                                                                                                        utf_new_char("(Ljava/lang/Throwable;)V")),
-                                                                ivte,
-                                                                exceptionToWrap,
-                                                                0,
-                                                                0);
-               }
+               cause = *exceptionptr;
+
+               /* clear exception pointer, we are calling JIT code again */
 
-               if (*exceptionptr != NULL)
-                       panic("jni.c: error while creating InvocationTargetException wrapper");
+               *exceptionptr = NULL;
 
-               *exceptionptr = ivte;
+               *exceptionptr =
+                       new_exception_throwable(string_java_lang_reflect_InvocationTargetException,
+                                                                       (java_lang_Throwable *) cause);
        }
 
-       return (jobject *) retVal;
+       return (jobject *) o;
 }
 
 
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where