fix DeleteGlobalRef missing argument for IdentityHashMap.put
[cacao.git] / src / native / jni.c
index 15d1cd22d19a33cef7dba31718212b516e1859de..651649e9ff2e57833775844a1ddedfcc5f89b220 100644 (file)
@@ -1,9 +1,9 @@
-/* jni.c - implementation of the Java Native Interface functions
+/* src/native/jni.c - implementation of the Java Native Interface functions
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
-   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger
+   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    Contact: cacao@complang.tuwien.ac.at
 
-   Authors: ?
+   Authors: Rainhard Grafl
+            Roman Obermaisser
 
    Changes: Joseph Wenninger
+            Martin Platter
+            Christian Thalinger
 
-   $Id: jni.c 1173 2004-06-16 14:56:18Z jowenn $
+   $Id: jni.c 3095 2005-07-21 13:51:36Z motse $
 
 */
 
 
+#include <assert.h>
 #include <string.h>
-#include "main.h"
-#include "jni.h"
-#include "global.h"
-#include "loader.h"
-#include "tables.h"
-#include "native.h"
-#include "builtin.h"
-#include "threads/thread.h"
+
+#include "config.h"
+#include "mm/boehm.h"
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_Byte.h"
+#include "native/include/java_lang_Character.h"
+#include "native/include/java_lang_Short.h"
+#include "native/include/java_lang_Integer.h"
+#include "native/include/java_lang_Boolean.h"
+#include "native/include/java_lang_Long.h"
+#include "native/include/java_lang_Float.h"
+#include "native/include/java_lang_Double.h"
+#include "native/include/java_lang_Throwable.h"
+#include "native/include/java_lang_reflect_Method.h"
+#include "native/include/java_lang_reflect_Constructor.h"
+#include "native/include/java_lang_reflect_Field.h"
+
+#include "native/include/java_lang_Class.h" /* for java_lang_VMClass.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"
+# else
+#  include "threads/green/threads.h"
+# endif
+#endif
+
 #include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "nat/java_lang_Byte.h"
-#include "nat/java_lang_Character.h"
-#include "nat/java_lang_Short.h"
-#include "nat/java_lang_Integer.h"
-#include "nat/java_lang_Boolean.h"
-#include "nat/java_lang_Long.h"
-#include "nat/java_lang_Float.h"
-#include "nat/java_lang_Double.h"
-#include "nat/java_lang_Throwable.h"
-#include "jit/jit.h"
-#include "asmpart.h"   
-#define JNI_VERSION       0x00010002
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/initialize.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
+#include "vm/statistics.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+#include "vm/statistics.h"
 
 
-#define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
+/* XXX TWISTI hack: define it extern so they can be found in this file */
 
-static utf* utf_char = 0;
-static utf* utf_bool = 0;
-static utf* utf_byte  =0;
-static utf* utf_short = 0;
-static utf* utf_int = 0;
-static utf* utf_long = 0;
-static utf* utf_float = 0;
-static utf* utf_double = 0;
+extern const struct JNIInvokeInterface JNI_JavaVMTable;
+extern struct JNINativeInterface JNI_JNIEnvTable;
 
+/* pointers to VM and the environment needed by GetJavaVM and GetEnv */
 
-/********************* accessing instance-fields **********************************/
+static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable;
+void* ptr_env = (void*) &JNI_JNIEnvTable;
 
-#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 PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
 
+/* global reference table */
+static jobject *global_ref_table;
+static bool initrunning=false;
 
-u4 get_parametercount(methodinfo *m)
-{
-       utf  *descr    =  m->descriptor;    /* method-descriptor */
-       char *utf_ptr  =  descr->text;      /* current position in utf-text */
-       char *desc_end =  utf_end(descr);   /* points behind utf string     */
-       u4 parametercount = 0;
+/* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/
+static jmethodID getmid = NULL;
+static jmethodID putmid = NULL;
+static jclass intclass = NULL;
+static jmethodID intvalue = NULL;
+static jmethodID newint = NULL;
+static jclass ihmclass = NULL;
+static jmethodID removemid = NULL;
 
-       /* skip '(' */
-       utf_nextu2(&utf_ptr);
+#define JWCLINITDEBUG(x)
 
-    /* determine number of parameters */
-       while (*utf_ptr != ')') {
-               get_type(&utf_ptr, desc_end, true);
-               parametercount++;
-       }
 
-       return parametercount;
-}
+/********************* accessing instance-fields **********************************/
 
+#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);
 
 
-void fill_callblock(void *obj, utf *descr, jni_callblock blk[], va_list data, char ret)
+static void fill_callblock_from_vargs(void *obj, methoddesc *descr,
+                                                                         jni_callblock blk[], va_list data,
+                                                                         s4 rettype)
 {
-    char *utf__ptr = descr->text;      /* current position in utf-text */
-    char **utf_ptr = &utf__ptr;
-    char *desc_end = utf_end(descr);   /* points behind utf string     */
-    int cnt;
-    u4 dummy;
-    char c;
+       typedesc *paramtypes;
+       s4        i;
+
+       paramtypes = descr->paramtypes;
+
+       /* if method is non-static fill first block and skip `this' pointer */
+
+       i = 0;
 
-       /*
-    log_text("fill_callblock");
-    utf_display(descr);
-    log_text("====");
-       */
-    /* skip '(' */
-    utf_nextu2(utf_ptr);
-
-    /* determine number of parameters */
        if (obj) {
+               /* the `this' pointer */
                blk[0].itemtype = TYPE_ADR;
                blk[0].item = PTR_TO_ITEM(obj);
-               cnt = 1;
-       } else cnt = 0;
-
-       while (**utf_ptr != ')') {
-               if (*utf_ptr >= desc_end)
-               panic("illegal method descriptor");
-
-               switch (utf_nextu2(utf_ptr)) {
-                       /* primitive types */
-               case 'B':
-               case 'C':
-               case 'S': 
-               case 'Z':
-                       blk[cnt].itemtype = TYPE_INT;
-                       blk[cnt].item = (u8) va_arg(data, int);
-                       break;
 
-               case 'I':
-                       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;
+               paramtypes++;
+               i++;
+       } 
+
+       for (; i < descr->paramcount; i++, paramtypes++) {
+               switch (paramtypes->decltype) {
+               /* primitive types */
+               case PRIMITIVETYPE_BYTE:
+               case PRIMITIVETYPE_CHAR:
+               case PRIMITIVETYPE_SHORT: 
+               case PRIMITIVETYPE_BOOLEAN: 
+                       blk[i].itemtype = TYPE_INT;
+                       blk[i].item = (s8) va_arg(data, s4);
                        break;
 
-               case 'J':
-                       blk[cnt].itemtype = TYPE_LNG;
-                       blk[cnt].item = (u8) va_arg(data, jlong);
+               case PRIMITIVETYPE_INT:
+                       blk[i].itemtype = TYPE_INT;
+                       blk[i].item = (s8) va_arg(data, s4);
                        break;
 
-               case 'F':
-                       blk[cnt].itemtype = TYPE_FLT;
-                       *((jfloat *) (&blk[cnt].item)) = (jfloat) va_arg(data, jdouble);
+               case PRIMITIVETYPE_LONG:
+                       blk[i].itemtype = TYPE_LNG;
+                       blk[i].item = (s8) va_arg(data, s8);
                        break;
 
-               case 'D':
-                       blk[cnt].itemtype = TYPE_DBL;
-                       *((jdouble *) (&blk[cnt].item)) = (jdouble) va_arg(data, jdouble);
+               case PRIMITIVETYPE_FLOAT:
+                       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 'V':
-                       panic ("V not allowed as function parameter");
+               case PRIMITIVETYPE_DOUBLE:
+                       blk[i].itemtype = TYPE_DBL;
+                       *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
                        break;
-                       
-               case 'L':
-                       while (utf_nextu2(utf_ptr) != ';')
-                           blk[cnt].itemtype = TYPE_ADR;
-                       blk[cnt].item = PTR_TO_ITEM(va_arg(data, void*));
+
+               case TYPE_ADR: 
+                       blk[i].itemtype = TYPE_ADR;
+                       blk[i].item = PTR_TO_ITEM(va_arg(data, void*));
                        break;
-                       
-               case '[':
-                       {
-                               /* XXX */
-                               /* arrayclass */
-/*                             char *start = *utf_ptr; */
-                               char ch;
-                               while ((ch = utf_nextu2(utf_ptr)) == '[')
-                                       if (ch == 'L') {
-                                               while (utf_nextu2(utf_ptr) != ';') {}
-                                       }
-       
-                               ch = utf_nextu2(utf_ptr);
-                               blk[cnt].itemtype = TYPE_ADR;
-                               blk[cnt].item = PTR_TO_ITEM(va_arg(data, void*));
-                               break;                  
-                       }
                }
-               cnt++;
        }
 
-       /*the standard doesn't say anything about return value checking, but it appears to be usefull*/
-       c = utf_nextu2(utf_ptr);
-       c = utf_nextu2(utf_ptr);
-       /*printf("%c  %c\n",ret,c);*/
-       if (ret == 'O') {
-               if (!((c == 'L') || (c == '[')))
-                       log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
-       } else if (ret != c)
+       /* 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 */
-char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_objectarray* params)
+
+static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
+                                                                                       jni_callblock blk[],
+                                                                                       java_objectarray *params)
 {
-    char *utf__ptr = descr->text;      /* current position in utf-text */
-    char **utf_ptr = &utf__ptr;
-    char *desc_end = utf_end(descr);   /* points behind utf string     */
+    jobject    param;
+       s4         paramcount;
+       typedesc  *paramtypes;
+       classinfo *c;
+    s4         i;
+       s4         j;
 
-    jobject param;
-    int cnt;
-    int cnts;
-    char c;
+       paramcount = descr->paramcount;
+       paramtypes = descr->paramtypes;
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-    intsDisable();
-#endif
-       if (utf_char==0) {
-               utf_char=utf_new_char("java/lang/Character");
-               utf_bool=utf_new_char("java/lang/Boolean");
-               utf_byte=utf_new_char("java/lang/Byte");
-               utf_short=utf_new_char("java/lang/Short");
-               utf_int=utf_new_char("java/lang/Integer");
-               utf_long=utf_new_char("java/lang/Long");
-               utf_float=utf_new_char("java/lang/Float");
-               utf_double=utf_new_char("java/lang/Double");
-       }
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-    intsRestore();
-#endif
+       /* if method is non-static fill first block and skip `this' pointer */
+
+       i = 0;
 
-       /*
-         log_text("fill_callblock");
-         utf_display(descr);
-         log_text("====");
-       */
-    /* skip '(' */
-    utf_nextu2(utf_ptr);
-
-    /* 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++;
        }
 
-       cnts = 0;
-       while (**utf_ptr != ')') {
-               if (*utf_ptr >= desc_end)
-               panic("illegal method descriptor");
-
+       for (j = 0; j < paramcount; i++, j++, paramtypes++) {
+               switch (paramtypes->type) {
                /* primitive types */
-               switch (utf_nextu2(utf_ptr)) {
-               case 'B':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       if (param->vftbl->class->name == utf_byte) {
-                               blk[cnt].itemtype = TYPE_INT;
-                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-
-                       } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       break;
-
-               case 'C':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       if (param->vftbl->class->name == utf_char) {
-                               blk[cnt].itemtype = TYPE_INT;
-                               blk[cnt].item = (u8) ((java_lang_Character *) param)->value;
-
-                       } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       break;
+               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;
 
-               case 'S':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       if (param->vftbl->class->name == utf_short) {
-                               blk[cnt].itemtype = TYPE_INT;
-                               blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
-
-                       } else  {
-                               if (param->vftbl->class->name == utf_byte) {
-                                       blk[cnt].itemtype = TYPE_INT;
-                                       blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-
-                               } else {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                       return 0;
-                               }
-                       }
-                       break;
+                       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 'Z':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       if (param->vftbl->class->name == utf_bool) {
-                               blk[cnt].itemtype = TYPE_INT;
-                               blk[cnt].item = (u8) ((java_lang_Boolean *) param)->value;
-
-                       } else {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       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 'I':
-                       /*log_text("fill_callblock_objA: param 'I'");*/
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       if (param->vftbl->class->name == utf_int) {
-                               blk[cnt].itemtype = TYPE_INT;
-                               blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
-                               /*printf("INT VALUE :%d\n",((struct java_lang_Integer * )param)->value);*/
-                       } else {
-                               if (param->vftbl->class->name == utf_short) {
-                                       blk[cnt].itemtype = TYPE_INT;
-                                       blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
-
-                               } else  {
-                                       if (param->vftbl->class->name == utf_byte) {
-                                               blk[cnt].itemtype = TYPE_INT;
-                                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-
-                                       } else  {
-                                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                               return 0;
-                                       }
-                               }
-                       }
-                       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 'J':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       if (param->vftbl->class->name == utf_long) {
-                               blk[cnt].itemtype = TYPE_LNG;
-                               blk[cnt].item = (u8) ((java_lang_Long *) param)->value;
-
-                       } else  {
-                               if (param->vftbl->class->name == utf_int) {
-                                       blk[cnt].itemtype = TYPE_LNG;
-                                       blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
-
-                               } else {
-                                       if (param->vftbl->class->name == utf_short) {
-                                               blk[cnt].itemtype = TYPE_LNG;
-                                               blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
-
-                                       } else  {
-                                               if (param->vftbl->class->name == utf_byte) {
-                                                       blk[cnt].itemtype = TYPE_LNG;
-                                                       blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
-                                               } else  {
-                                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                                       return 0;
-                                               }
-                                       }
-                               }
+                       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;
 
-                       }
-                       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 'F':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-
-                       if (param->vftbl->class->name == utf_float) {
-                               blk[cnt].itemtype = TYPE_FLT;
-                               *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value;
-
-                       } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       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 'D':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-
-                       if (param->vftbl->class->name == utf_double) {
-                               blk[cnt].itemtype = TYPE_DBL;
-                               *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
-
-                       } else  {
-                               if (param->vftbl->class->name == utf_float) {
-                                       blk[cnt].itemtype = TYPE_DBL;
-                                       *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
-
-                               } else  {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                       return 0;
-                               }
-                       }
-                       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;
 
-               case 'V':
-                       panic("V not allowed as function parameter");
+                       default:
+                               goto illegal_arg;
+                       } /* end declared type switch */
                        break;
-
-               case 'L':
-                       {
-                               char *start = (*utf_ptr) - 1;
-                               char *end = NULL;
-
-                               while (utf_nextu2(utf_ptr) != ';')
-                                       end = (*utf_ptr) + 1;
-
-                               if (!builtin_instanceof(params->data[cnts], class_from_descriptor(start, end, 0, CLASSLOAD_LOAD))) {
-                                       if (params->data[cnts] != 0) {
-                                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                               return 0;
-                                       }                       
+               
+                       case TYPE_ADDRESS:
+                               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;                  
-                       }
 
-               case '[':
-                       {
-                               char *start = (*utf_ptr) - 1;
-                               char *end;
+                       default:
+                               goto illegal_arg;
+               } /* end param type switch */
 
-                               char ch;
-                               while ((ch = utf_nextu2(utf_ptr)) == '[')
-                                       if (ch == 'L') {
-                                               while (utf_nextu2(utf_ptr) != ';') {}
-                                       }
+       } /* end param loop */
 
-                               end = (*utf_ptr) - 1;
-                               ch = utf_nextu2(utf_ptr);
+/*     if (rettype) */
+/*             *rettype = descr->returntype.decltype; */
 
-                               if (!builtin_arrayinstanceof(params->data[cnts], class_from_descriptor(start, end, 0, CLASSLOAD_LOAD)->vftbl)) {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                       return 0;
-                               }
-       
-                               blk[cnt].itemtype = TYPE_ADR;
-                               blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
-                               break;
-                       }
-               }
-               cnt++;
-               cnts++;
-       }
+       return true;
 
-       c = utf_nextu2(utf_ptr);
-       c = utf_nextu2(utf_ptr);
-       return c; /*return type needed usage of the right lowlevel methods*/
+illegal_arg:
+       *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+       return false;
 }
 
 
+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;
 
-
-
-
-
-
-
-
-
-
-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);
-}
-
-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);
+       /* class_resolvemethod -> classfindmethod? (JOWENN) */
+       return class_resolvemethod(clazz, methodID->name, methodID->descriptor);
 }
 
 
-
-jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
+static jobject callObjectMethod(jobject obj, jmethodID methodID, va_list args)
 {      
        int argcount;
        jni_callblock *blk;
        jobject ret;
 
-       /*
-         log_text("JNI-Call: CallObjectMethodV");
-         utf_display(methodID->name);
-         utf_display(methodID->descriptor);
-         printf("\nParmaeter count: %d\n",argcount);
-         utf_display(obj->vftbl->class->name);
-         printf("\n");
-       */
+
 
        if (methodID == 0) {
                *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
                return 0;
        }
 
-       argcount = get_parametercount(methodID);
+       argcount = methodID->parseddesc->paramcount;
 
        if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
                ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
                *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
-       
+
        if (obj && !builtin_instanceof(obj, methodID->class)) {
                *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
 
+#ifdef arglimit
+
        if (argcount > 3) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallObjectMethod does not support that");
                return 0;
        }
+#endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
-
-       fill_callblock(obj, methodID->descriptor, blk, args, 'O');
+       blk = MNEW(jni_callblock, /*4 */argcount+2);
 
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_ADR);
        /*      printf("parameter: obj: %p",blk[0].item); */
+       STATS(jnicallXmethodnvokation();)
        ret = asm_calljavafunction2(methodID,
                                                                argcount + 1,
                                                                (argcount + 1) * sizeof(jni_callblock),
                                                                blk);
-
        MFREE(blk, jni_callblock, argcount + 1);
        /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+
        return ret;
 }
 
@@ -571,13 +435,13 @@ jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
   core function for integer class methods (bool, byte, short, integer)
   This is basically needed for i386
 */
-jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list args)
+static jint callIntegerMethod(jobject obj, jmethodID methodID, int retType, va_list args)
 {
        int argcount;
        jni_callblock *blk;
        jint ret;
 
-/*     printf("%p,     %c\n",retType,methodID,retType);*/
+       STATS(jniinvokation();)
 
         /*
         log_text("JNI-Call: CallObjectMethodV");
@@ -592,7 +456,7 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar
                return 0;
        }
         
-       argcount = get_parametercount(methodID);
+       argcount = methodID->parseddesc->paramcount;
 
        if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
                ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
@@ -605,22 +469,24 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar
                return 0;
        }
 
-
+#ifdef arglimit
        if (argcount > 3) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallIntegerMethod does not support that");
                return 0;
        }
+#endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
-       fill_callblock(obj, methodID->descriptor, blk, args, retType);
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType);
 
        /*      printf("parameter: obj: %p",blk[0].item); */
-       ret = (jint) asm_calljavafunction2(methodID,
-                                                                          argcount + 1,
-                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                          blk);
+       STATS(jnicallXmethodnvokation();)
+       ret = asm_calljavafunction2int(methodID,
+                                                                  argcount + 1,
+                                                                  (argcount + 1) * sizeof(jni_callblock),
+                                                                  blk);
 
        MFREE(blk, jni_callblock, argcount + 1);
        /*      printf("(CallObjectMethodV)-->%p\n",ret); */
@@ -630,26 +496,28 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar
 
 
 /*core function for long class functions*/
-jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
+static jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
 {
        int argcount;
        jni_callblock *blk;
        jlong ret;
 
-       /*
+       STATS(jniinvokation();)
+
+/*     
         log_text("JNI-Call: CallObjectMethodV");
         utf_display(methodID->name);
         utf_display(methodID->descriptor);
         printf("\nParmaeter count: %d\n",argcount);
         utf_display(obj->vftbl->class->name);
         printf("\n");
-        */
+*/      
        if (methodID == 0) {
                *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
                return 0;
        }
 
-       argcount = get_parametercount(methodID);
+       argcount = methodID->parseddesc->paramcount;
 
        if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
                   ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) {
@@ -662,18 +530,20 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
                return 0;
        }
 
-
+#ifdef arglimit
        if (argcount > 3) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallObjectMethod does not support that");
                return 0;
        }
+#endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock,/* 4 */argcount+2);
 
-       fill_callblock(obj, methodID->descriptor, blk, args, 'L');
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_LNG);
 
        /*      printf("parameter: obj: %p",blk[0].item); */
+       STATS(jnicallXmethodnvokation();)
        ret = asm_calljavafunction2long(methodID,
                                                                        argcount + 1,
                                                                        (argcount + 1) * sizeof(jni_callblock),
@@ -687,12 +557,14 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
 
 
 /*core function for float class methods (float,double)*/
-jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType)
+static jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,int retType)
 {
-       int argcount = get_parametercount(methodID);
+       int argcount = methodID->parseddesc->paramcount;
        jni_callblock *blk;
        jdouble ret;
 
+       STATS(jniinvokation();)
+
         /*
         log_text("JNI-Call: CallObjectMethodV");
         utf_display(methodID->name);
@@ -702,17 +574,20 @@ jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retTy
         printf("\n");
         */
 
+#ifdef arglimit
        if (argcount > 3) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallObjectMethod does not support that");
                return 0;
        }
+#endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
-       fill_callblock(obj, methodID->descriptor, blk, args, retType);
+       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType);
 
        /*      printf("parameter: obj: %p",blk[0].item); */
+       STATS(jnicallXmethodnvokation();)
        ret = asm_calljavafunction2double(methodID,
                                                                          argcount + 1,
                                                                          (argcount + 1) * sizeof(jni_callblock),
@@ -732,9 +607,11 @@ jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retTy
 
 ************************************************************************************/
 
-fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
+static fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
 {
        s4 i;
+       STATS(jniinvokation();)
+
 /*     printf(" FieldCount: %d\n",c->fieldscount);
        utf_display(c->name); */
                for (i = 0; i < c->fieldscount; i++) {
@@ -746,144 +623,184 @@ fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
                        return &(c->fields[i]);
                }
 
-       if (c->super) return jclass_findfield(c->super,name,desc);
+       if (c->super.cls) return jclass_findfield(c->super.cls,name,desc);
 
        return NULL;
 }
 
-/********************* returns version of native method interface *****************/
 
-jint GetVersion (JNIEnv* env)
-{
-       return JNI_VERSION;
-}
+/* GetVersion ******************************************************************
 
+   Returns the major version number in the higher 16 bits and the
+   minor version number in the lower 16 bits.
 
-/****************** loads a class from a buffer of raw class data *****************/
+*******************************************************************************/
 
-jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *buf, jsize len) 
+jint GetVersion(JNIEnv *env)
 {
-       jclass clazz; 
-       classbuffer *cb;
-       s8 starttime;
-       s8 stoptime;
-
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
-       compiler_lock();
-       tables_lock();
-#else
-       intsDisable();
-#endif
-#endif
+       STATS(jniinvokation();)
 
-       /* measure time */
-       if (getloadingtime)
-               starttime = getcputime();
+       /* just say we support JNI 1.4 */
 
-       clazz = class_new(utf_new_char((char *) name));
+       return JNI_VERSION_1_4;
+}
 
-       /* build a classbuffer with the given data */
-       cb = NEW(classbuffer);
-       cb->class = clazz;
-       cb->size = len;
-       cb->data = (u1 *) buf;
-       cb->pos = cb->data - 1;
 
-       class_load_intern(cb);
+/* Class Operations ***********************************************************/
 
-       /* free memory */
-       FREE(cb, classbuffer);
+/* DefineClass *****************************************************************
 
-       /* measure time */
-       if (getloadingtime) {
-               stoptime = getcputime();
-               loadingtime += (stoptime - starttime);
-       }
+   Loads a class from a buffer of raw class data. The buffer
+   containing the raw class data is not referenced by the VM after the
+   DefineClass call returns, and it may be discarded if desired.
 
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
-       tables_unlock();
-       compiler_unlock();
-#else
-       intsRestore();
-#endif
-#endif
+*******************************************************************************/
 
-       if (*exceptionptr)
-               return NULL;
+jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
+                                  const jbyte *buf, jsize bufLen)
+{
+       java_lang_ClassLoader *cl;
+       java_lang_String      *s;
+       java_bytearray        *ba;
+       jclass                 c;
 
-       /* XXX link the class here? */
-       class_link(clazz);
+       STATS(jniinvokation();)
 
-       if (*exceptionptr)
-               return NULL;
+       cl = (java_lang_ClassLoader *) loader;
+       s = javastring_new_char(name);
+       ba = (java_bytearray *) buf;
 
-       if (clazz)
-               clazz->classloader = loader;
+       c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
+                                                                                                                 0, bufLen, NULL);
 
-       return clazz;
+       return c;
 }
 
 
-/*************** loads locally defined class with the specified name **************/
+/* FindClass *******************************************************************
+
+   This function loads a locally-defined class. It searches the
+   directories and zip files specified by the CLASSPATH environment
+   variable for the class with the specified name.
 
-jclass FindClass(JNIEnv* env, const char *name) 
+*******************************************************************************/
+
+jclass FindClass(JNIEnv *env, const char *name)
 {
-       classinfo *c;  
-  
-       c = class_new(utf_new_char_classname((char *) name));
+       utf               *u;
+       classinfo         *c;
+       java_objectheader *cl;
 
-       class_load(c);
+       STATS(jniinvokation();)
 
-       if (*exceptionptr)
-               return NULL;
+       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
 
-       class_link(c);
+       if (!(c = load_class_from_classloader(u, cl)))
+               return NULL;
 
-       if (*exceptionptr)
+       if (!link_class(c))
                return NULL;
 
+       use_class_as_object(c);
+
        return c;
 }
   
 
-/*********************************************************************************** 
+/* 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(JNIEnvenv, jobject method)
+jmethodID FromReflectedMethod(JNIEnv *env, jobject method)
 {
-       /* log_text("JNI-Call: FromReflectedMethod"); */
+       methodinfo *mi;
+       classinfo  *c;
+       s4          slot;
 
-       return 0;
+       STATS(jniinvokation();)
+
+       if (method == NULL)
+               return NULL;
+       
+       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);
+       }
+
+       mi = &(c->methods[slot]);
+
+       return mi;
 }
 
 
-/*************** return superclass of the class represented by sub ****************/
+/* GetSuperclass ***************************************************************
+
+   If clazz represents any class other than the class Object, then
+   this function returns the object that represents the superclass of
+   the class specified by clazz.
+
+*******************************************************************************/
  
-jclass GetSuperclass(JNIEnv* env, jclass sub) 
+jclass GetSuperclass(JNIEnv *env, jclass sub)
 {
        classinfo *c;
+       STATS(jniinvokation();)
 
-       c = ((classinfo*) sub)->super;
+       c = ((classinfo *) sub)->super.cls;
 
-       if (!c) return NULL; 
+       if (!c)
+               return NULL;
 
        use_class_as_object(c);
 
-       return c;               
+       return c;
 }
   
  
-/*********************** check whether sub can be cast to sup  ********************/
-  
-jboolean IsAssignableForm(JNIEnv* env, jclass sub, jclass sup)
+/* IsAssignableFrom ************************************************************
+
+   Determines whether an object of sub can be safely cast to sup.
+
+*******************************************************************************/
+
+jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
 {
-       return builtin_isanysubclass(sub, sup);
+       STATS(jniinvokation();)
+       return Java_java_lang_VMClass_isAssignableFrom(env,
+                                                                                                  NULL,
+                                                                                                  (java_lang_Class *) sup,
+                                                                                                  (java_lang_Class *) sub);
 }
 
 
@@ -891,39 +808,50 @@ jboolean IsAssignableForm(JNIEnv* env, jclass sub, jclass sup)
 
 jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic)
 {
-       /* log_text("JNI-Call: ToReflectedField"); */
-
+       log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!!!");
+       STATS(jniinvokation();)
        return NULL;
 }
 
 
-/***************** throw java.lang.Throwable object  ******************************/
+/* Throw ***********************************************************************
+
+   Causes a java.lang.Throwable object to be thrown.
+
+*******************************************************************************/
 
-jint Throw(JNIEnvenv, jthrowable obj)
+jint Throw(JNIEnv *env, jthrowable obj)
 {
-       *exceptionptr = (java_objectheader*) obj;
+       *exceptionptr = (java_objectheader *) obj;
+       STATS(jniinvokation();)
 
-       return 0;
+       return JNI_OK;
 }
 
 
-/*******************************************************************************
+/* ThrowNew ********************************************************************
 
-       create exception object from the class clazz with the 
-       specified message and cause it to be thrown
+   Constructs an exception object from the specified class with the
+   message specified by message and causes that exception to be
+   thrown.
 
 *******************************************************************************/
 
 jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
 {
        java_lang_Throwable *o;
+       java_lang_String    *s;
+       STATS(jniinvokation();)
+
+       s = (java_lang_String *) javastring_new_char(msg);
 
        /* instantiate exception object */
-       o = (java_lang_Throwable *) native_new_and_init((classinfo*) clazz);
 
-       if (!o) return (-1);
+       o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz,
+                                                                                                                  s);
 
-       o->detailMessage = (java_lang_String *) javastring_new_char((char *) msg);
+       if (!o)
+               return -1;
 
        *exceptionptr = (java_objectheader *) o;
 
@@ -931,43 +859,95 @@ jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
 }
 
 
-/************************* check if exception occured *****************************/
+/* ExceptionOccurred ***********************************************************
+
+   Determines if an exception is being thrown. The exception stays
+   being thrown until either the native code calls ExceptionClear(),
+   or the Java code handles the exception.
 
-jthrowable ExceptionOccurred (JNIEnv* env) 
+*******************************************************************************/
+
+jthrowable ExceptionOccurred(JNIEnv *env)
 {
+       STATS(jniinvokation();)
        return (jthrowable) *exceptionptr;
 }
 
-/********** print exception and a backtrace of the stack (for debugging) **********/
 
-void ExceptionDescribe (JNIEnv* env) 
+/* ExceptionDescribe ***********************************************************
+
+   Prints an exception and a backtrace of the stack to a system
+   error-reporting channel, such as stderr. This is a convenience
+   routine provided for debugging.
+
+*******************************************************************************/
+
+void ExceptionDescribe(JNIEnv *env)
 {
-       utf_display((*exceptionptr)->vftbl->class->name);
-       printf ("\n");
-       fflush (stdout);        
+       java_objectheader *e;
+       methodinfo        *m;
+       STATS(jniinvokation();)
+
+       e = *exceptionptr;
+
+       if (e) {
+               /* clear exception, because we are calling jit code again */
+
+               *exceptionptr = NULL;
+
+               /* get printStackTrace method from exception class */
+
+               m = class_resolveclassmethod(e->vftbl->class,
+                                                                        utf_printStackTrace,
+                                                                        utf_void__void,
+                                                                        NULL,
+                                                                        true);
+
+               if (!m)
+                       /* XXX what should we do? */
+                       return;
+
+               /* print the stacktrace */
+
+               asm_calljavafunction(m, e, NULL, NULL, NULL);
+       }
 }
 
 
-/******************* clear any exception currently being thrown *******************/
+/* ExceptionClear **************************************************************
 
-void ExceptionClear (JNIEnv* env) 
+   Clears any exception that is currently being thrown. If no
+   exception is currently being thrown, this routine has no effect.
+
+*******************************************************************************/
+
+void ExceptionClear(JNIEnv *env)
 {
-       *exceptionptr = NULL;   
+       STATS(jniinvokation();)
+       *exceptionptr = NULL;
 }
 
 
-/********** raises a fatal error and does not expect the VM to recover ************/
+/* FatalError ******************************************************************
+
+   Raises a fatal error and does not expect the VM to recover. This
+   function does not return.
 
-void FatalError (JNIEnv* env, const char *msg)
+*******************************************************************************/
+
+void FatalError(JNIEnv *env, const char *msg)
 {
-       panic((char *) msg);    
+       STATS(jniinvokation();)
+       throw_cacao_exception_exit(string_java_lang_InternalError, msg);
 }
 
+
 /******************* creates a new local reference frame **************************/ 
 
 jint PushLocalFrame(JNIEnv* env, jint capacity)
 {
-       /* empty */
+       log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!");
+       STATS(jniinvokation();)
 
        return 0;
 }
@@ -976,45 +956,50 @@ jint PushLocalFrame(JNIEnv* env, jint capacity)
 
 jobject PopLocalFrame(JNIEnv* env, jobject result)
 {
-       /* empty */
+       log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!");
+       STATS(jniinvokation();)
 
        return NULL;
 }
-    
 
-/** Creates a new global reference to the object referred to by the obj argument **/
-    
-jobject NewGlobalRef(JNIEnv* env, jobject lobj)
-{
-       return lobj;
-}
 
-/*************  Deletes the global reference pointed to by globalRef **************/
+/* DeleteLocalRef **************************************************************
 
-void DeleteGlobalRef (JNIEnv* env, jobject gref)
+   Deletes the local reference pointed to by localRef.
+
+*******************************************************************************/
+
+void DeleteLocalRef(JNIEnv *env, jobject localRef)
 {
-       /* empty */
+       STATS(jniinvokation();)
+
+       log_text("JNI-Call: DeleteLocalRef: IMPLEMENT ME!");
 }
 
 
-/*************** Deletes the local reference pointed to by localRef ***************/
+/* IsSameObject ****************************************************************
 
-void DeleteLocalRef (JNIEnv* env, jobject localRef)
-{
-       /* empty */
-}
+   Tests whether two references refer to the same Java object.
 
-/********** Tests whether two references refer to the same Java object ************/
+*******************************************************************************/
 
-jboolean IsSameObject (JNIEnv* env, jobject obj1, jobject obj2)
+jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
 {
-       return (obj1==obj2);
+       STATS(jniinvokation();)
+       return (ref1 == ref2);
 }
 
-/***** Creates a new local reference that refers to the same object as ref  *******/
 
-jobject NewLocalRef (JNIEnv* env, jobject ref)
+/* NewLocalRef *****************************************************************
+
+   Creates a new local reference that refers to the same object as ref.
+
+*******************************************************************************/
+
+jobject NewLocalRef(JNIEnv *env, jobject ref)
 {
+       log_text("JNI-Call: NewLocalRef: IMPLEMENT ME!");
+       STATS(jniinvokation();)
        return ref;
 }
 
@@ -1027,53 +1012,78 @@ jobject NewLocalRef (JNIEnv* env, jobject ref)
 
 jint EnsureLocalCapacity (JNIEnv* env, jint capacity)
 {
+       STATS(jniinvokation();)
        return 0; /* return 0 on success */
 }
 
 
-/********* Allocates a new Java object without invoking a constructor *************/
+/* AllocObject *****************************************************************
+
+   Allocates a new Java object without invoking any of the
+   constructors for the object. Returns a reference to the object.
+
+*******************************************************************************/
 
-jobject AllocObject (JNIEnv* env, jclass clazz)
+jobject AllocObject(JNIEnv *env, jclass clazz)
 {
-        java_objectheader *o = builtin_new(clazz);     
+       java_objectheader *o;
+       STATS(jniinvokation();)
+
+       if ((clazz->flags & ACC_INTERFACE) || (clazz->flags & ACC_ABSTRACT)) {
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_InstantiationException,
+                                                                        clazz->name);
+               return NULL;
+       }
+               
+       o = builtin_new(clazz);
+
        return o;
 }
 
 
-/*********************************************************************************** 
+/* NewObject *******************************************************************
 
-       Constructs a new Java object
-       arguments that are to be passed to the constructor are placed after methodID
+   Constructs a new Java object. The method ID indicates which
+   constructor method to invoke. This ID must be obtained by calling
+   GetMethodID() with <init> as the method name and void (V) as the
+   return type.
 
-***********************************************************************************/
+*******************************************************************************/
 
-jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
+jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        java_objectheader *o;
        void* args[3];
-       int argcount=get_parametercount(methodID);
+       int argcount=methodID->parseddesc->paramcount;
        int i;
        va_list vaargs;
+       STATS(jniinvokation();)
 
-       /* log_text("JNI-Call: NewObject"); */
-
+#ifdef arglimit
        if (argcount > 3) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. NewObject does not support that");
                return 0;
        }
+#endif
 
+       /* create object */
+
+       o = builtin_new(clazz);
        
-       o = builtin_new (clazz);         /*          create object */
-       
-       if (!o) return NULL;
+       if (!o)
+               return NULL;
 
-       va_start(vaargs,methodID);
-       for (i=0;i<argcount;i++) {
-               args[i]=va_arg(vaargs,void*);
+       va_start(vaargs, methodID);
+       for (i = 0; i < argcount; i++) {
+               args[i] = va_arg(vaargs, void*);
        }
        va_end(vaargs);
-       asm_calljavafunction(methodID,o,args[0],args[1],args[2]);
+
+       /* call constructor */
+
+       asm_calljavafunction(methodID, o, args[0], args[1], args[2]);
 
        return o;
 }
@@ -1088,7 +1098,8 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
 
 jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
 {
-       /* log_text("JNI-Call: NewObjectV"); */
+       log_text("JNI-Call: NewObjectV");
+       STATS(jniinvokation();)
 
        return NULL;
 }
@@ -1104,29 +1115,47 @@ jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
 
 jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       /* log_text("JNI-Call: NewObjectA"); */
+       log_text("JNI-Call: NewObjectA");
+       STATS(jniinvokation();)
 
        return NULL;
 }
 
 
-/************************ returns the class of an object **************************/ 
+/* GetObjectClass **************************************************************
+
+ Returns the class of an object.
+
+*******************************************************************************/
 
-jclass GetObjectClass(JNIEnvenv, jobject obj)
+jclass GetObjectClass(JNIEnv *env, jobject obj)
 {
-       classinfo *c = obj->vftbl->class;
+       classinfo *c;
+       STATS(jniinvokation();)
+       
+       if (!obj || !obj->vftbl)
+               return NULL;
 
+       c = obj->vftbl->class;
        use_class_as_object(c);
-
        return c;
 }
 
 
-/************* tests whether an object is an instance of a class ******************/
+/* IsInstanceOf ****************************************************************
+
+   Tests whether an object is an instance of a class.
+
+*******************************************************************************/
 
-jboolean IsInstanceOf(JNIEnvenv, jobject obj, jclass clazz)
+jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
 {
-       return builtin_instanceof(obj,clazz);
+       STATS(jniinvokation();)
+
+       return Java_java_lang_VMClass_isInstance(env,
+                                                                                        NULL,
+                                                                                        (java_lang_Class *) clazz,
+                                                                                        (java_lang_Object *) obj);
 }
 
 
@@ -1134,9 +1163,23 @@ jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
  
 jfieldID FromReflectedField(JNIEnv* env, jobject field)
 {
-       log_text("JNI-Call: FromReflectedField");
-
-       return 0;
+       java_lang_reflect_Field *f;
+       classinfo *c;
+       jfieldID fid;   /* the JNI-fieldid of the wrapping object */
+       STATS(jniinvokation();)
+       /*log_text("JNI-Call: FromReflectedField");*/
+
+       f=(java_lang_reflect_Field *)field;
+       if (f==0) return 0;
+       c=(classinfo*)(f->declaringClass);
+       if ( (f->slot<0) || (f->slot>=c->fieldscount)) {
+               /*this usually means a severe internal cacao error or somebody
+               tempered around with the reflected method*/
+               log_text("error illegal slot for field in class(FromReflectedField)");
+               assert(0);
+       }
+       fid=&(c->fields[f->slot]);
+       return fid;
 }
 
 
@@ -1150,28 +1193,34 @@ jfieldID FromReflectedField(JNIEnv* env, jobject field)
 jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
 {
        log_text("JNI-Call: ToReflectedMethod");
+       STATS(jniinvokation();)
 
        return NULL;
 }
 
 
-/**************** returns the method ID for an instance method ********************/
+/* GetMethodID *****************************************************************
+
+   returns the method ID for an instance method
+
+*******************************************************************************/
 
 jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *sig)
 {
        jmethodID m;
+       STATS(jniinvokation();)
 
-       m = class_resolvemethod (
-               clazz, 
-               utf_new_char ((char*) name), 
-               utf_new_char ((char*) sig)
-       );
+       m = class_resolvemethod(clazz, 
+                                                       utf_new_char((char *) name), 
+                                                       utf_new_char((char *) sig));
 
-       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-       else if (m->flags & ACC_STATIC)   {
-               m=0;
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       if (!m || (m->flags & ACC_STATIC)) {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoSuchMethodError, name);
+
+               return NULL;
        }
+
        return m;
 }
 
@@ -1182,6 +1231,7 @@ jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jobject ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
 /*     log_text("JNI-Call: CallObjectMethod");*/
 
@@ -1195,6 +1245,7 @@ jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        return callObjectMethod(obj,methodID,args);
 }
 
@@ -1202,6 +1253,7 @@ jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list
 jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
 {
        log_text("JNI-Call: CallObjectMethodA");
+       STATS(jniinvokation();)
 
        return NULL;
 }
@@ -1213,11 +1265,12 @@ jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jboolean ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
 /*     log_text("JNI-Call: CallBooleanMethod");*/
 
        va_start(vaargs,methodID);
-       ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',vaargs);
+       ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BOOLEAN,vaargs);
        va_end(vaargs);
        return ret;
 
@@ -1225,12 +1278,15 @@ jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jboolean CallBooleanMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',args);
+       STATS(jniinvokation();)
+
+       return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BOOLEAN,args);
 
 }
 
 jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallBooleanMethodA");
 
        return 0;
@@ -1240,11 +1296,12 @@ jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jbyte ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
 /*     log_text("JNI-Call: CallVyteMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_virtual(obj,methodID),'B',vaargs);
+       ret = callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BYTE,vaargs);
        va_end(vaargs);
        return ret;
 
@@ -1253,13 +1310,16 @@ jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
 /*     log_text("JNI-Call: CallByteMethodV");*/
-       return callIntegerMethod(obj,methodID,'B',args);
+       STATS(jniinvokation();)
+
+       return callIntegerMethod(obj,methodID,PRIMITIVETYPE_BYTE,args);
 }
 
 
 jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallByteMethodA");
+       STATS(jniinvokation();)
 
        return 0;
 }
@@ -1269,11 +1329,12 @@ jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jchar ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
 /*     log_text("JNI-Call: CallCharMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'C', vaargs);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_CHAR, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -1282,13 +1343,17 @@ jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
+
 /*     log_text("JNI-Call: CallCharMethodV");*/
-       return callIntegerMethod(obj,get_virtual(obj,methodID),'C',args);
+       return callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_CHAR,args);
 }
 
 
 jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
+
        log_text("JNI-Call: CallCharMethodA");
 
        return 0;
@@ -1299,11 +1364,12 @@ jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jshort ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
 /*     log_text("JNI-Call: CallShortMethod");*/
 
        va_start(vaargs, methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'S', vaargs);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_SHORT, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -1312,12 +1378,14 @@ jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       return callIntegerMethod(obj, get_virtual(obj, methodID), 'S', args);
+       STATS(jniinvokation();)
+       return callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_SHORT, args);
 }
 
 
 jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallShortMethodA");
 
        return 0;
@@ -1329,9 +1397,10 @@ jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jint ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'I', vaargs);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_INT, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -1340,12 +1409,14 @@ jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       return callIntegerMethod(obj, get_virtual(obj, methodID), 'I', args);
+       STATS(jniinvokation();)
+       return callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_INT, args);
 }
 
 
 jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallIntMethodA");
 
        return 0;
@@ -1355,22 +1426,28 @@ jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 
 jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallLongMethod");
+       jlong ret;
+       va_list vaargs;
+       STATS(jniinvokation();)
+       
+       va_start(vaargs,methodID);
+       ret = callLongMethod(obj,get_virtual(obj, methodID),vaargs);
+       va_end(vaargs);
 
-       return 0;
+       return ret;
 }
 
 
 jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallLongMethodV");
-
-       return 0;
+       STATS(jniinvokation();)
+       return  callLongMethod(obj,get_virtual(obj, methodID),args);
 }
 
 
 jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallLongMethodA");
 
        return 0;
@@ -1383,10 +1460,11 @@ jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
        jfloat ret;
        va_list vaargs;
 
+       STATS(jniinvokation();)
 /*     log_text("JNI-Call: CallFloatMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'F');
+       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, PRIMITIVETYPE_FLOAT);
        va_end(vaargs);
 
        return ret;
@@ -1395,13 +1473,15 @@ jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallFloatMethodV");
-       return callFloatMethod(obj, get_virtual(obj, methodID), args, 'F');
+       return callFloatMethod(obj, get_virtual(obj, methodID), args, PRIMITIVETYPE_FLOAT);
 }
 
 
 jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallFloatMethodA");
 
        return 0;
@@ -1413,11 +1493,12 @@ jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jdouble ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
 /*     log_text("JNI-Call: CallDoubleMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'D');
+       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, PRIMITIVETYPE_DOUBLE);
        va_end(vaargs);
 
        return ret;
@@ -1426,13 +1507,15 @@ jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallDoubleMethodV");
-       return callFloatMethod(obj, get_virtual(obj, methodID), args, 'D');
+       return callFloatMethod(obj, get_virtual(obj, methodID), args, PRIMITIVETYPE_DOUBLE);
 }
 
 
 jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallDoubleMethodA");
        return 0;
 }
@@ -1442,11 +1525,10 @@ jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *
 void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        va_list vaargs;
-
-/*      log_text("JNI-Call: CallVoidMethod");*/
+       STATS(jniinvokation();)
 
        va_start(vaargs,methodID);
-       (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs);
+       (void) callIntegerMethod(obj, get_virtual(obj, methodID),TYPE_VOID, vaargs);
        va_end(vaargs);
 }
 
@@ -1454,12 +1536,14 @@ void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 void CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallVoidMethodV");
-       (void)callIntegerMethod(obj,get_virtual(obj,methodID),'V',args);
+       STATS(jniinvokation();)
+       (void)callIntegerMethod(obj,get_virtual(obj,methodID),TYPE_VOID,args);
 }
 
 
 void CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallVoidMethodA");
 }
 
@@ -1467,6 +1551,7 @@ void CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * arg
 
 jobject CallNonvirtualObjectMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualObjectMethod");
 
        return NULL;
@@ -1475,6 +1560,7 @@ jobject CallNonvirtualObjectMethod (JNIEnv *env, jobject obj, jclass clazz, jmet
 
 jobject CallNonvirtualObjectMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualObjectMethodV");
 
        return NULL;
@@ -1483,6 +1569,7 @@ jobject CallNonvirtualObjectMethodV (JNIEnv *env, jobject obj, jclass clazz, jme
 
 jobject CallNonvirtualObjectMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualObjectMethodA");
 
        return NULL;
@@ -1494,11 +1581,12 @@ jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jm
 {
        jboolean ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
 /*     log_text("JNI-Call: CallNonvirtualBooleanMethod");*/
 
        va_start(vaargs,methodID);
-       ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',vaargs);
+       ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BOOLEAN,vaargs);
        va_end(vaargs);
        return ret;
 
@@ -1507,13 +1595,15 @@ jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jm
 
 jboolean CallNonvirtualBooleanMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
 /*     log_text("JNI-Call: CallNonvirtualBooleanMethodV");*/
-       return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',args);
+       return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BOOLEAN,args);
 }
 
 
 jboolean CallNonvirtualBooleanMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualBooleanMethodA");
 
        return 0;
@@ -1526,10 +1616,11 @@ jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodI
        jbyte ret;
        va_list vaargs;
 
+       STATS(jniinvokation();)
 /*     log_text("JNI-Call: CallNonvirutalByteMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',vaargs);
+       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BYTE,vaargs);
        va_end(vaargs);
        return ret;
 }
@@ -1537,14 +1628,16 @@ jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodI
 
 jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        /*log_text("JNI-Call: CallNonvirtualByteMethodV"); */
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',args);
+       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BYTE,args);
 
 }
 
 
 jbyte CallNonvirtualByteMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualByteMethodA");
 
        return 0;
@@ -1557,10 +1650,11 @@ jchar CallNonvirtualCharMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodI
        jchar ret;
        va_list vaargs;
 
+       STATS(jniinvokation();)
 /*     log_text("JNI-Call: CallNonVirtualCharMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',vaargs);
+       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_CHAR,vaargs);
        va_end(vaargs);
        return ret;
 }
@@ -1568,13 +1662,15 @@ jchar CallNonvirtualCharMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodI
 
 jchar CallNonvirtualCharMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        /*log_text("JNI-Call: CallNonvirtualCharMethodV");*/
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',args);
+       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_CHAR,args);
 }
 
 
 jchar CallNonvirtualCharMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualCharMethodA");
 
        return 0;
@@ -1586,11 +1682,12 @@ jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmetho
 {
        jshort ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*log_text("JNI-Call: CallNonvirtualShortMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',vaargs);
+       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_SHORT,vaargs);
        va_end(vaargs);
        return ret;
 }
@@ -1598,13 +1695,15 @@ jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmetho
 
 jshort CallNonvirtualShortMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        /*log_text("JNI-Call: CallNonvirtualShortMethodV");*/
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',args);
+       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_SHORT,args);
 }
 
 
 jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualShortMethodA");
 
        return 0;
@@ -1617,11 +1716,12 @@ jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID
 
         jint ret;
         va_list vaargs;
+       STATS(jniinvokation();)
 
        /*log_text("JNI-Call: CallNonvirtualIntMethod");*/
 
         va_start(vaargs,methodID);
-        ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',vaargs);
+        ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_INT,vaargs);
         va_end(vaargs);
         return ret;
 }
@@ -1629,13 +1729,15 @@ jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID
 
 jint CallNonvirtualIntMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        /*log_text("JNI-Call: CallNonvirtualIntMethodV");*/
-        return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',args);
+        return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_INT,args);
 }
 
 
 jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualIntMethodA");
 
        return 0;
@@ -1645,6 +1747,7 @@ jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID
 
 jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualLongMethod");
 
        return 0;
@@ -1653,6 +1756,7 @@ jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodI
 
 jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualLongMethodV");
 
        return 0;
@@ -1661,6 +1765,7 @@ jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethod
 
 jlong CallNonvirtualLongMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualLongMethodA");
 
        return 0;
@@ -1672,12 +1777,13 @@ jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmetho
 {
        jfloat ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/
 
 
        va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'F');
+       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,PRIMITIVETYPE_FLOAT);
        va_end(vaargs);
        return ret;
 
@@ -1686,13 +1792,15 @@ jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmetho
 
 jfloat CallNonvirtualFloatMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualFloatMethodV");
-       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'F');
+       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,PRIMITIVETYPE_FLOAT);
 }
 
 
 jfloat CallNonvirtualFloatMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualFloatMethodA");
 
        return 0;
@@ -1704,10 +1812,11 @@ jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmet
 {
        jdouble ret;
        va_list vaargs;
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualDoubleMethod");
 
        va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'D');
+       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,PRIMITIVETYPE_DOUBLE);
        va_end(vaargs);
        return ret;
 
@@ -1716,13 +1825,15 @@ jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmet
 
 jdouble CallNonvirtualDoubleMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
 /*     log_text("JNI-Call: CallNonvirtualDoubleMethodV");*/
-       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'D');
+       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,PRIMITIVETYPE_DOUBLE);
 }
 
 
 jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualDoubleMethodA");
 
        return 0;
@@ -1733,11 +1844,12 @@ jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jme
 void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
         va_list vaargs;
+       STATS(jniinvokation();)
 
 /*      log_text("JNI-Call: CallNonvirtualVoidMethod");*/
 
         va_start(vaargs,methodID);
-        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',vaargs);
+        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),TYPE_VOID,vaargs);
         va_end(vaargs);
 
 }
@@ -1746,14 +1858,16 @@ void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID
 void CallNonvirtualVoidMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
 /*     log_text("JNI-Call: CallNonvirtualVoidMethodV");*/
+       STATS(jniinvokation();)
 
-        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',args);
+        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),TYPE_VOID,args);
 
 }
 
 
 void CallNonvirtualVoidMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallNonvirtualVoidMethodA");
 }
 
@@ -1763,6 +1877,8 @@ jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *si
 {
        jfieldID f;
 
+       STATS(jniinvokation();)
+
 /*     log_text("========================= searching for:");
        log_text(name);
        log_text(sig);*/
@@ -1772,7 +1888,7 @@ jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *si
                            ); 
        
        if (!f) { 
-/*             utf_display(clazz->name);
+               /*utf_display(clazz->name);
                log_text(name);
                log_text(sig);*/
                *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
@@ -1785,6 +1901,7 @@ jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *si
 jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig)
 {
     jfieldID id = GetFieldID(env, clazz, name, sig);
+       STATS(jniinvokation();)
 
     if (!id) {
        log_text("class:");
@@ -1794,113 +1911,161 @@ 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;
 }
 
 jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       /*
+       jobject dbg,dretval,*dpretval;  
+       long int dli1, dli2, dli3;
+
+       printf("GetObjectField(1): thread: %s obj: %p name: %s desc: %s \n",GetStringUTFChars(env,
+                        ((threadobject *) THREADOBJECT)->o
+                        .thread->name,NULL)
+                        ,obj,((fieldinfo*)fieldID)->name->text,(fieldID->descriptor)->text);
+
+       dbg = getField(obj,jobject,fieldID);
+       dli1 = (long int) obj;
+       dli2 = (long int) fieldID->offset;
+       dli3 = dli1+dli2;
+       dpretval = (jobject*) dli3;
+       dretval = *dpretval;
+       jclass tmp;
+       jmethodID mid;
+       jstring jstr;
+
+       tmp = FindClass(env, "java/lang/Object");
+       mid = GetMethodID(env,tmp,"toString","()Ljava/lang/String;");
+       jstr = CallObjectMethod(env,dbg,mid);*/
+
+/*     printf("GetObjectField(2): retval %p (obj: %#lx + offset: %#lx = %#lx (jobject*) %p (jobject) %p\n"
+       ,dbg, dli1, dli2, dli3,dpretval, dretval);*/
+
+
+/*     return dbg;*/
+       STATS(jniinvokation();)
+
        return getField(obj,jobject,fieldID);
 }
 
 jboolean GetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
        return getField(obj,jboolean,fieldID);
 }
 
 
 jbyte GetByteField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
                return getField(obj,jbyte,fieldID);
 }
 
 
 jchar GetCharField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
        return getField(obj,jchar,fieldID);
 }
 
 
 jshort GetShortField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
        return getField(obj,jshort,fieldID);
 }
 
 
 jint GetIntField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
        return getField(obj,jint,fieldID);
 }
 
 
 jlong GetLongField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
        return getField(obj,jlong,fieldID);
 }
 
 
 jfloat GetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
        return getField(obj,jfloat,fieldID);
 }
 
 
 jdouble GetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       STATS(jniinvokation();)
        return getField(obj,jdouble,fieldID);
 }
 
 void SetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val)
 {
+       STATS(jniinvokation();)
         setField(obj,jobject,fieldID,val);
 }
 
 
 void SetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val)
 {
+       STATS(jniinvokation();)
         setField(obj,jboolean,fieldID,val);
 }
 
 
 void SetByteField (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val)
 {
+       STATS(jniinvokation();)
         setField(obj,jbyte,fieldID,val);
 }
 
 
 void SetCharField (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val)
 {
+       STATS(jniinvokation();)
         setField(obj,jchar,fieldID,val);
 }
 
 
 void SetShortField (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val)
 {
+       STATS(jniinvokation();)
         setField(obj,jshort,fieldID,val);
 }
 
 
 void SetIntField (JNIEnv *env, jobject obj, jfieldID fieldID, jint val)
 {
+       STATS(jniinvokation();)
         setField(obj,jint,fieldID,val);
 }
 
 
 void SetLongField (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val)
 {
+       STATS(jniinvokation();)
         setField(obj,jlong,fieldID,val);
 }
 
 
 void SetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val)
 {
+       STATS(jniinvokation();)
         setField(obj,jfloat,fieldID,val);
 }
 
 
 void SetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val)
 {
+       STATS(jniinvokation();)
         setField(obj,jdouble,fieldID,val);
 }
 
@@ -1910,15 +2075,17 @@ void SetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val)
 jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
 {
        jmethodID m;
+       STATS(jniinvokation();)
 
        m = class_resolvemethod(clazz,
                                                        utf_new_char((char *) name),
                                                        utf_new_char((char *) sig));
 
-       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-       else if (!(m->flags & ACC_STATIC))   {
-               m=0;
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       if (!m || !(m->flags & ACC_STATIC)) {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoSuchMethodError, name);
+
+               return NULL;
        }
 
        return m;
@@ -1929,6 +2096,7 @@ jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ..
 {
        jobject ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /* log_text("JNI-Call: CallStaticObjectMethod");*/
 
@@ -1942,6 +2110,7 @@ jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ..
 
 jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        /* log_text("JNI-Call: CallStaticObjectMethodV"); */
        
        return callObjectMethod(0,methodID,args);
@@ -1950,6 +2119,7 @@ jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, v
 
 jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticObjectMethodA");
 
        return NULL;
@@ -1960,9 +2130,10 @@ jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
 {
        jboolean ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        va_start(vaargs, methodID);
-       ret = (jboolean) callIntegerMethod(0, methodID, 'Z', vaargs);
+       ret = (jboolean) callIntegerMethod(0, methodID, PRIMITIVETYPE_BOOLEAN, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -1971,12 +2142,14 @@ jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
 
 jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       return (jboolean) callIntegerMethod(0, methodID, 'Z', args);
+       STATS(jniinvokation();)
+       return (jboolean) callIntegerMethod(0, methodID, PRIMITIVETYPE_BOOLEAN, args);
 }
 
 
 jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticBooleanMethodA");
 
        return 0;
@@ -1987,11 +2160,12 @@ jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        jbyte ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*      log_text("JNI-Call: CallStaticByteMethod");*/
 
        va_start(vaargs, methodID);
-       ret = (jbyte) callIntegerMethod(0, methodID, 'B', vaargs);
+       ret = (jbyte) callIntegerMethod(0, methodID, PRIMITIVETYPE_BYTE, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -2000,12 +2174,14 @@ jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 
 jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       return (jbyte) callIntegerMethod(0, methodID, 'B', args);
+       STATS(jniinvokation();)
+       return (jbyte) callIntegerMethod(0, methodID, PRIMITIVETYPE_BYTE, args);
 }
 
 
 jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticByteMethodA");
 
        return 0;
@@ -2016,11 +2192,12 @@ jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        jchar ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*      log_text("JNI-Call: CallStaticByteMethod");*/
 
        va_start(vaargs, methodID);
-       ret = (jchar) callIntegerMethod(0, methodID, 'C', vaargs);
+       ret = (jchar) callIntegerMethod(0, methodID, PRIMITIVETYPE_CHAR, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -2029,12 +2206,14 @@ jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 
 jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       return (jchar) callIntegerMethod(0, methodID, 'C', args);
+       STATS(jniinvokation();)
+       return (jchar) callIntegerMethod(0, methodID, PRIMITIVETYPE_CHAR, args);
 }
 
 
 jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticCharMethodA");
 
        return 0;
@@ -2046,11 +2225,12 @@ jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        jshort ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*      log_text("JNI-Call: CallStaticByteMethod");*/
 
        va_start(vaargs, methodID);
-       ret = (jshort) callIntegerMethod(0, methodID, 'S', vaargs);
+       ret = (jshort) callIntegerMethod(0, methodID, PRIMITIVETYPE_SHORT, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -2059,13 +2239,15 @@ jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 
 jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        /*log_text("JNI-Call: CallStaticShortMethodV");*/
-       return (jshort) callIntegerMethod(0, methodID, 'S', args);
+       return (jshort) callIntegerMethod(0, methodID, PRIMITIVETYPE_SHORT, args);
 }
 
 
 jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticShortMethodA");
 
        return 0;
@@ -2077,11 +2259,12 @@ jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        jint ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*      log_text("JNI-Call: CallStaticIntMethod");*/
 
        va_start(vaargs, methodID);
-       ret = callIntegerMethod(0, methodID, 'I', vaargs);
+       ret = callIntegerMethod(0, methodID, PRIMITIVETYPE_INT, vaargs);
        va_end(vaargs);
 
        return ret;
@@ -2090,14 +2273,16 @@ jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 
 jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticIntMethodV");
 
-       return callIntegerMethod(0, methodID, 'I', args);
+       return callIntegerMethod(0, methodID, PRIMITIVETYPE_INT, args);
 }
 
 
 jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticIntMethodA");
 
        return 0;
@@ -2109,6 +2294,7 @@ jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        jlong ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*      log_text("JNI-Call: CallStaticLongMethod");*/
 
@@ -2122,6 +2308,7 @@ jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 
 jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticLongMethodV");
        
        return callLongMethod(0,methodID,args);
@@ -2130,6 +2317,7 @@ jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_li
 
 jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticLongMethodA");
 
        return 0;
@@ -2141,11 +2329,12 @@ jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        jfloat ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*      log_text("JNI-Call: CallStaticLongMethod");*/
 
        va_start(vaargs, methodID);
-       ret = callFloatMethod(0, methodID, vaargs, 'F');
+       ret = callFloatMethod(0, methodID, vaargs, PRIMITIVETYPE_FLOAT);
        va_end(vaargs);
 
        return ret;
@@ -2154,14 +2343,16 @@ jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 
 jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
 
-       return callFloatMethod(0, methodID, args, 'F');
+       return callFloatMethod(0, methodID, args, PRIMITIVETYPE_FLOAT);
 
 }
 
 
 jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticFloatMethodA");
 
        return 0;
@@ -2173,11 +2364,12 @@ jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ..
 {
        jdouble ret;
        va_list vaargs;
+       STATS(jniinvokation();)
 
        /*      log_text("JNI-Call: CallStaticDoubleMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callFloatMethod(0, methodID, vaargs, 'D');
+       ret = callFloatMethod(0, methodID, vaargs, PRIMITIVETYPE_DOUBLE);
        va_end(vaargs);
 
        return ret;
@@ -2186,14 +2378,16 @@ jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ..
 
 jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticDoubleMethodV");
 
-       return callFloatMethod(0, methodID, args, 'D');
+       return callFloatMethod(0, methodID, args, PRIMITIVETYPE_DOUBLE);
 }
 
 
 jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticDoubleMethodA");
 
        return 0;
@@ -2203,11 +2397,10 @@ jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, j
 void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)
 {
        va_list vaargs;
-
-/*      log_text("JNI-Call: CallStaticVoidMethod");*/
+       STATS(jniinvokation();)
 
        va_start(vaargs, methodID);
-       (void) callIntegerMethod(0, methodID, 'V', vaargs);
+       (void) callIntegerMethod(0, methodID, TYPE_VOID, vaargs);
        va_end(vaargs);
 }
 
@@ -2215,318 +2408,519 @@ void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)
 void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallStaticVoidMethodV");
-       (void)callIntegerMethod(0, methodID, 'V', args);
+       STATS(jniinvokation();)
+       (void)callIntegerMethod(0, methodID, TYPE_VOID, args);
 }
 
 
 void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: CallStaticVoidMethodA");
 }
 
 
-/****************** JNI-functions for accessing static fields ********************/
+/* Accessing Static Fields ****************************************************/
 
-jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) 
+/* GetStaticFieldID ************************************************************
+
+   Returns the field ID for a static field of a class. The field is
+   specified by its name and signature. The GetStatic<type>Field and
+   SetStatic<type>Field families of accessor functions use field IDs
+   to retrieve static fields.
+
+*******************************************************************************/
+
+jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
 {
        jfieldID f;
+       STATS(jniinvokation();)
 
        f = jclass_findfield(clazz,
-                           utf_new_char ((char*) name), 
-                           utf_new_char ((char*) sig)
-                           ); 
+                                                utf_new_char((char *) name),
+                                                utf_new_char((char *) sig)); 
        
-       if (!f) *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
+       if (!f)
+               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
 
        return f;
 }
 
 
-jobject GetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+/* GetStatic<type>Field ********************************************************
+
+   This family of accessor routines returns the value of a static
+   field of an object.
+
+*******************************************************************************/
+
+jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticObjectField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return NULL;
+
        return fieldID->value.a;       
 }
 
 
-jboolean GetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticBooleanField: calling initialize_class %s\n",clazz->name->text);)
+
+       if (!initialize_class(clazz))
+               return false;
+
        return fieldID->value.i;       
 }
 
 
-jbyte GetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticByteField: calling initialize_class %s\n",clazz->name->text);)
+
+       if (!initialize_class(clazz))
+               return 0;
+
        return fieldID->value.i;       
 }
 
 
-jchar GetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticCharField: calling initialize_class %s\n",clazz->name->text);)
+
+       if (!initialize_class(clazz))
+               return 0;
+
        return fieldID->value.i;       
 }
 
 
-jshort GetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticShorttField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return 0;
+
        return fieldID->value.i;       
 }
 
 
-jint GetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticIntField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return 0;
+
        return fieldID->value.i;       
 }
 
 
-jlong GetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticLongField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return 0;
+
        return fieldID->value.l;
 }
 
 
-jfloat GetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticFloatField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return 0.0;
+
        return fieldID->value.f;
 }
 
 
-jdouble GetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("GetStaticDoubleField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return 0.0;
+
        return fieldID->value.d;
 }
 
 
+/*  SetStatic<type>Field *******************************************************
+
+       This family of accessor routines sets the value of a static field
+       of an object.
+
+*******************************************************************************/
 
-void SetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)
+void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticObjectField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.a = value;
 }
 
 
-void SetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value)
+void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticBooleanField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.i = value;
 }
 
 
-void SetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value)
+void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticByteField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.i = value;
 }
 
 
-void SetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value)
+void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticCharField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.i = value;
 }
 
 
-void SetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
+void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticShortField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.i = value;
 }
 
 
-void SetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value)
+void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticIntField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.i = value;
 }
 
 
-void SetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value)
+void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticLongField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.l = value;
 }
 
 
-void SetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value)
+void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticFloatField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.f = value;
 }
 
 
-void SetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value)
+void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value)
 {
-       class_init(clazz);
+       STATS(jniinvokation();)
+       JWCLINITDEBUG(printf("SetStaticDoubleField: calling initialize_class %s\n",clazz->name->text);)
+       if (!initialize_class(clazz))
+               return;
+
        fieldID->value.d = value;
 }
 
 
-/*****  create new java.lang.String object from an array of Unicode characters ****/ 
+/* String Operations **********************************************************/
+
+/* NewString *******************************************************************
+
+   Create new java.lang.String object from an array of Unicode
+   characters.
+
+*******************************************************************************/
 
-jstring NewString (JNIEnv *env, const jchar *buf, jsize len)
+jstring NewString(JNIEnv *env, const jchar *buf, jsize len)
 {
-       u4 i;
        java_lang_String *s;
-       java_chararray *a;
+       java_chararray   *a;
+       u4                i;
+
+       STATS(jniinvokation();)
        
-       s = (java_lang_String*) builtin_new (class_java_lang_String);
-       a = builtin_newarray_char (len);
+       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       a = builtin_newarray_char(len);
 
        /* javastring or characterarray could not be created */
-       if ( (!a) || (!s) ) return NULL;
+       if (!a || !s)
+               return NULL;
 
        /* copy text */
-       for (i=0; i<len; i++) a->data[i] = buf[i];
-       s -> value = a;
-       s -> offset = 0;
-       s -> count = len;
+       for (i = 0; i < len; i++)
+               a->data[i] = buf[i];
+
+       s->value = a;
+       s->offset = 0;
+       s->count = len;
 
        return (jstring) s;
 }
 
 
-static char emptyString[]="";
 static jchar emptyStringJ[]={0,0};
 
-/******************* returns the length of a Java string ***************************/
+/* GetStringLength *************************************************************
 
-jsize GetStringLength (JNIEnv *env, jstring str)
+   Returns the length (the count of Unicode characters) of a Java
+   string.
+
+*******************************************************************************/
+
+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)
 {
-       if (chars==emptyStringJ) return;
-       MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1);
+       STATS(jniinvokation();)
+
+       if (chars == emptyStringJ)
+               return;
+
+       MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1);
 }
 
-/************ create new java.lang.String object from utf8-characterarray **********/
 
-jstring NewStringUTF (JNIEnv *env, const char *utf)
+/* NewStringUTF ****************************************************************
+
+   Constructs a new java.lang.String object from an array of UTF-8 characters.
+
+*******************************************************************************/
+
+jstring NewStringUTF(JNIEnv *env, const char *bytes)
 {
-/*    log_text("NewStringUTF called");*/
-    return (jstring) javastring_new(utf_new_char((char *) utf));
+       STATS(jniinvokation();)
+    return (jstring) javastring_new(utf_new_char(bytes));
 }
 
+
 /****************** returns the utf8 length in bytes of a string *******************/
 
 jsize GetStringUTFLength (JNIEnv *env, jstring string)
 {   
     java_lang_String *s = (java_lang_String*) string;
+       STATS(jniinvokation();)
 
     return (jsize) u2_utflength(s->value->data, s->count); 
 }
 
 
-/************ 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 *******************************************************
+
+   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 str, const char* chars)
+*******************************************************************************/
+
+void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
 {
-    /*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));
-       */
+       STATS(jniinvokation();)
+
+    /* 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)
 {
-    return array->size;
+       STATS(jniinvokation();)
+
+       return array->size;
 }
 
 
-jobjectArray NewObjectArray (JNIEnv *env, jsize len, jclass clazz, jobject init)
+/* NewObjectArray **************************************************************
+
+   Constructs a new array holding objects in class elementClass. All
+   elements are initially set to initialElement.
+
+*******************************************************************************/
+
+jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)
 {
-       java_objectarray *j;
+       java_objectarray *oa;
+       s4 i;
+       STATS(jniinvokation();)
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+       if (length < 0) {
+               *exceptionptr = new_negativearraysizeexception();
                return NULL;
-    }
+       }
 
-    j = builtin_anewarray(len, clazz);
+    oa = builtin_anewarray(length, elementClass);
 
-    return j;
+       if (!oa)
+               return NULL;
+
+       /* set all elements to initialElement */
+
+       for (i = 0; i < length; i++)
+               oa->data[i] = initialElement;
+
+       return oa;
 }
 
 
 jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
 {
     jobject j = NULL;
+       STATS(jniinvokation();)
 
     if (index < array->header.size)    
                j = array->data[index];
@@ -2539,6 +2933,7 @@ jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
 
 void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val)
 {
+       STATS(jniinvokation();)
     if (index >= array->header.size)
                *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
@@ -2557,6 +2952,7 @@ void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject
 jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
 {
        java_booleanarray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2572,6 +2968,7 @@ jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
 jbyteArray NewByteArray(JNIEnv *env, jsize len)
 {
        java_bytearray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2587,6 +2984,7 @@ jbyteArray NewByteArray(JNIEnv *env, jsize len)
 jcharArray NewCharArray(JNIEnv *env, jsize len)
 {
        java_chararray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2602,6 +3000,7 @@ jcharArray NewCharArray(JNIEnv *env, jsize len)
 jshortArray NewShortArray(JNIEnv *env, jsize len)
 {
        java_shortarray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2617,6 +3016,7 @@ jshortArray NewShortArray(JNIEnv *env, jsize len)
 jintArray NewIntArray(JNIEnv *env, jsize len)
 {
        java_intarray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2632,6 +3032,7 @@ jintArray NewIntArray(JNIEnv *env, jsize len)
 jlongArray NewLongArray(JNIEnv *env, jsize len)
 {
        java_longarray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2647,6 +3048,7 @@ jlongArray NewLongArray(JNIEnv *env, jsize len)
 jfloatArray NewFloatArray(JNIEnv *env, jsize len)
 {
        java_floatarray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2662,6 +3064,7 @@ jfloatArray NewFloatArray(JNIEnv *env, jsize len)
 jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
 {
        java_doublearray *j;
+       STATS(jniinvokation();)
 
     if (len < 0) {
                *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
@@ -2674,369 +3077,733 @@ 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)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jbyte * GetByteArrayElements (JNIEnv *env, jbyteArray array, jboolean *isCopy)
+jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jchar * GetCharArrayElements (JNIEnv *env, jcharArray array, jboolean *isCopy)
+jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jshort * GetShortArrayElements (JNIEnv *env, jshortArray array, jboolean *isCopy)
+jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jint * GetIntArrayElements (JNIEnv *env, jintArray array, jboolean *isCopy)
+jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jlong * GetLongArrayElements (JNIEnv *env, jlongArray array, jboolean *isCopy)
+jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jfloat * GetFloatArrayElements (JNIEnv *env, jfloatArray array, jboolean *isCopy)
+jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
-jdouble * GetDoubleArrayElements (JNIEnv *env, jdoubleArray array, jboolean *isCopy)
+jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+                                                               jboolean *isCopy)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
+       STATS(jniinvokation();)
+
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+
     return array->data;
 }
 
 
+/* Release<PrimitiveType>ArrayElements *****************************************
 
-void ReleaseBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode)
+   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)
 {
-    /* 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 ReleaseByteArrayElements (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode)
+void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *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 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)
 {
-    /* 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 ReleaseIntArrayElements (JNIEnv *env, jintArray array, jint *elems, jint mode)
+void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *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 ReleaseLongArrayElements (JNIEnv *env, jlongArray array, jlong *elems, jint mode)
+void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *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 ReleaseFloatArrayElements (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode)
+void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *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 ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode)
+void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+                                                               jdouble *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 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)
-{
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+/*  Set<PrimitiveType>ArrayRegion **********************************************
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
-}
+       A family of functions that copies back a region of a primitive
+       array from a buffer.
 
+*******************************************************************************/
 
-void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
+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 SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *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
+               MCOPY(&array->data[start], buf, jbyte, len);
+}
+
+
+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);
 
     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)
 {
-    log_text("JNI-Call: RegisterNatives");
+       STATS(jniinvokation();)
+
+    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)
 {
-    log_text("JNI-Call: UnregisterNatives");
+       STATS(jniinvokation();)
+
+       /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
+
+    log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
+
     return 0;
 }
 
-/******************************* monitor operations ********************************/
 
-jint MonitorEnter (JNIEnv* env, jobject obj)
+/* Monitor Operations *********************************************************/
+
+/* MonitorEnter ****************************************************************
+
+   Enters the monitor associated with the underlying Java object
+   referred to by obj.
+
+*******************************************************************************/
+
+jint MonitorEnter(JNIEnv *env, jobject obj)
 {
-    builtin_monitorenter(obj);
-    return 0;
+       STATS(jniinvokation();)
+       if (!obj) {
+               *exceptionptr = new_nullpointerexception();
+               return JNI_ERR;
+       }
+
+#if defined(USE_THREADS)
+       builtin_monitorenter(obj);
+#endif
+
+       return JNI_OK;
 }
 
 
-jint MonitorExit (JNIEnv* env, jobject obj)
+/* MonitorExit *****************************************************************
+
+   The current thread must be the owner of the monitor associated with
+   the underlying Java object referred to by obj. The thread
+   decrements the counter indicating the number of times it has
+   entered this monitor. If the value of the counter becomes zero, the
+   current thread releases the monitor.
+
+*******************************************************************************/
+
+jint MonitorExit(JNIEnv *env, jobject obj)
 {
-    builtin_monitorexit(obj);
-    return 0;
+       STATS(jniinvokation();)
+       if (!obj) {
+               *exceptionptr = new_nullpointerexception();
+               return JNI_ERR;
+       }
+
+#if defined(USE_THREADS)
+       builtin_monitorexit(obj);
+#endif
+
+       return JNI_OK;
 }
 
 
-/************************************* JavaVM interface ****************************/
-#ifdef __cplusplus
-#error CPP mode not supported yet
-#else
-jint GetJavaVM (JNIEnv* env, JavaVM **vm)
+/* JavaVM Interface ***********************************************************/
+
+/* GetJavaVM *******************************************************************
+
+   Returns the Java VM interface (used in the Invocation API)
+   associated with the current thread. The result is placed at the
+   location pointed to by the second argument, vm.
+
+*******************************************************************************/
+
+jint GetJavaVM(JNIEnv *env, JavaVM **vm)
 {
-    log_text("JNI-Call: GetJavaVM");
-    *vm=&javaVM;
-    return 0;
+       STATS(jniinvokation();)
+    *vm = &ptr_jvm;
+
+       return 0;
 }
-#endif /*__cplusplus*/
+
 
 void GetStringRegion (JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
 {
-    log_text("JNI-Call: GetStringRegion");
-
+       STATS(jniinvokation();)
+       log_text("JNI-Call: GetStringRegion");
 }
 
+
 void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
 {
-    log_text("JNI-Call: GetStringUTFRegion");
-
+       STATS(jniinvokation();)
+       log_text("JNI-Call: GetStringUTFRegion");
 }
 
-/************** obtain direct pointer to array elements ***********************/
 
-void * GetPrimitiveArrayCritical (JNIEnv* env, jarray array, jboolean *isCopy)
+/* GetPrimitiveArrayCritical ***************************************************
+
+   Obtain a direct pointer to array elements.
+
+*******************************************************************************/
+
+void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
 {
-       java_objectheader *s = (java_objectheader*) array;
-       arraydescriptor *desc = s->vftbl->arraydesc;
+       java_objectheader *s;
+       arraydescriptor   *desc;
+
+       STATS(jniinvokation();)
+
+       s = (java_objectheader *) array;
+       desc = s->vftbl->arraydesc;
+
+       if (!desc)
+               return NULL;
+
+       if (isCopy)
+               *isCopy = JNI_FALSE;
 
-       if (!desc) return NULL;
+       /* TODO add to global refs */
 
-       return ((u1*)s) + desc->dataoffset;
+       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)
 {
-       log_text("JNI-Call: ReleasePrimitiveArrayCritical");
+       STATS(jniinvokation();)
 
-       /* 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)
 {
-       log_text("JNI-Call: GetStringCritical");
+       STATS(jniinvokation();)
 
-       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)
 {
-       log_text("JNI-Call: ReleaseStringCritical");
+       STATS(jniinvokation();)
 
-       ReleaseStringChars(env,string,cstring);
+       ReleaseStringChars(env, string, cstring);
 }
 
 
 jweak NewWeakGlobalRef (JNIEnv* env, jobject obj)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: NewWeakGlobalRef");
 
        return obj;
@@ -3045,542 +3812,930 @@ jweak NewWeakGlobalRef (JNIEnv* env, jobject obj)
 
 void DeleteWeakGlobalRef (JNIEnv* env, jweak ref)
 {
+       STATS(jniinvokation();)
        log_text("JNI-Call: DeleteWeakGlobalRef");
 
        /* empty */
 }
 
 
-/******************************* check for pending exception ***********************/
+/** Creates a new global reference to the object referred to by the obj argument **/
+    
+jobject NewGlobalRef(JNIEnv* env, jobject lobj)
+{
+       jobject refcount;
+       jint val;
+       jobject newval;
+       STATS(jniinvokation();)
+
+       MonitorEnter(env, *global_ref_table);
+       
+       refcount = CallObjectMethod(env, *global_ref_table, getmid, lobj);
+       val = (refcount == NULL) ? 0 : CallIntMethod(env, refcount, intvalue);
+       newval = NewObject(env, intclass, newint, val + 1);
+
+       if (newval != NULL) {
+               CallObjectMethod(env, *global_ref_table, putmid, lobj, newval);
+               MonitorExit(env, *global_ref_table);
+               return lobj;
+
+       } else {
+               log_text("JNI-NewGlobalRef: unable to create new java.lang.Integer");
+               MonitorExit(env, *global_ref_table);
+               return NULL;
+       }
+}
 
+/*************  Deletes the global reference pointed to by globalRef **************/
 
-jboolean ExceptionCheck(JNIEnv* env)
+void DeleteGlobalRef(JNIEnv* env, jobject gref)
 {
-       log_text("JNI-Call: ExceptionCheck");
+       jobject refcount;
+       jint val;
+       STATS(jniinvokation();)
+
+       MonitorEnter(env, *global_ref_table);
+       refcount = CallObjectMethod(env, *global_ref_table, getmid, gref);
+
+       if (refcount == NULL) {
+               log_text("JNI-DeleteGlobalRef: unable to find global reference");
+               return;
+       }
+
+       val = CallIntMethod(env, refcount, intvalue);
+       val--;
+
+       if (val == 0) {
+               CallObjectMethod(env, *global_ref_table, removemid,refcount);
+
+       } else {
+               jobject newval = NewObject(env, intclass, newint, val);
+
+               if (newval != NULL) {
+                       CallObjectMethod(env,*global_ref_table, putmid, gref, newval);
+
+               } else {
+                       log_text("JNI-DeleteGlobalRef: unable to create new java.lang.Integer");
+               }
+       }
+
+       MonitorExit(env,*global_ref_table);
+}
+
 
+/* ExceptionCheck **************************************************************
+
+   Returns JNI_TRUE when there is a pending exception; otherwise,
+   returns JNI_FALSE.
+
+*******************************************************************************/
+
+jboolean ExceptionCheck(JNIEnv *env)
+{
+       STATS(jniinvokation();)
        return *exceptionptr ? JNI_TRUE : JNI_FALSE;
 }
 
 
+/* New JNI 1.4 functions ******************************************************/
+
+/* 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.
+
+*******************************************************************************/
+
+jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
+{
+       STATS(jniinvokation();)
+       log_text("NewDirectByteBuffer: IMPLEMENT ME!");
+
+       return NULL;
+}
+
+
+/* GetDirectBufferAddress ******************************************************
 
+   Fetches and returns the starting address of the memory region
+   referenced by the given direct java.nio.Buffer.
 
+*******************************************************************************/
+
+void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
+{
+       STATS(jniinvokation();)
+       log_text("GetDirectBufferAddress: IMPLEMENT ME!");
+
+       return NULL;
+}
+
+
+/* GetDirectBufferCapacity *****************************************************
+
+   Fetches and returns the capacity in bytes of the memory region
+   referenced by the given direct java.nio.Buffer.
+
+*******************************************************************************/
+
+jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf)
+{
+       STATS(jniinvokation();)
+       log_text("GetDirectBufferCapacity: IMPLEMENT ME!");
+
+       return 0;
+}
 
 
 jint DestroyJavaVM(JavaVM *vm)
 {
+       STATS(jniinvokation();)
        log_text("DestroyJavaVM called");
 
        return 0;
 }
 
 
-jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2)
+/* 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)
+/*     cacao_thread_attach();*/
+#else
+       #error "No idea how to implement that. Perhaps Stefan knows"
+#endif
+
+       *env = &ptr_env;
+
        return 0;
 }
 
 
 jint DetachCurrentThread(JavaVM *vm)
 {
+       STATS(jniinvokation();)
        log_text("DetachCurrentThread called");
 
        return 0;
 }
 
 
-jint GetEnv(JavaVM *vm, void **environment, jint jniversion)
+/* 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)
 {
-       *environment = &env;
+       STATS(jniinvokation();)
 
-       return 0;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       if (thread_getself() == NULL) {
+               *env = NULL;
+
+               return JNI_EDETACHED;
+       }
+#endif
+
+       if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) ||
+               (version == JNI_VERSION_1_4)) {
+               *env = &ptr_env;
+
+               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();)
        log_text("AttachCurrentThreadAsDaemon called");
 
        return 0;
 }
 
+/************* JNI Initialization ****************************************************/
+
+jobject jni_init1(JNIEnv* env, jobject lobj) {
+#if defined(USE_THREADS)
+       while (initrunning) {yieldThread();} /* wait until init is done */
+#endif
+       if (global_ref_table == NULL) {
+               jni_init();
+       } 
+#if defined(USE_THREADS)
+       else {
+               /* wait until jni_init is done */
+               MonitorEnter(env, *global_ref_table) ;
+               MonitorExit(env, *global_ref_table);
+       }
+#endif
+       return NewGlobalRef(env, lobj); 
+}
+void jni_init2(JNIEnv* env, jobject gref) {
+       log_text("DeleteGlobalref called before NewGlobalref");
+#if defined(USE_THREADS)
+       while (initrunning) {yieldThread();} /* wait until init is done */
+#endif
+       if (global_ref_table == NULL) {
+               jni_init();
+       } 
+#if defined(USE_THREADS)
+       else {
+               /* wait until jni_init is done */
+               MonitorEnter(env, *global_ref_table) ;
+               MonitorExit(env, *global_ref_table);
+       }
+#endif
+       DeleteGlobalRef(env, gref); 
+}
+
 
-/********************************* JNI invocation table ******************************/
+void jni_init(void)
+{
+       jmethodID mid;
 
-struct _JavaVM javaVMTable={
-   NULL,
-   NULL,
-   NULL,
-   &DestroyJavaVM,
-   &AttachCurrentThread,
-   &DetachCurrentThread,
-   &GetEnv,
-   &AttachCurrentThreadAsDaemon
+       initrunning = true;
+
+       /* initalize global reference table */
+       ihmclass = FindClass(NULL, "java/util/IdentityHashMap");
+       
+       if (ihmclass == NULL) {
+               log_text("JNI-Init: unable to find java.util.IdentityHashMap");
+       }
+
+       mid = GetMethodID(NULL, ihmclass, "<init>","()V");
+       if (mid == NULL) {
+               log_text("JNI-Init: unable to find constructor in java.util.IdentityHashMap");
+       }
+       
+       global_ref_table = (jobject*)heap_allocate(sizeof(jobject),true,NULL);
+
+       *global_ref_table = NewObject(NULL,ihmclass,mid);
+
+       if (*global_ref_table == NULL) {
+               log_text("JNI-Init: unable to create new global_ref_table");
+       }
+
+       initrunning = false;
+
+       getmid = GetMethodID(NULL, ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (mid == NULL) {
+               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
+       }
+
+       getmid = GetMethodID(NULL ,ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (getmid == NULL) {
+               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
+       }
+
+       putmid = GetMethodID(NULL, ihmclass, "put","(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+       if (putmid == NULL) {
+               log_text("JNI-Init: unable to find method \"put\" in java.util.IdentityHashMap");
+       }
+
+       intclass = FindClass(NULL, "java/lang/Integer");
+       if (intclass == NULL) {
+               log_text("JNI-Init: unable to find java.lang.Integer");
+       }
+
+       newint = GetMethodID(NULL, intclass, "<init>","(I)V");
+       if (newint == NULL) {
+               log_text("JNI-Init: unable to find constructor in java.lang.Integer");
+       }
+
+       intvalue = GetMethodID(NULL, intclass, "intValue","()I");
+       if (intvalue == NULL) {
+               log_text("JNI-Init: unable to find method \"intValue\" in java.lang.Integer");
+       }
+
+       removemid = GetMethodID(NULL, ihmclass, "remove","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (removemid == NULL) {
+               log_text("JNI-DeleteGlobalRef: unable to find method \"remove\" in java.lang.Object");
+       }
+       
+       /* set NewGlobalRef, DeleteGlobalRef envTable entry to real implementation */
+
+       JNI_JNIEnvTable.NewGlobalRef = &NewGlobalRef;
+       JNI_JNIEnvTable.DeleteGlobalRef = &DeleteGlobalRef;
+}
+
+
+/* JNI invocation table *******************************************************/
+
+const struct JNIInvokeInterface JNI_JavaVMTable = {
+       NULL,
+       NULL,
+       NULL,
+
+       DestroyJavaVM,
+       AttachCurrentThread,
+       DetachCurrentThread,
+       GetEnv,
+       AttachCurrentThreadAsDaemon
 };
 
-JavaVM javaVM = &javaVMTable;
-
-
-/********************************* JNI function table ******************************/
-
-struct JNI_Table envTable = {   
-    NULL,
-    NULL,
-    NULL,
-    NULL,    
-    &GetVersion,
-    &DefineClass,
-    &FindClass,
-    &FromReflectedMethod,
-    &FromReflectedField,
-    &ToReflectedMethod,
-    &GetSuperclass,
-    &IsAssignableForm,
-    &ToReflectedField,
-    &Throw,
-    &ThrowNew,
-    &ExceptionOccurred,
-    &ExceptionDescribe,
-    &ExceptionClear,
-    &FatalError,
-    &PushLocalFrame,
-    &PopLocalFrame,
-    &NewGlobalRef,
-    &DeleteGlobalRef,
-    &DeleteLocalRef,
-    &IsSameObject,
-    &NewLocalRef,
-    &EnsureLocalCapacity,
-    &AllocObject,
-    &NewObject,
-    &NewObjectV,
-    &NewObjectA,
-    &GetObjectClass,
-    &IsInstanceOf,
-    &GetMethodID,
-    &CallObjectMethod,
-    &CallObjectMethodV,
-    &CallObjectMethodA,
-    &CallBooleanMethod,
-    &CallBooleanMethodV,
-    &CallBooleanMethodA,
-    &CallByteMethod,
-    &CallByteMethodV,
-    &CallByteMethodA,
-    &CallCharMethod,
-    &CallCharMethodV,
-    &CallCharMethodA,
-    &CallShortMethod,
-    &CallShortMethodV,
-    &CallShortMethodA,
-    &CallIntMethod,
-    &CallIntMethodV,
-    &CallIntMethodA,
-    &CallLongMethod,
-    &CallLongMethodV,
-    &CallLongMethodA,
-    &CallFloatMethod,
-    &CallFloatMethodV,
-    &CallFloatMethodA,
-    &CallDoubleMethod,
-    &CallDoubleMethodV,
-    &CallDoubleMethodA,
-    &CallVoidMethod,
-    &CallVoidMethodV,
-    &CallVoidMethodA,
-    &CallNonvirtualObjectMethod,
-    &CallNonvirtualObjectMethodV,
-    &CallNonvirtualObjectMethodA,
-    &CallNonvirtualBooleanMethod,
-    &CallNonvirtualBooleanMethodV,
-    &CallNonvirtualBooleanMethodA,
-    &CallNonvirtualByteMethod,
-    &CallNonvirtualByteMethodV,
-    &CallNonvirtualByteMethodA,
-    &CallNonvirtualCharMethod,
-    &CallNonvirtualCharMethodV,
-    &CallNonvirtualCharMethodA,
-    &CallNonvirtualShortMethod,
-    &CallNonvirtualShortMethodV,
-    &CallNonvirtualShortMethodA,
-    &CallNonvirtualIntMethod,
-    &CallNonvirtualIntMethodV,
-    &CallNonvirtualIntMethodA,
-    &CallNonvirtualLongMethod,
-    &CallNonvirtualLongMethodV,
-    &CallNonvirtualLongMethodA,
-    &CallNonvirtualFloatMethod,
-    &CallNonvirtualFloatMethodV,
-    &CallNonvirtualFloatMethodA,
-    &CallNonvirtualDoubleMethod,
-    &CallNonvirtualDoubleMethodV,
-    &CallNonvirtualDoubleMethodA,
-    &CallNonvirtualVoidMethod,
-    &CallNonvirtualVoidMethodV,
-    &CallNonvirtualVoidMethodA,
-    &GetFieldID,
-    &GetObjectField,
-    &GetBooleanField,
-    &GetByteField,
-    &GetCharField,
-    &GetShortField,
-    &GetIntField,
-    &GetLongField,
-    &GetFloatField,
-    &GetDoubleField,
-    &SetObjectField,
-    &SetBooleanField,
-    &SetByteField,
-    &SetCharField,
-    &SetShortField,
-    &SetIntField,
-    &SetLongField,
-    &SetFloatField,
-    &SetDoubleField,
-    &GetStaticMethodID,
-    &CallStaticObjectMethod,
-    &CallStaticObjectMethodV,
-    &CallStaticObjectMethodA,
-    &CallStaticBooleanMethod,
-    &CallStaticBooleanMethodV,
-    &CallStaticBooleanMethodA,
-    &CallStaticByteMethod,
-    &CallStaticByteMethodV,
-    &CallStaticByteMethodA,
-    &CallStaticCharMethod,
-    &CallStaticCharMethodV,
-    &CallStaticCharMethodA,
-    &CallStaticShortMethod,
-    &CallStaticShortMethodV,
-    &CallStaticShortMethodA,
-    &CallStaticIntMethod,
-    &CallStaticIntMethodV,
-    &CallStaticIntMethodA,
-    &CallStaticLongMethod,
-    &CallStaticLongMethodV,
-    &CallStaticLongMethodA,
-    &CallStaticFloatMethod,
-    &CallStaticFloatMethodV,
-    &CallStaticFloatMethodA,
-    &CallStaticDoubleMethod,
-    &CallStaticDoubleMethodV,
-    &CallStaticDoubleMethodA,
-    &CallStaticVoidMethod,
-    &CallStaticVoidMethodV,
-    &CallStaticVoidMethodA,
-    &GetStaticFieldID,
-    &GetStaticObjectField,
-    &GetStaticBooleanField,
-    &GetStaticByteField,
-    &GetStaticCharField,
-    &GetStaticShortField,
-    &GetStaticIntField,
-    &GetStaticLongField,
-    &GetStaticFloatField,
-    &GetStaticDoubleField,
-    &SetStaticObjectField,
-    &SetStaticBooleanField,
-    &SetStaticByteField,
-    &SetStaticCharField,
-    &SetStaticShortField,
-    &SetStaticIntField,
-    &SetStaticLongField,
-    &SetStaticFloatField,
-    &SetStaticDoubleField,
-    &NewString,
-    &GetStringLength,
-    &GetStringChars,
-    &ReleaseStringChars,
-    &NewStringUTF,
-    &GetStringUTFLength,
-    &GetStringUTFChars,
-    &ReleaseStringUTFChars,
-    &GetArrayLength,
-    &NewObjectArray,
-    &GetObjectArrayElement,
-    &SetObjectArrayElement,
-    &NewBooleanArray,
-    &NewByteArray,
-    &NewCharArray,
-    &NewShortArray,
-    &NewIntArray,
-    &NewLongArray,
-    &NewFloatArray,
-    &NewDoubleArray,
-    &GetBooleanArrayElements,
-    &GetByteArrayElements,
-    &GetCharArrayElements,
-    &GetShortArrayElements,
-    &GetIntArrayElements,
-    &GetLongArrayElements,
-    &GetFloatArrayElements,
-    &GetDoubleArrayElements,
-    &ReleaseBooleanArrayElements,
-    &ReleaseByteArrayElements,
-    &ReleaseCharArrayElements,
-    &ReleaseShortArrayElements,
-    &ReleaseIntArrayElements,
-    &ReleaseLongArrayElements,
-    &ReleaseFloatArrayElements,
-    &ReleaseDoubleArrayElements,
-    &GetBooleanArrayRegion,
-    &GetByteArrayRegion,
-    &GetCharArrayRegion,
-    &GetShortArrayRegion,
-    &GetIntArrayRegion,
-    &GetLongArrayRegion,
-    &GetFloatArrayRegion,
-    &GetDoubleArrayRegion,
-    &SetBooleanArrayRegion,
-    &SetByteArrayRegion,
-    &SetCharArrayRegion,
-    &SetShortArrayRegion,
-    &SetIntArrayRegion,
-    &SetLongArrayRegion,
-    &SetFloatArrayRegion,
-    &SetDoubleArrayRegion,
-    &RegisterNatives,
-    &UnregisterNatives,
-    &MonitorEnter,
-    &MonitorExit,
-    &GetJavaVM,
-    &GetStringRegion,
-    &GetStringUTFRegion,
-    &GetPrimitiveArrayCritical,
-    &ReleasePrimitiveArrayCritical,
-    &GetStringCritical,
-    &ReleaseStringCritical,
-    &NewWeakGlobalRef,
-    &DeleteWeakGlobalRef,
-    &ExceptionCheck
+
+/* JNI function table *********************************************************/
+
+struct JNINativeInterface JNI_JNIEnvTable = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,    
+       &GetVersion,
+
+       &DefineClass,
+       &FindClass,
+       &FromReflectedMethod,
+       &FromReflectedField,
+       &ToReflectedMethod,
+       &GetSuperclass,
+       &IsAssignableFrom,
+       &ToReflectedField,
+
+       &Throw,
+       &ThrowNew,
+       &ExceptionOccurred,
+       &ExceptionDescribe,
+       &ExceptionClear,
+       &FatalError,
+       &PushLocalFrame,
+       &PopLocalFrame,
+
+       &jni_init1, /* &NewGlobalRef,    initialize Global_Ref_Table*/
+       &jni_init2, /* &DeleteGlobalRef,*/
+       &DeleteLocalRef,
+       &IsSameObject,
+       &NewLocalRef,
+       &EnsureLocalCapacity,
+
+       &AllocObject,
+       &NewObject,
+       &NewObjectV,
+       &NewObjectA,
+
+       &GetObjectClass,
+       &IsInstanceOf,
+
+       &GetMethodID,
+
+       &CallObjectMethod,
+       &CallObjectMethodV,
+       &CallObjectMethodA,
+       &CallBooleanMethod,
+       &CallBooleanMethodV,
+       &CallBooleanMethodA,
+       &CallByteMethod,
+       &CallByteMethodV,
+       &CallByteMethodA,
+       &CallCharMethod,
+       &CallCharMethodV,
+       &CallCharMethodA,
+       &CallShortMethod,
+       &CallShortMethodV,
+       &CallShortMethodA,
+       &CallIntMethod,
+       &CallIntMethodV,
+       &CallIntMethodA,
+       &CallLongMethod,
+       &CallLongMethodV,
+       &CallLongMethodA,
+       &CallFloatMethod,
+       &CallFloatMethodV,
+       &CallFloatMethodA,
+       &CallDoubleMethod,
+       &CallDoubleMethodV,
+       &CallDoubleMethodA,
+       &CallVoidMethod,
+       &CallVoidMethodV,
+       &CallVoidMethodA,
+
+       &CallNonvirtualObjectMethod,
+       &CallNonvirtualObjectMethodV,
+       &CallNonvirtualObjectMethodA,
+       &CallNonvirtualBooleanMethod,
+       &CallNonvirtualBooleanMethodV,
+       &CallNonvirtualBooleanMethodA,
+       &CallNonvirtualByteMethod,
+       &CallNonvirtualByteMethodV,
+       &CallNonvirtualByteMethodA,
+       &CallNonvirtualCharMethod,
+       &CallNonvirtualCharMethodV,
+       &CallNonvirtualCharMethodA,
+       &CallNonvirtualShortMethod,
+       &CallNonvirtualShortMethodV,
+       &CallNonvirtualShortMethodA,
+       &CallNonvirtualIntMethod,
+       &CallNonvirtualIntMethodV,
+       &CallNonvirtualIntMethodA,
+       &CallNonvirtualLongMethod,
+       &CallNonvirtualLongMethodV,
+       &CallNonvirtualLongMethodA,
+       &CallNonvirtualFloatMethod,
+       &CallNonvirtualFloatMethodV,
+       &CallNonvirtualFloatMethodA,
+       &CallNonvirtualDoubleMethod,
+       &CallNonvirtualDoubleMethodV,
+       &CallNonvirtualDoubleMethodA,
+       &CallNonvirtualVoidMethod,
+       &CallNonvirtualVoidMethodV,
+       &CallNonvirtualVoidMethodA,
+
+       &GetFieldID,
+
+       &GetObjectField,
+       &GetBooleanField,
+       &GetByteField,
+       &GetCharField,
+       &GetShortField,
+       &GetIntField,
+       &GetLongField,
+       &GetFloatField,
+       &GetDoubleField,
+       &SetObjectField,
+       &SetBooleanField,
+       &SetByteField,
+       &SetCharField,
+       &SetShortField,
+       &SetIntField,
+       &SetLongField,
+       &SetFloatField,
+       &SetDoubleField,
+
+       &GetStaticMethodID,
+
+       &CallStaticObjectMethod,
+       &CallStaticObjectMethodV,
+       &CallStaticObjectMethodA,
+       &CallStaticBooleanMethod,
+       &CallStaticBooleanMethodV,
+       &CallStaticBooleanMethodA,
+       &CallStaticByteMethod,
+       &CallStaticByteMethodV,
+       &CallStaticByteMethodA,
+       &CallStaticCharMethod,
+       &CallStaticCharMethodV,
+       &CallStaticCharMethodA,
+       &CallStaticShortMethod,
+       &CallStaticShortMethodV,
+       &CallStaticShortMethodA,
+       &CallStaticIntMethod,
+       &CallStaticIntMethodV,
+       &CallStaticIntMethodA,
+       &CallStaticLongMethod,
+       &CallStaticLongMethodV,
+       &CallStaticLongMethodA,
+       &CallStaticFloatMethod,
+       &CallStaticFloatMethodV,
+       &CallStaticFloatMethodA,
+       &CallStaticDoubleMethod,
+       &CallStaticDoubleMethodV,
+       &CallStaticDoubleMethodA,
+       &CallStaticVoidMethod,
+       &CallStaticVoidMethodV,
+       &CallStaticVoidMethodA,
+
+       &GetStaticFieldID,
+
+       &GetStaticObjectField,
+       &GetStaticBooleanField,
+       &GetStaticByteField,
+       &GetStaticCharField,
+       &GetStaticShortField,
+       &GetStaticIntField,
+       &GetStaticLongField,
+       &GetStaticFloatField,
+       &GetStaticDoubleField,
+       &SetStaticObjectField,
+       &SetStaticBooleanField,
+       &SetStaticByteField,
+       &SetStaticCharField,
+       &SetStaticShortField,
+       &SetStaticIntField,
+       &SetStaticLongField,
+       &SetStaticFloatField,
+       &SetStaticDoubleField,
+
+       &NewString,
+       &GetStringLength,
+       &GetStringChars,
+       &ReleaseStringChars,
+
+       &NewStringUTF,
+       &GetStringUTFLength,
+       &GetStringUTFChars,
+       &ReleaseStringUTFChars,
+
+       &GetArrayLength,
+
+       &NewObjectArray,
+       &GetObjectArrayElement,
+       &SetObjectArrayElement,
+
+       &NewBooleanArray,
+       &NewByteArray,
+       &NewCharArray,
+       &NewShortArray,
+       &NewIntArray,
+       &NewLongArray,
+       &NewFloatArray,
+       &NewDoubleArray,
+
+       &GetBooleanArrayElements,
+       &GetByteArrayElements,
+       &GetCharArrayElements,
+       &GetShortArrayElements,
+       &GetIntArrayElements,
+       &GetLongArrayElements,
+       &GetFloatArrayElements,
+       &GetDoubleArrayElements,
+
+       &ReleaseBooleanArrayElements,
+       &ReleaseByteArrayElements,
+       &ReleaseCharArrayElements,
+       &ReleaseShortArrayElements,
+       &ReleaseIntArrayElements,
+       &ReleaseLongArrayElements,
+       &ReleaseFloatArrayElements,
+       &ReleaseDoubleArrayElements,
+
+       &GetBooleanArrayRegion,
+       &GetByteArrayRegion,
+       &GetCharArrayRegion,
+       &GetShortArrayRegion,
+       &GetIntArrayRegion,
+       &GetLongArrayRegion,
+       &GetFloatArrayRegion,
+       &GetDoubleArrayRegion,
+       &SetBooleanArrayRegion,
+       &SetByteArrayRegion,
+       &SetCharArrayRegion,
+       &SetShortArrayRegion,
+       &SetIntArrayRegion,
+       &SetLongArrayRegion,
+       &SetFloatArrayRegion,
+       &SetDoubleArrayRegion,
+
+       &RegisterNatives,
+       &UnregisterNatives,
+
+       &MonitorEnter,
+       &MonitorExit,
+
+       &GetJavaVM,
+
+       /* new JNI 1.2 functions */
+
+       &GetStringRegion,
+       &GetStringUTFRegion,
+
+       &GetPrimitiveArrayCritical,
+       &ReleasePrimitiveArrayCritical,
+
+       &GetStringCritical,
+       &ReleaseStringCritical,
+
+       &NewWeakGlobalRef,
+       &DeleteWeakGlobalRef,
+
+       &ExceptionCheck,
+
+       /* new JNI 1.4 functions */
+
+       &NewDirectByteBuffer,
+       &GetDirectBufferAddress,
+       &GetDirectBufferCapacity
 };
 
-JNIEnv env = &envTable;
 
+/* Invocation API Functions ***************************************************/
 
-jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, jobject obj, java_objectarray *params)
+/* JNI_GetDefaultJavaVMInitArgs ************************************************
+
+   Returns a default configuration for the Java VM.
+
+*******************************************************************************/
+
+jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
+{
+       JDK1_1InitArgs *_vm_args = (JDK1_1InitArgs *) vm_args;
+
+       /* GNU classpath currently supports JNI 1.2 */
+
+       _vm_args->version = JNI_VERSION_1_2;
+
+       return 0;
+}
+
+
+/* JNI_GetCreatedJavaVMs *******************************************************
+
+   Returns all Java VMs that have been created. Pointers to VMs are written in
+   the buffer vmBuf in the order they are created. At most bufLen number of
+   entries will be written. The total number of created VMs is returned in
+   *nVMs.
+
+*******************************************************************************/
+
+jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
+{
+       log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!");
+
+       return 0;
+}
+
+
+/* JNI_CreateJavaVM ************************************************************
+
+   Loads and initializes a Java VM. The current thread becomes the main thread.
+   Sets the env argument to the JNI interface pointer of the main thread.
+
+*******************************************************************************/
+
+jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args)
+{
+       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, methodinfo *methodID,
+                                                                          jobject obj, java_objectarray *params)
 {
-       int argcount;
        jni_callblock *blk;
-       char retT;
-       jobject retVal;
+       jobject        o;
+       s4             argcount;
 
        if (methodID == 0) {
                *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
                return NULL;
        }
 
-       argcount = get_parametercount(methodID);
+       argcount = methodID->parseddesc->paramcount;
+
+       /* if method is non-static, remove the `this' pointer */
+
+       if (!(methodID->flags & ACC_STATIC))
+               argcount--;
 
-       if (obj && (!builtin_instanceof((java_objectheader *) obj, methodID->class))) {
-               *exceptionptr = new_exception_message(string_java_lang_IllegalArgumentException,
+       /* 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,
                                                                                          "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
-               return 0;
+               return NULL;
        }
 
 
-
+#ifdef arglimit
        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) && (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) && (!obj))  {
-               *exceptionptr = new_exception_message(string_java_lang_NullPointerException,
-                                                                                         "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
-               return 0;
+       if (!(methodID->flags & ACC_STATIC) && !obj)  {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NullPointerException,
+                                                                 "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
+               return NULL;
        }
 
-       if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0;
+       if ((methodID->flags & ACC_STATIC) && (obj))
+               obj = NULL;
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       if (obj) {
+               if ((methodID->flags & ACC_ABSTRACT) ||
+                       (methodID->class->flags & ACC_INTERFACE)) {
+                       methodID = get_virtual(obj, methodID);
+               }
+       }
 
-       retT = fill_callblock_objA(obj, methodID->descriptor, blk, params);
+       blk = MNEW(jni_callblock, /*4 */argcount + 2);
+
+       if (!fill_callblock_from_objectarray(obj, methodID->parseddesc, blk,
+                                                                                params))
+               return NULL;
 
-       switch (retT) {
-       case 'V':
-               (void) asm_calljavafunction2(methodID,
-                                                                        argcount + 1,
+       switch (methodID->parseddesc->returntype.decltype) {
+       case TYPE_VOID:
+               (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 'I': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Integer")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(I)V")),
-                                          intVal);
+       case PRIMITIVETYPE_INT: {
+               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 'B': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Byte")));
+       case PRIMITIVETYPE_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,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(B)V")),
-                                          intVal);
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
+                                                                                  utf_init,
+                                                                                  utf_byte__void),
+                                          i);
        }
        break;
 
-       case 'C': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Character")));
+       case PRIMITIVETYPE_CHAR: {
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               o = builtin_new(class_java_lang_Character);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(C)V")),
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
+                                                                                  utf_init,
+                                                                                  utf_char__void),
                                           intVal);
        }
        break;
 
-       case 'S': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Short")));
+       case PRIMITIVETYPE_SHORT: {
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               o = builtin_new(class_java_lang_Short);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(S)V")),
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
+                                                                                  utf_init,
+                                                                                  utf_short__void),
                                           intVal);
        }
        break;
 
-       case 'Z': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Boolean")));
+       case PRIMITIVETYPE_BOOLEAN: {
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               o = builtin_new(class_java_lang_Boolean);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(Z)V")),
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
+                                                                                  utf_init,
+                                                                                  utf_boolean__void),
                                           intVal);
        }
        break;
 
        case 'J': {
-               jlong intVal;   
-               intVal = asm_calljavafunction2long(methodID,
-                                                                                  argcount + 1,
-                                                                                  (argcount + 1) * sizeof(jni_callblock),
-                                                                                  blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Long")));
+               jlong longVal;
+               longVal = asm_calljavafunction2long(methodID,
+                                                                                       argcount + 1,
+                                                                                       (argcount + 1) * sizeof(jni_callblock),
+                                                                                       blk);
+               o = builtin_new(class_java_lang_Long);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(J)V")),
-                                          intVal);
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
+                                                                                  utf_init,
+                                                                                  utf_long__void),
+                                          longVal);
        }
        break;
 
-       case 'F': {
+       case PRIMITIVETYPE_FLOAT: {
                jdouble floatVal;       
-               floatVal = asm_calljavafunction2double(methodID,
-                                                                                          argcount + 1,
-                                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                                          blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Float")));
+               floatVal = asm_calljavafunction2float(methodID,
+                                                                                         argcount + 1,
+                                                                                         (argcount + 1) * sizeof(jni_callblock),
+                                                                                         blk);
+               o = builtin_new(class_java_lang_Float);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(F)V")),
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
+                                                                                  utf_init,
+                                                                                  utf_float__void),
                                           floatVal);
        }
        break;
 
-       case 'D': {
-               jdouble floatVal;       
-               floatVal = asm_calljavafunction2double(methodID,
-                                                                                          argcount + 1,
-                                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                                          blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Double")));
+       case PRIMITIVETYPE_DOUBLE: {
+               jdouble doubleVal;
+               doubleVal = asm_calljavafunction2double(methodID,
+                                                                                               argcount + 1,
+                                                                                               (argcount + 1) * sizeof(jni_callblock),
+                                                                                               blk);
+               o = builtin_new(class_java_lang_Double);
                CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(D)V")),
-                                          floatVal);
+                                          o,
+                                          class_resolvemethod(o->vftbl->class,
+                                                                                  utf_init,
+                                                                                  utf_double__void),
+                                          doubleVal);
        }
        break;
 
-       case 'L': /* fall through */
-       case '[':
-               retVal = asm_calljavafunction2(methodID,
-                                                                          argcount + 1,
-                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                          blk);
+       case TYPE_ADR:
+               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*/
-               MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+               /* if this happens the exception has already been set by              */
+               /* fill_callblock_from_objectarray                                    */
+
+               MFREE(blk, jni_callblock, /*4 */ argcount+2);
                return (jobject *) 0;
        }
 
-       MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+       MFREE(blk, jni_callblock, /* 4 */ argcount+2);
 
        if (*exceptionptr) {
-               java_objectheader *exceptionToWrap = *exceptionptr;
-               classinfo *ivtec;
-               java_objectheader *ivte;
+               java_objectheader *cause;
 
-               *exceptionptr = NULL;
-               ivtec = class_new(utf_new_char("java/lang/reflect/InvocationTargetException"));
-               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;
 
-               if (*exceptionptr != NULL)
-                       panic("jni.c: error while creating InvocationTargetException wrapper");
+               /* clear exception pointer, we are calling JIT code again */
+
+               *exceptionptr = NULL;
 
-               *exceptionptr = ivte;
+               *exceptionptr =
+                       new_exception_throwable(string_java_lang_reflect_InvocationTargetException,
+                                                                       (java_lang_Throwable *) cause);
        }
 
-       return (jobject *) retVal;
+       return (jobject *) o;
 }