* src/native/jni.c (DeleteGlobalRef): Bugfix: handle the removal of
[cacao.git] / src / native / jni.c
index 6fd8cbe349f83854e31bff5aa33d09fb767ad0d0..1e1100652c996aa5b9614b29712d2a8a8ec2e69d 100644 (file)
@@ -30,8 +30,9 @@
    Changes: Joseph Wenninger
             Martin Platter
             Christian Thalinger
+                       Edwin Steiner
 
-   $Id: jni.c 4501 2006-02-13 18:55:55Z twisti $
+   $Id: jni.c 4901 2006-05-11 12:18:55Z twisti $
 
 */
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
 #include "vm/statistics.h"
+#include "vm/vm.h"
 
 
-/* XXX TWISTI hack: define it extern so they can be found in this file */
-
-extern const struct JNIInvokeInterface JNI_JavaVMTable;
-extern struct JNINativeInterface JNI_JNIEnvTable;
-
-/* pointers to VM and the environment needed by GetJavaVM and GetEnv */
-
-static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable;
-void *ptr_env = (void*) &JNI_JNIEnvTable;
-
-
-#define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
-
 /* global variables ***********************************************************/
 
 /* global reference table *****************************************************/
 
-static java_objectheader **global_ref_table;
+/* hashsize must be power of 2 */
 
-/* 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;
+#define HASHTABLE_GLOBAL_REF_SIZE    64 /* initial size of globalref-hash     */
+
+static hashtable *hashtable_global_ref; /* hashtable for globalrefs           */
 
 
 /* direct buffer stuff ********************************************************/
@@ -152,16 +139,17 @@ localref_table *_no_threads_localref_table;
 
 /* accessing instance fields macros *******************************************/
 
-#define SET_FIELD(obj,type,var,value) \
-    *((type *) ((ptrint) (obj) + (ptrint) (var)->offset)) = (type) (value)
+#define SET_FIELD(o,type,f,value) \
+    *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset)) = (type) (value)
 
-#define GET_FIELD(obj,type,var) \
-    *((type *) ((ptrint) (obj) + (ptrint) (var)->offset))
+#define GET_FIELD(o,type,f) \
+    *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset))
 
 
 /* some forward declarations **************************************************/
 
 jobject NewLocalRef(JNIEnv *env, jobject ref);
+jint EnsureLocalCapacity(JNIEnv* env, jint capacity);
 
 
 /* jni_init ********************************************************************
@@ -172,29 +160,11 @@ jobject NewLocalRef(JNIEnv *env, jobject ref);
 
 bool jni_init(void)
 {
-       /* initalize global reference table */
-
-       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;
+       /* create global ref hashtable */
 
-       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;
+       hashtable_global_ref = NEW(hashtable);
 
-       if (!(removemid =
-                 class_resolvemethod(ihmclass, utf_remove,
-                                                         utf_java_lang_Object__java_lang_Object)))
-               return false;
+       hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
 
 
        /* direct buffer stuff */
@@ -236,92 +206,24 @@ bool jni_init(void)
 }
 
 
-static void fill_callblock_from_vargs(void *obj, methoddesc *descr,
-                                                                         jni_callblock blk[], va_list data,
-                                                                         s4 rettype)
-{
-       typedesc *paramtypes;
-       s4        i;
-
-       paramtypes = descr->paramtypes;
-
-       /* if method is non-static fill first block and skip `this' pointer */
-
-       i = 0;
-
-       if (obj != NULL) {
-               /* the `this' pointer */
-               blk[0].itemtype = TYPE_ADR;
-               blk[0].item = PTR_TO_ITEM(obj);
-
-               paramtypes++;
-               i++;
-       } 
-
-       for (; i < descr->paramcount; i++, paramtypes++) {
-               switch (paramtypes->decltype) {
-               /* primitive types */
-               case PRIMITIVETYPE_BYTE:
-               case PRIMITIVETYPE_CHAR:
-               case PRIMITIVETYPE_SHORT: 
-               case PRIMITIVETYPE_BOOLEAN: 
-                       blk[i].itemtype = TYPE_INT;
-                       blk[i].item = (s8) va_arg(data, s4);
-                       break;
-
-               case PRIMITIVETYPE_INT:
-                       blk[i].itemtype = TYPE_INT;
-                       blk[i].item = (s8) va_arg(data, s4);
-                       break;
-
-               case PRIMITIVETYPE_LONG:
-                       blk[i].itemtype = TYPE_LNG;
-                       blk[i].item = (s8) va_arg(data, s8);
-                       break;
-
-               case PRIMITIVETYPE_FLOAT:
-                       blk[i].itemtype = TYPE_FLT;
-#if defined(__ALPHA__)
-                       /* this keeps the assembler function much simpler */
-
-                       *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
-#else
-                       *((jfloat *) (&blk[i].item)) = (jfloat) va_arg(data, jdouble);
-#endif
-                       break;
-
-               case PRIMITIVETYPE_DOUBLE:
-                       blk[i].itemtype = TYPE_DBL;
-                       *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
-                       break;
-
-               case TYPE_ADR: 
-                       blk[i].itemtype = TYPE_ADR;
-                       blk[i].item = PTR_TO_ITEM(va_arg(data, void*));
-                       break;
-               }
-       }
-
-       /* The standard doesn't say anything about return value checking,
-          but it appears to be useful. */
-
-       if (rettype != descr->returntype.decltype)
-               log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
-}
+/* _Jv_jni_vmargs_from_objectarray *********************************************
 
+   XXX
 
-/* XXX it could be considered if we should do typechecking here in the future */
+*******************************************************************************/
 
-static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
-                                                                                       jni_callblock blk[],
+static bool _Jv_jni_vmargs_from_objectarray(java_objectheader *o,
+                                                                                       methoddesc *descr,
+                                                                                       vm_arg *vmargs,
                                                                                        java_objectarray *params)
 {
-    jobject    param;
-       s4         paramcount;
-       typedesc  *paramtypes;
-       classinfo *c;
-    s4         i;
-       s4         j;
+       java_objectheader *param;
+       s4                 paramcount;
+       typedesc          *paramtypes;
+       classinfo         *c;
+       s4                 i;
+       s4                 j;
+       s8                 value;
 
        paramcount = descr->paramcount;
        paramtypes = descr->paramtypes;
@@ -330,10 +232,10 @@ static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
 
        i = 0;
 
-       if (obj) {
+       if (o != NULL) {
                /* this pointer */
-               blk[0].itemtype = TYPE_ADR;
-               blk[0].item = PTR_TO_ITEM(obj);
+               vmargs[0].type   = TYPE_ADR;
+               vmargs[0].data.l = (u8) (ptrint) o;
 
                paramtypes++;
                paramcount--;
@@ -348,11 +250,12 @@ static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
                case TYPE_FLOAT:
                case TYPE_DOUBLE:
                        param = params->data[j];
-                       if (!param)
+
+                       if (param == NULL)
                                goto illegal_arg;
 
                        /* internally used data type */
-                       blk[i].itemtype = paramtypes->type;
+                       vmargs[i].type = paramtypes->type;
 
                        /* convert the value according to its declared type */
 
@@ -361,77 +264,89 @@ static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
                        switch (paramtypes->decltype) {
                        case PRIMITIVETYPE_BOOLEAN:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Boolean *) param)->value;
+                                       value = (s8) ((java_lang_Boolean *) param)->value;
                                else
                                        goto illegal_arg;
+
+                               vmargs[i].data.l = value;
                                break;
 
                        case PRIMITIVETYPE_BYTE:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                                       value = (s8) ((java_lang_Byte *) param)->value;
                                else
                                        goto illegal_arg;
+
+                               vmargs[i].data.l = value;
                                break;
 
                        case PRIMITIVETYPE_CHAR:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Character *) param)->value;
+                                       value = (s8) ((java_lang_Character *) param)->value;
                                else
                                        goto illegal_arg;
+
+                               vmargs[i].data.l = value;
                                break;
 
                        case PRIMITIVETYPE_SHORT:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
+                                       value = (s8) ((java_lang_Short *) param)->value;
                                else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                                       value = (s8) ((java_lang_Byte *) param)->value;
                                else
                                        goto illegal_arg;
+
+                               vmargs[i].data.l = value;
                                break;
 
                        case PRIMITIVETYPE_INT:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
+                                       value = (s8) ((java_lang_Integer *) param)->value;
                                else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
+                                       value = (s8) ((java_lang_Short *) param)->value;
                                else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                                       value = (s8) ((java_lang_Byte *) param)->value;
                                else
                                        goto illegal_arg;
+
+                               vmargs[i].data.l = value;
                                break;
 
                        case PRIMITIVETYPE_LONG:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Long *) param)->value;
+                                       value = (s8) ((java_lang_Long *) param)->value;
                                else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
+                                       value = (s8) ((java_lang_Integer *) param)->value;
                                else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
+                                       value = (s8) ((java_lang_Short *) param)->value;
                                else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
+                                       value = (s8) ((java_lang_Byte *) param)->value;
                                else
                                        goto illegal_arg;
+
+                               vmargs[i].data.l = value;
                                break;
 
                        case PRIMITIVETYPE_FLOAT:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
+                                       vmargs[i].data.f = (jfloat) ((java_lang_Float *) param)->value;
                                else
                                        goto illegal_arg;
                                break;
 
                        case PRIMITIVETYPE_DOUBLE:
                                if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       *((jdouble *) (&blk[i].item)) = (jdouble) ((java_lang_Double *) param)->value;
+                                       vmargs[i].data.d = (jdouble) ((java_lang_Double *) param)->value;
                                else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
-                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
+                                       vmargs[i].data.f = (jfloat) ((java_lang_Float *) param)->value;
                                else
                                        goto illegal_arg;
                                break;
 
                        default:
                                goto illegal_arg;
-                       } /* end declared type switch */
+                       }
                        break;
                
                        case TYPE_ADDRESS:
@@ -448,15 +363,15 @@ static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
                                                        goto illegal_arg;
                                        }
                                }
-                               blk[i].itemtype = TYPE_ADR;
-                               blk[i].item = PTR_TO_ITEM(params->data[j]);
-                               break;                  
+
+                               vmargs[i].type   = TYPE_ADR;
+                               vmargs[i].data.l = (u8) (ptrint) params->data[j];
+                               break;
 
                        default:
                                goto illegal_arg;
-               } /* end param type switch */
-
-       } /* end param loop */
+               }
+       }
 
 /*     if (rettype) */
 /*             *rettype = descr->returntype.decltype; */
@@ -480,10 +395,7 @@ static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
                                                                                                   methodinfo *m, va_list ap)
 {
        methodinfo        *resm;
-       s4                 paramcount;
-       jni_callblock     *blk;
-       java_objectheader *ret;
-       s4                 dumpsize;
+       java_objectheader *ro;
 
        STATISTICS(jniinvokation());
 
@@ -511,27 +423,58 @@ static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
+       STATISTICS(jnicallXmethodnvokation());
 
-       dumpsize = dump_size();
+       ro = vm_call_method_valist(resm, o, ap);
 
-       paramcount = resm->parseddesc->paramcount;
+       return ro;
+}
 
-       blk = DMNEW(jni_callblock, paramcount);
 
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, TYPE_ADR);
+/* _Jv_jni_CallObjectMethodA ***************************************************
 
-       STATISTICS(jnicallXmethodnvokation());
+   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. */
 
-       ASM_CALLJAVAFUNCTION2_ADR(ret, resm, paramcount,
-                                                         paramcount * sizeof(jni_callblock),
-                                                         blk);
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       /* release dump area */
+       STATISTICS(jnicallXmethodnvokation());
 
-       dump_release(dumpsize);
+       ro = vm_call_method_jvalue(resm, o, args);
 
-       return ret;
+       return ro;
 }
 
 
@@ -543,13 +486,10 @@ static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
 *******************************************************************************/
 
 static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
-                                                                 methodinfo *m, va_list ap, s4 type)
+                                                                 methodinfo *m, va_list ap)
 {
-       methodinfo    *resm;
-       s4             paramcount;
-       jni_callblock *blk;
-       jint           ret;
-       s4             dumpsize;
+       methodinfo *resm;
+       jint        i;
 
        STATISTICS(jniinvokation());
 
@@ -577,27 +517,58 @@ static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
+       STATISTICS(jnicallXmethodnvokation());
+
+       i = vm_call_method_int_valist(resm, o, ap);
+
+       return i;
+}
 
-       dumpsize = dump_size();
 
-       paramcount = resm->parseddesc->paramcount;
+/* _Jv_jni_CallIntMethodA ******************************************************
 
-       blk = DMNEW(jni_callblock, paramcount);
+   Internal function to call Java integer class methods (boolean,
+   byte, char, short, int).
 
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, type);
+*******************************************************************************/
 
-       STATISTICS(jnicallXmethodnvokation());
+static jint _Jv_jni_CallIntMethodA(java_objectheader *o, vftbl_t *vftbl,
+                                                                  methodinfo *m, jvalue *args)
+{
+       methodinfo *resm;
+       jint        i;
+
+       STATISTICS(jniinvokation());
+
+       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. */
+
+       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. */
 
-       ASM_CALLJAVAFUNCTION2_INT(ret, resm, paramcount,
-                                                         paramcount * sizeof(jni_callblock),
-                                                         blk);
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       /* release dump area */
+       STATISTICS(jnicallXmethodnvokation());
 
-       dump_release(dumpsize);
+       i = vm_call_method_int_jvalue(resm, o, args);
 
-       return ret;
+       return i;
 }
 
 
@@ -610,11 +581,8 @@ static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
 static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
                                                                        methodinfo *m, va_list ap)
 {
-       methodinfo    *resm;
-       s4             paramcount;
-       jni_callblock *blk;
-       jlong          ret;
-       s4             dumpsize;
+       methodinfo *resm;
+       jlong       l;
 
        STATISTICS(jniinvokation());
 
@@ -642,27 +610,11 @@ static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
-       paramcount = resm->parseddesc->paramcount;
-
-       blk = DMNEW(jni_callblock, paramcount);
-
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, PRIMITIVETYPE_LONG);
-
        STATISTICS(jnicallXmethodnvokation());
 
-       ASM_CALLJAVAFUNCTION2_LONG(ret, resm, paramcount,
-                                                          paramcount * sizeof(jni_callblock),
-                                                          blk);
-
-       /* release dump area */
+       l = vm_call_method_long_valist(resm, o, ap);
 
-       dump_release(dumpsize);
-
-       return ret;
+       return l;
 }
 
 
@@ -675,11 +627,8 @@ static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
 static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
                                                                          methodinfo *m, va_list ap)
 {
-       methodinfo    *resm;
-       s4             paramcount;
-       jni_callblock *blk;
-       jdouble        ret;
-       s4             dumpsize;
+       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. */
@@ -700,28 +649,11 @@ static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
-       paramcount = resm->parseddesc->paramcount;
-
-       blk = DMNEW(jni_callblock, paramcount);
-
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap,
-                                                         PRIMITIVETYPE_FLOAT);
-
        STATISTICS(jnicallXmethodnvokation());
 
-       ASM_CALLJAVAFUNCTION2_FLOAT(ret, resm, paramcount,
-                                                               paramcount * sizeof(jni_callblock),
-                                                               blk);
-
-       /* release dump area */
+       f = vm_call_method_float_valist(resm, o, ap);
 
-       dump_release(dumpsize);
-
-       return ret;
+       return f;
 }
 
 
@@ -734,11 +666,8 @@ static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
 static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
                                                                                methodinfo *m, va_list ap)
 {
-       methodinfo    *resm;
-       s4             paramcount;
-       jni_callblock *blk;
-       jfloat         ret;
-       s4             dumpsize;
+       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. */
@@ -759,28 +688,9 @@ static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
-       paramcount = resm->parseddesc->paramcount;
-
-       blk = DMNEW(jni_callblock, paramcount);
-
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap,
-                                                         PRIMITIVETYPE_DOUBLE);
+       d = vm_call_method_double_valist(resm, o, ap);
 
-       STATISTICS(jnicallXmethodnvokation());
-
-       ASM_CALLJAVAFUNCTION2_DOUBLE(ret, resm, paramcount,
-                                                                paramcount * sizeof(jni_callblock),
-                                                                blk);
-
-       /* release dump area */
-
-       dump_release(dumpsize);
-
-       return ret;
+       return d;
 }
 
 
@@ -793,10 +703,7 @@ static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
 static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl,
                                                                   methodinfo *m, va_list ap)
 {      
-       methodinfo    *resm;
-       s4             paramcount;
-       jni_callblock *blk;
-       s4             dumpsize;
+       methodinfo *resm;
 
        if (m == NULL) {
                exceptions_throw_nullpointerexception();
@@ -822,44 +729,74 @@ static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
+       STATISTICS(jnicallXmethodnvokation());
+
+       (void) vm_call_method_valist(resm, o, ap);
+}
 
-       dumpsize = dump_size();
 
-       paramcount = resm->parseddesc->paramcount;
+/* _Jv_jni_CallVoidMethodA *****************************************************
 
-       blk = DMNEW(jni_callblock, paramcount);
+   Internal function to call Java void methods.
 
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, TYPE_VOID);
+*******************************************************************************/
 
-       STATISTICS(jnicallXmethodnvokation());
+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;
+
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       ASM_CALLJAVAFUNCTION2(resm, paramcount,
-                                                 paramcount * sizeof(jni_callblock),
-                                                 blk);
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       /* release dump area */
+       STATISTICS(jnicallXmethodnvokation());
 
-       dump_release(dumpsize);
+       (void) vm_call_method_jvalue(resm, o, args);
 }
 
 
 /* _Jv_jni_invokeNative ********************************************************
 
-   XXX
+   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.
 
 *******************************************************************************/
 
-jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
-                                                         java_objectarray *params)
+java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
+                                                                               java_objectarray *params)
 {
        methodinfo        *resm;
-       jni_callblock     *blk;
-       java_objectheader *o;
+       vm_arg            *vmargs;
+       java_objectheader *ro;
        s4                 argcount;
        s4                 paramcount;
 
-       if (m == NULL) {
+       if (!m) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
@@ -872,78 +809,72 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
        if (!(m->flags & ACC_STATIC))
                paramcount--;
 
-       /* the method is an instance method the obj has to be an instance of the 
-          class the method belongs to. For static methods the obj parameter
-          is ignored. */
+       /* 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) && obj &&
-               (!builtin_instanceof((java_objectheader *) obj, m->class))) {
+       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;
        }
 
+       /* check if we got the right number of arguments */
+
        if (((params == NULL) && (paramcount != 0)) ||
-               (params && (params->header.size != paramcount))) {
+               (params && (params->header.size != paramcount))) 
+       {
                *exceptionptr =
                        new_exception(string_java_lang_IllegalArgumentException);
                return NULL;
        }
 
-       if (!(m->flags & ACC_STATIC) && (obj == NULL))  {
+       /* 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;
        }
 
-       if ((m->flags & ACC_STATIC) && (obj != NULL))
-               obj = NULL;
-
-       /* For virtual calls with abstract method of interface classes we
-          have to do a virtual function table lookup (XXX TWISTI: not
-          sure if this is correct, took it from the old
-          implementation). */
+       /* for static methods, zero object to make subsequent code simpler */
+       if (m->flags & ACC_STATIC)
+               o = NULL;
 
-       if ((obj != NULL) &&
-               ((m->flags & ACC_ABSTRACT) || (m->class->flags & ACC_INTERFACE))) {
-               resm = method_vftbl_lookup(obj->vftbl, m);
+       if (o != NULL) {
+               /* for instance methods we must do a vftbl lookup */
+               resm = method_vftbl_lookup(o->vftbl, m);
 
        } else {
-               /* just for convenience */
-
+               /* for static methods, just for convenience */
                resm = m;
        }
 
-       blk = MNEW(jni_callblock, argcount);
+       vmargs = MNEW(vm_arg, argcount);
 
-       if (!fill_callblock_from_objectarray(obj, resm->parseddesc, blk,
-                                                                                params))
+       if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params))
                return NULL;
 
        switch (resm->parseddesc->returntype.decltype) {
        case TYPE_VOID:
-               ASM_CALLJAVAFUNCTION2(resm, argcount,
-                                                         argcount * sizeof(jni_callblock),
-                                                         blk);
+               (void) vm_call_method_vmarg(resm, argcount, vmargs);
 
-               o = NULL;
+               ro = NULL;
                break;
 
        case PRIMITIVETYPE_BOOLEAN: {
                s4 i;
                java_lang_Boolean *bo;
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Boolean);
+               ro = builtin_new(class_java_lang_Boolean);
 
                /* setting the value of the object direct */
 
-               bo = (java_lang_Boolean *) o;
+               bo = (java_lang_Boolean *) ro;
                bo->value = i;
        }
        break;
@@ -952,15 +883,13 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                s4 i;
                java_lang_Byte *bo;
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Byte);
+               ro = builtin_new(class_java_lang_Byte);
 
                /* setting the value of the object direct */
 
-               bo = (java_lang_Byte *) o;
+               bo = (java_lang_Byte *) ro;
                bo->value = i;
        }
        break;
@@ -969,15 +898,13 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                s4 i;
                java_lang_Character *co;
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Character);
+               ro = builtin_new(class_java_lang_Character);
 
                /* setting the value of the object direct */
 
-               co = (java_lang_Character *) o;
+               co = (java_lang_Character *) ro;
                co->value = i;
        }
        break;
@@ -986,15 +913,13 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                s4 i;
                java_lang_Short *so;
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Short);
+               ro = builtin_new(class_java_lang_Short);
 
                /* setting the value of the object direct */
 
-               so = (java_lang_Short *) o;
+               so = (java_lang_Short *) ro;
                so->value = i;
        }
        break;
@@ -1003,15 +928,13 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                s4 i;
                java_lang_Integer *io;
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+               i = vm_call_method_int_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Integer);
+               ro = builtin_new(class_java_lang_Integer);
 
                /* setting the value of the object direct */
 
-               io = (java_lang_Integer *) o;
+               io = (java_lang_Integer *) ro;
                io->value = i;
        }
        break;
@@ -1020,15 +943,13 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                s8 l;
                java_lang_Long *lo;
 
-               ASM_CALLJAVAFUNCTION2_LONG(l, resm, argcount,
-                                                                  argcount * sizeof(jni_callblock),
-                                                                  blk);
+               l = vm_call_method_long_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Long);
+               ro = builtin_new(class_java_lang_Long);
 
                /* setting the value of the object direct */
 
-               lo = (java_lang_Long *) o;
+               lo = (java_lang_Long *) ro;
                lo->value = l;
        }
        break;
@@ -1037,15 +958,13 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                float f;
                java_lang_Float *fo;
 
-               ASM_CALLJAVAFUNCTION2_FLOAT(f, resm, argcount,
-                                                                       argcount * sizeof(jni_callblock),
-                                                                       blk);
+               f = vm_call_method_float_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Float);
+               ro = builtin_new(class_java_lang_Float);
 
                /* setting the value of the object direct */
 
-               fo = (java_lang_Float *) o;
+               fo = (java_lang_Float *) ro;
                fo->value = f;
        }
        break;
@@ -1054,35 +973,31 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                double d;
                java_lang_Double *_do;
 
-               ASM_CALLJAVAFUNCTION2_DOUBLE(d, resm, argcount,
-                                                                        argcount * sizeof(jni_callblock),
-                                                                        blk);
+               d = vm_call_method_double_vmarg(resm, argcount, vmargs);
 
-               o = builtin_new(class_java_lang_Double);
+               ro = builtin_new(class_java_lang_Double);
 
                /* setting the value of the object direct */
 
-               _do = (java_lang_Double *) o;
+               _do = (java_lang_Double *) ro;
                _do->value = d;
        }
        break;
 
        case TYPE_ADR:
-               ASM_CALLJAVAFUNCTION2_ADR(o, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+               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(blk, jni_callblock, argcount);
+               MFREE(vmargs, vm_arg, argcount);
 
-               return (jobject *) 0;
+               return NULL;
        }
 
-       MFREE(blk, jni_callblock, argcount);
+       MFREE(vmargs, vm_arg, argcount);
 
        if (*exceptionptr) {
                java_objectheader *cause;
@@ -1098,7 +1013,7 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
                                                                        (java_lang_Throwable *) cause);
        }
 
-       return (jobject *) o;
+       return ro;
 }
 
 
@@ -1140,7 +1055,7 @@ jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
        STATISTICS(jniinvokation());
 
        cl = (java_lang_ClassLoader *) loader;
-       s = javastring_new_char(name);
+       s = javastring_new_from_ascii(name);
        ba = (java_bytearray *) buf;
 
        c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
@@ -1160,33 +1075,51 @@ jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
 
 jclass FindClass(JNIEnv *env, const char *name)
 {
-       utf               *u;
-       classinfo         *c;
-       java_objectheader *cl;
+       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. */
+          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 */
 
-       cl = stacktrace_getCurrentClassLoader();
+       cc = stacktrace_getCurrentClass();
 #else
 # if defined(ENABLE_INTRP)
        /* the interpreter supports stacktraces, even if the JIT does not */
 
        if (opt_intrp)
-               cl = stacktrace_getCurrentClassLoader();
+               cc = stacktrace_getCurrentClass();
        else
 # endif
-               cl = NULL;
+               cc = NULL;
 #endif
 
-       if (!(c = load_class_from_classloader(u, cl)))
+       /* 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))
@@ -1196,54 +1129,6 @@ jclass FindClass(JNIEnv *env, const char *name)
 }
   
 
-/* 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;
-
-       if ((slot < 0) || (slot >= c->methodscount)) {
-               /* this usually means a severe internal cacao error or somebody
-                  tempered around with the reflected method */
-               log_text("error illegal slot for method in class(FromReflectedMethod)");
-               assert(0);
-       }
-
-       mi = &(c->methods[slot]);
-
-       return mi;
-}
-
-
 /* GetSuperclass ***************************************************************
 
    If clazz represents any class other than the class Object, then
@@ -1315,7 +1200,7 @@ jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
 
        STATISTICS(jniinvokation());
 
-       s = (java_lang_String *) javastring_new_char(msg);
+       s = (java_lang_String *) javastring_new_from_ascii(msg);
 
        /* instantiate exception object */
 
@@ -1387,7 +1272,7 @@ void ExceptionDescribe(JNIEnv *env)
 
                /* print the stacktrace */
 
-               ASM_CALLJAVAFUNCTION(m, e, NULL, NULL, NULL);
+               (void) vm_call_method(m, e);
        }
 }
 
@@ -1431,15 +1316,48 @@ void FatalError(JNIEnv *env, const char *msg)
 
 jint PushLocalFrame(JNIEnv* env, jint capacity)
 {
+       s4              additionalrefs;
+       localref_table *lrt;
+       localref_table *nlrt;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!");
+       if (capacity <= 0)
+               return -1;
 
-       assert(0);
+       /* Allocate new local reference table on Java heap.  Calculate the
+          additional memory we have to allocate. */
+
+       if (capacity > LOCALREFTABLE_CAPACITY)
+               additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
+       else
+               additionalrefs = 0;
+
+       nlrt = GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+
+       if (nlrt == NULL)
+               return -1;
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+
+       /* Set up the new local reference table and add it to the local
+          frames chain. */
+
+       nlrt->capacity    = capacity;
+       nlrt->used        = 0;
+       nlrt->localframes = lrt->localframes + 1;
+       nlrt->prev        = lrt;
+
+       /* store new local reference table in thread */
+
+       LOCALREFTABLE = nlrt;
 
        return 0;
 }
 
+
 /* PopLocalFrame ***************************************************************
 
    Pops off the current local reference frame, frees all the local
@@ -1450,15 +1368,50 @@ jint PushLocalFrame(JNIEnv* env, jint capacity)
 
 jobject PopLocalFrame(JNIEnv* env, jobject result)
 {
+       localref_table *lrt;
+       localref_table *plrt;
+       s4              localframes;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!");
+       /* get current local reference table from thread */
 
-       assert(0);
+       lrt = LOCALREFTABLE;
+
+       localframes = lrt->localframes;
+
+       /* Don't delete the top local frame, as this one is allocated in
+          the native stub on the stack and is freed automagically on
+          return. */
+
+       if (localframes == 1)
+               return NewLocalRef(env, result);
+
+       /* release all current local frames */
+
+       for (; localframes >= 1; localframes--) {
+               /* get previous frame */
+
+               plrt = lrt->prev;
+
+               /* clear all reference entries */
+
+               MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
+
+               lrt->prev = NULL;
+
+               /* set new local references table */
+
+               lrt = plrt;
+       }
+
+       /* store new local reference table in thread */
+
+       LOCALREFTABLE = lrt;
 
        /* add local reference and return the value */
 
-       return NewLocalRef(env, NULL);
+       return NewLocalRef(env, result);
 }
 
 
@@ -1482,14 +1435,19 @@ void DeleteLocalRef(JNIEnv *env, jobject localRef)
 
        lrt = LOCALREFTABLE;
 
-       /* remove the reference */
+       /* go through all local frames */
 
-       for (i = 0; i < lrt->capacity; i++) {
-               if (lrt->refs[i] == o) {
-                       lrt->refs[i] = NULL;
-                       lrt->used--;
+       for (; lrt != NULL; lrt = lrt->prev) {
 
-                       return;
+               /* and try to remove the reference */
+
+               for (i = 0; i < lrt->capacity; i++) {
+                       if (lrt->refs[i] == o) {
+                               lrt->refs[i] = NULL;
+                               lrt->used--;
+
+                               return;
+                       }
                }
        }
 
@@ -1497,7 +1455,7 @@ void DeleteLocalRef(JNIEnv *env, jobject localRef)
 
 /*     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");
+       log_text("JNI-DeleteLocalRef: Local ref passed to JNI not found");
 }
 
 
@@ -1538,13 +1496,17 @@ jobject NewLocalRef(JNIEnv *env, jobject ref)
 
        lrt = LOCALREFTABLE;
 
-       /* check if we have space for the requested reference */
+       /* Check if we have space for the requested reference?  No,
+          allocate a new frame.  This is actually not what the spec says,
+          but for compatibility reasons... */
 
        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);
+               if (EnsureLocalCapacity(env, 16) != 0)
+                       return NULL;
+
+               /* get the new local reference table */
+
+               lrt = LOCALREFTABLE;
        }
 
        /* insert the reference */
@@ -1579,6 +1541,8 @@ jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
 {
        localref_table *lrt;
 
+       log_text("JNI-Call: EnsureLocalCapacity");
+
        STATISTICS(jniinvokation());
 
        /* get local reference table (thread specific) */
@@ -1587,10 +1551,8 @@ jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
 
        /* 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;
-       }
+       if ((lrt->used + capacity) > lrt->capacity)
+               return PushLocalFrame(env, capacity);
 
        return 0;
 }
@@ -1605,18 +1567,21 @@ jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
 
 jobject AllocObject(JNIEnv *env, jclass clazz)
 {
+       classinfo         *c;
        java_objectheader *o;
 
        STATISTICS(jniinvokation());
 
-       if ((clazz->flags & ACC_INTERFACE) || (clazz->flags & ACC_ABSTRACT)) {
+       c = (classinfo *) clazz;
+
+       if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
                *exceptionptr =
                        new_exception_utfmessage(string_java_lang_InstantiationException,
-                                                                        clazz->name);
+                                                                        c->name);
                return NULL;
        }
                
-       o = builtin_new(clazz);
+       o = builtin_new(c);
 
        return NewLocalRef(env, o);
 }
@@ -1634,21 +1599,24 @@ jobject AllocObject(JNIEnv *env, jclass clazz)
 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)
+       if (o == NULL)
                return NULL;
 
        /* call constructor */
 
        va_start(ap, methodID);
-       _Jv_jni_CallVoidMethod(o, o->vftbl, methodID, ap);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
        return NewLocalRef(env, o);
@@ -1668,39 +1636,58 @@ jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 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)
+       if (o == NULL)
                return NULL;
 
        /* call constructor */
 
-       _Jv_jni_CallVoidMethod(o, o->vftbl, methodID, args);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
 
        return NewLocalRef(env, o);
 }
 
 
-/*********************************************************************************** 
+/* NewObjectA ***************************************************************** 
 
-       Constructs a new Java object
-       arguments that are to be passed to the constructor are placed in 
-       args array of jvalues 
+   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());
 
-       log_text("JNI-Call: NewObjectA: IMPLEMENT ME!");
+       m = (methodinfo *) methodID;
 
-       return NewLocalRef(env, NULL);
+       /* 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);
 }
 
 
@@ -1712,14 +1699,17 @@ jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
 
 jclass GetObjectClass(JNIEnv *env, jobject obj)
 {
-       classinfo *c;
+       java_objectheader *o;
+       classinfo         *c;
 
        STATISTICS(jniinvokation());
-       
-       if (!obj || !obj->vftbl)
+
+       o = (java_objectheader *) obj;
+
+       if ((o == NULL) || (o->vftbl == NULL))
                return NULL;
 
-       c = obj->vftbl->class;
+       c = o->vftbl->class;
 
        return (jclass) NewLocalRef(env, (jobject) c);
 }
@@ -1742,29 +1732,73 @@ jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
 }
 
 
-/***************** converts a java.lang.reflect.Field to a field ID ***************/
+/* 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 *f;
-       classinfo *c;
-       jfieldID fid;   /* the JNI-fieldid of the wrapping object */
+       java_lang_reflect_Field *rf;
+       classinfo               *c;
+       fieldinfo               *f;
 
        STATISTICS(jniinvokation());
 
-       /*log_text("JNI-Call: FromReflectedField");*/
+       rf = (java_lang_reflect_Field *) field;
 
-       f=(java_lang_reflect_Field *)field;
-       if (f==0) return 0;
-       c=(classinfo*)(f->declaringClass);
-       if ( (f->slot<0) || (f->slot>=c->fieldscount)) {
-               /*this usually means a severe internal cacao error or somebody
-               tempered around with the reflected method*/
-               log_text("error illegal slot for field in class(FromReflectedField)");
-               assert(0);
-       }
-       fid=&(c->fields[f->slot]);
-       return fid;
+       if (rf == NULL)
+               return NULL;
+
+       c = (classinfo *) rf->declaringClass;
+
+       f = &(c->fields[rf->slot]);
+
+       return (jfieldID) f;
 }
 
 
@@ -1849,7 +1883,7 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
                return NULL;
        }
 
-       return m;
+       return (jmethodID) m;
 }
 
 
@@ -1857,11 +1891,16 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
 
 jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       java_objectheader* ret;
+       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(obj, obj->vftbl, methodID, ap);
+       ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
        return NewLocalRef(env, ret);
@@ -1870,77 +1909,112 @@ jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 
 jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       java_objectheader* ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       java_objectheader *ret;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallObjectMethod(obj, obj->vftbl, methodID, args);
+       ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, args);
 
        return NewLocalRef(env, ret);
 }
 
 
-jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallObjectMethodA: IMPLEMENT ME!");
+       java_objectheader *o;
+       methodinfo        *m;
+       java_objectheader *ret;
 
-       return NewLocalRef(env, NULL);
+       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, ...)
 {
-       va_list  ap;
-       jboolean ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jboolean           b;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return b;
 }
 
 
 jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jboolean ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jboolean           b;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
 
-       return ret;
+       return b;
 }
 
 
-jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallBooleanMethodA");
+       java_objectheader *o;
+       methodinfo        *m;
+       jboolean           b;
 
-       return 0;
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
+
+       b = _Jv_jni_CallIntMethodA(o, o->vftbl, m, args);
+
+       return b;
 }
 
 
 jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
-       jbyte   ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jbyte              b;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BYTE);
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return b;
 
 }
 
 jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jbyte ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jbyte              b;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BYTE);
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       return ret;
+       b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
+
+       return b;
 }
 
 
@@ -1954,26 +2028,34 @@ jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args
 
 jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
-       jchar   ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jchar              c;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_CHAR);
+       c = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return c;
 }
 
 
 jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jchar ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jchar              c;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_CHAR);
+       c = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
 
-       return ret;
+       return c;
 }
 
 
@@ -1987,26 +2069,34 @@ jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args
 
 jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
-       jshort  ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jshort             s;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_SHORT);
+       s = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return s;
 }
 
 
 jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jshort ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jshort             s;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_SHORT);
+       s = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
 
-       return ret;
+       return s;
 }
 
 
@@ -2021,26 +2111,34 @@ jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *ar
 
 jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
-       jint    ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jint               i;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_INT);
+       i = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return i;
 }
 
 
 jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jint ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jint               i;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_INT);
+       i = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
 
-       return ret;
+       return i;
 }
 
 
@@ -2055,24 +2153,34 @@ jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 
 jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
-       jlong   ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jlong              l;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallLongMethod(obj, obj->vftbl, methodID, ap);
+       l = _Jv_jni_CallLongMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return l;
 }
 
 
 jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jlong ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jlong              l;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallLongMethod(obj, obj->vftbl, methodID, args);
+       l = _Jv_jni_CallLongMethod(o, o->vftbl, m, args);
 
-       return ret;
+       return l;
 }
 
 
@@ -2087,24 +2195,34 @@ jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args
 
 jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
-       jfloat  ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jfloat             f;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallFloatMethod(obj, obj->vftbl, methodID, ap);
+       f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return f;
 }
 
 
 jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jfloat ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jfloat             f;
 
-       ret = _Jv_jni_CallFloatMethod(obj, obj->vftbl, methodID, args);
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       return ret;
+       f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, args);
+
+       return f;
 }
 
 
@@ -2119,24 +2237,34 @@ jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *ar
 
 jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
-       jdouble ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+       jdouble            d;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallDoubleMethod(obj, obj->vftbl, methodID, ap);
+       d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return d;
 }
 
 
 jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       jdouble ret;
+       java_objectheader *o;
+       methodinfo        *m;
+       jdouble            d;
 
-       ret = _Jv_jni_CallDoubleMethod(obj, obj->vftbl, methodID, args);
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
-       return ret;
+       d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, args);
+
+       return d;
 }
 
 
@@ -2151,47 +2279,78 @@ jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *
 
 void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       va_list ap;
+       java_objectheader *o;
+       methodinfo        *m;
+       va_list            ap;
+
+       o = (java_objectheader *) obj;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       _Jv_jni_CallVoidMethod(obj, obj->vftbl, methodID, ap);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
        va_end(ap);
 }
 
 
 void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       _Jv_jni_CallVoidMethod(obj, obj->vftbl, methodID, 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)
 {
-       log_text("JNI-Call: CallVoidMethodA: IMPLEMENT ME!");
+       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 *ret;
+       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);
-       ret = _Jv_jni_CallObjectMethod(obj, clazz->vftbl, methodID, ap);
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return NewLocalRef(env, ret);
+       return NewLocalRef(env, r);
 }
 
 
 jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       java_objectheader* ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       java_objectheader *r;
 
-       ret = _Jv_jni_CallObjectMethod(obj, clazz->vftbl, methodID, args);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       return NewLocalRef(env, ret);
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
+
+       return NewLocalRef(env, r);
 }
 
 
@@ -2206,27 +2365,38 @@ jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, jmet
 
 jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list  ap;
-       jboolean ret;
+       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);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
-
+       return b;
 }
 
 
 jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jboolean ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jboolean           b;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return b;
 }
 
 
@@ -2240,26 +2410,38 @@ jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, jm
 
 jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jbyte   ret;
+       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);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BYTE);
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return b;
 }
 
 
-jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jbyte CallNonvirtualByteMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jbyte ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jbyte              b;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BYTE);
+       b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return b;
 }
 
 
@@ -2274,26 +2456,38 @@ jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodI
 
 jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jchar   ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jchar              ch;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_CHAR);
+       ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return ch;
 }
 
 
 jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jchar ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jchar              ch;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_CHAR);
+       ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return ch;
 }
 
 
@@ -2306,28 +2500,40 @@ jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodI
 
 
 
-jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jshort  ret;
+jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+{
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jshort             s;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_SHORT);
+       s = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return s;
 }
 
 
 jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jshort ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jshort             s;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_SHORT);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       s = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return s;
 }
 
 
@@ -2342,26 +2548,38 @@ jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz, jmetho
 
 jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jint    ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jint               i;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_INT);
+       i = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return i;
 }
 
 
 jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jint ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jint               i;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_INT);
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       i = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return i;
 }
 
 
@@ -2376,24 +2594,38 @@ jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID
 
 jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jlong   ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jlong              l;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallLongMethod(obj, clazz->vftbl, methodID, ap);
+       l = _Jv_jni_CallLongMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return l;
 }
 
 
 jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jlong ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jlong              l;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallLongMethod(obj, clazz->vftbl, methodID, args);
+       l = _Jv_jni_CallLongMethod(o, c->vftbl, m, args);
 
-       return 0;
+       return l;
 }
 
 
@@ -2408,31 +2640,43 @@ jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodI
 
 jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jfloat  ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jfloat             f;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallFloatMethod(obj, clazz->vftbl, methodID, ap);
+       f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return f;
 }
 
 
 jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jfloat ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jfloat             f;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallFloatMethod(obj, clazz->vftbl, methodID, args);
+       f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return f;
 }
 
 
 jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       STATISTICS(jniinvokation());
-
        log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!");
 
        return 0;
@@ -2442,24 +2686,38 @@ jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, jmetho
 
 jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jdouble ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+       jdouble            d;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallDoubleMethod(obj, clazz->vftbl, methodID, ap);
+       d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
+       return d;
 }
 
 
 jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       jdouble ret;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       jdouble            d;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallDoubleMethod(obj, clazz->vftbl, methodID, args);
+       d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return d;
 }
 
 
@@ -2474,23 +2732,46 @@ jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, jmet
 
 void CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+       va_list            ap;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       _Jv_jni_CallVoidMethod(obj, clazz->vftbl, methodID, ap);
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
        va_end(ap);
 }
 
 
 void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       _Jv_jni_CallVoidMethod(obj, clazz->vftbl, methodID, args);
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
 }
 
 
 void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
-{
-       log_text("JNI-Call: CallNonvirtualVoidMethodA: IMPLEMENT ME!");
+{      
+       java_objectheader *o;
+       classinfo         *c;
+       methodinfo        *m;
+
+       o = (java_objectheader *) obj;
+       c = (classinfo *) clazz;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
 }
 
 
@@ -2522,7 +2803,7 @@ jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name,
        if (!f)
                *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
 
-       return f;
+       return (jfieldID) f;
 }
 
 
@@ -2596,11 +2877,16 @@ jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID)
 
 jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       s4 i;
+       java_objectheader *o;
+       fieldinfo         *f;
+       s4                 i;
 
        STATISTICS(jniinvokation());
 
-       i = GET_FIELD(obj, s4, fieldID);
+       o = (java_objectheader *) obj;
+       f = (fieldinfo *) fieldID;
+
+       i = GET_FIELD(o, s4, f);
 
        return i;
 }
@@ -2766,63 +3052,78 @@ jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
                return NULL;
        }
 
-       return m;
+       return (jmethodID) m;
 }
 
 
 jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       java_objectheader *ret;
+       methodinfo        *m;
+       java_objectheader *o;
        va_list            ap;
 
+       m = (methodinfo *) methodID;
+
        va_start(ap, methodID);
-       ret = _Jv_jni_CallObjectMethod(NULL, NULL, methodID, ap);
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return NewLocalRef(env, ret);
+       return NewLocalRef(env, o);
 }
 
 
 jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       java_objectheader *ret;
+       methodinfo        *m;
+       java_objectheader *o;
 
-       ret = _Jv_jni_CallObjectMethod(NULL, NULL, methodID, args);
+       m = (methodinfo *) methodID;
 
-       return NewLocalRef(env, ret);
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
+
+       return NewLocalRef(env, o);
 }
 
 
 jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
-       log_text("JNI-Call: CallStaticObjectMethodA: IMPLEMENT ME!");
+       methodinfo        *m;
+       java_objectheader *o;
 
-       return NewLocalRef(env, NULL);
+       m = (methodinfo *) methodID;
+
+       o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
+
+       return NewLocalRef(env, o);
 }
 
 
 jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list  ap;
-       jboolean ret;
+       methodinfo *m;
+       va_list     ap;
+       jboolean    b;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return b;
 }
 
 
 jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jboolean ret;
+       methodinfo *m;
+       jboolean    b;
 
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       m = (methodinfo *) methodID;
 
-       return ret;
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return b;
 }
 
 
@@ -2836,24 +3137,30 @@ jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
 
 jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jbyte   ret;
+       methodinfo *m;
+       va_list     ap;
+       jbyte       b;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_BYTE);
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return b;
 }
 
 
 jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jbyte ret;
+       methodinfo *m;
+       jbyte       b;
 
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_BYTE);
+       m = (methodinfo *) methodID;
 
-       return ret;
+       b = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return b;
 }
 
 
@@ -2867,24 +3174,30 @@ jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalu
 
 jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jchar   ret;
+       methodinfo *m;
+       va_list     ap;
+       jchar       c;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_CHAR);
+       c = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return c;
 }
 
 
 jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jchar ret;
+       methodinfo *m;
+       jchar       c;
 
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_CHAR);
+       m = (methodinfo *) methodID;
 
-       return ret;
+       c = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return c;
 }
 
 
@@ -2898,25 +3211,30 @@ jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalu
 
 jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jshort  ret;
+       methodinfo *m;
+       va_list     ap;
+       jshort      s;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_SHORT);
+       s = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return s;
 }
 
 
 jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jshort ret;
+       methodinfo *m;
+       jshort      s;
 
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args,
-                                                               PRIMITIVETYPE_SHORT);
+       m = (methodinfo *) methodID;
 
-       return ret;
+       s = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
+
+       return s;
 }
 
 
@@ -2930,24 +3248,30 @@ jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jva
 
 jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jint    ret;
+       methodinfo *m;
+       va_list     ap;
+       jint        i;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_INT);
+       i = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return i;
 }
 
 
 jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jint ret;
+       methodinfo *m;
+       jint        i;
+
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_INT);
+       i = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
 
-       return ret;
+       return i;
 }
 
 
@@ -2961,25 +3285,31 @@ jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue
 
 jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jlong   ret;
+       methodinfo *m;
+       va_list     ap;
+       jlong       l;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallLongMethod(NULL, NULL, methodID, ap);
+       l = _Jv_jni_CallLongMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return l;
 }
 
 
 jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
                                                        va_list args)
 {
-       jlong ret;
+       methodinfo *m;
+       jlong       l;
        
-       ret = _Jv_jni_CallLongMethod(NULL, NULL, methodID, args);
+       m = (methodinfo *) methodID;
+
+       l = _Jv_jni_CallLongMethod(NULL, NULL, m, args);
 
-       return ret;
+       return l;
 }
 
 
@@ -2994,24 +3324,30 @@ jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalu
 
 jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jfloat  ret;
+       methodinfo *m;
+       va_list     ap;
+       jfloat      f;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallFloatMethod(NULL, NULL, methodID, ap);
+       f = _Jv_jni_CallFloatMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return f;
 }
 
 
 jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jfloat ret;
+       methodinfo *m;
+       jfloat      f;
+
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallFloatMethod(NULL, NULL, methodID, args);
+       f = _Jv_jni_CallFloatMethod(NULL, NULL, m, args);
 
-       return ret;
+       return f;
 }
 
 
@@ -3025,24 +3361,30 @@ jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jva
 
 jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
-       jdouble ret;
+       methodinfo *m;
+       va_list     ap;
+       jdouble     d;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallDoubleMethod(NULL, NULL, methodID, ap);
+       d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return d;
 }
 
 
 jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       jdouble ret;
+       methodinfo *m;
+       jdouble     d;
+
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallDoubleMethod(NULL, NULL, methodID, args);
+       d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, args);
 
-       return ret;
+       return d;
 }
 
 
@@ -3056,23 +3398,34 @@ jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, j
 
 void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       va_list ap;
+       methodinfo *m;
+       va_list     ap;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       _Jv_jni_CallVoidMethod(NULL, NULL, methodID, ap);
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
        va_end(ap);
 }
 
 
 void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       _Jv_jni_CallVoidMethod(NULL, NULL, methodID, args);
+       methodinfo *m;
+
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
 }
 
 
 void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue * args)
 {
-       log_text("JNI-Call: CallStaticVoidMethodA: IMPLEMENT ME!");
+       methodinfo *m;
+
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
 }
 
 
@@ -3089,7 +3442,7 @@ void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue
 
 jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
 {
-       jfieldID f;
+       fieldinfo *f;
 
        STATISTICS(jniinvokation());
 
@@ -3097,10 +3450,10 @@ jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const cha
                                                utf_new_char((char *) name),
                                                utf_new_char((char *) sig));
        
-       if (!f)
+       if (f == NULL)
                *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);
 
-       return f;
+       return (jfieldID) f;
 }
 
 
@@ -3113,109 +3466,163 @@ jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const cha
 
 jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return NULL;
 
-       return NewLocalRef(env, fieldID->value.a);
+       return NewLocalRef(env, f->value.a);
 }
 
 
 jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return false;
 
-       return fieldID->value.i;       
+       return f->value.i;
 }
 
 
 jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return 0;
 
-       return fieldID->value.i;       
+       return f->value.i;
 }
 
 
 jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return 0;
 
-       return fieldID->value.i;       
+       return f->value.i;
 }
 
 
 jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return 0;
 
-       return fieldID->value.i;       
+       return f->value.i;
 }
 
 
 jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return 0;
 
-       return fieldID->value.i;       
+       return f->value.i;
 }
 
 
 jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return 0;
 
-       return fieldID->value.l;
+       return f->value.l;
 }
 
 
 jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return 0.0;
 
-       return fieldID->value.f;
+       return f->value.f;
 }
 
 
 jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return 0.0;
 
-       return fieldID->value.d;
+       return f->value.d;
 }
 
 
@@ -3228,109 +3635,163 @@ jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID)
 
 void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.a = value;
+       f->value.a = value;
 }
 
 
 void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.i = value;
+       f->value.i = value;
 }
 
 
 void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.i = value;
+       f->value.i = value;
 }
 
 
 void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.i = value;
+       f->value.i = value;
 }
 
 
-void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
-{
+void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
+{
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.i = value;
+       f->value.i = value;
 }
 
 
 void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.i = value;
+       f->value.i = value;
 }
 
 
 void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.l = value;
+       f->value.l = value;
 }
 
 
 void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.f = value;
+       f->value.f = value;
 }
 
 
 void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value)
 {
+       classinfo *c;
+       fieldinfo *f;
+
        STATISTICS(jniinvokation());
 
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
+       c = (classinfo *) clazz;
+       f = (fieldinfo *) fieldID;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
                        return;
 
-       fieldID->value.d = value;
+       f->value.d = value;
 }
 
 
@@ -3558,9 +4019,13 @@ void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
 
 jsize GetArrayLength(JNIEnv *env, jarray array)
 {
+       java_arrayheader *a;
+
        STATISTICS(jniinvokation());
 
-       return array->size;
+       a = (java_arrayheader *) array;
+
+       return a->size;
 }
 
 
@@ -3599,18 +4064,21 @@ jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobj
 
 jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
 {
-    jobject o;
+       java_objectarray *oa;
+       jobject           o;
 
        STATISTICS(jniinvokation());
 
-       if (index >= array->header.size) {
+       oa = (java_objectarray *) array;
+
+       if (index >= oa->header.size) {
                exceptions_throw_arrayindexoutofboundsexception();
                return NULL;
        }
 
-       o = array->data[index];
-    
-    return NewLocalRef(env, o);
+       o = oa->data[index];
+
+       return NewLocalRef(env, o);
 }
 
 
@@ -3624,7 +4092,7 @@ void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject
        oa = (java_objectarray *) array;
        o  = (java_objectheader *) val;
 
-    if (index >= array->header.size) {
+       if (index >= oa->header.size) {
                exceptions_throw_arrayindexoutofboundsexception();
                return;
        }
@@ -3638,7 +4106,7 @@ void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject
                return;
        }
 
-       array->data[index] = val;
+       oa->data[index] = val;
 }
 
 
@@ -3787,90 +4255,125 @@ jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
 jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array,
                                                                  jboolean *isCopy)
 {
+       java_booleanarray *ba;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       ba = (java_booleanarray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       return ba->data;
 }
 
 
 jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy)
 {
+       java_bytearray *ba;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       ba = (java_bytearray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       return ba->data;
 }
 
 
 jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy)
 {
+       java_chararray *ca;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       ca = (java_chararray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       return ca->data;
 }
 
 
 jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy)
 {
+       java_shortarray *sa;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       sa = (java_shortarray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       return sa->data;
 }
 
 
 jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy)
 {
+       java_intarray *ia;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       ia = (java_intarray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       return ia->data;
 }
 
 
 jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy)
 {
+       java_longarray *la;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       la = (java_longarray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       /* We cast this one to prevent a compiler warning on 64-bit
+          systems since GNU Classpath typedef jlong to long long. */
+
+       return (jlong *) la->data;
 }
 
 
 jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy)
 {
+       java_floatarray *fa;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       fa = (java_floatarray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       return fa->data;
 }
 
 
 jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
                                                                jboolean *isCopy)
 {
+       java_doublearray *da;
+
        STATISTICS(jniinvokation());
 
-    if (isCopy)
+       da = (java_doublearray *) array;
+
+       if (isCopy)
                *isCopy = JNI_FALSE;
 
-    return array->data;
+       return da->data;
 }
 
 
@@ -3888,15 +4391,19 @@ jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
 void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
                                                                 jboolean *elems, jint mode)
 {
+       java_booleanarray *ba;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       ba = (java_booleanarray *) array;
+
+       if (elems != ba->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ba->data, elems, u1, ba->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ba->data, elems, u1, ba->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -3910,15 +4417,19 @@ void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
 void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems,
                                                          jint mode)
 {
+       java_bytearray *ba;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       ba = (java_bytearray *) array;
+
+       if (elems != ba->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ba->data, elems, s1, ba->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ba->data, elems, s1, ba->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -3932,15 +4443,19 @@ void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems,
 void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems,
                                                          jint mode)
 {
+       java_chararray *ca;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       ca = (java_chararray *) array;
+
+       if (elems != ca->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ca->data, elems, u2, ca->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ca->data, elems, u2, ca->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -3954,15 +4469,19 @@ void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems,
 void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems,
                                                           jint mode)
 {
+       java_shortarray *sa;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       sa = (java_shortarray *) array;
+
+       if (elems != sa->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(sa->data, elems, s2, sa->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(sa->data, elems, s2, sa->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -3976,15 +4495,19 @@ void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems,
 void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
                                                         jint mode)
 {
+       java_intarray *ia;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       ia = (java_intarray *) array;
+
+       if (elems != ia->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ia->data, elems, s4, ia->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(ia->data, elems, s4, ia->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -3998,15 +4521,22 @@ void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
 void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems,
                                                          jint mode)
 {
+       java_longarray *la;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       la = (java_longarray *) array;
+
+       /* We cast this one to prevent a compiler warning on 64-bit
+          systems since GNU Classpath typedef jlong to long long. */
+
+       if ((s8 *) elems != la->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(la->data, elems, s8, la->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(la->data, elems, s8, la->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -4020,15 +4550,19 @@ void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems,
 void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems,
                                                           jint mode)
 {
+       java_floatarray *fa;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       fa = (java_floatarray *) array;
+
+       if (elems != fa->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(fa->data, elems, float, fa->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(fa->data, elems, float, fa->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -4042,15 +4576,19 @@ void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems,
 void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
                                                                jdouble *elems, jint mode)
 {
+       java_doublearray *da;
+
        STATISTICS(jniinvokation());
 
-       if (elems != array->data) {
+       da = (java_doublearray *) array;
+
+       if (elems != da->data) {
                switch (mode) {
                case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(da->data, elems, double, da->header.size);
                        break;
                case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
+                       MCOPY(da->data, elems, double, da->header.size);
                        /* XXX TWISTI how should it be freed? */
                        break;
                case JNI_ABORT:
@@ -4071,96 +4609,128 @@ void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
 void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
                                                   jsize len, jboolean *buf)
 {
+       java_booleanarray *ba;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       ba = (java_booleanarray *) array;
+
+    if ((start < 0) || (len < 0) || (start + len > ba->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
     else
-               MCOPY(buf, &array->data[start], jboolean, len);
+               MCOPY(buf, &ba->data[start], u1, len);
 }
 
 
 void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
                                                jbyte *buf)
 {
+       java_bytearray *ba;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size) 
+       ba = (java_bytearray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ba->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jbyte, len);
+       else
+               MCOPY(buf, &ba->data[start], s1, len);
 }
 
 
 void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
                                                jchar *buf)
 {
+       java_chararray *ca;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       ca = (java_chararray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ca->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jchar, len);
+       else
+               MCOPY(buf, &ca->data[start], u2, len);
 }
 
 
 void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
                                                 jsize len, jshort *buf)
 {
+       java_shortarray *sa;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       sa = (java_shortarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > sa->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else       
-               MCOPY(buf, &array->data[start], jshort, len);
+       else    
+               MCOPY(buf, &sa->data[start], s2, len);
 }
 
 
 void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
                                           jint *buf)
 {
+       java_intarray *ia;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       ia = (java_intarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ia->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jint, len);
+       else
+               MCOPY(buf, &ia->data[start], s4, len);
 }
 
 
 void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len,
                                                jlong *buf)
 {
+       java_longarray *la;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       la = (java_longarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > la->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jlong, len);
+       else
+               MCOPY(buf, &la->data[start], s8, len);
 }
 
 
 void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
                                                 jsize len, jfloat *buf)
 {
+       java_floatarray *fa;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       fa = (java_floatarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > fa->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jfloat, len);
+       else
+               MCOPY(buf, &fa->data[start], float, len);
 }
 
 
 void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
                                                  jsize len, jdouble *buf)
 {
+       java_doublearray *da;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start+len>array->header.size)
+       da = (java_doublearray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > da->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jdouble, len);
+       else
+               MCOPY(buf, &da->data[start], double, len);
 }
 
 
@@ -4174,96 +4744,128 @@ void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
 void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
                                                   jsize len, jboolean *buf)
 {
+       java_booleanarray *ba;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       ba = (java_booleanarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ba->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jboolean, len);
+       else
+               MCOPY(&ba->data[start], buf, u1, len);
 }
 
 
 void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
                                                jbyte *buf)
 {
+       java_bytearray *ba;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       ba = (java_bytearray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ba->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jbyte, len);
+       else
+               MCOPY(&ba->data[start], buf, s1, len);
 }
 
 
 void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
                                                jchar *buf)
 {
+       java_chararray *ca;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       ca = (java_chararray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ca->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jchar, len);
+       else
+               MCOPY(&ca->data[start], buf, u2, len);
 }
 
 
 void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
                                                 jsize len, jshort *buf)
 {
+       java_shortarray *sa;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       sa = (java_shortarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > sa->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jshort, len);
+       else
+               MCOPY(&sa->data[start], buf, s2, len);
 }
 
 
 void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
                                           jint *buf)
 {
+       java_intarray *ia;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       ia = (java_intarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > ia->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jint, len);
+       else
+               MCOPY(&ia->data[start], buf, s4, len);
 }
 
 
 void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len,
                                                jlong *buf)
 {
+       java_longarray *la;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       la = (java_longarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > la->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jlong, len);
+       else
+               MCOPY(&la->data[start], buf, s8, len);
 }
 
 
 void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
                                                 jsize len, jfloat *buf)
 {
+       java_floatarray *fa;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       fa = (java_floatarray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > fa->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jfloat, len);
+       else
+               MCOPY(&fa->data[start], buf, float, len);
 }
 
 
 void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
                                                  jsize len, jdouble *buf)
 {
+       java_doublearray *da;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
+       da = (java_doublearray *) array;
+
+       if ((start < 0) || (len < 0) || (start + len > da->header.size))
                exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jdouble, len);
+       else
+               MCOPY(&da->data[start], buf, double, len);
 }
 
 
@@ -4381,17 +4983,38 @@ jint GetJavaVM(JNIEnv *env, JavaVM **vm)
 {
        STATISTICS(jniinvokation());
 
-    *vm = &ptr_jvm;
+    *vm = (JavaVM *) _Jv_jvm;
 
        return 0;
 }
 
 
+/* GetStringRegion *************************************************************
+
+   Copies len number of Unicode characters beginning at offset start
+   to the given buffer buf.
+
+   Throws StringIndexOutOfBoundsException on index overflow.
+
+*******************************************************************************/
+
 void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
 {
+       java_lang_String *s;
+       java_chararray   *ca;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: GetStringRegion: IMPLEMENT ME!");
+       s  = (java_lang_String *) str;
+       ca = s->value;
+
+       if ((start < 0) || (len < 0) || (start > s->count) ||
+               (start + len > s->count)) {
+               exceptions_throw_stringindexoutofboundsexception();
+               return;
+       }
+
+       MCOPY(buf, &ca->data[start], u2, len);
 }
 
 
@@ -4489,46 +5112,64 @@ void DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
 
 *******************************************************************************/
     
-jobject NewGlobalRef(JNIEnv* env, jobject lobj)
+jobject NewGlobalRef(JNIEnv* env, jobject obj)
 {
-       java_objectheader *o;
-       java_lang_Integer *refcount;
-       java_objectheader *newval;
+       hashtable_global_ref_entry *gre;
+       u4   key;                           /* hashkey                            */
+       u4   slot;                          /* slot in hashtable                  */
 
        STATISTICS(jniinvokation());
 
 #if defined(USE_THREADS)
-       builtin_monitorenter(*global_ref_table);
+       builtin_monitorenter(hashtable_global_ref->header);
 #endif
+
+       /* normally addresses are aligned to 4, 8 or 16 bytes */
+
+       key  = ((u4) (ptrint) obj) >> 4;           /* align to 16-byte boundaries */
+       slot = key & (hashtable_global_ref->size - 1);
+       gre  = hashtable_global_ref->ptr[slot];
        
-       ASM_CALLJAVAFUNCTION_ADR(o, getmid, *global_ref_table, lobj, NULL, NULL);
+       /* search external hash chain for the entry */
 
-       refcount = (java_lang_Integer *) o;
+       while (gre) {
+               if (gre->o == obj) {
+                       /* global object found, increment the reference */
 
-       if (refcount == NULL) {
-               newval = native_new_and_init_int(class_java_lang_Integer, 1);
+                       gre->refs++;
 
-               if (newval == NULL) {
 #if defined(USE_THREADS)
-                       builtin_monitorexit(*global_ref_table);
+                       builtin_monitorexit(hashtable_global_ref->header);
 #endif
-                       return NULL;
+
+                       return obj;
                }
 
-               ASM_CALLJAVAFUNCTION(putmid, *global_ref_table, lobj, newval, NULL);
+               gre = gre->hashlink;                /* next element in external chain */
+       }
 
-       } else {
-               /* we can access the object itself, as we are in a
-           synchronized section */
+       /* global ref not found, create a new one */
 
-               refcount->value++;
-       }
+       gre = NEW(hashtable_global_ref_entry);
+
+       gre->o    = obj;
+       gre->refs = 1;
+
+       /* insert entry into hashtable */
+
+       gre->hashlink = hashtable_global_ref->ptr[slot];
+
+       hashtable_global_ref->ptr[slot] = gre;
+
+       /* update number of hashtable-entries */
+
+       hashtable_global_ref->entries++;
 
 #if defined(USE_THREADS)
-       builtin_monitorexit(*global_ref_table);
+       builtin_monitorexit(hashtable_global_ref->header);
 #endif
 
-       return lobj;
+       return obj;
 }
 
 
@@ -4540,44 +5181,63 @@ jobject NewGlobalRef(JNIEnv* env, jobject lobj)
 
 void DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 {
-       java_objectheader *o;
-       java_lang_Integer *refcount;
-       s4                 val;
+       hashtable_global_ref_entry *gre;
+       hashtable_global_ref_entry *prevgre;
+       u4   key;                           /* hashkey                            */
+       u4   slot;                          /* slot in hashtable                  */
 
        STATISTICS(jniinvokation());
 
 #if defined(USE_THREADS)
-       builtin_monitorenter(*global_ref_table);
+       builtin_monitorenter(hashtable_global_ref->header);
 #endif
 
-       ASM_CALLJAVAFUNCTION_ADR(o, getmid, *global_ref_table, globalRef, NULL,
-                                                        NULL);
+       /* normally addresses are aligned to 4, 8 or 16 bytes */
 
-       refcount = (java_lang_Integer *) o;
+       key  = ((u4) (ptrint) globalRef) >> 4;     /* align to 16-byte boundaries */
+       slot = key & (hashtable_global_ref->size - 1);
+       gre  = hashtable_global_ref->ptr[slot];
 
-       if (refcount == NULL) {
-               log_text("JNI-DeleteGlobalRef: unable to find global reference");
-               return;
-       }
+       /* initialize prevgre */
 
-       /* we can access the object itself, as we are in a synchronized
-          section */
+       prevgre = NULL;
 
-       val = refcount->value - 1;
+       /* search external hash chain for the entry */
 
-       if (val == 0) {
-               ASM_CALLJAVAFUNCTION(removemid, *global_ref_table, refcount, NULL,
-                                                        NULL);
+       while (gre) {
+               if (gre->o == globalRef) {
+                       /* global object found, decrement the reference count */
 
-       } else {
-               /* we do not create a new object, but set the new value into
-           the old one */
+                       gre->refs--;
+
+                       /* if reference count is 0, remove the entry */
+
+                       if (gre->refs == 0) {
+                               /* special handling if it's the first in the chain */
+
+                               if (prevgre == NULL)
+                                       hashtable_global_ref->ptr[slot] = gre->hashlink;
+                               else
+                                       prevgre->hashlink = gre->hashlink;
+
+                               FREE(gre, hashtable_global_ref_entry);
+                       }
+
+#if defined(USE_THREADS)
+                       builtin_monitorexit(hashtable_global_ref->header);
+#endif
+
+                       return;
+               }
 
-               refcount->value = val;
+               prevgre = gre;                    /* save current pointer for removal */
+               gre     = gre->hashlink;            /* next element in external chain */
        }
 
+       log_println("JNI-DeleteGlobalRef: global reference not found");
+
 #if defined(USE_THREADS)
-       builtin_monitorexit(*global_ref_table);
+       builtin_monitorexit(hashtable_global_ref->header);
 #endif
 }
 
@@ -4636,7 +5296,7 @@ jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
        /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
 
        nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite,
-                                                        dbbirw_init, NULL, paddress,
+                                                        (jmethodID) dbbirw_init, NULL, paddress,
                                                         (jint) capacity, (jint) capacity, (jint) 0);
 
        /* add local reference and return the value */
@@ -4700,13 +5360,23 @@ jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf)
 }
 
 
+/* 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)
 {
+       s4 status;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: DestroyJavaVM: IMPLEMENT ME!");
+    status = vm_destroy(vm);
 
-       return 0;
+       return status;
 }
 
 
@@ -4736,7 +5406,7 @@ jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args)
        #error "No idea how to implement that. Perhaps Stefan knows"
 #endif
 
-       *env = &ptr_env;
+       *env = _Jv_env;
 
        return 0;
 }
@@ -4775,7 +5445,7 @@ jint GetEnv(JavaVM *vm, void **env, jint version)
 
        if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) ||
                (version == JNI_VERSION_1_4)) {
-               *env = &ptr_env;
+               *env = _Jv_env;
 
                return JNI_OK;
        }
@@ -4808,7 +5478,7 @@ jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
 
 /* JNI invocation table *******************************************************/
 
-const struct JNIInvokeInterface JNI_JavaVMTable = {
+const struct JNIInvokeInterface _Jv_JNIInvokeInterface = {
        NULL,
        NULL,
        NULL,
@@ -4823,274 +5493,274 @@ const struct JNIInvokeInterface JNI_JavaVMTable = {
 
 /* JNI function table *********************************************************/
 
-struct JNINativeInterface JNI_JNIEnvTable = {
+struct JNINativeInterface _Jv_JNINativeInterface = {
        NULL,
        NULL,
        NULL,
        NULL,    
-       &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,
+       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
 };
 
 
@@ -5104,12 +5774,28 @@ struct JNINativeInterface JNI_JNIEnvTable = {
 
 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
 {
-       JDK1_1InitArgs *_vm_args = (JDK1_1InitArgs *) 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;
 }
 
@@ -5138,16 +5824,61 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 
 *******************************************************************************/
 
-jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args)
+jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
 {
-       const struct JNIInvokeInterface *vm;
-       struct JNINativeInterface *env;
+       JavaVMInitArgs *_vm_args;
+       _Jv_JNIEnv     *env;
+       _Jv_JavaVM     *jvm;
+       localref_table *lrt;
+
+       /* get the arguments for the new JVM */
+
+       _vm_args = (JavaVMInitArgs *) vm_args;
+
+       /* get the VM and Env tables (must be set before vm_create) */
+
+       env = NEW(_Jv_JNIEnv);
+       env->env = &_Jv_JNINativeInterface;
+
+       /* XXX Set the global variable.  Maybe we should do that differently. */
+
+       _Jv_env = env;
+
+
+       /* create and fill a JavaVM structure */
+
+       jvm = NEW(_Jv_JavaVM);
+       jvm->functions = &_Jv_JNIInvokeInterface;
+
+       /* XXX Set the global variable.  Maybe we should do that differently. */
+       /* XXX JVMTI Agents needs a JavaVM  */
+       _Jv_jvm = jvm;
+
+
+       /* actually create the JVM */
+
+       if (!vm_create(_vm_args))
+               return -1;
+
+       /* setup the local ref table (must be created after vm_create) */
+
+       lrt = GCNEW(localref_table);
+
+       lrt->capacity    = LOCALREFTABLE_CAPACITY;
+       lrt->used        = 0;
+       lrt->localframes = 1;
+       lrt->prev        = LOCALREFTABLE;
+
+       /* clear the references array (memset is faster then a for-loop) */
+
+       MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
+
+       LOCALREFTABLE = lrt;
 
-       vm = &JNI_JavaVMTable;
-       env = &JNI_JNIEnvTable;
+       /* now return the values */
 
-       *p_vm = (JavaVM *) vm;
-       *p_env = (JNIEnv *) env;
+       *p_vm  = (JavaVM *) jvm;
+       *p_env = (void *) env;
 
        return 0;
 }
@@ -5164,4 +5895,5 @@ jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */