* src/vm/vm.c (vm_call_method_intern): Removed.
[cacao.git] / src / native / jni.c
index b367c46fdef50fac22bd3f5b53df112aa5aea42b..0e58a9a6176e855198b40ae4ffa9a9ad486d8ac6 100644 (file)
@@ -1,9 +1,9 @@
-/* native/jni.c - implementation of the Java Native Interface functions
+/* src/native/jni.c - implementation of the Java Native Interface functions
 
-   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
+   Copyright (C) 1996-2005, 2006 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.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
-   Authors: ?
+   Authors: Rainhard Grafl
+            Roman Obermaisser
 
-   Changes: Joseph Wenninger, Martin Platter
+   Changes: Joseph Wenninger
+            Martin Platter
+            Christian Thalinger
+                       Edwin Steiner
 
-   $Id: jni.c 1853 2005-01-04 12:07:41Z twisti $
+   $Id: jni.c 4559 2006-03-05 23:24:50Z twisti $
 
 */
 
 
+#include "config.h"
+
+#include <assert.h>
 #include <string.h>
 
+#include "vm/types.h"
+
 #include "mm/boehm.h"
 #include "mm/memory.h"
 #include "native/jni.h"
 #include "native/native.h"
+
+#include "native/include/gnu_classpath_Pointer.h"
+
+#if SIZEOF_VOID_P == 8
+# include "native/include/gnu_classpath_Pointer64.h"
+#else
+# include "native/include/gnu_classpath_Pointer32.h"
+#endif
+
+#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_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"
+#include "native/include/java_nio_Buffer.h"
+#include "native/include/java_nio_DirectByteBufferImpl.h"
+
+#if defined(ENABLE_JVMTI)
+# include "native/jvmti/jvmti.h"
+#endif
 
 #if defined(USE_THREADS)
 # if defined(NATIVE_THREADS)
 #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/tables.h"
+#include "vm/stringlocal.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
+#include "vm/statistics.h"
+#include "vm/vm.h"
 
 
-/* XXX TWISTI hack: define it extern to be found in this file */
-extern struct _JavaVM JNI_javaVMTable;
-extern struct JNI_Table JNI_envTable;
+/* pointers to VM and the environment needed by GetJavaVM and GetEnv */
 
+static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable;
+void *ptr_env = (void*) &JNI_JNIEnvTable;
 
-#define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
 
-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;
+/* global variables ***********************************************************/
 
-/* global reference table */
-static jobject *global_ref_table;
-static bool initrunning=false;
+/* global reference table *****************************************************/
 
-/* 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;
+static java_objectheader **global_ref_table;
 
+/* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/
+static classinfo *ihmclass = NULL;
+static methodinfo *putmid = NULL;
+static methodinfo *getmid = NULL;
+static methodinfo *removemid = NULL;
 
-/********************* 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); 
+/* direct buffer stuff ********************************************************/
 
+static classinfo *class_java_nio_Buffer;
+static classinfo *class_java_nio_DirectByteBufferImpl;
+static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
+#if SIZEOF_VOID_P == 8
+static classinfo *class_gnu_classpath_Pointer64;
+#else
+static classinfo *class_gnu_classpath_Pointer32;
+#endif
 
+static methodinfo *dbbirw_init;
 
-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;
 
-       /* skip '(' */
-       utf_nextu2(&utf_ptr);
+/* local reference table ******************************************************/
 
-    /* determine number of parameters */
-       while (*utf_ptr != ')') {
-               get_type(&utf_ptr, desc_end, true);
-               parametercount++;
-       }
+#if !defined(USE_THREADS)
+localref_table *_no_threads_localref_table;
+#endif
 
-       return parametercount;
-}
 
+/* accessing instance fields macros *******************************************/
 
+#define SET_FIELD(o,type,f,value) \
+    *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset)) = (type) (value)
 
-void fill_callblock(void *obj, utf *descr, jni_callblock blk[], va_list data, char ret)
-{
-    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;
+#define GET_FIELD(o,type,f) \
+    *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset))
 
-       /*
-    log_text("fill_callblock");
-    utf_display(descr);
-    log_text("====");
-       */
-    /* skip '(' */
-    utf_nextu2(utf_ptr);
 
-    /* determine number of parameters */
-       if (obj) {
-               blk[0].itemtype = TYPE_ADR;
-               blk[0].item = PTR_TO_ITEM(obj);
-               cnt = 1;
-       } else cnt = 0;
+/* some forward declarations **************************************************/
 
-       while (**utf_ptr != ')') {
-               if (*utf_ptr >= desc_end)
-               panic("illegal method descriptor");
+jobject NewLocalRef(JNIEnv *env, jobject ref);
 
-               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;
-                       break;
+/* jni_init ********************************************************************
 
-               case 'J':
-                       blk[cnt].itemtype = TYPE_LNG;
-                       blk[cnt].item = (u8) va_arg(data, jlong);
-                       break;
+   Initialize the JNI subsystem.
 
-               case 'F':
-                       blk[cnt].itemtype = TYPE_FLT;
-                       *((jfloat *) (&blk[cnt].item)) = (jfloat) va_arg(data, jdouble);
-                       break;
+*******************************************************************************/
 
-               case 'D':
-                       blk[cnt].itemtype = TYPE_DBL;
-                       *((jdouble *) (&blk[cnt].item)) = (jdouble) va_arg(data, jdouble);
-                       break;
+bool jni_init(void)
+{
+       /* initalize global reference table */
 
-               case 'V':
-                       panic ("V not allowed as function parameter");
-                       break;
-                       
-               case 'L':
-                       while (utf_nextu2(utf_ptr) != ';')
-                           blk[cnt].itemtype = TYPE_ADR;
-                       blk[cnt].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++;
-       }
+       if (!(ihmclass =
+                 load_class_bootstrap(utf_new_char("java/util/IdentityHashMap"))))
+               return false;
+
+       global_ref_table = GCNEW(jobject);
+
+       if (!(*global_ref_table = native_new_and_init(ihmclass)))
+               return false;
+
+       if (!(getmid = class_resolvemethod(ihmclass, utf_get,
+                                                                          utf_java_lang_Object__java_lang_Object)))
+               return false;
+
+       if (!(putmid = class_resolvemethod(ihmclass, utf_put,
+                                                                          utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"))))
+               return false;
+
+       if (!(removemid =
+                 class_resolvemethod(ihmclass, utf_remove,
+                                                         utf_java_lang_Object__java_lang_Object)))
+               return false;
+
+
+       /* direct buffer stuff */
+
+       if (!(class_java_nio_Buffer =
+                 load_class_bootstrap(utf_new_char("java/nio/Buffer"))) ||
+               !link_class(class_java_nio_Buffer))
+               return false;
+
+       if (!(class_java_nio_DirectByteBufferImpl =
+                 load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
+               !link_class(class_java_nio_DirectByteBufferImpl))
+               return false;
+
+       if (!(class_java_nio_DirectByteBufferImpl_ReadWrite =
+                 load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) ||
+               !link_class(class_java_nio_DirectByteBufferImpl_ReadWrite))
+               return false;
+
+       if (!(dbbirw_init =
+               class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite,
+                                                       utf_init,
+                                                       utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
+               return false;
+
+#if SIZEOF_VOID_P == 8
+       if (!(class_gnu_classpath_Pointer64 =
+                 load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
+               !link_class(class_gnu_classpath_Pointer64))
+               return false;
+#else
+       if (!(class_gnu_classpath_Pointer32 =
+                 load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
+               !link_class(class_gnu_classpath_Pointer32))
+               return false;
+#endif
 
-       /*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)
-               log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
+       return true;
 }
 
 
-/* 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)
+/* _Jv_jni_vmargs_from_objectarray *********************************************
+
+   XXX
+
+*******************************************************************************/
+
+static bool _Jv_jni_vmargs_from_objectarray(java_objectheader *o,
+                                                                                       methoddesc *descr,
+                                                                                       vm_arg *vmargs,
+                                                                                       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     */
+       java_objectheader *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 */
 
-       /*
-         log_text("fill_callblock");
-         utf_display(descr);
-         log_text("====");
-       */
-    /* skip '(' */
-    utf_nextu2(utf_ptr);
+       i = 0;
 
-    /* determine number of parameters */
-       if (obj) {
-               blk[0].itemtype = TYPE_ADR;
-               blk[0].item = PTR_TO_ITEM(obj);
-               cnt=1;
+       if (o != NULL) {
+               /* this pointer */
+               vmargs[0].type = TYPE_ADR;
+               vmargs[0].data = (u8) (ptrint) o;
 
-       } 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;
+               case TYPE_INT:
+               case TYPE_LONG:
+               case TYPE_FLOAT:
+               case TYPE_DOUBLE:
+                       param = params->data[j];
 
-                       } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       break;
+                       if (param == NULL)
+                               goto illegal_arg;
 
-               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;
+                       /* internally used data type */
+                       vmargs[i].type = paramtypes->type;
 
-                       } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       break;
+                       /* convert the value according to its declared type */
 
-               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;
+                       c = param->vftbl->class;
 
-               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;
+                       switch (paramtypes->decltype) {
+                       case PRIMITIVETYPE_BOOLEAN:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Boolean *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
 
-                       } else {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       break;
+                       case PRIMITIVETYPE_BYTE:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Byte *) 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_CHAR:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Character *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_SHORT:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Short *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Byte *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_INT:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Integer *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Short *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Byte *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_LONG:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Long *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Integer *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Short *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
+                                       vmargs[i].data = (s8) ((java_lang_Byte *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_FLOAT:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       *((jfloat *) (&vmargs[i].data)) = (jfloat) ((java_lang_Float *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
+
+                       case PRIMITIVETYPE_DOUBLE:
+                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
+                                       *((jdouble *) (&vmargs[i].data)) = (jdouble) ((java_lang_Double *) param)->value;
+                               else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
+                                       *((jfloat *) (&vmargs[i].data)) = (jfloat) ((java_lang_Float *) param)->value;
+                               else
+                                       goto illegal_arg;
+                               break;
 
-               case 'J':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
+                       default:
+                               goto illegal_arg;
                        }
-                       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;
-                                               }
+                       break;
+               
+                       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))
+                                                       goto illegal_arg;
+
+                                       } else {
+                                               if (!builtin_instanceof(params->data[j], c))
+                                                       goto illegal_arg;
                                        }
                                }
+                               vmargs[i].type = TYPE_ADR;
+                               vmargs[i].data = (u8) (ptrint) params->data[j];
+                               break;
 
-                       }
-                       break;
+                       default:
+                               goto illegal_arg;
+               }
+       }
 
-               case 'F':
-                       param = params->data[cnts];
-                       if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
+/*     if (rettype) */
+/*             *rettype = descr->returntype.decltype; */
 
-                       if (param->vftbl->class->name == utf_float) {
-                               blk[cnt].itemtype = TYPE_FLT;
-                               *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value;
+       return true;
 
-                       } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                               return 0;
-                       }
-                       break;
+illegal_arg:
+       exceptions_throw_illegalargumentexception();
+       return false;
+}
 
-               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;
+/* _Jv_jni_CallObjectMethod ****************************************************
 
-                       } else  {
-                               if (param->vftbl->class->name == utf_float) {
-                                       blk[cnt].itemtype = TYPE_DBL;
-                                       *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
+   Internal function to call Java Object methods.
 
-                               } else  {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                       return 0;
-                               }
-                       }
-                       break;
+*******************************************************************************/
 
-               case 'V':
-                       panic("V not allowed as function parameter");
-                       break;
+static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
+                                                                                                  vftbl_t *vftbl,
+                                                                                                  methodinfo *m, va_list ap)
+{
+       methodinfo        *resm;
+       java_objectheader *ro;
 
-               case 'L':
-                       {
-                               char *start = (*utf_ptr) - 1;
-                               /*char *end = NULL;
+       STATISTICS(jniinvokation());
 
-                               while (utf_nextu2(utf_ptr) != ';')
-                                       end = (*utf_ptr) + 1;*/
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
 
-                               if (!builtin_instanceof(params->data[cnts], class_from_descriptor(start, desc_end, utf_ptr, CLASSLOAD_LOAD))) {
-                                       if (params->data[cnts] != 0) {
-                                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                               return 0;
-                                       }                       
-                               }
-                               blk[cnt].itemtype = TYPE_ADR;
-                               blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
-                               break;                  
-                       }
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-               case '[':
-                       {
-                               char *start = (*utf_ptr) - 1;
-                               /*char *end;
-                               
-                               char ch;
-                               while ((ch = utf_nextu2(utf_ptr)) == '[')
-                                       if (ch == 'L') {
-                                               while (utf_nextu2(utf_ptr) != ';') {}
-                                       }
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-                               end = (*utf_ptr) - 1;
-                               ch = utf_nextu2(utf_ptr); */
+               if (o != NULL)
+                       o = NULL;
 
-                               if (!builtin_arrayinstanceof(params->data[cnts], class_from_descriptor(start, desc_end, utf_ptr, CLASSLOAD_LOAD)->vftbl)) {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
-                                       return 0;
-                               }
+               /* for convenience */
 
-                               blk[cnt].itemtype = TYPE_ADR;
-                               blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
-                               break;
-                       }
-               }
-               cnt++;
-               cnts++;
+               resm = m;
+
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
        }
 
-       c = utf_nextu2(utf_ptr);
-       c = utf_nextu2(utf_ptr);
-       return c; /*return type needed usage of the right lowlevel methods*/
+       STATISTICS(jnicallXmethodnvokation());
+
+       ro = vm_call_method_valist(resm, o, ap);
+
+       return ro;
 }
 
 
+/* _Jv_jni_CallObjectMethodA ***************************************************
+
+   Internal function to call Java Object methods.
+
+*******************************************************************************/
 
+static java_objectheader *_Jv_jni_CallObjectMethodA(java_objectheader *o,
+                                                                                                       vftbl_t *vftbl,
+                                                                                                       methodinfo *m, jvalue *args)
+{
+       methodinfo        *resm;
+       java_objectheader *ro;
 
+       STATISTICS(jniinvokation());
 
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
 
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
+               if (o != NULL)
+                       o = NULL;
 
+               /* for convenience */
 
+               resm = m;
 
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
+       STATISTICS(jnicallXmethodnvokation());
 
+       ro = vm_call_method_jvalue(resm, o, args);
 
-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);
+       return ro;
 }
 
-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);
-}
 
+/* _Jv_jni_CallIntMethod *******************************************************
 
+   Internal function to call Java integer class methods (boolean,
+   byte, char, short, int).
 
-jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
-{      
-       int argcount;
-       jni_callblock *blk;
-       jobject ret;
+*******************************************************************************/
 
+static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
+                                                                 methodinfo *m, va_list ap)
+{
+       methodinfo *resm;
+       jint        i;
 
+       STATISTICS(jniinvokation());
 
-       if (methodID == 0) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
                return 0;
        }
+        
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       argcount = get_parametercount(methodID);
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
-               ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
+               if (o != NULL)
+                       o = NULL;
+
+               /* for convenience */
+
+               resm = m;
+
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
        }
 
-       if (obj && !builtin_instanceof(obj, methodID->class)) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       STATISTICS(jnicallXmethodnvokation());
+
+       i = vm_call_method_int_valist(resm, o, ap);
+
+       return i;
+}
+
+
+/* _Jv_jni_CallLongMethod ******************************************************
+
+   Internal function to call Java long methods.
+
+*******************************************************************************/
+
+static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
+                                                                       methodinfo *m, va_list ap)
+{
+       methodinfo *resm;
+       jlong       l;
+
+       STATISTICS(jniinvokation());
+
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
                return 0;
        }
 
-#ifdef arglimit
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       if (argcount > 3) {
-               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
-               log_text("Too many arguments. CallObjectMethod does not support that");
-               return 0;
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
+
+               if (o != NULL)
+                       o = NULL;
+
+               /* for convenience */
+
+               resm = m;
+
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
        }
-#endif
 
-       blk = MNEW(jni_callblock, /*4 */argcount+2);
+       STATISTICS(jnicallXmethodnvokation());
 
-       fill_callblock(obj, methodID->descriptor, blk, args, 'O');
-       /*      printf("parameter: obj: %p",blk[0].item); */
-       ret = asm_calljavafunction2(methodID,
-                                                               argcount + 1,
-                                                               (argcount + 1) * sizeof(jni_callblock),
-                                                               blk);
-       MFREE(blk, jni_callblock, argcount + 1);
-       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+       l = vm_call_method_long_valist(resm, o, ap);
 
-       return ret;
+       return l;
 }
 
 
-/*
-  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)
-{
-       int argcount;
-       jni_callblock *blk;
-       jint ret;
-
-/*     printf("%p,     %c\n",retType,methodID,retType);*/
-
-        /*
-        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;
+/* _Jv_jni_CallFloatMethod *****************************************************
+
+   Internal function to call Java float methods.
+
+*******************************************************************************/
+
+static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
+                                                                         methodinfo *m, va_list ap)
+{
+       methodinfo *resm;
+       jfloat      f;
+
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
+
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
+
+               if (o != NULL)
+                       o = NULL;
+
+               /* for convenience */
+
+               resm = m;
+
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
        }
-        
-       argcount = get_parametercount(methodID);
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
-               ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
+       STATISTICS(jnicallXmethodnvokation());
+
+       f = vm_call_method_float_valist(resm, o, ap);
+
+       return f;
+}
+
+
+/* _Jv_jni_CallDoubleMethod ****************************************************
+
+   Internal function to call Java double methods.
+
+*******************************************************************************/
+
+static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
+                                                                               methodinfo *m, va_list ap)
+{
+       methodinfo *resm;
+       jdouble     d;
+
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
+
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
+
+               if (o != NULL)
+                       o = NULL;
+
+               /* for convenience */
+
+               resm = m;
+
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
        }
 
-       if (obj && !builtin_instanceof(obj, methodID->class)) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
+       d = vm_call_method_double_valist(resm, o, ap);
+
+       return d;
+}
+
+
+/* _Jv_jni_CallVoidMethod ******************************************************
+
+   Internal function to call Java void methods.
+
+*******************************************************************************/
+
+static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl,
+                                                                  methodinfo *m, va_list ap)
+{      
+       methodinfo *resm;
+
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return;
        }
 
-#ifdef arglimit
-       if (argcount > 3) {
-               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
-               log_text("Too many arguments. CallIntegerMethod does not support that");
-               return 0;
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
+
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
+
+               if (o != NULL)
+                       o = NULL;
+
+               /* for convenience */
+
+               resm = m;
+
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
        }
-#endif
 
-       blk = MNEW(jni_callblock, /*4 */ argcount+2);
+       STATISTICS(jnicallXmethodnvokation());
+
+       (void) vm_call_method_valist(resm, o, ap);
+}
+
+
+/* _Jv_jni_CallVoidMethodA *****************************************************
+
+   Internal function to call Java void methods.
+
+*******************************************************************************/
+
+static void _Jv_jni_CallVoidMethodA(java_objectheader *o, vftbl_t *vftbl,
+                                                                       methodinfo *m, jvalue *args)
+{      
+       methodinfo *resm;
+
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return;
+       }
+
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
+
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
+
+               if (o != NULL)
+                       o = NULL;
+
+               /* for convenience */
+
+               resm = m;
 
-       fill_callblock(obj, methodID->descriptor, blk, args, retType);
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       /*      printf("parameter: obj: %p",blk[0].item); */
-       ret = asm_calljavafunction2int(methodID,
-                                                                  argcount + 1,
-                                                                  (argcount + 1) * sizeof(jni_callblock),
-                                                                  blk);
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       MFREE(blk, jni_callblock, argcount + 1);
-       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+       STATISTICS(jnicallXmethodnvokation());
 
-       return ret;
+       (void) vm_call_method_jvalue(resm, o, args);
 }
 
 
-/*core function for long class functions*/
-jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
+/* _Jv_jni_invokeNative ********************************************************
+
+   Invoke a method on the given object with the given arguments.
+
+   For instance methods OBJ must be != NULL and the method is looked up
+   in the vftbl of the object.
+
+   For static methods, OBJ is ignored.
+
+*******************************************************************************/
+
+java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
+                                                                               java_objectarray *params)
 {
-       int argcount;
-       jni_callblock *blk;
-       jlong ret;
+       methodinfo        *resm;
+       vm_arg            *vmargs;
+       java_objectheader *ro;
+       s4                 argcount;
+       s4                 paramcount;
 
-/*     
-        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;
+       if (!m) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
        }
 
-       argcount = get_parametercount(methodID);
+       argcount = m->parseddesc->paramcount;
+       paramcount = argcount;
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
-                  ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
+       /* if method is non-static, remove the `this' pointer */
+
+       if (!(m->flags & ACC_STATIC))
+               paramcount--;
+
+       /* For instance methods the object has to be an instance of the
+          class the method belongs to. For static methods the obj
+          parameter is ignored. */
+
+       if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_IllegalArgumentException,
+                                                                 "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
+               return NULL;
        }
 
-       if (obj && !builtin_instanceof(obj,methodID->class)) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
+       /* check if we got the right number of arguments */
+
+       if (((params == NULL) && (paramcount != 0)) ||
+               (params && (params->header.size != paramcount))) 
+       {
+               *exceptionptr =
+                       new_exception(string_java_lang_IllegalArgumentException);
+               return NULL;
        }
 
-#ifdef arglimit
-       if (argcount > 3) {
-               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
-               log_text("Too many arguments. CallObjectMethod does not support that");
-               return 0;
+       /* for instance methods we need an object */
+
+       if (!(m->flags & ACC_STATIC) && (o == NULL)) {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NullPointerException,
+                                                                 "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
+               return NULL;
        }
-#endif
 
-       blk = MNEW(jni_callblock,/* 4 */argcount+2);
+       /* for static methods, zero object to make subsequent code simpler */
+       if (m->flags & ACC_STATIC)
+               o = NULL;
+
+       if (o != NULL) {
+               /* for instance methods we must do a vftbl lookup */
+               resm = method_vftbl_lookup(o->vftbl, m);
+
+       } else {
+               /* for static methods, just for convenience */
+               resm = m;
+       }
+
+       vmargs = MNEW(vm_arg, argcount);
+
+       if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params))
+               return NULL;
+
+       switch (resm->parseddesc->returntype.decltype) {
+       case TYPE_VOID:
+               (void) vm_call_method_vmarg(resm, argcount, vmargs);
+
+               ro = NULL;
+               break;
+
+       case PRIMITIVETYPE_BOOLEAN: {
+               s4 i;
+               java_lang_Boolean *bo;
+
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Boolean);
+
+               /* setting the value of the object direct */
+
+               bo = (java_lang_Boolean *) ro;
+               bo->value = i;
+       }
+       break;
+
+       case PRIMITIVETYPE_BYTE: {
+               s4 i;
+               java_lang_Byte *bo;
+
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Byte);
+
+               /* setting the value of the object direct */
+
+               bo = (java_lang_Byte *) ro;
+               bo->value = i;
+       }
+       break;
+
+       case PRIMITIVETYPE_CHAR: {
+               s4 i;
+               java_lang_Character *co;
+
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Character);
+
+               /* setting the value of the object direct */
+
+               co = (java_lang_Character *) ro;
+               co->value = i;
+       }
+       break;
+
+       case PRIMITIVETYPE_SHORT: {
+               s4 i;
+               java_lang_Short *so;
+
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Short);
+
+               /* setting the value of the object direct */
+
+               so = (java_lang_Short *) ro;
+               so->value = i;
+       }
+       break;
+
+       case PRIMITIVETYPE_INT: {
+               s4 i;
+               java_lang_Integer *io;
+
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Integer);
+
+               /* setting the value of the object direct */
+
+               io = (java_lang_Integer *) ro;
+               io->value = i;
+       }
+       break;
+
+       case PRIMITIVETYPE_LONG: {
+               s8 l;
+               java_lang_Long *lo;
+
+               l = vm_call_method_long_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Long);
+
+               /* setting the value of the object direct */
+
+               lo = (java_lang_Long *) ro;
+               lo->value = l;
+       }
+       break;
+
+       case PRIMITIVETYPE_FLOAT: {
+               float f;
+               java_lang_Float *fo;
+
+               f = vm_call_method_float_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Float);
+
+               /* setting the value of the object direct */
+
+               fo = (java_lang_Float *) ro;
+               fo->value = f;
+       }
+       break;
+
+       case PRIMITIVETYPE_DOUBLE: {
+               double d;
+               java_lang_Double *_do;
+
+               d = vm_call_method_double_vmarg(resm, argcount, vmargs);
+
+               ro = builtin_new(class_java_lang_Double);
+
+               /* setting the value of the object direct */
+
+               _do = (java_lang_Double *) ro;
+               _do->value = d;
+       }
+       break;
+
+       case TYPE_ADR:
+               ro = vm_call_method_vmarg(resm, argcount, vmargs);
+               break;
+
+       default:
+               /* if this happens the exception has already been set by
+                  fill_callblock_from_objectarray */
+
+               MFREE(vmargs, vm_arg, argcount);
+
+               return NULL;
+       }
+
+       MFREE(vmargs, vm_arg, argcount);
+
+       if (*exceptionptr) {
+               java_objectheader *cause;
+
+               cause = *exceptionptr;
+
+               /* clear exception pointer, we are calling JIT code again */
+
+               *exceptionptr = NULL;
+
+               *exceptionptr =
+                       new_exception_throwable(string_java_lang_reflect_InvocationTargetException,
+                                                                       (java_lang_Throwable *) cause);
+       }
+
+       return ro;
+}
+
+
+/* GetVersion ******************************************************************
+
+   Returns the major version number in the higher 16 bits and the
+   minor version number in the lower 16 bits.
+
+*******************************************************************************/
+
+jint GetVersion(JNIEnv *env)
+{
+       STATISTICS(jniinvokation());
+
+       /* we support JNI 1.4 */
+
+       return JNI_VERSION_1_4;
+}
+
+
+/* Class Operations ***********************************************************/
+
+/* DefineClass *****************************************************************
+
+   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.
+
+*******************************************************************************/
+
+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;
+
+       STATISTICS(jniinvokation());
+
+       cl = (java_lang_ClassLoader *) loader;
+       s = javastring_new_char(name);
+       ba = (java_bytearray *) buf;
+
+       c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
+                                                                                                                 0, bufLen, NULL);
+
+       return (jclass) NewLocalRef(env, (jobject) c);
+}
+
+
+/* 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)
+{
+       utf       *u;
+       classinfo *cc;
+       classinfo *c;
+
+       STATISTICS(jniinvokation());
+
+       u = utf_new_char_classname((char *) name);
+
+       /* Check stacktrace for classloader, if one found use it,
+          otherwise use the system classloader. */
+
+       /* Quote from the JNI documentation:
+        
+          In the Java 2 Platform, FindClass locates the class loader
+          associated with the current native method.  If the native code
+          belongs to a system class, no class loader will be
+          involved. Otherwise, the proper class loader will be invoked to
+          load and link the named class. When FindClass is called through
+          the Invocation Interface, there is no current native method or
+          its associated class loader. In that case, the result of
+          ClassLoader.getBaseClassLoader is used." */
+
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__)
+       /* these JITs support stacktraces, and so does the interpreter */
+
+       cc = stacktrace_getCurrentClass();
+#else
+# if defined(ENABLE_INTRP)
+       /* the interpreter supports stacktraces, even if the JIT does not */
+
+       if (opt_intrp)
+               cc = stacktrace_getCurrentClass();
+       else
+# endif
+               cc = NULL;
+#endif
+
+       /* if no Java method was found, use the system classloader */
+
+       if (cc == NULL)
+               c = load_class_from_sysloader(u);
+       else
+               c = load_class_from_classloader(u, cc->classloader);
+
+       if (c == NULL)
+               return NULL;
+
+       if (!link_class(c))
+               return NULL;
+
+       return (jclass) NewLocalRef(env, (jobject) c);
+}
+  
+
+/* 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)
+{
+       classinfo *c;
+
+       STATISTICS(jniinvokation());
+
+       c = ((classinfo *) sub)->super.cls;
+
+       if (!c)
+               return NULL;
+
+       return (jclass) NewLocalRef(env, (jobject) c);
+}
+  
+/* IsAssignableFrom ************************************************************
+
+   Determines whether an object of sub can be safely cast to sup.
+
+*******************************************************************************/
+
+jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
+{
+       STATISTICS(jniinvokation());
+
+       return Java_java_lang_VMClass_isAssignableFrom(env,
+                                                                                                  NULL,
+                                                                                                  (java_lang_Class *) sup,
+                                                                                                  (java_lang_Class *) sub);
+}
+
+
+/* Throw ***********************************************************************
+
+   Causes a java.lang.Throwable object to be thrown.
+
+*******************************************************************************/
+
+jint Throw(JNIEnv *env, jthrowable obj)
+{
+       STATISTICS(jniinvokation());
+
+       *exceptionptr = (java_objectheader *) obj;
+
+       return JNI_OK;
+}
+
+
+/* ThrowNew ********************************************************************
+
+   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;
+
+       STATISTICS(jniinvokation());
+
+       s = (java_lang_String *) javastring_new_char(msg);
+
+       /* instantiate exception object */
+
+       o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz,
+                                                                                                                  s);
+
+       if (!o)
+               return -1;
+
+       *exceptionptr = (java_objectheader *) o;
+
+       return 0;
+}
+
+
+/* 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)
+{
+       java_objectheader *e;
+
+       STATISTICS(jniinvokation());
+
+       e = *exceptionptr;
+
+       return NewLocalRef(env, (jthrowable) e);
+}
+
+
+/* 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)
+{
+       java_objectheader *e;
+       methodinfo        *m;
+
+       STATISTICS(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 */
+
+               (void) vm_call_method(m, e);
+       }
+}
+
+
+/* ExceptionClear **************************************************************
+
+   Clears any exception that is currently being thrown. If no
+   exception is currently being thrown, this routine has no effect.
+
+*******************************************************************************/
+
+void ExceptionClear(JNIEnv *env)
+{
+       STATISTICS(jniinvokation());
+
+       *exceptionptr = NULL;
+}
+
+
+/* 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)
+{
+       STATISTICS(jniinvokation());
+
+       throw_cacao_exception_exit(string_java_lang_InternalError, msg);
+}
+
+
+/* PushLocalFrame **************************************************************
+
+   Creates a new local reference frame, in which at least a given
+   number of local references can be created.
+
+*******************************************************************************/
+
+jint PushLocalFrame(JNIEnv* env, jint capacity)
+{
+       STATISTICS(jniinvokation());
+
+       log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!");
+
+       assert(0);
+
+       return 0;
+}
+
+/* PopLocalFrame ***************************************************************
+
+   Pops off the current local reference frame, frees all the local
+   references, and returns a local reference in the previous local
+   reference frame for the given result object.
+
+*******************************************************************************/
+
+jobject PopLocalFrame(JNIEnv* env, jobject result)
+{
+       STATISTICS(jniinvokation());
+
+       log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!");
+
+       assert(0);
+
+       /* add local reference and return the value */
+
+       return NewLocalRef(env, NULL);
+}
+
+
+/* DeleteLocalRef **************************************************************
+
+   Deletes the local reference pointed to by localRef.
+
+*******************************************************************************/
+
+void DeleteLocalRef(JNIEnv *env, jobject localRef)
+{
+       java_objectheader *o;
+       localref_table    *lrt;
+       s4                 i;
+
+       STATISTICS(jniinvokation());
+
+       o = (java_objectheader *) localRef;
+
+       /* get local reference table (thread specific) */
+
+       lrt = LOCALREFTABLE;
+
+       /* remove the reference */
+
+       for (i = 0; i < lrt->capacity; i++) {
+               if (lrt->refs[i] == o) {
+                       lrt->refs[i] = NULL;
+                       lrt->used--;
+
+                       return;
+               }
+       }
+
+       /* this should not happen */
+
+/*     if (opt_checkjni) */
+/*     FatalError(env, "Bad global or local ref passed to JNI"); */
+       log_text("JNI-DeleteLocalRef: Bad global or local ref passed to JNI");
+}
+
+
+/* IsSameObject ****************************************************************
+
+   Tests whether two references refer to the same Java object.
+
+*******************************************************************************/
+
+jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
+{
+       STATISTICS(jniinvokation());
+
+       if (ref1 == ref2)
+               return JNI_TRUE;
+       else
+               return JNI_FALSE;
+}
+
+
+/* NewLocalRef *****************************************************************
+
+   Creates a new local reference that refers to the same object as ref.
+
+*******************************************************************************/
+
+jobject NewLocalRef(JNIEnv *env, jobject ref)
+{
+       localref_table *lrt;
+       s4              i;
+
+       STATISTICS(jniinvokation());
+
+       if (ref == NULL)
+               return NULL;
+
+       /* get local reference table (thread specific) */
+
+       lrt = LOCALREFTABLE;
+
+       /* check if we have space for the requested reference */
+
+       if (lrt->used == lrt->capacity) {
+/*             throw_cacao_exception_exit(string_java_lang_InternalError, */
+/*                                                                "Too many local references"); */
+               fprintf(stderr, "Too many local references");
+               assert(0);
+       }
+
+       /* insert the reference */
+
+       for (i = 0; i < lrt->capacity; i++) {
+               if (lrt->refs[i] == NULL) {
+                       lrt->refs[i] = (java_objectheader *) ref;
+                       lrt->used++;
+
+                       return ref;
+               }
+       }
+
+       /* should not happen, just to be sure */
+
+       assert(0);
+
+       /* keep compiler happy */
+
+       return NULL;
+}
+
+
+/* EnsureLocalCapacity *********************************************************
+
+   Ensures that at least a given number of local references can be
+   created in the current thread
+
+*******************************************************************************/
+
+jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
+{
+       localref_table *lrt;
+
+       STATISTICS(jniinvokation());
+
+       /* get local reference table (thread specific) */
+
+       lrt = LOCALREFTABLE;
+
+       /* check if capacity elements are available in the local references table */
+
+       if ((lrt->used + capacity) > lrt->capacity) {
+               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* 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)
+{
+       classinfo         *c;
+       java_objectheader *o;
+
+       STATISTICS(jniinvokation());
+
+       c = (classinfo *) clazz;
+
+       if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_InstantiationException,
+                                                                        c->name);
+               return NULL;
+       }
+               
+       o = builtin_new(c);
+
+       return NewLocalRef(env, o);
+}
+
+
+/* NewObject *******************************************************************
+
+   Programmers place all arguments that are to be passed to the
+   constructor immediately following the methodID
+   argument. NewObject() accepts these arguments and passes them to
+   the Java method that the programmer wishes to invoke.
+
+*******************************************************************************/
+
+jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+
+       STATISTICS(jniinvokation());
+
+       m = (methodinfo *) methodID;
+
+       /* create object */
+
+       o = builtin_new(clazz);
+       
+       if (o == NULL)
+               return NULL;
+
+       /* call constructor */
+
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return NewLocalRef(env, o);
+}
+
+
+/* NewObjectV ******************************************************************
+
+   Programmers place all arguments that are to be passed to the
+   constructor in an args argument of type va_list that immediately
+   follows the methodID argument. NewObjectV() accepts these
+   arguments, and, in turn, passes them to the Java method that the
+   programmer wishes to invoke.
+
+*******************************************************************************/
+
+jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+
+       STATISTICS(jniinvokation());
+
+       m = (methodinfo *) methodID;
+
+       /* create object */
+
+       o = builtin_new(clazz);
+       
+       if (o == NULL)
+               return NULL;
+
+       /* call constructor */
+
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
+
+       return NewLocalRef(env, o);
+}
+
+
+/* NewObjectA ***************************************************************** 
+
+   Programmers place all arguments that are to be passed to the
+   constructor in an args array of jvalues that immediately follows
+   the methodID argument. NewObjectA() accepts the arguments in this
+   array, and, in turn, passes them to the Java method that the
+   programmer wishes to invoke.
+
+*******************************************************************************/
+
+jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+
+       STATISTICS(jniinvokation());
+
+       m = (methodinfo *) methodID;
+
+       /* create object */
+
+       o = builtin_new(clazz);
+       
+       if (o == NULL)
+               return NULL;
+
+       /* call constructor */
+
+       _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
+
+       return NewLocalRef(env, o);
+}
+
+
+/* GetObjectClass **************************************************************
+
+ Returns the class of an object.
+
+*******************************************************************************/
+
+jclass GetObjectClass(JNIEnv *env, jobject obj)
+{
+       java_objectheader *o;
+       classinfo         *c;
+
+       STATISTICS(jniinvokation());
+
+       o = (java_objectheader *) obj;
+
+       if ((o == NULL) || (o->vftbl == NULL))
+               return NULL;
+
+       c = o->vftbl->class;
+
+       return (jclass) NewLocalRef(env, (jobject) c);
+}
+
+
+/* IsInstanceOf ****************************************************************
+
+   Tests whether an object is an instance of a class.
+
+*******************************************************************************/
+
+jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
+{
+       STATISTICS(jniinvokation());
+
+       return Java_java_lang_VMClass_isInstance(env,
+                                                                                        NULL,
+                                                                                        (java_lang_Class *) clazz,
+                                                                                        (java_lang_Object *) obj);
+}
+
+
+/* Reflection Support *********************************************************/
+
+/* FromReflectedMethod *********************************************************
+
+   Converts java.lang.reflect.Method or java.lang.reflect.Constructor
+   object to a method ID.
+  
+*******************************************************************************/
+  
+jmethodID FromReflectedMethod(JNIEnv *env, jobject method)
+{
+       methodinfo *mi;
+       classinfo  *c;
+       s4          slot;
+
+       STATISTICS(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;
+
+       mi = &(c->methods[slot]);
+
+       return (jmethodID) mi;
+}
+
+
+/* FromReflectedField **********************************************************
+
+   Converts a java.lang.reflect.Field to a field ID.
+
+*******************************************************************************/
+jfieldID FromReflectedField(JNIEnv* env, jobject field)
+{
+       java_lang_reflect_Field *rf;
+       classinfo               *c;
+       fieldinfo               *f;
+
+       STATISTICS(jniinvokation());
+
+       rf = (java_lang_reflect_Field *) field;
+
+       if (rf == NULL)
+               return NULL;
+
+       c = (classinfo *) rf->declaringClass;
+
+       f = &(c->fields[rf->slot]);
+
+       return (jfieldID) f;
+}
+
+
+/* ToReflectedMethod ***********************************************************
+
+   Converts a method ID derived from cls to an instance of the
+   java.lang.reflect.Method class or to an instance of the
+   java.lang.reflect.Constructor class.
+
+*******************************************************************************/
+
+jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
+{
+       STATISTICS(jniinvokation());
+
+       log_text("JNI-Call: ToReflectedMethod: IMPLEMENT ME!");
+
+       return NULL;
+}
+
+
+/* ToReflectedField ************************************************************
+
+   Converts a field ID derived from cls to an instance of the
+   java.lang.reflect.Field class.
+
+*******************************************************************************/
+
+jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
+                                                jboolean isStatic)
+{
+       STATISTICS(jniinvokation());
+
+       log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
+
+       return NULL;
+}
+
+
+/* Calling Instance Methods ***************************************************/
+
+/* GetMethodID *****************************************************************
+
+   Returns the method ID for an instance (nonstatic) method of a class
+   or interface. The method may be defined in one of the clazz's
+   superclasses and inherited by clazz. The method is determined by
+   its name and signature.
+
+   GetMethodID() causes an uninitialized class to be initialized.
+
+*******************************************************************************/
+
+jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
+                                         const char *sig)
+{
+       classinfo  *c;
+       utf        *uname;
+       utf        *udesc;
+       methodinfo *m;
+
+       STATISTICS(jniinvokation());
+
+       c = (classinfo *) clazz;
+
+       if (!c)
+               return NULL;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return NULL;
+
+       /* try to get the method of the class or one of it's superclasses */
+
+       uname = utf_new_char((char *) name);
+       udesc = utf_new_char((char *) sig);
+
+       m = class_resolvemethod(clazz, uname, udesc);
+
+       if ((m == NULL) || (m->flags & ACC_STATIC)) {
+               exceptions_throw_nosuchmethoderror(c, uname, udesc);
+
+               return NULL;
+       }
+
+       return (jmethodID) m;
+}
+
+
+/* JNI-functions for calling instance methods *********************************/
+
+jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       java_objectheader *ret;
+       va_list            ap;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return NewLocalRef(env, ret);
+}
+
+
+jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       java_objectheader *ret;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, args);
+
+       return NewLocalRef(env, ret);
+}
+
+
+jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       java_objectheader *ret;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       ret = _Jv_jni_CallObjectMethodA(o, o->vftbl, m, args);
+
+       return NewLocalRef(env, ret);
+}
+
+
+jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jboolean           b;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return b;
+}
+
+
+jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jboolean           b;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
+
+       return b;
+}
+
+
+jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+{
+       log_text("JNI-Call: CallBooleanMethodA");
+
+       return 0;
+}
+
+
+jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jbyte              b;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return b;
+
+}
+
+jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jbyte              b;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
+
+       return b;
+}
+
+
+jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallByteMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jchar              c;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       c = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return c;
+}
+
+
+jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jchar              c;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       c = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
+
+       return c;
+}
+
+
+jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallCharMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jshort             s;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       s = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return s;
+}
+
+
+jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jshort             s;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       s = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
+
+       return s;
+}
+
+
+jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallShortMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+
+jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jint               i;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       i = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return i;
+}
+
+
+jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jint               i;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       i = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
+
+       return i;
+}
+
+
+jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallIntMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+
+jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jlong              l;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       l = _Jv_jni_CallLongMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return l;
+}
+
+
+jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jlong              l;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       l = _Jv_jni_CallLongMethod(o, o->vftbl, m, args);
+
+       return l;
+}
+
+
+jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallLongMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+
+jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jfloat             f;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return f;
+}
+
+
+jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jfloat             f;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, args);
+
+       return f;
+}
+
+
+jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallFloatMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+
+jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jdouble            d;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+
+       return d;
+}
+
+
+jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       jdouble            d;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, args);
+
+       return d;
+}
+
+
+jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallDoubleMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+
+void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
+       va_end(ap);
+}
+
+
+void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
+}
+
+
+void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+{
+       java_objectheader *o;
+       methodinfo        *m;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
+}
+
+
+
+jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       java_objectheader *r;
+       va_list            ap;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
+       va_end(ap);
+
+       return NewLocalRef(env, r);
+}
+
+
+jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       java_objectheader *r;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
+
+       return NewLocalRef(env, r);
+}
+
+
+jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
+
+       return NewLocalRef(env, NULL);
+}
+
+
+
+jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jboolean           b;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
+       va_end(ap);
+
+       return b;
+}
+
+
+jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jboolean           b;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
+
+       return b;
+}
+
+
+jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallNonvirtualBooleanMethodA: IMPLEMENT ME!");
+
+       return 0;
+}
+
+
+jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jbyte              b;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
-       fill_callblock(obj, methodID->descriptor, blk, args, 'J');
+       return b;
+}
+
+
+jbyte CallNonvirtualByteMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jbyte              b;
 
-       /*      printf("parameter: obj: %p",blk[0].item); */
-       ret = asm_calljavafunction2long(methodID,
-                                                                       argcount + 1,
-                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                       blk);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       MFREE(blk, jni_callblock, argcount + 1);
-       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return b;
 }
 
 
-/*core function for float class methods (float,double)*/
-jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType)
+jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       int argcount = get_parametercount(methodID);
-       jni_callblock *blk;
-       jdouble ret;
+       log_text("JNI-Call: CallNonvirtualByteMethodA: IMPLEMENT ME!");
 
-        /*
-        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");
-        */
+       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, retType);
+jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jchar              ch;
 
-       /*      printf("parameter: obj: %p",blk[0].item); */
-       ret = asm_calljavafunction2double(methodID,
-                                                                         argcount + 1,
-                                                                         (argcount + 1) * sizeof(jni_callblock),
-                                                                         blk);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       MFREE(blk, jni_callblock, argcount + 1);
-       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+       va_start(ap, methodID);
+       ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
-       return ret;
+       return ch;
 }
 
 
-/*************************** function: jclass_findfield ****************************
-       
-       searches for field with specified name and type in a 'classinfo'-structur
-       if no such field is found NULL is returned 
-
-************************************************************************************/
-
-fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
+jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       s4 i;
-/*     printf(" FieldCount: %d\n",c->fieldscount);
-       utf_display(c->name); */
-               for (i = 0; i < c->fieldscount; i++) {
-/*             utf_display(c->fields[i].name);
-               printf("\n");
-               utf_display(c->fields[i].descriptor);
-               printf("\n");*/
-               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
-                       return &(c->fields[i]);
-               }
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jchar              ch;
 
-       if (c->super) return jclass_findfield(c->super,name,desc);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       return NULL;
+       ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
+
+       return ch;
 }
 
-/********************* returns version of native method interface *****************/
 
-jint GetVersion (JNIEnv* env)
+jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       return JNI_VERSION;
+       log_text("JNI-Call: CallNonvirtualCharMethodA: IMPLEMENT ME!");
+
+       return 0;
 }
 
 
-/************** loads a class from a buffer of raw class data *****************/
 
-jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *buf, jsize len) 
+jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       jclass c; 
-       jclass r;
-       classbuffer *cb;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jshort             s;
 
-       c = class_new(utf_new_char_classname((char *) name));
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-#if defined(USE_THREADS)
-       /* enter a monitor on the class */
+       va_start(ap, methodID);
+       s = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
-       builtin_monitorenter((java_objectheader *) c);
-#endif
+       return s;
+}
 
-       /* measure time */
-       if (getloadingtime)
-               loadingtime_start();
 
-       /* build a classbuffer with the given data */
-       cb = NEW(classbuffer);
-       cb->class = c;
-       cb->size = len;
-       cb->data = (u1 *) buf;
-       cb->pos = cb->data - 1;
+jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jshort             s;
 
-       r = class_load_intern(cb);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       /* if return value is NULL, we had a problem and the class is not loaded */
-       if (!r) {
-               c->loaded = false;
+       s = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-               /* now free the allocated memory, otherwise we could ran into a DOS */
-               class_remove(c);
-       }
+       return s;
+}
 
-       /* free memory */
-       FREE(cb, classbuffer);
 
-       /* measure time */
-       if (getloadingtime)
-               loadingtime_stop();
+jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+{
+       log_text("JNI-Call: CallNonvirtualShortMethodA: IMPLEMENT ME!");
 
-#if defined(USE_THREADS)
-       /* leave the monitor */
+       return 0;
+}
 
-       builtin_monitorexit((java_objectheader *) c);
-#endif
 
-       /* XXX link the class here? */
-/*     if (class_link(c)) */
-/*             return NULL; */
 
-       if (r) {
-               c->classloader = loader;
-               use_class_as_object(r);
-       }
+jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jint               i;
 
-       return r;
-}
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       i = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
+       return i;
+}
 
-/*********** loads locally defined class with the specified name **************/
 
-jclass FindClass(JNIEnv* env, const char *name) 
+jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       classinfo *c;  
-  
-       c = class_new(utf_new_char_classname((char *) name));
-
-       if (!class_load(c))
-               return NULL;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jint               i;
 
-       if (!class_link(c))
-               return NULL;
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       use_class_as_object(c);
+       i = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-       return c;
+       return i;
 }
-  
 
-/*******************************************************************************
 
-       converts java.lang.reflect.Method or 
-       java.lang.reflect.Constructor object to a method ID  
-  
-*******************************************************************************/
-  
-jmethodID FromReflectedMethod(JNIEnv* env, jobject method)
+jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       /* log_text("JNI-Call: FromReflectedMethod"); */
+       log_text("JNI-Call: CallNonvirtualIntMethodA: IMPLEMENT ME!");
 
        return 0;
 }
 
 
-/*************** return superclass of the class represented by sub ****************/
-jclass GetSuperclass(JNIEnv* env, jclass sub) 
-{
-       classinfo *c;
 
-       c = ((classinfo*) sub)->super;
+jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jlong              l;
 
-       if (!c) return NULL; 
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       use_class_as_object(c);
+       va_start(ap, methodID);
+       l = _Jv_jni_CallLongMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
-       return c;               
+       return l;
 }
-  
-/* IsAssignableFrom ************************************************************
-
-   Determines whether an object of sub can be safely cast to sup.
 
-*******************************************************************************/
 
-jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
+jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       return builtin_isanysubclass(sub, sup);
-}
-
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jlong              l;
 
-/***** converts a field ID derived from cls to a java.lang.reflect.Field object ***/
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic)
-{
-       /* log_text("JNI-Call: ToReflectedField"); */
+       l = _Jv_jni_CallLongMethod(o, c->vftbl, m, args);
 
-       return NULL;
+       return l;
 }
 
 
-/***************** throw java.lang.Throwable object  ******************************/
-
-jint Throw(JNIEnv* env, jthrowable obj)
+jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       *exceptionptr = (java_objectheader*) obj;
+       log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!");
 
        return 0;
 }
 
 
-/*******************************************************************************
 
-       create exception object from the class clazz with the 
-       specified message and cause it to be thrown
-
-*******************************************************************************/
-
-jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
+jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       java_lang_Throwable *o;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jfloat             f;
 
-       /* instantiate exception object */
-       o = (java_lang_Throwable *) native_new_and_init((classinfo*) clazz);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       if (!o) return (-1);
+       va_start(ap, methodID);
+       f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
-       o->detailMessage = (java_lang_String *) javastring_new_char((char *) msg);
+       return f;
+}
 
-       *exceptionptr = (java_objectheader *) o;
 
-       return 0;
-}
+jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jfloat             f;
 
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-/************************* check if exception occured *****************************/
+       f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, args);
 
-jthrowable ExceptionOccurred (JNIEnv* env) 
-{
-       return (jthrowable) *exceptionptr;
+       return f;
 }
 
-/********** print exception and a backtrace of the stack (for debugging) **********/
 
-void ExceptionDescribe (JNIEnv* env) 
+jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       utf_display((*exceptionptr)->vftbl->class->name);
-       printf ("\n");
-       fflush (stdout);        
+       log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!");
+
+       return 0;
 }
 
 
-/******************* clear any exception currently being thrown *******************/
 
-void ExceptionClear (JNIEnv* env) 
+jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       *exceptionptr = NULL;   
-}
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jdouble            d;
 
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-/********** raises a fatal error and does not expect the VM to recover ************/
+       va_start(ap, methodID);
+       d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
-void FatalError (JNIEnv* env, const char *msg)
-{
-       panic((char *) msg);    
+       return d;
 }
 
-/******************* creates a new local reference frame **************************/ 
 
-jint PushLocalFrame(JNIEnv* env, jint capacity)
+jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       /* empty */
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jdouble            d;
 
-       return 0;
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, args);
+
+       return d;
 }
 
-/**************** Pops off the current local reference frame **********************/
 
-jobject PopLocalFrame(JNIEnv* env, jobject result)
+jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
-    log_text("JNI-Call: PopLocalFrame");
-       /* empty */
+       log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!");
 
-       return NULL;
+       return 0;
 }
 
 
-/*************** Deletes the local reference pointed to by localRef ***************/
 
-void DeleteLocalRef (JNIEnv* env, jobject localRef)
+void CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-/*    log_text("JNI-Call: DeleteLocalRef");*/
-       /* empty */
-}
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
 
-/********** Tests whether two references refer to the same Java object ************/
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-jboolean IsSameObject (JNIEnv* env, jobject obj1, jobject obj2)
-{
-       return (obj1==obj2);
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 }
 
-/***** Creates a new local reference that refers to the same object as ref  *******/
 
-jobject NewLocalRef (JNIEnv* env, jobject ref)
+void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       return ref;
-}
-
-/*********************************************************************************** 
-
-       Ensures that at least a given number of local references can 
-       be created in the current thread
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
 
- **********************************************************************************/   
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-jint EnsureLocalCapacity (JNIEnv* env, jint capacity)
-{
-       return 0; /* return 0 on success */
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
 }
 
 
-/********* Allocates a new Java object without invoking a constructor *************/
+void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
+{      
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
 
-jobject AllocObject (JNIEnv* env, jclass clazz)
-{
-        java_objectheader *o = builtin_new(clazz);     
-       return o;
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
 }
 
 
-/*********************************************************************************** 
+/* Accessing Fields of Objects ************************************************/
+
+/* GetFieldID ******************************************************************
 
-       Constructs a new Java object
-       arguments that are to be passed to the constructor are placed after methodID
+   Returns the field ID for an instance (nonstatic) field of a
+   class. The field is specified by its name and signature. The
+   Get<type>Field and Set<type>Field families of accessor functions
+   use field IDs to retrieve object fields.
 
-***********************************************************************************/
+*******************************************************************************/
 
-jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
+jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name,
+                                       const char *sig) 
 {
-       java_objectheader *o;
-       void* args[3];
-       int argcount=get_parametercount(methodID);
-       int i;
-       va_list vaargs;
+       fieldinfo *f;
+       utf       *uname;
+       utf       *udesc;
 
-       /* log_text("JNI-Call: NewObject"); */
+       STATISTICS(jniinvokation());
 
-#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
-       
-       o = builtin_new (clazz);         /*          create object */
-       
-       if (!o) return NULL;
+       uname = utf_new_char((char *) name);
+       udesc = utf_new_char((char *) sig);
 
-       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]);
+       f = class_findfield(clazz, uname, udesc); 
+       
+       if (!f)
+               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
 
-       return o;
+       return (jfieldID) f;
 }
 
 
-/*********************************************************************************** 
+/* Get<type>Field Routines *****************************************************
 
-       Constructs a new Java object
-       arguments that are to be passed to the constructor are placed in va_list args 
+   This family of accessor routines returns the value of an instance
+   (nonstatic) field of an object. The field to access is specified by
+   a field ID obtained by calling GetFieldID().
 
-***********************************************************************************/
+*******************************************************************************/
 
-jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
+jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       /* log_text("JNI-Call: NewObjectV"); */
-
-       return NULL;
-}
+       java_objectheader *o;
 
+       STATISTICS(jniinvokation());
 
-/*********************************************************************************** 
+       o = GET_FIELD(obj, java_objectheader*, fieldID);
 
-       Constructs a new Java object
-       arguments that are to be passed to the constructor are placed in 
-       args array of jvalues 
+       return NewLocalRef(env, o);
+}
 
-***********************************************************************************/
 
-jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
+jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       /* log_text("JNI-Call: NewObjectA"); */
+       s4 i;
 
-       return NULL;
-}
+       STATISTICS(jniinvokation());
+
+       i = GET_FIELD(obj, s4, fieldID);
 
+       return (jboolean) i;
+}
 
-/************************ returns the class of an object **************************/ 
 
-jclass GetObjectClass(JNIEnv* env, jobject obj)
+jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       classinfo *c = obj->vftbl->class;
+       s4 i;
 
-       use_class_as_object(c);
+       STATISTICS(jniinvokation());
 
-       return c;
-}
+       i = GET_FIELD(obj, s4, fieldID);
 
+       return (jbyte) i;
+}
 
-/************* tests whether an object is an instance of a class ******************/
 
-jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
+jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       return builtin_instanceof(obj,clazz);
-}
+       s4 i;
 
+       STATISTICS(jniinvokation());
 
-/***************** converts a java.lang.reflect.Field to a field ID ***************/
-jfieldID FromReflectedField(JNIEnv* env, jobject field)
-{
-       log_text("JNI-Call: FromReflectedField");
+       i = GET_FIELD(obj, s4, fieldID);
 
-       return 0;
+       return (jchar) i;
 }
 
 
-/**********************************************************************************
+jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID)
+{
+       s4 i;
+
+       STATISTICS(jniinvokation());
 
-       converts a method ID to a java.lang.reflect.Method or 
-       java.lang.reflect.Constructor object
+       i = GET_FIELD(obj, s4, fieldID);
 
-**********************************************************************************/
+       return (jshort) i;
+}
 
-jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
+
+jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       log_text("JNI-Call: ToReflectedMethod");
+       java_objectheader *o;
+       fieldinfo         *f;
+       s4                 i;
 
-       return NULL;
-}
+       STATISTICS(jniinvokation());
 
+       o = (java_objectheader *) obj;
+       f = (fieldinfo *) fieldID;
 
-/* GetMethodID *****************************************************************
+       i = GET_FIELD(o, s4, f);
 
-   returns the method ID for an instance method
+       return i;
+}
 
-*******************************************************************************/
 
-jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *sig)
+jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       jmethodID m;
-
-       m = class_resolvemethod(clazz, 
-                                                       utf_new_char((char *) name), 
-                                                       utf_new_char((char *) sig));
+       s8 l;
 
-       if (!m || (m->flags & ACC_STATIC)) {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NoSuchMethodError, name);
+       STATISTICS(jniinvokation());
 
-               return 0;
-       }
+       l = GET_FIELD(obj, s8, fieldID);
 
-       return m;
+       return l;
 }
 
 
-/******************** JNI-functions for calling instance methods ******************/
-
-jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       jobject ret;
-       va_list vaargs;
+       float f;
 
-/*     log_text("JNI-Call: CallObjectMethod");*/
+       STATISTICS(jniinvokation());
 
-       va_start(vaargs, methodID);
-       ret = callObjectMethod(obj, methodID, vaargs);
-       va_end(vaargs);
+       f = GET_FIELD(obj, float, fieldID);
 
-       return ret;
+       return f;
 }
 
 
-jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       return callObjectMethod(obj,methodID,args);
-}
+       double d;
 
+       STATISTICS(jniinvokation());
 
-jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
-{
-       log_text("JNI-Call: CallObjectMethodA");
+       d = GET_FIELD(obj, double, fieldID);
 
-       return NULL;
+       return d;
 }
 
 
+/* Set<type>Field Routines *****************************************************
 
+   This family of accessor routines sets the value of an instance
+   (nonstatic) field of an object. The field to access is specified by
+   a field ID obtained by calling GetFieldID().
 
-jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       jboolean ret;
-       va_list vaargs;
-
-/*     log_text("JNI-Call: CallBooleanMethod");*/
+*******************************************************************************/
 
-       va_start(vaargs,methodID);
-       ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',vaargs);
-       va_end(vaargs);
-       return ret;
+void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)
+{
+       STATISTICS(jniinvokation());
 
+       SET_FIELD(obj, java_objectheader*, fieldID, value);
 }
 
-jboolean CallBooleanMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+
+void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean value)
 {
-       return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',args);
+       STATISTICS(jniinvokation());
 
+       SET_FIELD(obj, s4, fieldID, value);
 }
 
-jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+
+void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value)
 {
-       log_text("JNI-Call: CallBooleanMethodA");
+       STATISTICS(jniinvokation());
 
-       return 0;
+       SET_FIELD(obj, s4, fieldID, value);
 }
 
-jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       jbyte ret;
-       va_list vaargs;
-
-/*     log_text("JNI-Call: CallVyteMethod");*/
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_virtual(obj,methodID),'B',vaargs);
-       va_end(vaargs);
-       return ret;
+void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value)
+{
+       STATISTICS(jniinvokation());
 
+       SET_FIELD(obj, s4, fieldID, value);
 }
 
-jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+
+void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value)
 {
-/*     log_text("JNI-Call: CallByteMethodV");*/
-       return callIntegerMethod(obj,methodID,'B',args);
+       STATISTICS(jniinvokation());
+
+       SET_FIELD(obj, s4, fieldID, value);
 }
 
 
-jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value)
 {
-       log_text("JNI-Call: CallByteMethodA");
+       STATISTICS(jniinvokation());
 
-       return 0;
+       SET_FIELD(obj, s4, fieldID, value);
 }
 
 
-jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value)
 {
-       jchar ret;
-       va_list vaargs;
-
-/*     log_text("JNI-Call: CallCharMethod");*/
-
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'C', vaargs);
-       va_end(vaargs);
+       STATISTICS(jniinvokation());
 
-       return ret;
+       SET_FIELD(obj, s8, fieldID, value);
 }
 
 
-jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value)
 {
-/*     log_text("JNI-Call: CallCharMethodV");*/
-       return callIntegerMethod(obj,get_virtual(obj,methodID),'C',args);
+       STATISTICS(jniinvokation());
+
+       SET_FIELD(obj, float, fieldID, value);
 }
 
 
-jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value)
 {
-       log_text("JNI-Call: CallCharMethodA");
+       STATISTICS(jniinvokation());
 
-       return 0;
+       SET_FIELD(obj, double, fieldID, value);
 }
 
 
-jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       jshort ret;
-       va_list vaargs;
+/* Calling Static Methods *****************************************************/
 
-/*     log_text("JNI-Call: CallShortMethod");*/
+/* GetStaticMethodID ***********************************************************
 
-       va_start(vaargs, methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'S', vaargs);
-       va_end(vaargs);
+   Returns the method ID for a static method of a class. The method is
+   specified by its name and signature.
 
-       return ret;
-}
+   GetStaticMethodID() causes an uninitialized class to be
+   initialized.
 
+*******************************************************************************/
 
-jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
+                                                       const char *sig)
 {
-       return callIntegerMethod(obj, get_virtual(obj, methodID), 'S', args);
-}
+       classinfo  *c;
+       utf        *uname;
+       utf        *udesc;
+       methodinfo *m;
 
+       STATISTICS(jniinvokation());
 
-jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallShortMethodA");
+       c = (classinfo *) clazz;
 
-       return 0;
-}
+       if (!c)
+               return NULL;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return NULL;
 
+       /* try to get the static method of the class */
 
-jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       jint ret;
-       va_list vaargs;
+       uname = utf_new_char((char *) name);
+       udesc = utf_new_char((char *) sig);
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'I', vaargs);
-       va_end(vaargs);
+       m = class_resolvemethod(c, uname, udesc);
 
-       return ret;
-}
+       if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+               exceptions_throw_nosuchmethoderror(c, uname, udesc);
 
+               return NULL;
+       }
 
-jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       return callIntegerMethod(obj, get_virtual(obj, methodID), 'I', args);
+       return (jmethodID) m;
 }
 
 
-jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallIntMethodA");
+       methodinfo        *m;
+       java_objectheader *o;
+       va_list            ap;
 
-       return 0;
-}
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
+       va_end(ap);
 
+       return NewLocalRef(env, o);
+}
 
 
-jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jlong ret;
-       va_list vaargs;
-       
-       va_start(vaargs,methodID);
-       ret = callLongMethod(obj,get_virtual(obj, methodID),vaargs);
-       va_end(vaargs);
+       methodinfo        *m;
+       java_objectheader *o;
 
-       return ret;
-}
+       m = (methodinfo *) methodID;
 
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
 
-jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       return  callLongMethod(obj,get_virtual(obj, methodID),args);
+       return NewLocalRef(env, o);
 }
 
 
-jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallLongMethodA");
+       log_text("JNI-Call: CallStaticObjectMethodA: IMPLEMENT ME!");
 
-       return 0;
+       return NewLocalRef(env, NULL);
 }
 
 
-
-jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       jfloat ret;
-       va_list vaargs;
+       methodinfo *m;
+       va_list     ap;
+       jboolean    b;
 
-/*     log_text("JNI-Call: CallFloatMethod");*/
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'F');
-       va_end(vaargs);
+       va_start(ap, methodID);
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
+       va_end(ap);
 
-       return ret;
+       return b;
 }
 
 
-jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallFloatMethodV");
-       return callFloatMethod(obj, get_virtual(obj, methodID), args, 'F');
+       methodinfo *m;
+       jboolean    b;
+
+       m = (methodinfo *) methodID;
+
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return b;
 }
 
 
-jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallFloatMethodA");
+       log_text("JNI-Call: CallStaticBooleanMethodA: IMPLEMENT ME!");
 
        return 0;
 }
 
 
-
-jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       jdouble ret;
-       va_list vaargs;
+       methodinfo *m;
+       va_list     ap;
+       jbyte       b;
 
-/*     log_text("JNI-Call: CallDoubleMethod");*/
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'D');
-       va_end(vaargs);
+       va_start(ap, methodID);
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
+       va_end(ap);
 
-       return ret;
+       return b;
 }
 
 
-jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallDoubleMethodV");
-       return callFloatMethod(obj, get_virtual(obj, methodID), args, 'D');
+       methodinfo *m;
+       jbyte       b;
+
+       m = (methodinfo *) methodID;
+
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return b;
 }
 
 
-jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallDoubleMethodA");
+       log_text("JNI-Call: CallStaticByteMethodA: IMPLEMENT ME!");
+
        return 0;
 }
 
 
+jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+{
+       methodinfo *m;
+       va_list     ap;
+       jchar       c;
+
+       m = (methodinfo *) methodID;
+
+       va_start(ap, methodID);
+       c = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
+       va_end(ap);
+
+       return c;
+}
+
+
+jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+{
+       methodinfo *m;
+       jchar       c;
+
+       m = (methodinfo *) methodID;
 
-void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       va_list vaargs;
+       c = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
 
-       va_start(vaargs,methodID);
-       (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs);
-       va_end(vaargs);
+       return c;
 }
 
 
-void CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallVoidMethodV");
-       (void)callIntegerMethod(obj,get_virtual(obj,methodID),'V',args);
+       log_text("JNI-Call: CallStaticCharMethodA: IMPLEMENT ME!");
+
+       return 0;
 }
 
 
-void CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallVoidMethodA");
-}
+       methodinfo *m;
+       va_list     ap;
+       jshort      s;
 
+       m = (methodinfo *) methodID;
 
+       va_start(ap, methodID);
+       s = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
+       va_end(ap);
 
-jobject CallNonvirtualObjectMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       log_text("JNI-Call: CallNonvirtualObjectMethod");
-
-       return NULL;
+       return s;
 }
 
 
-jobject CallNonvirtualObjectMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualObjectMethodV");
+       methodinfo *m;
+       jshort      s;
 
-       return NULL;
+       m = (methodinfo *) methodID;
+
+       s = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return s;
 }
 
 
-jobject CallNonvirtualObjectMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
+jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallNonvirtualObjectMethodA");
+       log_text("JNI-Call: CallStaticShortMethodA: IMPLEMENT ME!");
 
-       return NULL;
+       return 0;
 }
 
 
-
-jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       jboolean ret;
-       va_list vaargs;
+       methodinfo *m;
+       va_list     ap;
+       jint        i;
 
-/*     log_text("JNI-Call: CallNonvirtualBooleanMethod");*/
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',vaargs);
-       va_end(vaargs);
-       return ret;
+       va_start(ap, methodID);
+       i = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
+       va_end(ap);
 
+       return i;
 }
 
 
-jboolean CallNonvirtualBooleanMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-/*     log_text("JNI-Call: CallNonvirtualBooleanMethodV");*/
-       return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',args);
+       methodinfo *m;
+       jint        i;
+
+       m = (methodinfo *) methodID;
+
+       i = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return i;
 }
 
 
-jboolean CallNonvirtualBooleanMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
+jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallNonvirtualBooleanMethodA");
+       log_text("JNI-Call: CallStaticIntMethodA: IMPLEMENT ME!");
 
        return 0;
 }
 
 
-
-jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       jbyte ret;
-       va_list vaargs;
+       methodinfo *m;
+       va_list     ap;
+       jlong       l;
+
+       m = (methodinfo *) methodID;
 
-/*     log_text("JNI-Call: CallNonvirutalByteMethod");*/
+       va_start(ap, methodID);
+       l = _Jv_jni_CallLongMethod(NULL, NULL, m, ap);
+       va_end(ap);
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',vaargs);
-       va_end(vaargs);
-       return ret;
+       return l;
 }
 
 
-jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+                                                       va_list args)
 {
-       /*log_text("JNI-Call: CallNonvirtualByteMethodV"); */
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',args);
+       methodinfo *m;
+       jlong       l;
+       
+       m = (methodinfo *) methodID;
+
+       l = _Jv_jni_CallLongMethod(NULL, NULL, m, args);
 
+       return l;
 }
 
 
-jbyte CallNonvirtualByteMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallNonvirtualByteMethodA");
+       log_text("JNI-Call: CallStaticLongMethodA: IMPLEMENT ME!");
 
        return 0;
 }
 
 
 
-jchar CallNonvirtualCharMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       jchar ret;
-       va_list vaargs;
+       methodinfo *m;
+       va_list     ap;
+       jfloat      f;
 
-/*     log_text("JNI-Call: CallNonVirtualCharMethod");*/
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',vaargs);
-       va_end(vaargs);
-       return ret;
+       va_start(ap, methodID);
+       f = _Jv_jni_CallFloatMethod(NULL, NULL, m, ap);
+       va_end(ap);
+
+       return f;
 }
 
 
-jchar CallNonvirtualCharMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       /*log_text("JNI-Call: CallNonvirtualCharMethodV");*/
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',args);
+       methodinfo *m;
+       jfloat      f;
+
+       m = (methodinfo *) methodID;
+
+       f = _Jv_jni_CallFloatMethod(NULL, NULL, m, args);
+
+       return f;
 }
 
 
-jchar CallNonvirtualCharMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallNonvirtualCharMethodA");
+       log_text("JNI-Call: CallStaticFloatMethodA: IMPLEMENT ME!");
 
        return 0;
 }
 
 
-
-jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       jshort ret;
-       va_list vaargs;
+       methodinfo *m;
+       va_list     ap;
+       jdouble     d;
 
-       /*log_text("JNI-Call: CallNonvirtualShortMethod");*/
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',vaargs);
-       va_end(vaargs);
-       return ret;
+       va_start(ap, methodID);
+       d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, ap);
+       va_end(ap);
+
+       return d;
 }
 
 
-jshort CallNonvirtualShortMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       /*log_text("JNI-Call: CallNonvirtualShortMethodV");*/
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',args);
+       methodinfo *m;
+       jdouble     d;
+
+       m = (methodinfo *) methodID;
+
+       d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, args);
+
+       return d;
 }
 
 
-jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallNonvirtualShortMethodA");
+       log_text("JNI-Call: CallStaticDoubleMethodA: IMPLEMENT ME!");
 
        return 0;
 }
 
 
-
-jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
+       methodinfo *m;
+       va_list     ap;
 
-        jint ret;
-        va_list vaargs;
-
-       /*log_text("JNI-Call: CallNonvirtualIntMethod");*/
+       m = (methodinfo *) methodID;
 
-        va_start(vaargs,methodID);
-        ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',vaargs);
-        va_end(vaargs);
-        return ret;
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
+       va_end(ap);
 }
 
 
-jint CallNonvirtualIntMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       /*log_text("JNI-Call: CallNonvirtualIntMethodV");*/
-        return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',args);
+       methodinfo *m;
+
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
 }
 
 
-jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue * args)
 {
-       log_text("JNI-Call: CallNonvirtualIntMethodA");
+       methodinfo *m;
 
-       return 0;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
 }
 
 
+/* Accessing Static Fields ****************************************************/
 
-jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       log_text("JNI-Call: CallNonvirtualLongMethod");
+/* GetStaticFieldID ************************************************************
 
-       return 0;
-}
+   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.
 
+*******************************************************************************/
 
-jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
 {
-       log_text("JNI-Call: CallNonvirtualLongMethodV");
-
-       return 0;
-}
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-jlong CallNonvirtualLongMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualLongMethodA");
+       f = class_findfield(clazz,
+                                               utf_new_char((char *) name),
+                                               utf_new_char((char *) sig));
+       
+       if (f == NULL)
+               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);
 
-       return 0;
+       return (jfieldID) f;
 }
 
 
+/* GetStatic<type>Field ********************************************************
 
-jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+   This family of accessor routines returns the value of a static
+   field of an object.
+
+*******************************************************************************/
+
+jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       jfloat ret;
-       va_list vaargs;
+       classinfo *c;
+       fieldinfo *f;
 
-       /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/
+       STATISTICS(jniinvokation());
 
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'F');
-       va_end(vaargs);
-       return ret;
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return NULL;
 
+       return NewLocalRef(env, f->value.a);
 }
 
 
-jfloat CallNonvirtualFloatMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       log_text("JNI-Call: CallNonvirtualFloatMethodV");
-       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'F');
-}
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-jfloat CallNonvirtualFloatMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualFloatMethodA");
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
-       return 0;
-}
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return false;
 
+       return f->value.i;
+}
 
 
-jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       jdouble ret;
-       va_list vaargs;
-       log_text("JNI-Call: CallNonvirtualDoubleMethod");
+       classinfo *c;
+       fieldinfo *f;
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'D');
-       va_end(vaargs);
-       return ret;
+       STATISTICS(jniinvokation());
 
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return 0;
 
-jdouble CallNonvirtualDoubleMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-/*     log_text("JNI-Call: CallNonvirtualDoubleMethodV");*/
-       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'D');
+       return f->value.i;
 }
 
 
-jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       log_text("JNI-Call: CallNonvirtualDoubleMethodA");
+       classinfo *c;
+       fieldinfo *f;
 
-       return 0;
-}
+       STATISTICS(jniinvokation());
 
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return 0;
 
-void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+       return f->value.i;
+}
+
+
+jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-        va_list vaargs;
+       classinfo *c;
+       fieldinfo *f;
 
-/*      log_text("JNI-Call: CallNonvirtualVoidMethod");*/
+       STATISTICS(jniinvokation());
 
-        va_start(vaargs,methodID);
-        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',vaargs);
-        va_end(vaargs);
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return 0;
+
+       return f->value.i;
 }
 
 
-void CallNonvirtualVoidMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-/*     log_text("JNI-Call: CallNonvirtualVoidMethodV");*/
+       classinfo *c;
+       fieldinfo *f;
 
-        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',args);
+       STATISTICS(jniinvokation());
 
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return 0;
 
-void CallNonvirtualVoidMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
-{
-       log_text("JNI-Call: CallNonvirtualVoidMethodA");
+       return f->value.i;
 }
 
-/************************* JNI-functions for accessing fields ************************/
 
-jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) 
+jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-       jfieldID f;
+       classinfo *c;
+       fieldinfo *f;
 
-/*     log_text("========================= searching for:");
-       log_text(name);
-       log_text(sig);*/
-       f = jclass_findfield(clazz,
-                           utf_new_char ((char*) name), 
-                           utf_new_char ((char*) sig)
-                           ); 
-       
-       if (!f) { 
-               /*utf_display(clazz->name);
-               log_text(name);
-               log_text(sig);*/
-               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
-       }
-       return f;
+       STATISTICS(jniinvokation());
+
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return 0;
+
+       return f->value.l;
 }
 
-/*************************** retrieve fieldid, abort on error ************************/
 
-jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig)
+jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
-    jfieldID id = GetFieldID(env, clazz, name, sig);
+       classinfo *c;
+       fieldinfo *f;
 
-    if (!id) {
-       log_text("class:");
-       utf_display(clazz->name);
-       log_text("\nfield:");
-       log_text(name);
-       log_text("sig:");
-       log_text(sig);
+       STATISTICS(jniinvokation());
 
-       panic("setfield_critical failed"); 
-    }
-    return id;
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
-jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       /*
-       jobject dbg,dretval,*dpretval;  
-       long int dli1, dli2, dli3;
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return 0.0;
 
-       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);
+       return f->value.f;
+}
 
-       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);*/
+jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID)
+{
+       classinfo *c;
+       fieldinfo *f;
 
-/*     printf("GetObjectField(2): retval %p (obj: %#lx + offset: %#lx = %#lx (jobject*) %p (jobject) %p\n"
-       ,dbg, dli1, dli2, dli3,dpretval, dretval);*/
+       STATISTICS(jniinvokation());
 
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
-/*     return dbg;*/
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return 0.0;
 
-       return getField(obj,jobject,fieldID);
+       return f->value.d;
 }
 
-jboolean GetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       return getField(obj,jboolean,fieldID);
-}
 
+/*  SetStatic<type>Field *******************************************************
 
-jbyte GetByteField (JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-               return getField(obj,jbyte,fieldID);
-}
+       This family of accessor routines sets the value of a static field
+       of an object.
 
+*******************************************************************************/
 
-jchar GetCharField (JNIEnv *env, jobject obj, jfieldID fieldID)
+void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)
 {
-       return getField(obj,jchar,fieldID);
-}
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-jshort GetShortField (JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       return getField(obj,jshort,fieldID);
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-jint GetIntField (JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       return getField(obj,jint,fieldID);
+       f->value.a = value;
 }
 
 
-jlong GetLongField (JNIEnv *env, jobject obj, jfieldID fieldID)
+void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value)
 {
-       return getField(obj,jlong,fieldID);
-}
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-jfloat GetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       return getField(obj,jfloat,fieldID);
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-jdouble GetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       return getField(obj,jdouble,fieldID);
+       f->value.i = value;
 }
 
-void SetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val)
+
+void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value)
 {
-        setField(obj,jobject,fieldID,val);
-}
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-void SetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val)
-{
-        setField(obj,jboolean,fieldID,val);
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-void SetByteField (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val)
-{
-        setField(obj,jbyte,fieldID,val);
+       f->value.i = value;
 }
 
 
-void SetCharField (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val)
+void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value)
 {
-        setField(obj,jchar,fieldID,val);
-}
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-void SetShortField (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val)
-{
-        setField(obj,jshort,fieldID,val);
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-void SetIntField (JNIEnv *env, jobject obj, jfieldID fieldID, jint val)
-{
-        setField(obj,jint,fieldID,val);
+       f->value.i = value;
 }
 
 
-void SetLongField (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val)
+void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
 {
-        setField(obj,jlong,fieldID,val);
-}
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-void SetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val)
-{
-        setField(obj,jfloat,fieldID,val);
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-void SetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val)
-{
-        setField(obj,jdouble,fieldID,val);
+       f->value.i = value;
 }
 
 
-/**************** JNI-functions for calling static methods **********************/ 
-
-jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
+void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value)
 {
-       jmethodID m;
+       classinfo *c;
+       fieldinfo *f;
 
-       m = class_resolvemethod(clazz,
-                                                       utf_new_char((char *) name),
-                                                       utf_new_char((char *) sig));
+       STATISTICS(jniinvokation());
 
-       if (!m || !(m->flags & ACC_STATIC)) {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NoSuchMethodError, name);
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
-               return NULL;
-       }
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-       return m;
+       f->value.i = value;
 }
 
 
-jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value)
 {
-       jobject ret;
-       va_list vaargs;
+       classinfo *c;
+       fieldinfo *f;
 
-       /* log_text("JNI-Call: CallStaticObjectMethod");*/
+       STATISTICS(jniinvokation());
 
-       va_start(vaargs, methodID);
-       ret = callObjectMethod(0, methodID, vaargs);
-       va_end(vaargs);
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
-       return ret;
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
+
+       f->value.l = value;
 }
 
 
-jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value)
 {
-       /* log_text("JNI-Call: CallStaticObjectMethodV"); */
-       
-       return callObjectMethod(0,methodID,args);
-}
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticObjectMethodA");
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
-       return NULL;
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
+
+       f->value.f = value;
 }
 
 
-jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value)
 {
-       jboolean ret;
-       va_list vaargs;
+       classinfo *c;
+       fieldinfo *f;
 
-       va_start(vaargs, methodID);
-       ret = (jboolean) callIntegerMethod(0, methodID, 'Z', vaargs);
-       va_end(vaargs);
+       STATISTICS(jniinvokation());
 
-       return ret;
-}
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
 
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       return (jboolean) callIntegerMethod(0, methodID, 'Z', args);
+       f->value.d = value;
 }
 
 
-jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticBooleanMethodA");
+/* String Operations **********************************************************/
 
-       return 0;
-}
+/* NewString *******************************************************************
 
+   Create new java.lang.String object from an array of Unicode
+   characters.
 
-jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+*******************************************************************************/
+
+jstring NewString(JNIEnv *env, const jchar *buf, jsize len)
 {
-       jbyte ret;
-       va_list vaargs;
+       java_lang_String *s;
+       java_chararray   *a;
+       u4                i;
 
-       /*      log_text("JNI-Call: CallStaticByteMethod");*/
+       STATISTICS(jniinvokation());
+       
+       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       a = builtin_newarray_char(len);
 
-       va_start(vaargs, methodID);
-       ret = (jbyte) callIntegerMethod(0, methodID, 'B', vaargs);
-       va_end(vaargs);
+       /* javastring or characterarray could not be created */
+       if (!a || !s)
+               return NULL;
 
-       return ret;
-}
+       /* copy text */
+       for (i = 0; i < len; i++)
+               a->data[i] = buf[i];
 
+       s->value = a;
+       s->offset = 0;
+       s->count = len;
 
-jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       return (jbyte) callIntegerMethod(0, methodID, 'B', args);
+       return (jstring) NewLocalRef(env, (jobject) s);
 }
 
 
-jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticByteMethodA");
-
-       return 0;
-}
-
+static jchar emptyStringJ[]={0,0};
 
-jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       jchar ret;
-       va_list vaargs;
+/* GetStringLength *************************************************************
 
-       /*      log_text("JNI-Call: CallStaticByteMethod");*/
+   Returns the length (the count of Unicode characters) of a Java
+   string.
 
-       va_start(vaargs, methodID);
-       ret = (jchar) callIntegerMethod(0, methodID, 'C', vaargs);
-       va_end(vaargs);
+*******************************************************************************/
 
-       return ret;
+jsize GetStringLength(JNIEnv *env, jstring str)
+{
+       return ((java_lang_String *) str)->count;
 }
 
 
-jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+/********************  convertes javastring to u2-array ****************************/
+       
+u2 *javastring_tou2(jstring so) 
 {
-       return (jchar) callIntegerMethod(0, methodID, 'C', args);
-}
+       java_lang_String *s;
+       java_chararray   *a;
+       u2               *stringbuffer;
+       u4                i;
 
+       STATISTICS(jniinvokation());
+       
+       s = (java_lang_String *) so;
 
-jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticCharMethodA");
+       if (!s)
+               return NULL;
 
-       return 0;
-}
+       a = s->value;
 
+       if (!a)
+               return NULL;
 
+       /* allocate memory */
 
-jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       jshort ret;
-       va_list vaargs;
+       stringbuffer = MNEW(u2, s->count + 1);
 
-       /*      log_text("JNI-Call: CallStaticByteMethod");*/
+       /* copy text */
+
+       for (i = 0; i < s->count; i++)
+               stringbuffer[i] = a->data[s->offset + i];
+       
+       /* terminate string */
 
-       va_start(vaargs, methodID);
-       ret = (jshort) callIntegerMethod(0, methodID, 'S', vaargs);
-       va_end(vaargs);
+       stringbuffer[i] = '\0';
 
-       return ret;
+       return stringbuffer;
 }
 
 
-jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       /*log_text("JNI-Call: CallStaticShortMethodV");*/
-       return (jshort) callIntegerMethod(0, methodID, 'S', args);
-}
+/* GetStringChars **************************************************************
 
+   Returns a pointer to the array of Unicode characters of the
+   string. This pointer is valid until ReleaseStringchars() is called.
 
-jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticShortMethodA");
+*******************************************************************************/
 
-       return 0;
-}
+const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
+{      
+       jchar *jc;
 
+       STATISTICS(jniinvokation());
 
+       jc = javastring_tou2(str);
 
-jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       jint ret;
-       va_list vaargs;
+       if (jc) {
+               if (isCopy)
+                       *isCopy = JNI_TRUE;
 
-       /*      log_text("JNI-Call: CallStaticIntMethod");*/
+               return jc;
+       }
 
-       va_start(vaargs, methodID);
-       ret = callIntegerMethod(0, methodID, 'I', vaargs);
-       va_end(vaargs);
+       if (isCopy)
+               *isCopy = JNI_TRUE;
 
-       return ret;
+       return emptyStringJ;
 }
 
 
-jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       log_text("JNI-Call: CallStaticIntMethodV");
+/* ReleaseStringChars **********************************************************
 
-       return callIntegerMethod(0, methodID, 'I', args);
-}
+   Informs the VM that the native code no longer needs access to
+   chars. The chars argument is a pointer obtained from string using
+   GetStringChars().
 
+*******************************************************************************/
 
-jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
 {
-       log_text("JNI-Call: CallStaticIntMethodA");
+       STATISTICS(jniinvokation());
 
-       return 0;
+       if (chars == emptyStringJ)
+               return;
+
+       MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1);
 }
 
 
+/* NewStringUTF ****************************************************************
 
-jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+   Constructs a new java.lang.String object from an array of UTF-8 characters.
+
+*******************************************************************************/
+
+jstring NewStringUTF(JNIEnv *env, const char *bytes)
 {
-       jlong ret;
-       va_list vaargs;
+       java_lang_String *s;
 
-       /*      log_text("JNI-Call: CallStaticLongMethod");*/
+       STATISTICS(jniinvokation());
 
-       va_start(vaargs, methodID);
-       ret = callLongMethod(0, methodID, vaargs);
-       va_end(vaargs);
+       s = javastring_new(utf_new_char(bytes));
 
-       return ret;
+    return (jstring) NewLocalRef(env, (jobject) s);
 }
 
 
-jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       log_text("JNI-Call: CallStaticLongMethodV");
-       
-       return callLongMethod(0,methodID,args);
-}
+/****************** returns the utf8 length in bytes of a string *******************/
 
+jsize GetStringUTFLength (JNIEnv *env, jstring string)
+{   
+    java_lang_String *s = (java_lang_String*) string;
 
-jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticLongMethodA");
+       STATISTICS(jniinvokation());
 
-       return 0;
+    return (jsize) u2_utflength(s->value->data, s->count); 
 }
 
 
+/* GetStringUTFChars ***********************************************************
 
-jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+   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)
 {
-       jfloat ret;
-       va_list vaargs;
+       utf *u;
 
-       /*      log_text("JNI-Call: CallStaticLongMethod");*/
+       STATISTICS(jniinvokation());
 
-       va_start(vaargs, methodID);
-       ret = callFloatMethod(0, methodID, vaargs, 'F');
-       va_end(vaargs);
+       if (!string)
+               return "";
 
-       return ret;
+       if (isCopy)
+               *isCopy = JNI_TRUE;
+       
+       u = javastring_toutf((java_lang_String *) string, false);
+
+       if (u)
+               return u->text;
+
+       return "";
 }
 
 
-jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+/* 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 string, const char *utf)
 {
+       STATISTICS(jniinvokation());
 
-       return callFloatMethod(0, methodID, args, 'F');
-
+    /* 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 */
 }
 
 
-jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticFloatMethodA");
+/* Array Operations ***********************************************************/
 
-       return 0;
-}
+/* GetArrayLength **************************************************************
 
+   Returns the number of elements in the array.
 
+*******************************************************************************/
 
-jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jsize GetArrayLength(JNIEnv *env, jarray array)
 {
-       jdouble ret;
-       va_list vaargs;
+       java_arrayheader *a;
 
-       /*      log_text("JNI-Call: CallStaticDoubleMethod");*/
+       STATISTICS(jniinvokation());
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(0, methodID, vaargs, 'D');
-       va_end(vaargs);
+       a = (java_arrayheader *) array;
 
-       return ret;
+       return a->size;
 }
 
 
-jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       log_text("JNI-Call: CallStaticDoubleMethodV");
+/* NewObjectArray **************************************************************
 
-       return callFloatMethod(0, methodID, args, 'D');
-}
+   Constructs a new array holding objects in class elementClass. All
+   elements are initially set to initialElement.
 
+*******************************************************************************/
 
-jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)
 {
-       log_text("JNI-Call: CallStaticDoubleMethodA");
+       java_objectarray *oa;
+       s4                i;
 
-       return 0;
-}
+       STATISTICS(jniinvokation());
 
+       if (length < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
-void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)
-{
-       va_list vaargs;
+    oa = builtin_anewarray(length, elementClass);
 
-       va_start(vaargs, methodID);
-       (void) callIntegerMethod(0, methodID, 'V', vaargs);
-       va_end(vaargs);
-}
+       if (!oa)
+               return NULL;
 
+       /* set all elements to initialElement */
 
-void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)
-{
-       log_text("JNI-Call: CallStaticVoidMethodV");
-       (void)callIntegerMethod(0, methodID, 'V', args);
+       for (i = 0; i < length; i++)
+               oa->data[i] = initialElement;
+
+       return (jobjectArray) NewLocalRef(env, (jobject) oa);
 }
 
 
-void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args)
+jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
 {
-       log_text("JNI-Call: CallStaticVoidMethodA");
-}
+       java_objectarray *oa;
+       jobject           o;
 
+       STATISTICS(jniinvokation());
 
-/****************** JNI-functions for accessing static fields ********************/
+       oa = (java_objectarray *) array;
 
-jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) 
-{
-       jfieldID f;
+       if (index >= oa->header.size) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return NULL;
+       }
 
-       f = jclass_findfield(clazz,
-                           utf_new_char ((char*) name), 
-                           utf_new_char ((char*) sig)
-                           ); 
-       
-       if (!f) *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
+       o = oa->data[index];
 
-       return f;
+       return NewLocalRef(env, o);
 }
 
 
-jobject GetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val)
 {
-       class_init(clazz);
-       return fieldID->value.a;       
-}
-
+       java_objectarray  *oa;
+       java_objectheader *o;
 
-jboolean GetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       class_init(clazz);
-       return fieldID->value.i;       
-}
+       STATISTICS(jniinvokation());
 
+       oa = (java_objectarray *) array;
+       o  = (java_objectheader *) val;
 
-jbyte GetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       class_init(clazz);
-       return fieldID->value.i;       
-}
+       if (index >= oa->header.size) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return;
+       }
 
+       /* check if the class of value is a subclass of the element class
+          of the array */
 
-jchar GetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       class_init(clazz);
-       return fieldID->value.i;       
-}
+       if (!builtin_canstore(oa, o)) {
+               *exceptionptr = new_exception(string_java_lang_ArrayStoreException);
 
+               return;
+       }
 
-jshort GetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       class_init(clazz);
-       return fieldID->value.i;       
+       oa->data[index] = val;
 }
 
 
-jint GetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
 {
-       class_init(clazz);
-       return fieldID->value.i;       
-}
+       java_booleanarray *ba;
 
+       STATISTICS(jniinvokation());
 
-jlong GetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       class_init(clazz);
-       return fieldID->value.l;
-}
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
+       ba = builtin_newarray_boolean(len);
 
-jfloat GetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       class_init(clazz);
-       return fieldID->value.f;
+       return (jbooleanArray) NewLocalRef(env, (jobject) ba);
 }
 
 
-jdouble GetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID)
+jbyteArray NewByteArray(JNIEnv *env, jsize len)
 {
-       class_init(clazz);
-       return fieldID->value.d;
-}
+       java_bytearray *ba;
 
+       STATISTICS(jniinvokation());
 
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
-void SetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)
-{
-       class_init(clazz);
-       fieldID->value.a = value;
-}
-
+       ba = builtin_newarray_byte(len);
 
-void SetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value)
-{
-       class_init(clazz);
-       fieldID->value.i = value;
+       return (jbyteArray) NewLocalRef(env, (jobject) ba);
 }
 
 
-void SetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value)
+jcharArray NewCharArray(JNIEnv *env, jsize len)
 {
-       class_init(clazz);
-       fieldID->value.i = value;
-}
+       java_chararray *ca;
 
+       STATISTICS(jniinvokation());
 
-void SetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value)
-{
-       class_init(clazz);
-       fieldID->value.i = value;
-}
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
+       ca = builtin_newarray_char(len);
 
-void SetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
-{
-       class_init(clazz);
-       fieldID->value.i = value;
+       return (jcharArray) NewLocalRef(env, (jobject) ca);
 }
 
 
-void SetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value)
+jshortArray NewShortArray(JNIEnv *env, jsize len)
 {
-       class_init(clazz);
-       fieldID->value.i = value;
-}
+       java_shortarray *sa;
 
+       STATISTICS(jniinvokation());
 
-void SetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value)
-{
-       class_init(clazz);
-       fieldID->value.l = value;
-}
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
+       sa = builtin_newarray_short(len);
 
-void SetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value)
-{
-       class_init(clazz);
-       fieldID->value.f = value;
+       return (jshortArray) NewLocalRef(env, (jobject) sa);
 }
 
 
-void SetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value)
+jintArray NewIntArray(JNIEnv *env, jsize len)
 {
-       class_init(clazz);
-       fieldID->value.d = value;
-}
+       java_intarray *ia;
 
+       STATISTICS(jniinvokation());
 
-/*****  create new java.lang.String object from an array of Unicode characters ****/ 
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
-jstring NewString (JNIEnv *env, const jchar *buf, jsize len)
-{
-       u4 i;
-       java_lang_String *s;
-       java_chararray *a;
-       
-       s = (java_lang_String*) builtin_new (class_java_lang_String);
-       a = builtin_newarray_char (len);
+       ia = builtin_newarray_int(len);
 
-       /* javastring or characterarray could not be created */
-       if ( (!a) || (!s) ) return NULL;
+       return (jintArray) NewLocalRef(env, (jobject) ia);
+}
 
-       /* copy text */
-       for (i=0; i<len; i++) a->data[i] = buf[i];
-       s -> value = a;
-       s -> offset = 0;
-       s -> count = len;
 
-       return (jstring) s;
-}
+jlongArray NewLongArray(JNIEnv *env, jsize len)
+{
+       java_longarray *la;
 
+       STATISTICS(jniinvokation());
 
-static char emptyString[]="";
-static jchar emptyStringJ[]={0,0};
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
-/******************* returns the length of a Java string ***************************/
+       la = builtin_newarray_long(len);
 
-jsize GetStringLength (JNIEnv *env, jstring str)
-{
-       return ((java_lang_String*) str)->count;
+       return (jlongArray) NewLocalRef(env, (jobject) la);
 }
 
 
-/********************  convertes javastring to u2-array ****************************/
-       
-u2 *javastring_tou2 (jstring so) 
+jfloatArray NewFloatArray(JNIEnv *env, jsize len)
 {
-       java_lang_String *s = (java_lang_String*) so;
-       java_chararray *a;
-       u4 i;
-       u2 *stringbuffer;
-       
-       if (!s) return NULL;
+       java_floatarray *fa;
 
-       a = s->value;
-       if (!a) return NULL;
+       STATISTICS(jniinvokation());
 
-       /* allocate memory */
-       stringbuffer = MNEW( u2 , s->count + 1 );
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
-       /* copy text */
-       for (i=0; i<s->count; i++) stringbuffer[i] = a->data[s->offset+i];
-       
-       /* terminate string */
-       stringbuffer[i] = '\0';
+       fa = builtin_newarray_float(len);
 
-       return stringbuffer;
+       return (jfloatArray) NewLocalRef(env, (jobject) fa);
 }
 
-/********* returns a pointer to an array of Unicode characters of the string *******/
 
-const jchar *GetStringChars (JNIEnv *env, jstring str, jboolean *isCopy)
-{      
-       jchar *jc=javastring_tou2(str);
+jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
+{
+       java_doublearray *da;
 
-       if (jc) {
-               if (isCopy) *isCopy=JNI_TRUE;
-               return jc;
+       STATISTICS(jniinvokation());
+
+       if (len < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
        }
-       if (isCopy) *isCopy=JNI_TRUE;
-       return emptyStringJ;
-}
 
-/**************** native code no longer needs access to chars **********************/
+       da = builtin_newarray_double(len);
 
-void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars)
-{
-       if (chars==emptyStringJ) return;
-       MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1);
+       return (jdoubleArray) NewLocalRef(env, (jobject) da);
 }
 
 
-/* NewStringUTF ****************************************************************
+/* Get<PrimitiveType>ArrayElements *********************************************
 
-   Constructs a new java.lang.String object from an array of UTF-8 characters.
+   A family of functions that returns the body of the primitive array.
 
 *******************************************************************************/
 
-jstring NewStringUTF(JNIEnv *env, const char *bytes)
+jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array,
+                                                                 jboolean *isCopy)
 {
-    return (jstring) javastring_new(utf_new_char(bytes));
-}
+       java_booleanarray *ba;
 
+       STATISTICS(jniinvokation());
 
-/****************** returns the utf8 length in bytes of a string *******************/
+       ba = (java_booleanarray *) array;
 
-jsize GetStringUTFLength (JNIEnv *env, jstring string)
-{   
-    java_lang_String *s = (java_lang_String*) string;
+       if (isCopy)
+               *isCopy = JNI_FALSE;
 
-    return (jsize) u2_utflength(s->value->data, s->count); 
+       return ba->data;
 }
 
 
-/************ converts a Javastring to an array of UTF-8 characters ****************/
-
-const char* GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)
+jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy)
 {
-    utf *u;
+       java_bytearray *ba;
+
+       STATISTICS(jniinvokation());
 
-    u = javastring_toutf((java_lang_String *) string, false);
+       ba = (java_bytearray *) array;
 
-    if (isCopy)
+       if (isCopy)
                *isCopy = JNI_FALSE;
-       
-    if (u)
-               return u->text;
 
-    return emptyString;
-       
+       return ba->data;
 }
 
 
-/***************** native code no longer needs access to utf ***********************/
-
-void ReleaseStringUTFChars (JNIEnv *env, jstring str, const char* chars)
+jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy)
 {
-    /*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));
-       */
-}
+       java_chararray *ca;
 
-/************************** array operations ***************************************/
+       STATISTICS(jniinvokation());
 
-jsize GetArrayLength(JNIEnv *env, jarray array)
-{
-    return array->size;
+       ca = (java_chararray *) array;
+
+       if (isCopy)
+               *isCopy = JNI_FALSE;
+
+       return ca->data;
 }
 
 
-jobjectArray NewObjectArray (JNIEnv *env, jsize len, jclass clazz, jobject init)
+jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy)
 {
-       java_objectarray *j;
+       java_shortarray *sa;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
+
+       sa = (java_shortarray *) array;
 
-    j = builtin_anewarray(len, clazz);
+       if (isCopy)
+               *isCopy = JNI_FALSE;
 
-    return j;
+       return sa->data;
 }
 
 
-jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
+jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy)
 {
-    jobject j = NULL;
+       java_intarray *ia;
 
-    if (index < array->header.size)    
-               j = array->data[index];
-    else
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
-    
-    return j;
+       STATISTICS(jniinvokation());
+
+       ia = (java_intarray *) array;
+
+       if (isCopy)
+               *isCopy = JNI_FALSE;
+
+       return ia->data;
 }
 
 
-void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val)
+jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy)
 {
-    if (index >= array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_longarray *la;
 
-    else {
-               /* check if the class of value is a subclass of the element class of the array */
-               if (!builtin_canstore((java_objectarray *) array, (java_objectheader *) val))
-                       *exceptionptr = new_exception(string_java_lang_ArrayStoreException);
+       STATISTICS(jniinvokation());
 
-               else
-                       array->data[index] = val;
-    }
-}
+       la = (java_longarray *) array;
 
+       if (isCopy)
+               *isCopy = JNI_FALSE;
 
+       /* We cast this one to prevent a compiler warning on 64-bit
+          systems since GNU Classpath typedef jlong to long long. */
 
-jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
+       return (jlong *) la->data;
+}
+
+
+jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy)
 {
-       java_booleanarray *j;
+       java_floatarray *fa;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
 
-    j = builtin_newarray_boolean(len);
+       fa = (java_floatarray *) array;
+
+       if (isCopy)
+               *isCopy = JNI_FALSE;
 
-    return j;
+       return fa->data;
 }
 
 
-jbyteArray NewByteArray(JNIEnv *env, jsize len)
+jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+                                                               jboolean *isCopy)
 {
-       java_bytearray *j;
+       java_doublearray *da;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
 
-    j = builtin_newarray_byte(len);
+       da = (java_doublearray *) array;
+
+       if (isCopy)
+               *isCopy = JNI_FALSE;
 
-    return j;
+       return da->data;
 }
 
 
-jcharArray NewCharArray(JNIEnv *env, jsize len)
+/* Release<PrimitiveType>ArrayElements *****************************************
+
+   A family of functions that informs the VM that the native code no
+   longer needs access to elems. The elems argument is a pointer
+   derived from array using the corresponding
+   Get<PrimitiveType>ArrayElements() function. If necessary, this
+   function copies back all changes made to elems to the original
+   array.
+
+*******************************************************************************/
+
+void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
+                                                                jboolean *elems, jint mode)
 {
-       java_chararray *j;
+       java_booleanarray *ba;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
 
-    j = builtin_newarray_char(len);
+       ba = (java_booleanarray *) array;
 
-    return j;
+       if (elems != ba->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(ba->data, elems, u1, ba->header.size);
+                       break;
+               case 0:
+                       MCOPY(ba->data, elems, u1, ba->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jshortArray NewShortArray(JNIEnv *env, jsize len)
+void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems,
+                                                         jint mode)
 {
-       java_shortarray *j;
+       java_bytearray *ba;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
 
-    j = builtin_newarray_short(len);
+       ba = (java_bytearray *) array;
 
-    return j;
+       if (elems != ba->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(ba->data, elems, s1, ba->header.size);
+                       break;
+               case 0:
+                       MCOPY(ba->data, elems, s1, ba->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jintArray NewIntArray(JNIEnv *env, jsize len)
+void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems,
+                                                         jint mode)
 {
-       java_intarray *j;
+       java_chararray *ca;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
 
-    j = builtin_newarray_int(len);
+       ca = (java_chararray *) array;
 
-    return j;
+       if (elems != ca->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(ca->data, elems, u2, ca->header.size);
+                       break;
+               case 0:
+                       MCOPY(ca->data, elems, u2, ca->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jlongArray NewLongArray(JNIEnv *env, jsize len)
+void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems,
+                                                          jint mode)
 {
-       java_longarray *j;
+       java_shortarray *sa;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
 
-    j = builtin_newarray_long(len);
+       sa = (java_shortarray *) array;
 
-    return j;
+       if (elems != sa->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(sa->data, elems, s2, sa->header.size);
+                       break;
+               case 0:
+                       MCOPY(sa->data, elems, s2, sa->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jfloatArray NewFloatArray(JNIEnv *env, jsize len)
+void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
+                                                        jint mode)
 {
-       java_floatarray *j;
+       java_intarray *ia;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
 
-    j = builtin_newarray_float(len);
+       ia = (java_intarray *) array;
 
-    return j;
+       if (elems != ia->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(ia->data, elems, s4, ia->header.size);
+                       break;
+               case 0:
+                       MCOPY(ia->data, elems, s4, ia->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
+void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems,
+                                                         jint mode)
 {
-       java_doublearray *j;
+       java_longarray *la;
 
-    if (len < 0) {
-               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
-               return NULL;
-    }
+       STATISTICS(jniinvokation());
+
+       la = (java_longarray *) array;
 
-    j = builtin_newarray_double(len);
+       /* We cast this one to prevent a compiler warning on 64-bit
+          systems since GNU Classpath typedef jlong to long long. */
 
-    return j;
+       if ((s8 *) elems != la->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(la->data, elems, s8, la->header.size);
+                       break;
+               case 0:
+                       MCOPY(la->data, elems, s8, la->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jboolean * GetBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *isCopy)
+void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems,
+                                                          jint mode)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
-}
+       java_floatarray *fa;
 
+       STATISTICS(jniinvokation());
 
-jbyte * GetByteArrayElements (JNIEnv *env, jbyteArray array, jboolean *isCopy)
-{
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
+       fa = (java_floatarray *) array;
+
+       if (elems != fa->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(fa->data, elems, float, fa->header.size);
+                       break;
+               case 0:
+                       MCOPY(fa->data, elems, float, fa->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jchar * GetCharArrayElements (JNIEnv *env, jcharArray array, jboolean *isCopy)
+void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+                                                               jdouble *elems, jint mode)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
-}
+       java_doublearray *da;
 
+       STATISTICS(jniinvokation());
 
-jshort * GetShortArrayElements (JNIEnv *env, jshortArray array, jboolean *isCopy)
-{
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
+       da = (java_doublearray *) array;
+
+       if (elems != da->data) {
+               switch (mode) {
+               case JNI_COMMIT:
+                       MCOPY(da->data, elems, double, da->header.size);
+                       break;
+               case 0:
+                       MCOPY(da->data, elems, double, da->header.size);
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               case JNI_ABORT:
+                       /* XXX TWISTI how should it be freed? */
+                       break;
+               }
+       }
 }
 
 
-jint * GetIntArrayElements (JNIEnv *env, jintArray array, jboolean *isCopy)
-{
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
-}
+/*  Get<PrimitiveType>ArrayRegion **********************************************
+
+       A family of functions that copies a region of a primitive array
+       into a buffer.
 
+*******************************************************************************/
 
-jlong * GetLongArrayElements (JNIEnv *env, jlongArray array, jboolean *isCopy)
+void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
+                                                  jsize len, jboolean *buf)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
-}
+       java_booleanarray *ba;
 
+       STATISTICS(jniinvokation());
 
-jfloat * GetFloatArrayElements (JNIEnv *env, jfloatArray array, jboolean *isCopy)
-{
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
+       ba = (java_booleanarray *) array;
+
+    if ((start < 0) || (len < 0) || (start + len > ba->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+    else
+               MCOPY(buf, &ba->data[start], u1, len);
 }
 
 
-jdouble * GetDoubleArrayElements (JNIEnv *env, jdoubleArray array, jboolean *isCopy)
+void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
+                                               jbyte *buf)
 {
-    if (isCopy) *isCopy = JNI_FALSE;
-    return array->data;
-}
+       java_bytearray *ba;
 
+       STATISTICS(jniinvokation());
 
+       ba = (java_bytearray *) array;
 
-void ReleaseBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode)
-{
-    /* empty */
+       if ((start < 0) || (len < 0) || (start + len > ba->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(buf, &ba->data[start], s1, len);
 }
 
 
-void ReleaseByteArrayElements (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode)
+void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
+                                               jchar *buf)
 {
-    /* empty */
-}
+       java_chararray *ca;
 
+       STATISTICS(jniinvokation());
 
-void ReleaseCharArrayElements (JNIEnv *env, jcharArray array, jchar *elems, jint mode)
-{
-    /* empty */
+       ca = (java_chararray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ca->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(buf, &ca->data[start], u2, len);
 }
 
 
-void ReleaseShortArrayElements (JNIEnv *env, jshortArray array, jshort *elems, jint mode)
+void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
+                                                jsize len, jshort *buf)
 {
-    /* empty */
-}
+       java_shortarray *sa;
 
+       STATISTICS(jniinvokation());
 
-void ReleaseIntArrayElements (JNIEnv *env, jintArray array, jint *elems, jint mode)
-{
-    /* empty */
+       sa = (java_shortarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > sa->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else    
+               MCOPY(buf, &sa->data[start], s2, len);
 }
 
 
-void ReleaseLongArrayElements (JNIEnv *env, jlongArray array, jlong *elems, jint mode)
+void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
+                                          jint *buf)
 {
-    /* empty */
-}
+       java_intarray *ia;
 
+       STATISTICS(jniinvokation());
 
-void ReleaseFloatArrayElements (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode)
-{
-    /* empty */
+       ia = (java_intarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ia->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(buf, &ia->data[start], s4, len);
 }
 
 
-void ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode)
+void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len,
+                                               jlong *buf)
 {
-    /* empty */
-}
+       java_longarray *la;
 
+       STATISTICS(jniinvokation());
 
-void GetBooleanArrayRegion(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);
+       la = (java_longarray *) array;
 
-    else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+       if ((start < 0) || (len < 0) || (start + len > la->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(buf, &la->data[start], s8, len);
 }
 
 
-void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
+void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
+                                                jsize len, jfloat *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size) 
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_floatarray *fa;
 
-    else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       fa = (java_floatarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > fa->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(buf, &fa->data[start], float, len);
 }
 
 
-void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
+void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
+                                                 jsize len, jdouble *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_doublearray *da;
 
-    else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       da = (java_doublearray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > da->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(buf, &da->data[start], double, len);
 }
 
 
-void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
-{
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+/*  Set<PrimitiveType>ArrayRegion **********************************************
 
-    else       
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
-}
+       A family of functions that copies back a region of a primitive
+       array from a buffer.
 
+*******************************************************************************/
 
-void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
+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);
+       java_booleanarray *ba;
+
+       STATISTICS(jniinvokation());
+
+       ba = (java_booleanarray *) array;
 
-    else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+       if ((start < 0) || (len < 0) || (start + len > ba->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&ba->data[start], buf, u1, len);
 }
 
 
-void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
+void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
+                                               jbyte *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_bytearray *ba;
 
-    else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       ba = (java_bytearray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ba->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&ba->data[start], buf, s1, len);
 }
 
 
-void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
+void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
+                                               jchar *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_chararray *ca;
 
-    else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       ca = (java_chararray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ca->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&ca->data[start], buf, u2, len);
 }
 
 
-void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
+void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
+                                                jsize len, jshort *buf)
 {
-    if (start < 0 || len < 0 || start+len>array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_shortarray *sa;
 
-    else
-               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       sa = (java_shortarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > sa->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&sa->data[start], buf, s2, len);
 }
 
 
-void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf)
+void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
+                                          jint *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_intarray *ia;
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       ia = (java_intarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ia->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&ia->data[start], buf, s4, len);
 }
 
 
-void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
+void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len,
+                                               jlong *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_longarray *la;
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       la = (java_longarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > la->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&la->data[start], buf, s8, len);
 }
 
 
-void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
+void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
+                                                jsize len, jfloat *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_floatarray *fa;
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       fa = (java_floatarray *) array;
 
+       if ((start < 0) || (len < 0) || (start + len > fa->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&fa->data[start], buf, float, len);
 }
 
 
-void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
+void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
+                                                 jsize len, jdouble *buf)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       java_doublearray *da;
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+       STATISTICS(jniinvokation());
+
+       da = (java_doublearray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > da->header.size))
+               exceptions_throw_arrayindexoutofboundsexception();
+       else
+               MCOPY(&da->data[start], buf, double, len);
 }
 
 
-void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
-{
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+/* Registering Native Methods *************************************************/
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+/* 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.
 
+*******************************************************************************/
 
-void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
+jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+                                        jint nMethods)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       STATISTICS(jniinvokation());
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+    log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!");
 
+    return 0;
 }
 
 
-void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
-{
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+/* UnregisterNatives ***********************************************************
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
+   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.
 
+*******************************************************************************/
 
-void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
+jint UnregisterNatives(JNIEnv *env, jclass clazz)
 {
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+       STATISTICS(jniinvokation());
 
-    else
-               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
-}
+       /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
 
+    log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
 
-jint RegisterNatives (JNIEnv* env, jclass clazz, const JNINativeMethod *methods, jint nMethods)
-{
-    log_text("JNI-Call: RegisterNatives");
     return 0;
 }
 
 
-jint UnregisterNatives (JNIEnv* env, jclass clazz)
-{
-    log_text("JNI-Call: UnregisterNatives");
-    return 0;
-}
+/* Monitor Operations *********************************************************/
+
+/* MonitorEnter ****************************************************************
 
-/******************************* monitor operations ********************************/
+   Enters the monitor associated with the underlying Java object
+   referred to by obj.
+
+*******************************************************************************/
 
-jint MonitorEnter(JNIEnvenv, jobject obj)
+jint MonitorEnter(JNIEnv *env, jobject obj)
 {
+       STATISTICS(jniinvokation());
+
+       if (!obj) {
+               exceptions_throw_nullpointerexception();
+               return JNI_ERR;
+       }
+
 #if defined(USE_THREADS)
-    builtin_monitorenter(obj);
+       builtin_monitorenter(obj);
 #endif
 
-    return 0;
+       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)
 {
+       STATISTICS(jniinvokation());
+
+       if (!obj) {
+               exceptions_throw_nullpointerexception();
+               return JNI_ERR;
+       }
+
 #if defined(USE_THREADS)
-    builtin_monitorexit(obj);
+       builtin_monitorexit(obj);
 #endif
 
-    return 0;
+       return JNI_OK;
 }
 
 
-/* JavaVM interface ***********************************************************/
+/* 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.
+   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(JNIEnvenv, JavaVM **vm)
+jint GetJavaVM(JNIEnv *env, JavaVM **vm)
 {
-    *vm = &JNI_javaVMTable;
+       STATISTICS(jniinvokation());
 
-    return 0;
+    *vm = &ptr_jvm;
+
+       return 0;
 }
 
 
-void GetStringRegion (JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
+void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
 {
-    log_text("JNI-Call: GetStringRegion");
+       STATISTICS(jniinvokation());
 
+       log_text("JNI-Call: GetStringRegion: IMPLEMENT ME!");
 }
 
+
 void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
 {
-    log_text("JNI-Call: GetStringUTFRegion");
+       STATISTICS(jniinvokation());
 
+       log_text("JNI-Call: GetStringUTFRegion: IMPLEMENT ME!");
 }
 
-/************** 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_bytearray *ba;
+       jbyte          *bp;
 
-       if (!desc) return NULL;
+       ba = (java_bytearray *) array;
 
-       return ((u1*)s) + desc->dataoffset;
+       /* do the same as Kaffe does */
+
+       bp = GetByteArrayElements(env, ba, isCopy);
+
+       return (void *) bp;
 }
 
 
-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");
+       STATISTICS(jniinvokation());
 
-       /* empty */
+       /* do the same as Kaffe does */
+
+       ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray, mode);
 }
 
-/**** 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");
+       STATISTICS(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");
+       STATISTICS(jniinvokation());
 
-       ReleaseStringChars(env,string,cstring);
+       ReleaseStringChars(env, string, cstring);
 }
 
 
-jweak NewWeakGlobalRef (JNIEnv* env, jobject obj)
+jweak NewWeakGlobalRef(JNIEnv* env, jobject obj)
 {
-       log_text("JNI-Call: NewWeakGlobalRef");
+       STATISTICS(jniinvokation());
+
+       log_text("JNI-Call: NewWeakGlobalRef: IMPLEMENT ME!");
 
        return obj;
 }
 
 
-void DeleteWeakGlobalRef (JNIEnv* env, jweak ref)
+void DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
 {
-       log_text("JNI-Call: DeleteWeakGlobalRef");
+       STATISTICS(jniinvokation());
 
-       /* empty */
+       log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME");
 }
 
 
-/** Creates a new global reference to the object referred to by the obj argument **/
+/* NewGlobalRef ****************************************************************
+
+   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;
+       java_objectheader *o;
+       java_lang_Integer *refcount;
+       java_objectheader *newval;
 
-       MonitorEnter(env, *global_ref_table);
+       STATISTICS(jniinvokation());
+
+#if defined(USE_THREADS)
+       builtin_monitorenter(*global_ref_table);
+#endif
        
-       refcount = CallObjectMethod(env, *global_ref_table, getmid, lobj);
-       val = (refcount == NULL) ? 0 : CallIntMethod(env, refcount, intvalue);
-       newval = NewObject(env, intclass, newint, val + 1);
+       o = vm_call_method(getmid, *global_ref_table, lobj);
+
+       refcount = (java_lang_Integer *) o;
 
-       if (newval != NULL) {
-               CallObjectMethod(env, *global_ref_table, putmid, lobj, newval);
-               MonitorExit(env, *global_ref_table);
-               return lobj;
+       if (refcount == NULL) {
+               newval = native_new_and_init_int(class_java_lang_Integer, 1);
+
+               if (newval == NULL) {
+#if defined(USE_THREADS)
+                       builtin_monitorexit(*global_ref_table);
+#endif
+                       return NULL;
+               }
+
+               (void) vm_call_method(putmid, *global_ref_table, lobj, newval);
 
        } else {
-               log_text("JNI-NewGlobalRef: unable to create new java.lang.Integer");
-               MonitorExit(env, *global_ref_table);
-               return NULL;
+               /* we can access the object itself, as we are in a
+           synchronized section */
+
+               refcount->value++;
        }
+
+#if defined(USE_THREADS)
+       builtin_monitorexit(*global_ref_table);
+#endif
+
+       return lobj;
 }
 
-/*************  Deletes the global reference pointed to by globalRef **************/
 
-void DeleteGlobalRef(JNIEnv* env, jobject gref)
+/* DeleteGlobalRef *************************************************************
+
+   Deletes the global reference pointed to by globalRef.
+
+*******************************************************************************/
+
+void DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 {
-       jobject refcount;
-       jint val;
+       java_objectheader *o;
+       java_lang_Integer *refcount;
+       s4                 val;
+
+       STATISTICS(jniinvokation());
+
+#if defined(USE_THREADS)
+       builtin_monitorenter(*global_ref_table);
+#endif
+
+       o = vm_call_method(getmid, *global_ref_table, globalRef);
 
-       MonitorEnter(env, *global_ref_table);
-       refcount = CallObjectMethod(env, *global_ref_table, getmid, gref);
+       refcount = (java_lang_Integer *) o;
 
        if (refcount == NULL) {
                log_text("JNI-DeleteGlobalRef: unable to find global reference");
                return;
        }
 
-       val = CallIntMethod(env, refcount, intvalue);
-       val--;
+       /* we can access the object itself, as we are in a synchronized
+          section */
+
+       val = refcount->value - 1;
 
        if (val == 0) {
-               CallObjectMethod(env, *global_ref_table, removemid,refcount);
+               (void) vm_call_method(removemid, *global_ref_table, refcount);
 
        } else {
-               jobject newval = NewObject(env, intclass, newint, val);
-
-               if (newval != NULL) {
-                       CallObjectMethod(env,*global_ref_table, putmid,newval);
+               /* we do not create a new object, but set the new value into
+           the old one */
 
-               } else {
-                       log_text("JNI-DeleteGlobalRef: unable to create new java.lang.Integer");
-               }
+               refcount->value = val;
        }
 
-       MonitorExit(env,*global_ref_table);
+#if defined(USE_THREADS)
+       builtin_monitorexit(*global_ref_table);
+#endif
 }
 
 
-/* ExceptionCheck *****************************************************************
+/* ExceptionCheck **************************************************************
 
-   check for pending exception
+   Returns JNI_TRUE when there is a pending exception; otherwise,
+   returns JNI_FALSE.
 
-**********************************************************************************/
+*******************************************************************************/
 
 jboolean ExceptionCheck(JNIEnv *env)
 {
+       STATISTICS(jniinvokation());
+
        return *exceptionptr ? JNI_TRUE : JNI_FALSE;
 }
 
@@ -3192,477 +5076,506 @@ jboolean ExceptionCheck(JNIEnv *env)
 
 /* NewDirectByteBuffer *********************************************************
 
-   Allocates and returns a direct java.nio.ByteBuffer referring to the block of
-   memory starting at the memory address address and extending capacity bytes.
+   Allocates and returns a direct java.nio.ByteBuffer referring to the
+   block of memory starting at the memory address address and
+   extending capacity bytes.
 
 *******************************************************************************/
 
 jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 {
-       log_text("NewDirectByteBuffer: IMPLEMENT ME!");
+       java_objectheader       *nbuf;
+#if SIZEOF_VOID_P == 8
+       gnu_classpath_Pointer64 *paddress;
+#else
+       gnu_classpath_Pointer32 *paddress;
+#endif
 
-       return NULL;
+       STATISTICS(jniinvokation());
+
+       /* alocate a gnu.classpath.Pointer{32,64} object */
+
+#if SIZEOF_VOID_P == 8
+       if (!(paddress = (gnu_classpath_Pointer64 *)
+                 builtin_new(class_gnu_classpath_Pointer64)))
+#else
+       if (!(paddress = (gnu_classpath_Pointer32 *)
+                 builtin_new(class_gnu_classpath_Pointer32)))
+#endif
+               return NULL;
+
+       /* fill gnu.classpath.Pointer{32,64} with address */
+
+       paddress->data = (ptrint) address;
+
+       /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
+
+       nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite,
+                                                        (jmethodID) dbbirw_init, NULL, paddress,
+                                                        (jint) capacity, (jint) capacity, (jint) 0);
+
+       /* add local reference and return the value */
+
+       return NewLocalRef(env, nbuf);
 }
 
 
 /* GetDirectBufferAddress ******************************************************
 
-   Fetches and returns the starting address of the memory region referenced by
-   the given direct java.nio.Buffer.
+   Fetches and returns the starting address of the memory region
+   referenced by the given direct java.nio.Buffer.
 
 *******************************************************************************/
 
 void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
 {
-       log_text("GetDirectBufferAddress: IMPLEMENT ME!");
+       java_nio_DirectByteBufferImpl *nbuf;
+#if SIZEOF_VOID_P == 8
+       gnu_classpath_Pointer64       *address;
+#else
+       gnu_classpath_Pointer32       *address;
+#endif
 
-       return NULL;
+       STATISTICS(jniinvokation());
+
+       if (!builtin_instanceof(buf, class_java_nio_Buffer))
+               return NULL;
+
+       nbuf = (java_nio_DirectByteBufferImpl *) buf;
+
+#if SIZEOF_VOID_P == 8
+       address = (gnu_classpath_Pointer64 *) nbuf->address;
+#else
+       address = (gnu_classpath_Pointer32 *) nbuf->address;
+#endif
+
+       return (void *) address->data;
 }
 
 
 /* GetDirectBufferCapacity *****************************************************
 
-   Fetches and returns the capacity in bytes of the memory region referenced by
-   the given direct java.nio.Buffer.
+   Fetches and returns the capacity in bytes of the memory region
+   referenced by the given direct java.nio.Buffer.
 
 *******************************************************************************/
 
 jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf)
 {
-       log_text("GetDirectBufferCapacity: IMPLEMENT ME!");
+       java_nio_Buffer *nbuf;
 
-       return 0;
+       STATISTICS(jniinvokation());
+
+       if (!builtin_instanceof(buf, class_java_nio_DirectByteBufferImpl))
+               return -1;
+
+       nbuf = (java_nio_Buffer *) buf;
+
+       return (jlong) nbuf->cap;
 }
 
 
+/* DestroyJavaVM ***************************************************************
+
+   Unloads a Java VM and reclaims its resources. Only the main thread
+   can unload the VM. The system waits until the main thread is only
+   remaining user thread before it destroys the VM.
+
+*******************************************************************************/
+
 jint DestroyJavaVM(JavaVM *vm)
 {
-       log_text("DestroyJavaVM called");
+       s4 status;
 
-       return 0;
+       STATISTICS(jniinvokation());
+
+    status = vm_destroy(vm);
+
+       return status;
 }
 
 
-jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2)
-{
-       log_text("AttachCurrentThread called");
+/* AttachCurrentThread *********************************************************
 
-       return 0;
-}
+   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.
 
-jint DetachCurrentThread(JavaVM *vm)
-{
-       log_text("DetachCurrentThread called");
+   A native thread cannot be attached simultaneously to two Java VMs.
 
-       return 0;
-}
+   When a thread is attached to the VM, the context class loader is
+   the bootstrap loader.
 
+*******************************************************************************/
 
-jint GetEnv(JavaVM *vm, void **environment, jint jniversion)
+jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args)
 {
-       *environment = &JNI_envTable;
+       STATISTICS(jniinvokation());
+
+       log_text("JNI-Call: AttachCurrentThread: IMPLEMENT ME!");
+
+#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 AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
+jint DetachCurrentThread(JavaVM *vm)
 {
-       log_text("AttachCurrentThreadAsDaemon called");
+       STATISTICS(jniinvokation());
+
+       log_text("JNI-Call: DetachCurrentThread: IMPLEMENT ME!");
 
        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); 
-}
+/* GetEnv **********************************************************************
 
-void jni_init(){
-       jmethodID mid;
+   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.
 
-       initrunning = true;
-       log_text("JNI-Init: initialize global_ref_table");
-       /* 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);
+jint GetEnv(JavaVM *vm, void **env, jint version)
+{
+       STATISTICS(jniinvokation());
 
-       *global_ref_table = NewObject(NULL,ihmclass,mid);
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       if (thread_getself() == NULL) {
+               *env = NULL;
 
-       if (*global_ref_table == NULL) {
-               log_text("JNI-Init: unable to create new global_ref_table");
+               return JNI_EDETACHED;
        }
+#endif
 
-       initrunning = false;
+       if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) ||
+               (version == JNI_VERSION_1_4)) {
+               *env = &ptr_env;
 
-       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");
+               return JNI_OK;
        }
 
-       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");
-       }
+#if defined(ENABLE_JVMTI)
+       if (version == JVMTI_VERSION_1_0) {
+               *env = (void *) new_jvmtienv();
 
-       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");
+               if (env != NULL)
+                       return JNI_OK;
        }
+#endif
+       
+       *env = NULL;
 
-       intclass = FindClass(NULL, "java/lang/Integer");
-       if (intclass == NULL) {
-               log_text("JNI-Init: unable to find java.lang.Integer");
-       }
+       return JNI_EVERSION;
+}
 
-       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 */
+jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
+{
+       STATISTICS(jniinvokation());
 
-       JNI_envTable.NewGlobalRef = &NewGlobalRef;
-       JNI_envTable.DeleteGlobalRef = &DeleteGlobalRef;
+       log_text("JNI-Call: AttachCurrentThreadAsDaemon: IMPLEMENT ME!");
+
+       return 0;
 }
 
 
 /* JNI invocation table *******************************************************/
 
-struct _JavaVM JNI_javaVMTable = {
+const struct JNIInvokeInterface JNI_JavaVMTable = {
        NULL,
        NULL,
        NULL,
-       &DestroyJavaVM,
-       &AttachCurrentThread,
-       &DetachCurrentThread,
-       &GetEnv,
-       &AttachCurrentThreadAsDaemon
+
+       DestroyJavaVM,
+       AttachCurrentThread,
+       DetachCurrentThread,
+       GetEnv,
+       AttachCurrentThreadAsDaemon
 };
 
 
 /* JNI function table *********************************************************/
 
-struct JNI_Table JNI_envTable = {
+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,
+       GetVersion,
+
+       DefineClass,
+       FindClass,
+       FromReflectedMethod,
+       FromReflectedField,
+       ToReflectedMethod,
+       GetSuperclass,
+       IsAssignableFrom,
+       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,
 
        /* new JNI 1.2 functions */
 
-       &GetStringRegion,
-       &GetStringUTFRegion,
+       GetStringRegion,
+       GetStringUTFRegion,
 
-       &GetPrimitiveArrayCritical,
-       &ReleasePrimitiveArrayCritical,
+       GetPrimitiveArrayCritical,
+       ReleasePrimitiveArrayCritical,
 
-       &GetStringCritical,
-       &ReleaseStringCritical,
+       GetStringCritical,
+       ReleaseStringCritical,
 
-       &NewWeakGlobalRef,
-       &DeleteWeakGlobalRef,
+       NewWeakGlobalRef,
+       DeleteWeakGlobalRef,
 
-       &ExceptionCheck,
+       ExceptionCheck,
 
        /* new JNI 1.4 functions */
 
-       &NewDirectByteBuffer,
-       &GetDirectBufferAddress,
-       &GetDirectBufferCapacity
+       NewDirectByteBuffer,
+       GetDirectBufferAddress,
+       GetDirectBufferCapacity
 };
 
 
@@ -3674,14 +5587,30 @@ struct JNI_Table JNI_envTable = {
 
 *******************************************************************************/
 
-jint JNI_GetDefaultJavaVMInitArgs(void *p_vm_args)
+jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
 {
-       JDK1_1InitArgs *vm_args = (JDK1_1InitArgs *) p_vm_args;
+       JavaVMInitArgs *_vm_args;
+
+       _vm_args = (JavaVMInitArgs *) vm_args;
 
        /* GNU classpath currently supports JNI 1.2 */
 
-       vm_args->version = JNI_VERSION_1_2;
+       switch (_vm_args->version) {
+    case JNI_VERSION_1_1:
+               _vm_args->version = JNI_VERSION_1_1;
+               break;
+
+    case JNI_VERSION_1_2:
+    case JNI_VERSION_1_4:
+               _vm_args->ignoreUnrecognized = JNI_FALSE;
+               _vm_args->options = NULL;
+               _vm_args->nOptions = 0;
+               break;
 
+    default:
+               return -1;
+       }
+  
        return 0;
 }
 
@@ -3698,6 +5627,8 @@ jint JNI_GetDefaultJavaVMInitArgs(void *p_vm_args)
 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 {
        log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!");
+
+       return 0;
 }
 
 
@@ -3708,249 +5639,53 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 
 *******************************************************************************/
 
-jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *p_vm_args)
-{
-       *p_vm = &JNI_javaVMTable;
-       *p_env = &JNI_envTable;
-
-       return 0;
-}
-
-
-jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, jobject obj, java_objectarray *params)
+jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
 {
-       int argcount;
-       jni_callblock *blk;
-       char retT;
-       jobject retVal;
-
-       if (methodID == 0) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
-               return NULL;
-       }
-
-       argcount = get_parametercount(methodID);
-
-       if (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;
-       }
-
-
-#ifdef arglimit
-       if (argcount > 3) {
-               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
-               log_text("Too many arguments. invokeNativeHelper does not support that");
-               return 0;
-       }
-#endif
-       if (((params==0) && (argcount != 0)) || (params && (params->header.size != argcount))) {
-               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
-               return 0;
-       }
-
-
-       if (((methodID->flags & ACC_STATIC)==0) && (0==obj))  {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NullPointerException,
-                                                                 "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
-               return 0;
-       }
+       JavaVMInitArgs *_vm_args;
+       _Jv_JNIEnv     *env;
+       localref_table *lrt;
 
-       if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0;
+       /* get the arguments for the new JVM */
 
-       if (obj) {
-               if ( (methodID->flags & ACC_ABSTRACT) || (methodID->class->flags & ACC_INTERFACE) ) {
-                       methodID=get_virtual(obj,methodID);
-               }
-       }
-
-       blk = MNEW(jni_callblock, /*4 */argcount+2);
-
-       retT = fill_callblock_objA(obj, methodID->descriptor, blk, params);
-
-       switch (retT) {
-       case 'V':
-               (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")));*/
-               break;
-
-       case 'I': {
-               s4 intVal;
-               intVal = asm_calljavafunction2int(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);
-       }
-       break;
+       _vm_args = (JavaVMInitArgs *) vm_args;
 
-       case 'B': {
-               s4 intVal;
-               intVal = asm_calljavafunction2int(methodID,
-                                                                                 argcount + 1,
-                                                                                 (argcount + 1) * sizeof(jni_callblock),
-                                                                                 blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Byte")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(B)V")),
-                                          intVal);
-       }
-       break;
+       /* get the VM and Env tables (must be set before vm_create) */
 
-       case 'C': {
-               s4 intVal;
-               intVal = asm_calljavafunction2int(methodID,
-                                                                                 argcount + 1,
-                                                                                 (argcount + 1) * sizeof(jni_callblock),
-                                                                                 blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Character")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(C)V")),
-                                          intVal);
-       }
-       break;
+       env = NEW(_Jv_JNIEnv);
 
-       case 'S': {
-               s4 intVal;
-               intVal = asm_calljavafunction2int(methodID,
-                                                                                 argcount + 1,
-                                                                                 (argcount + 1) * sizeof(jni_callblock),
-                                                                                 blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Short")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(S)V")),
-                                          intVal);
-       }
-       break;
+       env->env = &JNI_JNIEnvTable;
 
-       case 'Z': {
-               s4 intVal;
-               intVal = asm_calljavafunction2int(methodID,
-                                                                                 argcount + 1,
-                                                                                 (argcount + 1) * sizeof(jni_callblock),
-                                                                                 blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Boolean")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(Z)V")),
-                                          intVal);
-       }
-       break;
+       *p_vm  = (JavaVM *) &JNI_JavaVMTable;
+       *p_env = (void *) env;
 
-       case 'J': {
-               jlong longVal;
-               longVal = asm_calljavafunction2long(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Long")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(J)V")),
-                                          longVal);
-       }
-       break;
+       /* XXX Set the global env variable.  Maybe we should do that differently. */
 
-       case 'F': {
-               jdouble floatVal;       
-               floatVal = asm_calljavafunction2float(methodID,
-                                                                                         argcount + 1,
-                                                                                         (argcount + 1) * sizeof(jni_callblock),
-                                                                                         blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Float")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(F)V")),
-                                          floatVal);
-       }
-       break;
+       _Jv_env = env;
 
-       case 'D': {
-               jdouble doubleVal;
-               doubleVal = asm_calljavafunction2double(methodID,
-                                                                                               argcount + 1,
-                                                                                               (argcount + 1) * sizeof(jni_callblock),
-                                                                                               blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Double")));
-               CallVoidMethod(env,
-                                          retVal,
-                                          class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(D)V")),
-                                          doubleVal);
-       }
-       break;
+       /* actually create the JVM */
 
-       case 'L': /* fall through */
-       case '[':
-               retVal = asm_calljavafunction2(methodID,
-                                                                          argcount + 1,
-                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                          blk);
-               break;
+       if (!vm_create(_vm_args))
+               return -1;
 
-       default:
-               /* if this happens the acception has already been set by fill_callblock_objA*/
-               MFREE(blk, jni_callblock, /*4 */ argcount+2);
-               return (jobject *) 0;
-       }
+       /* setup the local ref table (must be created after vm_create) */
 
-       MFREE(blk, jni_callblock, /* 4 */ argcount+2);
+       lrt = GCNEW(localref_table);
 
-       if (*exceptionptr) {
-               java_objectheader *exceptionToWrap = *exceptionptr;
-               classinfo *ivtec;
-               java_objectheader *ivte;
+       lrt->capacity    = LOCALREFTABLE_CAPACITY;
+       lrt->used        = 0;
+       lrt->localframes = 1;
+       lrt->prev        = LOCALREFTABLE;
 
-               *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);
+       /* clear the references array (memset is faster then a for-loop) */
 
-               if (*exceptionptr != NULL)
-                       panic("jni.c: error while creating InvocationTargetException wrapper");
+       MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
 
-               *exceptionptr = ivte;
-       }
+       LOCALREFTABLE = lrt;
 
-       return (jobject *) retVal;
+       return 0;
 }
 
 
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
@@ -3962,4 +5697,5 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */