* Removed all Id tags.
[cacao.git] / src / native / jni.c
index 5406975df12ce3b780097b940b6fc5db6d0bff99..a28cd68df14fa8481bda0f7a7d8034280a0b197d 100644 (file)
@@ -1,6 +1,6 @@
 /* src/native/jni.c - implementation of the Java Native Interface functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Rainhard Grafl
-            Roman Obermaisser
-
-   Changes: Joseph Wenninger
-            Martin Platter
-            Christian Thalinger
-
-   $Id: jni.c 4521 2006-02-14 20:10:58Z edwin $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <stdint.h>
 #include <string.h>
 
 #include "vm/types.h"
 
-#include "mm/boehm.h"
+#include "mm/gc-common.h"
 #include "mm/memory.h"
+
 #include "native/jni.h"
+#include "native/llni.h"
+#include "native/localref.h"
 #include "native/native.h"
 
-#include "native/include/gnu_classpath_Pointer.h"
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_GNU)
+#  include "native/include/gnu_classpath_Pointer.h"
 
-#if SIZEOF_VOID_P == 8
-# include "native/include/gnu_classpath_Pointer64.h"
-#else
-# include "native/include/gnu_classpath_Pointer32.h"
+#  if SIZEOF_VOID_P == 8
+#   include "native/include/gnu_classpath_Pointer64.h"
+#  else
+#   include "native/include/gnu_classpath_Pointer32.h"
+#  endif
+# endif
 #endif
 
 #include "native/include/java_lang_Object.h"
 #include "native/include/java_lang_Long.h"
 #include "native/include/java_lang_Float.h"
 #include "native/include/java_lang_Double.h"
+#include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
-#include "native/include/java_lang_reflect_Method.h"
-#include "native/include/java_lang_reflect_Constructor.h"
-#include "native/include/java_lang_reflect_Field.h"
 
-#include "native/include/java_lang_Class.h" /* for java_lang_VMClass.h */
-#include "native/include/java_lang_VMClass.h"
-#include "native/include/java_lang_VMClassLoader.h"
-#include "native/include/java_nio_Buffer.h"
-#include "native/include/java_nio_DirectByteBufferImpl.h"
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_SUN)
+#  include "native/include/java_nio_ByteBuffer.h"       /* required by j.l.CL */
+# endif
+
+# include "native/include/java_lang_ClassLoader.h"
+
+# include "native/include/java_lang_reflect_Constructor.h"
+# include "native/include/java_lang_reflect_Field.h"
+# include "native/include/java_lang_reflect_Method.h"
+
+# include "native/include/java_nio_Buffer.h"
+
+# if defined(WITH_CLASSPATH_GNU)
+#  include "native/include/java_nio_DirectByteBufferImpl.h"
+# endif
+#endif
 
 #if defined(ENABLE_JVMTI)
-# include "native/jvmti/jvmti.h"
+# include "native/jvmti/cacaodbg.h"
 #endif
 
-#if defined(USE_THREADS)
-# if defined(NATIVE_THREADS)
-#  include "threads/native/threads.h"
-# else
-#  include "threads/green/threads.h"
-# endif
+#include "native/vm/java_lang_Class.h"
+
+#if defined(ENABLE_JAVASE)
+# include "native/vm/java_lang_ClassLoader.h"
+# include "native/vm/reflect.h"
 #endif
 
+#include "threads/lock-common.h"
+#include "threads/threads-common.h"
+
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/initialize.h"
-#include "vm/loader.h"
-#include "vm/options.h"
+#include "vm/primitive.h"
 #include "vm/resolve.h"
-#include "vm/statistics.h"
 #include "vm/stringlocal.h"
+#include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
-#include "vm/statistics.h"
+#include "vm/jit/stacktrace.h"
 
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vmcore/statistics.h"
 
-/* XXX TWISTI hack: define it extern so they can be found in this file */
 
-extern const struct JNIInvokeInterface JNI_JavaVMTable;
-extern struct JNINativeInterface JNI_JNIEnvTable;
-
-/* pointers to VM and the environment needed by GetJavaVM and GetEnv */
-
-static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable;
-void *ptr_env = (void*) &JNI_JNIEnvTable;
+/* debug **********************************************************************/
 
+#if !defined(NDEBUG)
+# define TRACEJNICALLS(format, ...) \
+    do { \
+        if (opt_TraceJNICalls) { \
+            log_println((format), __VA_ARGS__); \
+        } \
+    } while (0)
+#else
+# define TRACEJNICALLS(format, ...)
+#endif
 
-#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 ********************************************************/
 
+#if defined(ENABLE_JAVASE)
 static classinfo *class_java_nio_Buffer;
 static classinfo *class_java_nio_DirectByteBufferImpl;
 static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
-#if SIZEOF_VOID_P == 8
+
+# if defined(WITH_CLASSPATH_GNU)
+#  if SIZEOF_VOID_P == 8
 static classinfo *class_gnu_classpath_Pointer64;
-#else
+#  else
 static classinfo *class_gnu_classpath_Pointer32;
-#endif
+#  endif
+# endif
 
 static methodinfo *dbbirw_init;
-
-
-/* local reference table ******************************************************/
-
-#if !defined(USE_THREADS)
-localref_table *_no_threads_localref_table;
 #endif
 
 
 /* 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 *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
 
-#define GET_FIELD(obj,type,var) \
-    *((type *) ((ptrint) (obj) + (ptrint) (var)->offset))
+#define GET_FIELD(o,type,f) \
+    *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset)))
 
 
 /* some forward declarations **************************************************/
 
-jobject NewLocalRef(JNIEnv *env, jobject ref);
+jobject _Jv_JNI_NewLocalRef(JNIEnv *env, jobject ref);
+jint _Jv_JNI_EnsureLocalCapacity(JNIEnv* env, jint capacity);
 
 
 /* jni_init ********************************************************************
@@ -172,31 +184,14 @@ jobject NewLocalRef(JNIEnv *env, jobject ref);
 
 bool jni_init(void)
 {
-       /* initalize global reference table */
+       /* create global ref hashtable */
 
-       if (!(ihmclass =
-                 load_class_bootstrap(utf_new_char("java/util/IdentityHashMap"))))
-               return false;
-
-       global_ref_table = GCNEW(jobject);
-
-       if (!(*global_ref_table = native_new_and_init(ihmclass)))
-               return false;
-
-       if (!(getmid = class_resolvemethod(ihmclass, utf_get,
-                                                                          utf_java_lang_Object__java_lang_Object)))
-               return false;
-
-       if (!(putmid = class_resolvemethod(ihmclass, utf_put,
-                                                                          utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"))))
-               return false;
+       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);
 
 
+#if defined(ENABLE_JAVASE)
        /* direct buffer stuff */
 
        if (!(class_java_nio_Buffer =
@@ -204,6 +199,7 @@ bool jni_init(void)
                !link_class(class_java_nio_Buffer))
                return false;
 
+# if defined(WITH_CLASSPATH_GNU)
        if (!(class_java_nio_DirectByteBufferImpl =
                  load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
                !link_class(class_java_nio_DirectByteBufferImpl))
@@ -220,278 +216,139 @@ bool jni_init(void)
                                                        utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
                return false;
 
-#if SIZEOF_VOID_P == 8
+#  if SIZEOF_VOID_P == 8
        if (!(class_gnu_classpath_Pointer64 =
                  load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
                !link_class(class_gnu_classpath_Pointer64))
                return false;
-#else
+#  else
        if (!(class_gnu_classpath_Pointer32 =
                  load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
                !link_class(class_gnu_classpath_Pointer32))
                return false;
-#endif
+#  endif
+# endif
+#endif /* defined(ENABLE_JAVASE) */
 
        return true;
 }
 
 
-static void fill_callblock_from_vargs(void *obj, methoddesc *descr,
-                                                                         jni_callblock blk[], va_list data,
-                                                                         s4 rettype)
+/* _Jv_jni_CallObjectMethod ****************************************************
+
+   Internal function to call Java Object methods.
+
+*******************************************************************************/
+
+static java_handle_t *_Jv_jni_CallObjectMethod(java_handle_t *o,
+                                                                                          vftbl_t *vftbl,
+                                                                                          methodinfo *m, va_list ap)
 {
-       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;
+       methodinfo    *resm;
+       java_handle_t *ro;
 
-               case PRIMITIVETYPE_DOUBLE:
-                       blk[i].itemtype = TYPE_DBL;
-                       *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
-                       break;
+       STATISTICS(jniinvokation());
 
-               case TYPE_ADR: 
-                       blk[i].itemtype = TYPE_ADR;
-                       blk[i].item = PTR_TO_ITEM(va_arg(data, void*));
-                       break;
-               }
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
        }
 
-       /* The standard doesn't say anything about return value checking,
-          but it appears to be useful. */
+       /* 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 (rettype != descr->returntype.decltype)
-               log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
-}
+               if (o != NULL)
+                       o = NULL;
 
+               /* for convenience */
 
-/* XXX it could be considered if we should do typechecking here in the future */
+               resm = m;
 
-static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
-                                                                                       jni_callblock blk[],
-                                                                                       java_objectarray *params)
-{
-    jobject    param;
-       s4         paramcount;
-       typedesc  *paramtypes;
-       classinfo *c;
-    s4         i;
-       s4         j;
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       paramcount = descr->paramcount;
-       paramtypes = descr->paramtypes;
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       /* if method is non-static fill first block and skip `this' pointer */
+       STATISTICS(jnicallXmethodnvokation());
 
-       i = 0;
+       ro = vm_call_method_valist(resm, o, ap);
 
-       if (obj) {
-               /* this pointer */
-               blk[0].itemtype = TYPE_ADR;
-               blk[0].item = PTR_TO_ITEM(obj);
+       return ro;
+}
 
-               paramtypes++;
-               paramcount--;
-               i++;
-       }
 
-       for (j = 0; j < paramcount; i++, j++, paramtypes++) {
-               switch (paramtypes->type) {
-               /* primitive types */
-               case TYPE_INT:
-               case TYPE_LONG:
-               case TYPE_FLOAT:
-               case TYPE_DOUBLE:
-                       param = params->data[j];
-                       if (!param)
-                               goto illegal_arg;
+/* _Jv_jni_CallObjectMethodA ***************************************************
 
-                       /* internally used data type */
-                       blk[i].itemtype = paramtypes->type;
+   Internal function to call Java Object methods.
 
-                       /* convert the value according to its declared type */
+*******************************************************************************/
 
-                       c = param->vftbl->class;
+static java_handle_t *_Jv_jni_CallObjectMethodA(java_handle_t *o,
+                                                                                               vftbl_t *vftbl,
+                                                                                               methodinfo *m,
+                                                                                               const jvalue *args)
+{
+       methodinfo    *resm;
+       java_handle_t *ro;
 
-                       switch (paramtypes->decltype) {
-                       case PRIMITIVETYPE_BOOLEAN:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Boolean *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
+       STATISTICS(jniinvokation());
 
-                       case PRIMITIVETYPE_BYTE:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
 
-                       case PRIMITIVETYPE_CHAR:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Character *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_SHORT:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_INT:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_LONG:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Long *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-                       case PRIMITIVETYPE_FLOAT:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_DOUBLE:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       *((jdouble *) (&blk[i].item)) = (jdouble) ((java_lang_Double *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
-                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-                       default:
-                               goto illegal_arg;
-                       } /* end declared type switch */
-                       break;
-               
-                       case TYPE_ADDRESS:
-                               if (!resolve_class_from_typedesc(paramtypes, true, true, &c))
-                                       return false;
+               if (o != NULL)
+                       o = NULL;
 
-                               if (params->data[j] != 0) {
-                                       if (paramtypes->arraydim > 0) {
-                                               if (!builtin_arrayinstanceof(params->data[j], c))
-                                                       goto illegal_arg;
+               /* for convenience */
 
-                                       } else {
-                                               if (!builtin_instanceof(params->data[j], c))
-                                                       goto illegal_arg;
-                                       }
-                               }
-                               blk[i].itemtype = TYPE_ADR;
-                               blk[i].item = PTR_TO_ITEM(params->data[j]);
-                               break;                  
+               resm = m;
 
-                       default:
-                               goto illegal_arg;
-               } /* end param type switch */
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       } /* end param loop */
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-/*     if (rettype) */
-/*             *rettype = descr->returntype.decltype; */
+       STATISTICS(jnicallXmethodnvokation());
 
-       return true;
+       ro = vm_call_method_jvalue(resm, o, args);
 
-illegal_arg:
-       exceptions_throw_illegalargumentexception();
-       return false;
+       return ro;
 }
 
 
-/* _Jv_jni_CallObjectMethod ****************************************************
+/* _Jv_jni_CallIntMethod *******************************************************
 
-   Internal function to call Java Object methods.
+   Internal function to call Java integer class methods (boolean,
+   byte, char, short, int).
 
 *******************************************************************************/
 
-static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
-                                                                                                  vftbl_t *vftbl,
-                                                                                                  methodinfo *m, va_list ap)
+static jint _Jv_jni_CallIntMethod(java_handle_t *o, vftbl_t *vftbl,
+                                                                 methodinfo *m, va_list ap)
 {
-       methodinfo        *resm;
-       s4                 paramcount;
-       jni_callblock     *blk;
-       java_objectheader *ret;
-       s4                 dumpsize;
+       methodinfo *resm;
+       jint        i;
 
        STATISTICS(jniinvokation());
 
        if (m == NULL) {
                exceptions_throw_nullpointerexception();
-               return NULL;
+               return 0;
        }
-
+        
        /* Class initialization is done by the JIT compiler.  This is ok
           since a static method always belongs to the declaring class. */
 
@@ -511,45 +368,26 @@ static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
                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, TYPE_ADR);
-
        STATISTICS(jnicallXmethodnvokation());
 
-       ASM_CALLJAVAFUNCTION2_ADR(ret, resm, paramcount,
-                                                         paramcount * sizeof(jni_callblock),
-                                                         blk);
-
-       /* release dump area */
-
-       dump_release(dumpsize);
+       i = vm_call_method_int_valist(resm, o, ap);
 
-       return ret;
+       return i;
 }
 
 
-/* _Jv_jni_CallIntMethod *******************************************************
+/* _Jv_jni_CallIntMethod******************************************************
 
    Internal function to call Java integer class methods (boolean,
    byte, char, short, int).
 
 *******************************************************************************/
 
-static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
-                                                                 methodinfo *m, va_list ap, s4 type)
+static jint _Jv_jni_CallIntMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                  methodinfo *m, const jvalue *args)
 {
-       methodinfo    *resm;
-       s4             paramcount;
-       jni_callblock *blk;
-       jint           ret;
-       s4             dumpsize;
+       methodinfo *resm;
+       jint        i;
 
        STATISTICS(jniinvokation());
 
@@ -577,27 +415,11 @@ static jint _Jv_jni_CallIntMethod(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, type);
-
        STATISTICS(jnicallXmethodnvokation());
 
-       ASM_CALLJAVAFUNCTION2_INT(ret, resm, paramcount,
-                                                         paramcount * sizeof(jni_callblock),
-                                                         blk);
-
-       /* release dump area */
-
-       dump_release(dumpsize);
+       i = vm_call_method_int_jvalue(resm, o, args);
 
-       return ret;
+       return i;
 }
 
 
@@ -607,14 +429,11 @@ static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
 
 *******************************************************************************/
 
-static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
+static jlong _Jv_jni_CallLongMethod(java_handle_t *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 +461,57 @@ static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
+       STATISTICS(jnicallXmethodnvokation());
 
-       dumpsize = dump_size();
+       l = vm_call_method_long_valist(resm, o, ap);
 
-       paramcount = resm->parseddesc->paramcount;
+       return l;
+}
 
-       blk = DMNEW(jni_callblock, paramcount);
 
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, PRIMITIVETYPE_LONG);
+/* _Jv_jni_CallLongMethodA *****************************************************
 
-       STATISTICS(jnicallXmethodnvokation());
+   Internal function to call Java long methods.
 
-       ASM_CALLJAVAFUNCTION2_LONG(ret, resm, paramcount,
-                                                          paramcount * sizeof(jni_callblock),
-                                                          blk);
+*******************************************************************************/
 
-       /* release dump area */
+static jlong _Jv_jni_CallLongMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                        methodinfo *m, const jvalue *args)
+{
+       methodinfo *resm;
+       jlong       l;
 
-       dump_release(dumpsize);
+       STATISTICS(jniinvokation());
 
-       return ret;
+       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. */
+
+               resm = method_vftbl_lookup(vftbl, m);
+       }
+
+       STATISTICS(jnicallXmethodnvokation());
+
+       l = vm_call_method_long_jvalue(resm, o, args);
+
+       return l;
 }
 
 
@@ -672,14 +521,11 @@ static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
 
 *******************************************************************************/
 
-static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
+static jfloat _Jv_jni_CallFloatMethod(java_handle_t *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 +546,50 @@ static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
+       STATISTICS(jnicallXmethodnvokation());
 
-       dumpsize = dump_size();
+       f = vm_call_method_float_valist(resm, o, ap);
 
-       paramcount = resm->parseddesc->paramcount;
+       return f;
+}
 
-       blk = DMNEW(jni_callblock, paramcount);
 
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap,
-                                                         PRIMITIVETYPE_FLOAT);
+/* _Jv_jni_CallFloatMethodA ****************************************************
 
-       STATISTICS(jnicallXmethodnvokation());
+   Internal function to call Java float methods.
 
-       ASM_CALLJAVAFUNCTION2_FLOAT(ret, resm, paramcount,
-                                                               paramcount * sizeof(jni_callblock),
-                                                               blk);
+*******************************************************************************/
 
-       /* release dump area */
+static jfloat _Jv_jni_CallFloatMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                          methodinfo *m, const jvalue *args)
+{
+       methodinfo *resm;
+       jfloat      f;
 
-       dump_release(dumpsize);
+       /* 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;
 
-       return ret;
+               /* for convenience */
+
+               resm = m;
+       }
+       else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
+       }
+
+       STATISTICS(jnicallXmethodnvokation());
+
+       f = vm_call_method_float_jvalue(resm, o, args);
+
+       return f;
 }
 
 
@@ -731,14 +599,11 @@ static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
 
 *******************************************************************************/
 
-static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
+static jdouble _Jv_jni_CallDoubleMethod(java_handle_t *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 +624,46 @@ static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
                resm = method_vftbl_lookup(vftbl, m);
        }
 
-       /* mark start of dump memory area */
+       d = vm_call_method_double_valist(resm, o, ap);
 
-       dumpsize = dump_size();
+       return d;
+}
 
-       paramcount = resm->parseddesc->paramcount;
 
-       blk = DMNEW(jni_callblock, paramcount);
+/* _Jv_jni_CallDoubleMethodA ***************************************************
 
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap,
-                                                         PRIMITIVETYPE_DOUBLE);
+   Internal function to call Java double methods.
 
-       STATISTICS(jnicallXmethodnvokation());
+*******************************************************************************/
 
-       ASM_CALLJAVAFUNCTION2_DOUBLE(ret, resm, paramcount,
-                                                                paramcount * sizeof(jni_callblock),
-                                                                blk);
+static jdouble _Jv_jni_CallDoubleMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                                methodinfo *m, const jvalue *args)
+{
+       methodinfo *resm;
+       jdouble     d;
 
-       /* release dump area */
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       dump_release(dumpsize);
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
+
+               if (o != NULL)
+                       o = NULL;
 
-       return ret;
+               /* for convenience */
+
+               resm = m;
+       }
+       else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
+       }
+
+       d = vm_call_method_double_jvalue(resm, o, args);
+
+       return d;
 }
 
 
@@ -790,13 +673,10 @@ static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
 
 *******************************************************************************/
 
-static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl,
+static void _Jv_jni_CallVoidMethod(java_handle_t *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,282 +702,202 @@ 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());
 
-       dumpsize = dump_size();
-
-       paramcount = resm->parseddesc->paramcount;
-
-       blk = DMNEW(jni_callblock, paramcount);
-
-       fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, TYPE_VOID);
-
-       STATISTICS(jnicallXmethodnvokation());
-
-       ASM_CALLJAVAFUNCTION2(resm, paramcount,
-                                                 paramcount * sizeof(jni_callblock),
-                                                 blk);
-
-       /* release dump area */
-
-       dump_release(dumpsize);
+       (void) vm_call_method_valist(resm, o, ap);
 }
 
 
-/* _Jv_jni_invokeNative ********************************************************
+/* _Jv_jni_CallVoidMethodA *****************************************************
 
-   XXX
+   Internal function to call Java void methods.
 
 *******************************************************************************/
 
-jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
-                                                         java_objectarray *params)
-{
-       methodinfo        *resm;
-       jni_callblock     *blk;
-       java_objectheader *o;
-       s4                 argcount;
-       s4                 paramcount;
+static void _Jv_jni_CallVoidMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                       methodinfo *m, const jvalue *args)
+{      
+       methodinfo *resm;
 
        if (m == NULL) {
                exceptions_throw_nullpointerexception();
-               return NULL;
-       }
-
-       argcount = m->parseddesc->paramcount;
-       paramcount = argcount;
-
-       /* if method is non-static, remove the `this' pointer */
-
-       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. */
-
-       if (!(m->flags & ACC_STATIC) && obj &&
-               (!builtin_instanceof((java_objectheader *) obj, m->class))) {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_IllegalArgumentException,
-                                                                 "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
-               return NULL;
+               return;
        }
 
-       if (((params == NULL) && (paramcount != 0)) ||
-               (params && (params->header.size != paramcount))) {
-               *exceptionptr =
-                       new_exception(string_java_lang_IllegalArgumentException);
-               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) && (obj == 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) {
+               /* For static methods we reset the object. */
 
-       if ((m->flags & ACC_STATIC) && (obj != NULL))
-               obj = NULL;
+               if (o != NULL)
+                       o = 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 convenience */
 
-       if (obj) {
-               resm = method_vftbl_lookup(obj->vftbl, m);
+               resm = m;
 
        } else {
-               /* just for convenience */
+               /* For instance methods we make a virtual function table lookup. */
 
-               resm = m;
+               resm = method_vftbl_lookup(vftbl, m);
        }
 
-       blk = MNEW(jni_callblock, argcount);
-
-       if (!fill_callblock_from_objectarray(obj, resm->parseddesc, blk,
-                                                                                params))
-               return NULL;
-
-       switch (resm->parseddesc->returntype.decltype) {
-       case TYPE_VOID:
-               ASM_CALLJAVAFUNCTION2(resm, argcount,
-                                                         argcount * sizeof(jni_callblock),
-                                                         blk);
-
-               o = NULL;
-               break;
-
-       case PRIMITIVETYPE_BOOLEAN: {
-               s4 i;
-               java_lang_Boolean *bo;
+       STATISTICS(jnicallXmethodnvokation());
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+       (void) vm_call_method_jvalue(resm, o, args);
+}
 
-               o = builtin_new(class_java_lang_Boolean);
 
-               /* setting the value of the object direct */
+/* _Jv_jni_invokeNative ********************************************************
 
-               bo = (java_lang_Boolean *) o;
-               bo->value = i;
-       }
-       break;
+   Invoke a method on the given object with the given arguments.
 
-       case PRIMITIVETYPE_BYTE: {
-               s4 i;
-               java_lang_Byte *bo;
+   For instance methods OBJ must be != NULL and the method is looked up
+   in the vftbl of the object.
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+   For static methods, OBJ is ignored.
 
-               o = builtin_new(class_java_lang_Byte);
+*******************************************************************************/
 
-               /* setting the value of the object direct */
+java_handle_t *_Jv_jni_invokeNative(methodinfo *m, java_handle_t *o,
+                                                                       java_handle_objectarray_t *params)
+{
+       methodinfo    *resm;
+       java_handle_t *ro;
+       s4             argcount;
+       s4             paramcount;
+       java_handle_t *xptr;
+       int32_t        dumpsize;
+       uint64_t      *array;
+       imm_union          value;
 
-               bo = (java_lang_Byte *) o;
-               bo->value = i;
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
        }
-       break;
 
-       case PRIMITIVETYPE_CHAR: {
-               s4 i;
-               java_lang_Character *co;
+       argcount = m->parseddesc->paramcount;
+       paramcount = argcount;
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+       /* if method is non-static, remove the `this' pointer */
 
-               o = builtin_new(class_java_lang_Character);
+       if (!(m->flags & ACC_STATIC))
+               paramcount--;
 
-               /* setting the value of the object direct */
+       /* 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. */
 
-               co = (java_lang_Character *) o;
-               co->value = i;
+       if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) {
+               exceptions_throw_illegalargumentexception();
+               return NULL;
        }
-       break;
-
-       case PRIMITIVETYPE_SHORT: {
-               s4 i;
-               java_lang_Short *so;
-
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
 
-               o = builtin_new(class_java_lang_Short);
+       /* check if we got the right number of arguments */
 
-               /* setting the value of the object direct */
-
-               so = (java_lang_Short *) o;
-               so->value = i;
+       if (((params == NULL) && (paramcount != 0)) ||
+               (params && (LLNI_array_size(params) != paramcount))) 
+       {
+               exceptions_throw_illegalargumentexception();
+               return NULL;
        }
-       break;
-
-       case PRIMITIVETYPE_INT: {
-               s4 i;
-               java_lang_Integer *io;
 
-               ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+       /* for instance methods we need an object */
 
-               o = builtin_new(class_java_lang_Integer);
-
-               /* setting the value of the object direct */
-
-               io = (java_lang_Integer *) o;
-               io->value = i;
+       if (!(m->flags & ACC_STATIC) && (o == NULL)) {
+               /* XXX not sure if that is the correct exception */
+               exceptions_throw_nullpointerexception();
+               return NULL;
        }
-       break;
 
-       case PRIMITIVETYPE_LONG: {
-               s8 l;
-               java_lang_Long *lo;
+       /* for static methods, zero object to make subsequent code simpler */
+       if (m->flags & ACC_STATIC)
+               o = NULL;
 
-               ASM_CALLJAVAFUNCTION2_LONG(l, resm, argcount,
-                                                                  argcount * sizeof(jni_callblock),
-                                                                  blk);
+       if (o != NULL) {
+               /* for instance methods we must do a vftbl lookup */
+               resm = method_vftbl_lookup(o->vftbl, m);
+       }
+       else {
+               /* for static methods, just for convenience */
+               resm = m;
+       }
 
-               o = builtin_new(class_java_lang_Long);
+       /* mark start of dump memory area */
 
-               /* setting the value of the object direct */
+       dumpsize = dump_size();
 
-               lo = (java_lang_Long *) o;
-               lo->value = l;
-       }
-       break;
+       /* Fill the argument array from a object-array. */
 
-       case PRIMITIVETYPE_FLOAT: {
-               float f;
-               java_lang_Float *fo;
+       array = vm_array_from_objectarray(resm, o, params);
 
-               ASM_CALLJAVAFUNCTION2_FLOAT(f, resm, argcount,
-                                                                       argcount * sizeof(jni_callblock),
-                                                                       blk);
+       /* The array can be NULL if we don't have any arguments to pass
+          and the architecture does not have any argument registers
+          (e.g. i386).  In that case we additionally check for an
+          exception thrown. */
 
-               o = builtin_new(class_java_lang_Float);
+       if ((array == NULL) && (exceptions_get_exception() != NULL)) {
+               /* release dump area */
 
-               /* setting the value of the object direct */
+               dump_release(dumpsize);
 
-               fo = (java_lang_Float *) o;
-               fo->value = f;
+               return NULL;
        }
-       break;
 
-       case PRIMITIVETYPE_DOUBLE: {
-               double d;
-               java_lang_Double *_do;
+       switch (resm->parseddesc->returntype.decltype) {
+       case TYPE_VOID:
+               (void) vm_call_array(resm, array);
+               ro = NULL;
+               break;
 
-               ASM_CALLJAVAFUNCTION2_DOUBLE(d, resm, argcount,
-                                                                        argcount * sizeof(jni_callblock),
-                                                                        blk);
+       case PRIMITIVETYPE_BOOLEAN:
+       case PRIMITIVETYPE_BYTE:
+       case PRIMITIVETYPE_CHAR:
+       case PRIMITIVETYPE_SHORT:
+       case PRIMITIVETYPE_INT:
+               value.i = vm_call_int_array(resm, array);
+               ro = primitive_box(resm->parseddesc->returntype.decltype, value);
+               break;
 
-               o = builtin_new(class_java_lang_Double);
+       case PRIMITIVETYPE_LONG:
+               value.l = vm_call_long_array(resm, array);
+               ro = primitive_box(resm->parseddesc->returntype.decltype, value);
+               break;
 
-               /* setting the value of the object direct */
+       case PRIMITIVETYPE_FLOAT:
+               value.f = vm_call_float_array(resm, array);
+               ro = primitive_box(resm->parseddesc->returntype.decltype, value);
+               break;
 
-               _do = (java_lang_Double *) o;
-               _do->value = d;
-       }
-       break;
+       case PRIMITIVETYPE_DOUBLE:
+               value.d = vm_call_double_array(resm, array);
+               ro = primitive_box(resm->parseddesc->returntype.decltype, value);
+               break;
 
        case TYPE_ADR:
-               ASM_CALLJAVAFUNCTION2_ADR(o, resm, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
+               ro = vm_call_array(resm, array);
                break;
 
        default:
-               /* if this happens the exception has already been set by
-                  fill_callblock_from_objectarray */
-
-               MFREE(blk, jni_callblock, argcount);
-
-               return (jobject *) 0;
+               vm_abort("_Jv_jni_invokeNative: invalid return type %d", resm->parseddesc->returntype.decltype);
        }
 
-       MFREE(blk, jni_callblock, argcount);
-
-       if (*exceptionptr) {
-               java_objectheader *cause;
-
-               cause = *exceptionptr;
+       xptr = exceptions_get_exception();
 
+       if (xptr != NULL) {
                /* clear exception pointer, we are calling JIT code again */
 
-               *exceptionptr = NULL;
+               exceptions_clear_exception();
 
-               *exceptionptr =
-                       new_exception_throwable(string_java_lang_reflect_InvocationTargetException,
-                                                                       (java_lang_Throwable *) cause);
+               exceptions_throw_invocationtargetexception(xptr);
        }
 
-       return (jobject *) o;
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+       return ro;
 }
 
 
@@ -1108,7 +908,7 @@ jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
 
 *******************************************************************************/
 
-jint GetVersion(JNIEnv *env)
+jint _Jv_JNI_GetVersion(JNIEnv *env)
 {
        STATISTICS(jniinvokation());
 
@@ -1128,24 +928,29 @@ jint GetVersion(JNIEnv *env)
 
 *******************************************************************************/
 
-jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
-                                  const jbyte *buf, jsize bufLen)
+jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
+                                                  const jbyte *buf, jsize bufLen)
 {
-       java_lang_ClassLoader *cl;
-       java_lang_String      *s;
-       java_bytearray        *ba;
-       jclass                 c;
+#if defined(ENABLE_JAVASE)
+       utf         *u;
+       classloader *cl;
+       classinfo   *c;
 
-       STATISTICS(jniinvokation());
+       TRACEJNICALLS("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen);
+
+       u  = utf_new_char(name);
+       cl = (classloader *) loader;
 
-       cl = (java_lang_ClassLoader *) loader;
-       s = javastring_new_char(name);
-       ba = (java_bytearray *) buf;
+       c = class_define(u, cl, bufLen, (const uint8_t *) buf, NULL);
+
+       return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
+#else
+       vm_abort("_Jv_JNI_DefineClass: not implemented in this configuration");
 
-       c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
-                                                                                                                 0, bufLen, NULL);
+       /* keep compiler happy */
 
-       return (jclass) NewLocalRef(env, (jobject) c);
+       return 0;
+#endif
 }
 
 
@@ -1157,91 +962,54 @@ jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
 
 *******************************************************************************/
 
-jclass FindClass(JNIEnv *env, const char *name)
+jclass _Jv_JNI_FindClass(JNIEnv *env, const char *name)
 {
-       utf               *u;
-       classinfo         *c;
-       java_objectheader *cl;
+#if defined(ENABLE_JAVASE)
+       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. */
-
-#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();
-#else
-# if defined(ENABLE_INTRP)
-       /* the interpreter supports stacktraces, even if the JIT does not */
-
-       if (opt_intrp)
-               cl = stacktrace_getCurrentClassLoader();
+          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." */
+
+       cc = stacktrace_getCurrentClass();
+
+       if (cc == NULL)
+               c = load_class_from_sysloader(u);
        else
-# endif
-               cl = NULL;
-#endif
+               c = load_class_from_classloader(u, cc->classloader);
 
-       if (!(c = load_class_from_classloader(u, cl)))
+       if (c == NULL)
                return NULL;
 
        if (!link_class(c))
                return NULL;
 
-       return (jclass) NewLocalRef(env, (jobject) c);
-}
-  
-
-/* 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);
-       }
+       return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
+#else
+       vm_abort("_Jv_JNI_FindClass: not implemented in this configuration");
 
-       mi = &(c->methods[slot]);
+       /* keep compiler happy */
 
-       return mi;
+       return NULL;
+#endif
 }
-
+  
 
 /* GetSuperclass ***************************************************************
 
@@ -1251,18 +1019,21 @@ jmethodID FromReflectedMethod(JNIEnv *env, jobject method)
 
 *******************************************************************************/
  
-jclass GetSuperclass(JNIEnv *env, jclass sub)
+jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
 {
        classinfo *c;
+       classinfo *super;
 
-       STATISTICS(jniinvokation());
+       TRACEJNICALLS("_Jv_JNI_GetSuperclass(env=%p, sub=%p)", env, sub);
 
-       c = ((classinfo *) sub)->super.cls;
+       c = LLNI_classinfo_unwrap(sub);
 
-       if (!c)
+       if (c == NULL)
                return NULL;
 
-       return (jclass) NewLocalRef(env, (jobject) c);
+       super = class_get_superclass(c);
+
+       return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) super);
 }
   
  
@@ -1272,14 +1043,17 @@ jclass GetSuperclass(JNIEnv *env, jclass sub)
 
 *******************************************************************************/
 
-jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
+jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
 {
+       java_lang_Class *csup;
+       java_lang_Class *csub;
+
+       csup = (java_lang_Class *) sup;
+       csub = (java_lang_Class *) sub;
+
        STATISTICS(jniinvokation());
 
-       return Java_java_lang_VMClass_isAssignableFrom(env,
-                                                                                                  NULL,
-                                                                                                  (java_lang_Class *) sup,
-                                                                                                  (java_lang_Class *) sub);
+       return _Jv_java_lang_Class_isAssignableFrom(csup, csub);
 }
 
 
@@ -1289,11 +1063,15 @@ jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
 
 *******************************************************************************/
 
-jint Throw(JNIEnv *env, jthrowable obj)
+jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
 {
+       java_handle_t *o;
+
        STATISTICS(jniinvokation());
 
-       *exceptionptr = (java_objectheader *) obj;
+       o = (java_handle_t *) obj;
+
+       exceptions_set_exception(o);
 
        return JNI_OK;
 }
@@ -1307,24 +1085,27 @@ jint Throw(JNIEnv *env, jthrowable obj)
 
 *******************************************************************************/
 
-jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
+jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
 {
-       java_lang_Throwable *o;
-       java_lang_String    *s;
+       classinfo     *c;
+       java_handle_t *o;
+       java_handle_t *s;
 
        STATISTICS(jniinvokation());
 
-       s = (java_lang_String *) javastring_new_char(msg);
+       c = LLNI_classinfo_unwrap(clazz);
+       if (msg == NULL)
+               msg = "";
+       s = javastring_new_from_utf_string(msg);
 
        /* instantiate exception object */
 
-       o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz,
-                                                                                                                  s);
+       o = native_new_and_init_string(c, s);
 
-       if (!o)
+       if (o == NULL)
                return -1;
 
-       *exceptionptr = (java_objectheader *) o;
+       exceptions_set_exception(o);
 
        return 0;
 }
@@ -1338,15 +1119,15 @@ jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
 
 *******************************************************************************/
 
-jthrowable ExceptionOccurred(JNIEnv *env)
+jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
 {
-       java_objectheader *e;
+       java_handle_t *o;
 
        STATISTICS(jniinvokation());
 
-       e = *exceptionptr;
+       o = exceptions_get_exception();
 
-       return NewLocalRef(env, (jthrowable) e);
+       return _Jv_JNI_NewLocalRef(env, (jthrowable) o);
 }
 
 
@@ -1358,35 +1139,35 @@ jthrowable ExceptionOccurred(JNIEnv *env)
 
 *******************************************************************************/
 
-void ExceptionDescribe(JNIEnv *env)
+void _Jv_JNI_ExceptionDescribe(JNIEnv *env)
 {
-       java_objectheader *e;
-       methodinfo        *m;
+       java_handle_t *o;
+       methodinfo    *m;
 
        STATISTICS(jniinvokation());
 
-       e = *exceptionptr;
+       o = exceptions_get_exception();
 
-       if (e) {
+       if (o == NULL) {
                /* clear exception, because we are calling jit code again */
 
-               *exceptionptr = NULL;
+               exceptions_clear_exception();
 
                /* get printStackTrace method from exception class */
 
-               m = class_resolveclassmethod(e->vftbl->class,
+               m = class_resolveclassmethod(o->vftbl->class,
                                                                         utf_printStackTrace,
                                                                         utf_void__void,
                                                                         NULL,
                                                                         true);
 
-               if (!m)
+               if (m == NULL)
                        /* XXX what should we do? */
                        return;
 
                /* print the stacktrace */
 
-               ASM_CALLJAVAFUNCTION(m, e, NULL, NULL, NULL);
+               (void) vm_call_method(m, o);
        }
 }
 
@@ -1398,11 +1179,11 @@ void ExceptionDescribe(JNIEnv *env)
 
 *******************************************************************************/
 
-void ExceptionClear(JNIEnv *env)
+void _Jv_JNI_ExceptionClear(JNIEnv *env)
 {
        STATISTICS(jniinvokation());
 
-       *exceptionptr = NULL;
+       exceptions_clear_exception();
 }
 
 
@@ -1413,11 +1194,13 @@ void ExceptionClear(JNIEnv *env)
 
 *******************************************************************************/
 
-void FatalError(JNIEnv *env, const char *msg)
+void _Jv_JNI_FatalError(JNIEnv *env, const char *msg)
 {
        STATISTICS(jniinvokation());
 
-       throw_cacao_exception_exit(string_java_lang_InternalError, msg);
+       /* this seems to be the best way */
+
+       vm_abort("JNI Fatal error: %s", msg);
 }
 
 
@@ -1428,17 +1211,22 @@ void FatalError(JNIEnv *env, const char *msg)
 
 *******************************************************************************/
 
-jint PushLocalFrame(JNIEnv* env, jint capacity)
+jint _Jv_JNI_PushLocalFrame(JNIEnv* env, jint capacity)
 {
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!");
+       if (capacity <= 0)
+               return -1;
 
-       assert(0);
+       /* add new local reference frame to current table */
+
+       if (!localref_frame_push(capacity))
+               return -1;
 
        return 0;
 }
 
+
 /* PopLocalFrame ***************************************************************
 
    Pops off the current local reference frame, frees all the local
@@ -1447,17 +1235,17 @@ jint PushLocalFrame(JNIEnv* env, jint capacity)
 
 *******************************************************************************/
 
-jobject PopLocalFrame(JNIEnv* env, jobject result)
+jobject _Jv_JNI_PopLocalFrame(JNIEnv* env, jobject result)
 {
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!");
+       /* release all current local frames */
 
-       assert(0);
+       localref_frame_pop_all();
 
        /* add local reference and return the value */
 
-       return NewLocalRef(env, NULL);
+       return _Jv_JNI_NewLocalRef(env, result);
 }
 
 
@@ -1467,28 +1255,33 @@ jobject PopLocalFrame(JNIEnv* env, jobject result)
 
 *******************************************************************************/
 
-void DeleteLocalRef(JNIEnv *env, jobject localRef)
+void _Jv_JNI_DeleteLocalRef(JNIEnv *env, jobject localRef)
 {
-       java_objectheader *o;
-       localref_table    *lrt;
-       s4                 i;
+       java_handle_t  *o;
+       localref_table *lrt;
+       s4              i;
 
        STATISTICS(jniinvokation());
 
-       o = (java_objectheader *) localRef;
+       o = (java_handle_t *) localRef;
 
        /* get local reference table (thread specific) */
 
        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;
+                       }
                }
        }
 
@@ -1496,7 +1289,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");
 }
 
 
@@ -1506,7 +1299,7 @@ void DeleteLocalRef(JNIEnv *env, jobject localRef)
 
 *******************************************************************************/
 
-jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
+jboolean _Jv_JNI_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
 {
        STATISTICS(jniinvokation());
 
@@ -1523,7 +1316,7 @@ jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
 
 *******************************************************************************/
 
-jobject NewLocalRef(JNIEnv *env, jobject ref)
+jobject _Jv_JNI_NewLocalRef(JNIEnv *env, jobject ref)
 {
        localref_table *lrt;
        s4              i;
@@ -1537,20 +1330,24 @@ 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 (_Jv_JNI_EnsureLocalCapacity(env, 16) != 0)
+                       return NULL;
+
+               /* get the new local reference table */
+
+               lrt = LOCALREFTABLE;
        }
 
        /* insert the reference */
 
        for (i = 0; i < lrt->capacity; i++) {
                if (lrt->refs[i] == NULL) {
-                       lrt->refs[i] = (java_objectheader *) ref;
+                       lrt->refs[i] = (java_handle_t *) ref;
                        lrt->used++;
 
                        return ref;
@@ -1574,7 +1371,7 @@ jobject NewLocalRef(JNIEnv *env, jobject ref)
 
 *******************************************************************************/
 
-jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
+jint _Jv_JNI_EnsureLocalCapacity(JNIEnv* env, jint capacity)
 {
        localref_table *lrt;
 
@@ -1586,10 +1383,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 _Jv_JNI_PushLocalFrame(env, capacity);
 
        return 0;
 }
@@ -1602,22 +1397,23 @@ jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
 
 *******************************************************************************/
 
-jobject AllocObject(JNIEnv *env, jclass clazz)
+jobject _Jv_JNI_AllocObject(JNIEnv *env, jclass clazz)
 {
-       java_objectheader *o;
+       classinfo     *c;
+       java_handle_t *o;
 
        STATISTICS(jniinvokation());
 
-       if ((clazz->flags & ACC_INTERFACE) || (clazz->flags & ACC_ABSTRACT)) {
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_InstantiationException,
-                                                                        clazz->name);
+       c = LLNI_classinfo_unwrap(clazz);
+
+       if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
+               exceptions_throw_instantiationexception(c);
                return NULL;
        }
                
-       o = builtin_new(clazz);
+       o = builtin_new(c);
 
-       return NewLocalRef(env, o);
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
@@ -1630,27 +1426,32 @@ jobject AllocObject(JNIEnv *env, jclass clazz)
 
 *******************************************************************************/
 
-jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jobject _Jv_JNI_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       java_objectheader *o;
-       va_list            ap;
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+       va_list        ap;
 
        STATISTICS(jniinvokation());
 
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
+
        /* create object */
 
-       o = builtin_new(clazz);
+       o = builtin_new(c);
        
-       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);
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
@@ -1664,42 +1465,67 @@ jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 
 *******************************************************************************/
 
-jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
+jobject _Jv_JNI_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
+                                                  va_list args)
 {
-       java_objectheader *o;
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
 
        STATISTICS(jniinvokation());
 
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
+
        /* create object */
 
-       o = builtin_new(clazz);
+       o = builtin_new(c);
        
-       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);
+       return _Jv_JNI_NewLocalRef(env, (jobject) 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)
+jobject _Jv_JNI_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
+                                                  const jvalue *args)
 {
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: NewObjectA: IMPLEMENT ME!");
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
+
+       /* create object */
+
+       o = builtin_new(c);
+       
+       if (o == NULL)
+               return NULL;
+
+       /* call constructor */
+
+       _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
 
-       return NewLocalRef(env, NULL);
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
@@ -1709,18 +1535,21 @@ jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
 
 *******************************************************************************/
 
-jclass GetObjectClass(JNIEnv *env, jobject obj)
+jclass _Jv_JNI_GetObjectClass(JNIEnv *env, jobject obj)
 {
-       classinfo *c;
+       java_handle_t *o;
+       classinfo     *c;
 
        STATISTICS(jniinvokation());
-       
-       if (!obj || !obj->vftbl)
+
+       o = (java_handle_t *) obj;
+
+       if ((o == NULL) || (o->vftbl == NULL))
                return NULL;
 
-       c = obj->vftbl->class;
+       c = o->vftbl->class;
 
-       return (jclass) NewLocalRef(env, (jobject) c);
+       return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
 }
 
 
@@ -1730,40 +1559,107 @@ jclass GetObjectClass(JNIEnv *env, jobject obj)
 
 *******************************************************************************/
 
-jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
+jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
 {
+       java_lang_Class  *c;
+       java_lang_Object *o;
+
        STATISTICS(jniinvokation());
 
-       return Java_java_lang_VMClass_isInstance(env,
-                                                                                        NULL,
-                                                                                        (java_lang_Class *) clazz,
-                                                                                        (java_lang_Object *) obj);
+       c = (java_lang_Class *) clazz;
+       o = (java_lang_Object *) obj;
+
+       return _Jv_java_lang_Class_isInstance(c, o);
 }
 
 
-/***************** converts a java.lang.reflect.Field to a field ID ***************/
-jfieldID FromReflectedField(JNIEnv* env, jobject field)
+/* Reflection Support *********************************************************/
+
+/* FromReflectedMethod *********************************************************
+
+   Converts java.lang.reflect.Method or java.lang.reflect.Constructor
+   object to a method ID.
+  
+*******************************************************************************/
+  
+jmethodID _Jv_JNI_FromReflectedMethod(JNIEnv *env, jobject method)
 {
-       java_lang_reflect_Field *f;
-       classinfo *c;
-       jfieldID fid;   /* the JNI-fieldid of the wrapping object */
+#if defined(ENABLE_JAVASE)
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+       s4             slot;
 
        STATISTICS(jniinvokation());
 
-       /*log_text("JNI-Call: FromReflectedField");*/
+       o = (java_handle_t *) method;
+
+       if (o == NULL)
+               return NULL;
+       
+       if (builtin_instanceof(o, class_java_lang_reflect_Method)) {
+               java_lang_reflect_Method *rm;
+
+               rm   = (java_lang_reflect_Method *) method;
+               LLNI_field_get_cls(rm, clazz, c);
+               LLNI_field_get_val(rm, slot , slot);
+       }
+       else if (builtin_instanceof(o, class_java_lang_reflect_Constructor)) {
+               java_lang_reflect_Constructor *rc;
 
-       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);
+               rc   = (java_lang_reflect_Constructor *) method;
+               LLNI_field_get_cls(rc, clazz, c);
+               LLNI_field_get_val(rc, slot , slot);
        }
-       fid=&(c->fields[f->slot]);
-       return fid;
+       else
+               return NULL;
+
+       m = &(c->methods[slot]);
+
+       return (jmethodID) m;
+#else
+       vm_abort("_Jv_JNI_FromReflectedMethod: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
+}
+
+
+/* FromReflectedField **********************************************************
+
+   Converts a java.lang.reflect.Field to a field ID.
+
+*******************************************************************************/
+jfieldID _Jv_JNI_FromReflectedField(JNIEnv* env, jobject field)
+{
+#if defined(ENABLE_JAVASE)
+       java_lang_reflect_Field *rf;
+       classinfo               *c;
+       fieldinfo               *f;
+       int32_t                  slot;
+
+       STATISTICS(jniinvokation());
+
+       rf = (java_lang_reflect_Field *) field;
+
+       if (rf == NULL)
+               return NULL;
+
+       LLNI_field_get_cls(rf, clazz, c);
+       LLNI_field_get_val(rf, slot , slot);
+       f = &(c->fields[slot]);
+
+       return (jfieldID) f;
+#else
+       vm_abort("_Jv_JNI_FromReflectedField: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
 }
 
 
@@ -1775,13 +1671,39 @@ jfieldID FromReflectedField(JNIEnv* env, jobject field)
 
 *******************************************************************************/
 
-jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
+jobject _Jv_JNI_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
+                                                                 jboolean isStatic)
 {
+#if defined(ENABLE_JAVASE)
+       methodinfo                    *m;
+       java_lang_reflect_Constructor *rc;
+       java_lang_reflect_Method      *rm;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: ToReflectedMethod: IMPLEMENT ME!");
+       m = (methodinfo *) methodID;
+
+       /* HotSpot does the same assert. */
+
+       assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
+
+       if (m->name == utf_init) {
+               rc = reflect_constructor_new(m);
+
+               return (jobject) rc;
+       }
+       else {
+               rm = reflect_method_new(m);
+
+               return (jobject) rm;
+       }
+#else
+       vm_abort("_Jv_JNI_ToReflectedMethod: not implemented in this configuration");
+
+       /* keep compiler happy */
 
        return NULL;
+#endif
 }
 
 
@@ -1792,8 +1714,8 @@ jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean
 
 *******************************************************************************/
 
-jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
-                                                jboolean isStatic)
+jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
+                                                                jboolean isStatic)
 {
        STATISTICS(jniinvokation());
 
@@ -1816,8 +1738,8 @@ jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
 
 *******************************************************************************/
 
-jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
-                                         const char *sig)
+jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
+                                                         const char *sig)
 {
        classinfo  *c;
        utf        *uname;
@@ -1826,9 +1748,9 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
 
        STATISTICS(jniinvokation());
 
-       c = (classinfo *) clazz;
+       c = LLNI_classinfo_unwrap(clazz);
 
-       if (!c)
+       if (c == NULL)
                return NULL;
 
        if (!(c->state & CLASS_INITIALIZED))
@@ -1840,7 +1762,7 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
        uname = utf_new_char((char *) name);
        udesc = utf_new_char((char *) sig);
 
-       m = class_resolvemethod(clazz, uname, udesc);
+       m = class_resolvemethod(c, uname, udesc);
 
        if ((m == NULL) || (m->flags & ACC_STATIC)) {
                exceptions_throw_nosuchmethoderror(c, uname, udesc);
@@ -1848,2422 +1770,1352 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
                return NULL;
        }
 
-       return m;
+       return (jmethodID) m;
 }
 
 
 /* JNI-functions for calling instance methods *********************************/
 
-jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       java_objectheader* ret;
-       va_list            ap;
+#define JNI_CALL_VIRTUAL_METHOD(name, type, intern)         \
+type _Jv_JNI_Call##name##Method(JNIEnv *env, jobject obj,   \
+                                                               jmethodID methodID, ...)    \
+{                                                           \
+       java_handle_t *o;                                       \
+       methodinfo    *m;                                       \
+       va_list        ap;                                      \
+       type           ret;                                     \
+                                                            \
+       o = (java_handle_t *) obj;                              \
+       m = (methodinfo *) methodID;                            \
+                                                            \
+       va_start(ap, methodID);                                 \
+       ret = _Jv_jni_Call##intern##Method(o, o->vftbl, m, ap); \
+       va_end(ap);                                             \
+                                                            \
+       return ret;                                             \
+}
+
+JNI_CALL_VIRTUAL_METHOD(Boolean, jboolean, Int)
+JNI_CALL_VIRTUAL_METHOD(Byte,    jbyte,    Int)
+JNI_CALL_VIRTUAL_METHOD(Char,    jchar,    Int)
+JNI_CALL_VIRTUAL_METHOD(Short,   jshort,   Int)
+JNI_CALL_VIRTUAL_METHOD(Int,     jint,     Int)
+JNI_CALL_VIRTUAL_METHOD(Long,    jlong,    Long)
+JNI_CALL_VIRTUAL_METHOD(Float,   jfloat,   Float)
+JNI_CALL_VIRTUAL_METHOD(Double,  jdouble,  Double)
+
+
+#define JNI_CALL_VIRTUAL_METHOD_V(name, type, intern)              \
+type _Jv_JNI_Call##name##MethodV(JNIEnv *env, jobject obj,         \
+                                                                jmethodID methodID, va_list args) \
+{                                                                  \
+       java_handle_t *o;                                              \
+       methodinfo    *m;                                              \
+       type           ret;                                            \
+                                                                   \
+       o = (java_handle_t *) obj;                                     \
+       m = (methodinfo *) methodID;                                   \
+                                                                   \
+       ret = _Jv_jni_Call##intern##Method(o, o->vftbl, m, args);      \
+                                                                   \
+       return ret;                                                    \
+}
+
+JNI_CALL_VIRTUAL_METHOD_V(Boolean, jboolean, Int)
+JNI_CALL_VIRTUAL_METHOD_V(Byte,    jbyte,    Int)
+JNI_CALL_VIRTUAL_METHOD_V(Char,    jchar,    Int)
+JNI_CALL_VIRTUAL_METHOD_V(Short,   jshort,   Int)
+JNI_CALL_VIRTUAL_METHOD_V(Int,     jint,     Int)
+JNI_CALL_VIRTUAL_METHOD_V(Long,    jlong,    Long)
+JNI_CALL_VIRTUAL_METHOD_V(Float,   jfloat,   Float)
+JNI_CALL_VIRTUAL_METHOD_V(Double,  jdouble,  Double)
+
+
+#define JNI_CALL_VIRTUAL_METHOD_A(name, type, intern)          \
+type _Jv_JNI_Call##name##MethodA(JNIEnv *env, jobject obj,     \
+                                                                jmethodID methodID,           \
+                                                                const jvalue *args)           \
+{                                                              \
+       java_handle_t *o;                                          \
+       methodinfo    *m;                                          \
+       type           ret;                                        \
+                                                               \
+       o = (java_handle_t *) obj;                                 \
+       m = (methodinfo *) methodID;                               \
+                                                               \
+       ret = _Jv_jni_Call##intern##MethodA(o, o->vftbl, m, args); \
+                                                               \
+       return ret;                                                \
+}
+
+JNI_CALL_VIRTUAL_METHOD_A(Boolean, jboolean, Int)
+JNI_CALL_VIRTUAL_METHOD_A(Byte,    jbyte,    Int)
+JNI_CALL_VIRTUAL_METHOD_A(Char,    jchar,    Int)
+JNI_CALL_VIRTUAL_METHOD_A(Short,   jshort,   Int)
+JNI_CALL_VIRTUAL_METHOD_A(Int,     jint,     Int)
+JNI_CALL_VIRTUAL_METHOD_A(Long,    jlong,    Long)
+JNI_CALL_VIRTUAL_METHOD_A(Float,   jfloat,   Float)
+JNI_CALL_VIRTUAL_METHOD_A(Double,  jdouble,  Double)
+
+
+jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
+                                                                ...)
+{
+       java_handle_t *o;
+       methodinfo    *m;
+       java_handle_t *ret;
+       va_list        ap;
+
+       o = (java_handle_t *) 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);
+       return _Jv_JNI_NewLocalRef(env, (jobject) ret);
 }
 
 
-jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+                                                                 va_list args)
 {
-       java_objectheader* ret;
-
-       ret = _Jv_jni_CallObjectMethod(obj, obj->vftbl, methodID, args);
-
-       return NewLocalRef(env, ret);
-}
+       java_handle_t *o;
+       methodinfo    *m;
+       java_handle_t *ret;
 
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
 
-jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
-{
-       log_text("JNI-Call: CallObjectMethodA: IMPLEMENT ME!");
+       ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, args);
 
-       return NewLocalRef(env, NULL);
+       return _Jv_JNI_NewLocalRef(env, (jobject) ret);
 }
 
 
-jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+                                                                 const jvalue *args)
 {
-       va_list  ap;
-       jboolean ret;
+       java_handle_t *o;
+       methodinfo    *m;
+       java_handle_t *ret;
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BOOLEAN);
-       va_end(ap);
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
+
+       ret = _Jv_jni_CallObjectMethodA(o, o->vftbl, m, args);
 
-       return ret;
+       return _Jv_JNI_NewLocalRef(env, (jobject) ret);
 }
 
 
-jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+
+void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       jboolean ret;
+       java_handle_t *o;
+       methodinfo    *m;
+       va_list        ap;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
 
-       return ret;
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
+       va_end(ap);
 }
 
 
-jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+                                                        va_list args)
 {
-       log_text("JNI-Call: CallBooleanMethodA");
-
-       return 0;
+       java_handle_t *o;
+       methodinfo    *m;
+
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
 }
 
-
-jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       va_list ap;
-       jbyte   ret;
+
+void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+                                                        const jvalue *args)
+{
+       java_handle_t *o;
+       methodinfo    *m;
+
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
+}
+
+
+
+#define JNI_CALL_NONVIRTUAL_METHOD(name, type, intern)                      \
+type _Jv_JNI_CallNonvirtual##name##Method(JNIEnv *env, jobject obj,         \
+                                                                                 jclass clazz, jmethodID methodID, \
+                                                                                 ...)                              \
+{                                                                           \
+       java_handle_t *o;                                                       \
+       classinfo     *c;                                                       \
+       methodinfo    *m;                                                       \
+       va_list        ap;                                                      \
+       type           ret;                                                     \
+                                                                            \
+       o = (java_handle_t *) obj;                                              \
+       c = LLNI_classinfo_unwrap(clazz);                                       \
+       m = (methodinfo *) methodID;                                            \
+                                                                            \
+       va_start(ap, methodID);                                                 \
+       ret = _Jv_jni_Call##intern##Method(o, c->vftbl, m, ap);                 \
+       va_end(ap);                                                             \
+                                                                            \
+       return ret;                                                             \
+}
+
+JNI_CALL_NONVIRTUAL_METHOD(Boolean, jboolean, Int)
+JNI_CALL_NONVIRTUAL_METHOD(Byte,    jbyte,    Int)
+JNI_CALL_NONVIRTUAL_METHOD(Char,    jchar,    Int)
+JNI_CALL_NONVIRTUAL_METHOD(Short,   jshort,   Int)
+JNI_CALL_NONVIRTUAL_METHOD(Int,     jint,     Int)
+JNI_CALL_NONVIRTUAL_METHOD(Long,    jlong,    Long)
+JNI_CALL_NONVIRTUAL_METHOD(Float,   jfloat,   Float)
+JNI_CALL_NONVIRTUAL_METHOD(Double,  jdouble,  Double)
+
+
+#define JNI_CALL_NONVIRTUAL_METHOD_V(name, type, intern)                     \
+type _Jv_JNI_CallNonvirtual##name##MethodV(JNIEnv *env, jobject obj,         \
+                                                                                  jclass clazz, jmethodID methodID, \
+                                                                                  va_list args)                     \
+{                                                                            \
+       java_handle_t *o;                                                        \
+       classinfo     *c;                                                        \
+       methodinfo    *m;                                                        \
+       type           ret;                                                      \
+                                                                             \
+       o = (java_handle_t *) obj;                                               \
+       c = LLNI_classinfo_unwrap(clazz);                                        \
+       m = (methodinfo *) methodID;                                             \
+                                                                             \
+       ret = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);                       \
+                                                                             \
+       return ret;                                                              \
+}
+
+JNI_CALL_NONVIRTUAL_METHOD_V(Boolean, jboolean, Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Byte,    jbyte,    Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Char,    jchar,    Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Short,   jshort,   Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Int,     jint,     Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Long,    jlong,    Long)
+JNI_CALL_NONVIRTUAL_METHOD_V(Float,   jfloat,   Float)
+JNI_CALL_NONVIRTUAL_METHOD_V(Double,  jdouble,  Double)
+
+
+#define JNI_CALL_NONVIRTUAL_METHOD_A(name, type, intern)                     \
+type _Jv_JNI_CallNonvirtual##name##MethodA(JNIEnv *env, jobject obj,         \
+                                                                                  jclass clazz, jmethodID methodID, \
+                                                                                  const jvalue *args)               \
+{                                                                            \
+       log_text("JNI-Call: CallNonvirtual##name##MethodA: IMPLEMENT ME!");      \
+                                                                             \
+       return 0;                                                                \
+}
+
+JNI_CALL_NONVIRTUAL_METHOD_A(Boolean, jboolean, Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Byte,    jbyte,    Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Char,    jchar,    Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Short,   jshort,   Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Int,     jint,     Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Long,    jlong,    Long)
+JNI_CALL_NONVIRTUAL_METHOD_A(Float,   jfloat,   Float)
+JNI_CALL_NONVIRTUAL_METHOD_A(Double,  jdouble,  Double)
+
+jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
+                                                                                  jclass clazz, jmethodID methodID,
+                                                                                  ...)
+{
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+       java_handle_t *r;
+       va_list        ap;
+
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BYTE);
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
        va_end(ap);
 
-       return ret;
-
+       return _Jv_JNI_NewLocalRef(env, (jobject) r);
 }
 
-jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+
+jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
+                                                                                       jclass clazz, jmethodID methodID,
+                                                                                       va_list args)
 {
-       jbyte ret;
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+       java_handle_t *r;
+
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BYTE);
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
 
-       return ret;
+       return _Jv_JNI_NewLocalRef(env, (jobject) r);
 }
 
 
-jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
+                                                                                       jclass clazz, jmethodID methodID,
+                                                                                       const jvalue *args)
 {
-       log_text("JNI-Call: CallByteMethodA: IMPLEMENT ME!");
+       log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
 
-       return 0;
+       return _Jv_JNI_NewLocalRef(env, NULL);
 }
 
 
-jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
+                                                                         jmethodID methodID, ...)
 {
-       va_list ap;
-       jchar   ret;
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+       va_list        ap;
+
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_CHAR);
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
        va_end(ap);
-
-       return ret;
 }
 
 
-jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
+                                                                          jmethodID methodID, va_list args)
 {
-       jchar ret;
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_CHAR);
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
-       return ret;
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
 }
 
 
-jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallCharMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       va_list ap;
-       jshort  ret;
+void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
+                                                                          jmethodID methodID, const jvalue * args)
+{      
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_SHORT);
-       va_end(ap);
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
-       return ret;
+       _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
 }
 
 
-jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       jshort ret;
+/* Accessing Fields of Objects ************************************************/
 
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_SHORT);
+/* GetFieldID ******************************************************************
 
-       return ret;
-}
+   Returns the field ID for an instance (nonstatic) field of a
+   class. The field is specified by its name and signature. The
+   Get<type>Field and Set<type>Field families of accessor functions
+   use field IDs to retrieve object fields.
 
+*******************************************************************************/
 
-jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
+                                                       const char *sig)
 {
-       log_text("JNI-Call: CallShortMethodA: IMPLEMENT ME!");
+       classinfo *c;
+       fieldinfo *f;
+       utf       *uname;
+       utf       *udesc;
 
-       return 0;
-}
+       STATISTICS(jniinvokation());
 
+       c = LLNI_classinfo_unwrap(clazz);
 
+       /* XXX NPE check? */
 
-jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       va_list ap;
-       jint    ret;
+       uname = utf_new_char((char *) name);
+       udesc = utf_new_char((char *) sig);
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_INT);
-       va_end(ap);
+       f = class_findfield(c, uname, udesc); 
+       
+       if (f == NULL)
+               exceptions_throw_nosuchfielderror(c, uname);  
 
-       return ret;
+       return (jfieldID) f;
 }
 
 
-jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       jint ret;
-
-       ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_INT);
-
-       return ret;
-}
+/* Get<type>Field Routines *****************************************************
 
+   This family of accessor routines returns the value of an instance
+   (nonstatic) field of an object. The field to access is specified by
+   a field ID obtained by calling GetFieldID().
 
-jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallIntMethodA: IMPLEMENT ME!");
+*******************************************************************************/
 
-       return 0;
+#define JNI_GET_FIELD(name, type, intern)                                 \
+type _Jv_JNI_Get##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID) \
+{                                                                         \
+       intern ret;                                                           \
+                                                                          \
+       STATISTICS(jniinvokation());                                          \
+                                                                          \
+       ret = GET_FIELD(obj, intern, fieldID);                                \
+                                                                          \
+       return (type) ret;                                                    \
 }
 
+JNI_GET_FIELD(Boolean, jboolean, s4)
+JNI_GET_FIELD(Byte,    jbyte,    s4)
+JNI_GET_FIELD(Char,    jchar,    s4)
+JNI_GET_FIELD(Short,   jshort,   s4)
+JNI_GET_FIELD(Int,     jint,     s4)
+JNI_GET_FIELD(Long,    jlong,    s8)
+JNI_GET_FIELD(Float,   jfloat,   float)
+JNI_GET_FIELD(Double,  jdouble,  double)
 
 
-jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       va_list ap;
-       jlong   ret;
+       java_handle_t *o;
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallLongMethod(obj, obj->vftbl, methodID, ap);
-       va_end(ap);
+       STATISTICS(jniinvokation());
+
+#warning this needs to be fixed
+       o = GET_FIELD(obj, java_handle_t*, fieldID);
 
-       return ret;
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       jlong ret;
+/* Set<type>Field Routines *****************************************************
+
+   This family of accessor routines sets the value of an instance
+   (nonstatic) field of an object. The field to access is specified by
+   a field ID obtained by calling GetFieldID().
 
-       ret = _Jv_jni_CallLongMethod(obj, obj->vftbl, methodID, args);
+*******************************************************************************/
 
-       return ret;
+#define JNI_SET_FIELD(name, type, intern)                                 \
+void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID, \
+                                                         type value)                                 \
+{                                                                         \
+       STATISTICS(jniinvokation());                                          \
+                                                                          \
+       SET_FIELD(obj, intern, fieldID, value);                               \
 }
 
+JNI_SET_FIELD(Boolean, jboolean, s4)
+JNI_SET_FIELD(Byte,    jbyte,    s4)
+JNI_SET_FIELD(Char,    jchar,    s4)
+JNI_SET_FIELD(Short,   jshort,   s4)
+JNI_SET_FIELD(Int,     jint,     s4)
+JNI_SET_FIELD(Long,    jlong,    s8)
+JNI_SET_FIELD(Float,   jfloat,   float)
+JNI_SET_FIELD(Double,  jdouble,  double)
+
 
-jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
+                                                       jobject value)
 {
-       log_text("JNI-Call: CallLongMethodA: IMPLEMENT ME!");
+       STATISTICS(jniinvokation());
 
-       return 0;
+#warning this needs to be fixed
+       SET_FIELD(obj, java_handle_t*, fieldID, value);
 }
 
 
+/* Calling Static Methods *****************************************************/
 
-jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       va_list ap;
-       jfloat  ret;
+/* GetStaticMethodID ***********************************************************
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallFloatMethod(obj, obj->vftbl, methodID, ap);
-       va_end(ap);
+   Returns the method ID for a static method of a class. The method is
+   specified by its name and signature.
 
-       return ret;
-}
+   GetStaticMethodID() causes an uninitialized class to be
+   initialized.
 
+*******************************************************************************/
 
-jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
+                                                                       const char *sig)
 {
-       jfloat ret;
+       classinfo  *c;
+       utf        *uname;
+       utf        *udesc;
+       methodinfo *m;
 
-       ret = _Jv_jni_CallFloatMethod(obj, obj->vftbl, methodID, args);
+       STATISTICS(jniinvokation());
 
-       return ret;
-}
+       c = LLNI_classinfo_unwrap(clazz);
 
+       if (!c)
+               return NULL;
 
-jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallFloatMethodA: IMPLEMENT ME!");
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return NULL;
 
-       return 0;
-}
+       /* try to get the static method of the class */
 
+       uname = utf_new_char((char *) name);
+       udesc = utf_new_char((char *) sig);
 
+       m = class_resolvemethod(c, uname, udesc);
 
-jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       va_list ap;
-       jdouble ret;
+       if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+               exceptions_throw_nosuchmethoderror(c, uname, udesc);
+
+               return NULL;
+       }
+
+       return (jmethodID) m;
+}
+
+
+#define JNI_CALL_STATIC_METHOD(name, type, intern)               \
+type _Jv_JNI_CallStatic##name##Method(JNIEnv *env, jclass clazz, \
+                                                                         jmethodID methodID, ...)   \
+{                                                                \
+       methodinfo *m;                                               \
+       va_list     ap;                                              \
+       type        res;                                             \
+                                                                 \
+       m = (methodinfo *) methodID;                                 \
+                                                                 \
+       va_start(ap, methodID);                                      \
+       res = _Jv_jni_Call##intern##Method(NULL, NULL, m, ap);       \
+       va_end(ap);                                                  \
+                                                                 \
+       return res;                                                  \
+}
+
+JNI_CALL_STATIC_METHOD(Boolean, jboolean, Int)
+JNI_CALL_STATIC_METHOD(Byte,    jbyte,    Int)
+JNI_CALL_STATIC_METHOD(Char,    jchar,    Int)
+JNI_CALL_STATIC_METHOD(Short,   jshort,   Int)
+JNI_CALL_STATIC_METHOD(Int,     jint,     Int)
+JNI_CALL_STATIC_METHOD(Long,    jlong,    Long)
+JNI_CALL_STATIC_METHOD(Float,   jfloat,   Float)
+JNI_CALL_STATIC_METHOD(Double,  jdouble,  Double)
+
+
+#define JNI_CALL_STATIC_METHOD_V(name, type, intern)                     \
+type _Jv_JNI_CallStatic##name##MethodV(JNIEnv *env, jclass clazz,        \
+                                                                          jmethodID methodID, va_list args) \
+{                                                                        \
+       methodinfo *m;                                                       \
+       type        res;                                                     \
+                                                                         \
+       m = (methodinfo *) methodID;                                         \
+                                                                         \
+       res = _Jv_jni_Call##intern##Method(NULL, NULL, m, args);             \
+                                                                         \
+       return res;                                                          \
+}
+
+JNI_CALL_STATIC_METHOD_V(Boolean, jboolean, Int)
+JNI_CALL_STATIC_METHOD_V(Byte,    jbyte,    Int)
+JNI_CALL_STATIC_METHOD_V(Char,    jchar,    Int)
+JNI_CALL_STATIC_METHOD_V(Short,   jshort,   Int)
+JNI_CALL_STATIC_METHOD_V(Int,     jint,     Int)
+JNI_CALL_STATIC_METHOD_V(Long,    jlong,    Long)
+JNI_CALL_STATIC_METHOD_V(Float,   jfloat,   Float)
+JNI_CALL_STATIC_METHOD_V(Double,  jdouble,  Double)
+
+
+#define JNI_CALL_STATIC_METHOD_A(name, type, intern)                           \
+type _Jv_JNI_CallStatic##name##MethodA(JNIEnv *env, jclass clazz,              \
+                                                                          jmethodID methodID, const jvalue *args) \
+{                                                                              \
+       methodinfo *m;                                                             \
+       type        res;                                                           \
+                                                                               \
+       m = (methodinfo *) methodID;                                               \
+                                                                               \
+       res = _Jv_jni_Call##intern##MethodA(NULL, NULL, m, args);                  \
+                                                                               \
+       return res;                                                                \
+}
+
+JNI_CALL_STATIC_METHOD_A(Boolean, jboolean, Int)
+JNI_CALL_STATIC_METHOD_A(Byte,    jbyte,    Int)
+JNI_CALL_STATIC_METHOD_A(Char,    jchar,    Int)
+JNI_CALL_STATIC_METHOD_A(Short,   jshort,   Int)
+JNI_CALL_STATIC_METHOD_A(Int,     jint,     Int)
+JNI_CALL_STATIC_METHOD_A(Long,    jlong,    Long)
+JNI_CALL_STATIC_METHOD_A(Float,   jfloat,   Float)
+JNI_CALL_STATIC_METHOD_A(Double,  jdouble,  Double)
+
+
+jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
+                                                                          jmethodID methodID, ...)
+{
+       methodinfo    *m;
+       java_handle_t *o;
+       va_list        ap;
+
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallDoubleMethod(obj, obj->vftbl, methodID, ap);
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
        va_end(ap);
 
-       return ret;
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
+                                                                               jmethodID methodID, va_list args)
 {
-       jdouble ret;
-
-       ret = _Jv_jni_CallDoubleMethod(obj, obj->vftbl, methodID, args);
-
-       return ret;
-}
+       methodinfo    *m;
+       java_handle_t *o;
 
+       m = (methodinfo *) methodID;
 
-jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallDoubleMethodA: IMPLEMENT ME!");
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
 
-       return 0;
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-
-void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
+                                                                               jmethodID methodID, const jvalue *args)
 {
-       va_list ap;
+       methodinfo    *m;
+       java_handle_t *o;
 
-       va_start(ap, methodID);
-       _Jv_jni_CallVoidMethod(obj, obj->vftbl, methodID, ap);
-       va_end(ap);
-}
+       m = (methodinfo *) methodID;
 
+       o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
 
-void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       _Jv_jni_CallVoidMethod(obj, obj->vftbl, methodID, args);
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
+                                                                 jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallVoidMethodA: IMPLEMENT ME!");
-}
-
-
+       methodinfo *m;
+       va_list     ap;
 
-jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       java_objectheader *ret;
-       va_list            ap;
+       m = (methodinfo *) methodID;
 
        va_start(ap, methodID);
-       ret = _Jv_jni_CallObjectMethod(obj, clazz->vftbl, methodID, ap);
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
        va_end(ap);
-
-       return NewLocalRef(env, ret);
 }
 
 
-jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
+                                                                  jmethodID methodID, va_list args)
 {
-       java_objectheader* ret;
+       methodinfo *m;
 
-       ret = _Jv_jni_CallObjectMethod(obj, clazz->vftbl, methodID, args);
+       m = (methodinfo *) methodID;
 
-       return NewLocalRef(env, ret);
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
 }
 
 
-jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
+                                                                  jmethodID methodID, const jvalue * args)
 {
-       log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
-
-       return NewLocalRef(env, NULL);
-}
+       methodinfo *m;
 
+       m = (methodinfo *) methodID;
 
+       _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
+}
 
-jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list  ap;
-       jboolean ret;
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BOOLEAN);
-       va_end(ap);
+/* Accessing Static Fields ****************************************************/
 
-       return ret;
+/* GetStaticFieldID ************************************************************
 
-}
+   Returns the field ID for a static field of a class. The field is
+   specified by its name and signature. The GetStatic<type>Field and
+   SetStatic<type>Field families of accessor functions use field IDs
+   to retrieve static fields.
 
+*******************************************************************************/
 
-jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
+                                                                 const char *sig)
 {
-       jboolean ret;
+       classinfo *c;
+       fieldinfo *f;
+       utf       *uname;
+       utf       *usig;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BOOLEAN);
+       STATISTICS(jniinvokation());
 
-       return ret;
-}
+       c = LLNI_classinfo_unwrap(clazz);
 
+       uname = utf_new_char((char *) name);
+       usig  = utf_new_char((char *) sig);
 
-jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualBooleanMethodA: IMPLEMENT ME!");
+       f = class_findfield(c, uname, usig);
+       
+       if (f == NULL)
+               exceptions_throw_nosuchfielderror(c, uname);
 
-       return 0;
+       return (jfieldID) f;
 }
 
 
-jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jbyte   ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_BYTE);
-       va_end(ap);
+/* GetStatic<type>Field ********************************************************
 
-       return ret;
-}
+   This family of accessor routines returns the value of a static
+   field of an object.
 
+*******************************************************************************/
 
-jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+#define JNI_GET_STATIC_FIELD(name, type, field)                \
+type _Jv_JNI_GetStatic##name##Field(JNIEnv *env, jclass clazz, \
+                                                                       jfieldID fieldID)          \
+{                                                              \
+       classinfo *c;                                              \
+       fieldinfo *f;                                              \
+                                                               \
+       STATISTICS(jniinvokation());                               \
+                                                               \
+       c = LLNI_classinfo_unwrap(clazz);                          \
+       f = (fieldinfo *) fieldID;                                 \
+                                                               \
+       if (!(c->state & CLASS_INITIALIZED))                       \
+               if (!initialize_class(c))                              \
+                       return 0;                                          \
+                                                               \
+       return f->value->field;                                    \
+}
+
+JNI_GET_STATIC_FIELD(Boolean, jboolean, i)
+JNI_GET_STATIC_FIELD(Byte,    jbyte,    i)
+JNI_GET_STATIC_FIELD(Char,    jchar,    i)
+JNI_GET_STATIC_FIELD(Short,   jshort,   i)
+JNI_GET_STATIC_FIELD(Int,     jint,     i)
+JNI_GET_STATIC_FIELD(Long,    jlong,    l)
+JNI_GET_STATIC_FIELD(Float,   jfloat,   f)
+JNI_GET_STATIC_FIELD(Double,  jdouble,  d)
+
+
+jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
+                                                                        jfieldID fieldID)
 {
-       jbyte ret;
-
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_BYTE);
+       classinfo *c;
+       fieldinfo *f;
 
-       return ret;
-}
+       STATISTICS(jniinvokation());
 
+       c = LLNI_classinfo_unwrap(clazz);
+       f = (fieldinfo *) fieldID;
 
-jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualByteMethodA: IMPLEMENT ME!");
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return NULL;
 
-       return 0;
+       return _Jv_JNI_NewLocalRef(env, f->value->a);
 }
 
 
+/*  SetStatic<type>Field *******************************************************
 
-jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jchar   ret;
+       This family of accessor routines sets the value of a static field
+       of an object.
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_CHAR);
-       va_end(ap);
+*******************************************************************************/
 
-       return ret;
-}
+#define JNI_SET_STATIC_FIELD(name, type, field)                \
+void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
+                                                                       jfieldID fieldID,          \
+                                                                       type value)                \
+{                                                              \
+       classinfo *c;                                              \
+       fieldinfo *f;                                              \
+                                                               \
+       STATISTICS(jniinvokation());                               \
+                                                               \
+       c = LLNI_classinfo_unwrap(clazz);                          \
+       f = (fieldinfo *) fieldID;                                 \
+                                                               \
+       if (!(c->state & CLASS_INITIALIZED))                       \
+               if (!initialize_class(c))                              \
+                       return;                                            \
+                                                               \
+       f->value->field = value;                                   \
+}
+
+JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
+JNI_SET_STATIC_FIELD(Byte,    jbyte,    i)
+JNI_SET_STATIC_FIELD(Char,    jchar,    i)
+JNI_SET_STATIC_FIELD(Short,   jshort,   i)
+JNI_SET_STATIC_FIELD(Int,     jint,     i)
+JNI_SET_STATIC_FIELD(Long,    jlong,    l)
+JNI_SET_STATIC_FIELD(Float,   jfloat,   f)
+JNI_SET_STATIC_FIELD(Double,  jdouble,  d)
+
+
+void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+                                                                 jobject value)
+{
+       classinfo *c;
+       fieldinfo *f;
 
+       STATISTICS(jniinvokation());
 
-jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       jchar ret;
+       c = LLNI_classinfo_unwrap(clazz);
+       f = (fieldinfo *) fieldID;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_CHAR);
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-       return ret;
+       f->value->a = value;
 }
 
 
-jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualCharMethodA: IMPLEMENT ME!");
+/* String Operations **********************************************************/
 
-       return 0;
-}
+/* NewString *******************************************************************
 
+   Create new java.lang.String object from an array of Unicode
+   characters.
 
+*******************************************************************************/
 
-jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jstring _Jv_JNI_NewString(JNIEnv *env, const jchar *buf, jsize len)
 {
-       va_list ap;
-       jshort  ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_SHORT);
-       va_end(ap);
+       java_lang_String        *s;
+       java_handle_chararray_t *a;
+       u4                       i;
 
-       return ret;
-}
+       STATISTICS(jniinvokation());
+       
+       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       a = builtin_newarray_char(len);
 
+       /* javastring or characterarray could not be created */
+       if ((a == NULL) || (s == NULL))
+               return NULL;
 
-jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       jshort ret;
+       /* copy text */
+       for (i = 0; i < len; i++)
+               LLNI_array_direct(a, i) = buf[i];
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_SHORT);
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , len);
 
-       return ret;
+       return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
 }
 
 
-jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualShortMethodA: IMPLEMENT ME!");
+static jchar emptyStringJ[]={0,0};
 
-       return 0;
-}
+/* GetStringLength *************************************************************
 
+   Returns the length (the count of Unicode characters) of a Java
+   string.
 
+*******************************************************************************/
 
-jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jsize _Jv_JNI_GetStringLength(JNIEnv *env, jstring str)
 {
-       va_list ap;
-       jint    ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
-                                                               PRIMITIVETYPE_INT);
-       va_end(ap);
-
-       return ret;
-}
+       java_lang_String *s;
+       jsize             len;
 
+       TRACEJNICALLS("_Jv_JNI_GetStringLength(env=%p, str=%p)", env, str);
 
-jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       jint ret;
+       s = (java_lang_String *) str;
 
-       ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
-                                                               PRIMITIVETYPE_INT);
+       LLNI_field_get_val(s, count, len);
 
-       return ret;
+       return len;
 }
 
 
-jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+/********************  convertes javastring to u2-array ****************************/
+       
+u2 *javastring_tou2(jstring so) 
 {
-       log_text("JNI-Call: CallNonvirtualIntMethodA: IMPLEMENT ME!");
+       java_lang_String        *s;
+       java_handle_chararray_t *a;
+       u2                      *stringbuffer;
+       u4                       i;
+       int32_t                  count;
+       int32_t                  offset;
 
-       return 0;
-}
+       STATISTICS(jniinvokation());
+       
+       s = (java_lang_String *) so;
+
+       if (!s)
+               return NULL;
 
+       LLNI_field_get_ref(s, value, a);
 
+       if (!a)
+               return NULL;
 
-jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jlong   ret;
+       LLNI_field_get_val(s, count, count);
+       LLNI_field_get_val(s, offset, offset);
 
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallLongMethod(obj, clazz->vftbl, methodID, ap);
-       va_end(ap);
+       /* allocate memory */
 
-       return ret;
-}
+       stringbuffer = MNEW(u2, count + 1);
 
+       /* copy text */
 
-jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       jlong ret;
+       for (i = 0; i < count; i++)
+               stringbuffer[i] = LLNI_array_direct(a, offset + i);
+       
+       /* terminate string */
 
-       ret = _Jv_jni_CallLongMethod(obj, clazz->vftbl, methodID, args);
+       stringbuffer[i] = '\0';
 
-       return 0;
+       return stringbuffer;
 }
 
 
-jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-
-jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jfloat  ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallFloatMethod(obj, clazz->vftbl, methodID, ap);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       jfloat ret;
+/* GetStringChars **************************************************************
 
-       ret = _Jv_jni_CallFloatMethod(obj, clazz->vftbl, methodID, args);
+   Returns a pointer to the array of Unicode characters of the
+   string. This pointer is valid until ReleaseStringChars() is called.
 
-       return ret;
-}
+*******************************************************************************/
 
+const jchar *_Jv_JNI_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
+{      
+       jchar *jc;
 
-jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-
-jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jdouble ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallDoubleMethod(obj, clazz->vftbl, methodID, ap);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       jdouble ret;
-
-       ret = _Jv_jni_CallDoubleMethod(obj, clazz->vftbl, methodID, args);
-
-       return ret;
-}
-
-
-jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-
-void CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-
-       va_start(ap, methodID);
-       _Jv_jni_CallVoidMethod(obj, clazz->vftbl, methodID, ap);
-       va_end(ap);
-}
+       jc = javastring_tou2(str);
 
+       if (jc) {
+               if (isCopy)
+                       *isCopy = JNI_TRUE;
 
-void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       _Jv_jni_CallVoidMethod(obj, clazz->vftbl, methodID, args);
-}
+               return jc;
+       }
 
+       if (isCopy)
+               *isCopy = JNI_TRUE;
 
-void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
-{
-       log_text("JNI-Call: CallNonvirtualVoidMethodA: IMPLEMENT ME!");
+       return emptyStringJ;
 }
 
 
-/* Accessing Fields of Objects ************************************************/
-
-/* GetFieldID ******************************************************************
+/* ReleaseStringChars **********************************************************
 
-   Returns the field ID for an instance (nonstatic) field of a
-   class. The field is specified by its name and signature. The
-   Get<type>Field and Set<type>Field families of accessor functions
-   use field IDs to retrieve object fields.
+   Informs the VM that the native code no longer needs access to
+   chars. The chars argument is a pointer obtained from string using
+   GetStringChars().
 
 *******************************************************************************/
 
-jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name,
-                                       const char *sig) 
+void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
 {
-       fieldinfo *f;
-       utf       *uname;
-       utf       *udesc;
+       java_lang_String *s;
 
        STATISTICS(jniinvokation());
 
-       uname = utf_new_char((char *) name);
-       udesc = utf_new_char((char *) sig);
+       if (chars == emptyStringJ)
+               return;
 
-       f = class_findfield(clazz, uname, udesc); 
-       
-       if (!f)
-               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
+       s = (java_lang_String *) str;
 
-       return f;
+       MFREE(((jchar *) chars), jchar, LLNI_field_direct(s, count) + 1);
 }
 
 
-/* Get<type>Field Routines *****************************************************
+/* NewStringUTF ****************************************************************
 
-   This family of accessor routines returns the value of an instance
-   (nonstatic) field of an object. The field to access is specified by
-   a field ID obtained by calling GetFieldID().
+   Constructs a new java.lang.String object from an array of UTF-8
+   characters.
 
 *******************************************************************************/
 
-jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       java_objectheader *o;
-
-       STATISTICS(jniinvokation());
-
-       o = GET_FIELD(obj, java_objectheader*, fieldID);
-
-       return NewLocalRef(env, o);
-}
-
-
-jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       s4 i;
-
-       STATISTICS(jniinvokation());
-
-       i = GET_FIELD(obj, s4, fieldID);
-
-       return (jboolean) i;
-}
-
-
-jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       s4 i;
-
-       STATISTICS(jniinvokation());
-
-       i = GET_FIELD(obj, s4, fieldID);
-
-       return (jbyte) i;
-}
-
-
-jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       s4 i;
-
-       STATISTICS(jniinvokation());
-
-       i = GET_FIELD(obj, s4, fieldID);
-
-       return (jchar) i;
-}
-
-
-jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       s4 i;
-
-       STATISTICS(jniinvokation());
-
-       i = GET_FIELD(obj, s4, fieldID);
-
-       return (jshort) i;
-}
-
-
-jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       s4 i;
-
-       STATISTICS(jniinvokation());
-
-       i = GET_FIELD(obj, s4, fieldID);
-
-       return i;
-}
-
-
-jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID)
+jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
 {
-       s8 l;
+       java_lang_String *s;
 
-       STATISTICS(jniinvokation());
+       TRACEJNICALLS("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes);
 
-       l = GET_FIELD(obj, s8, fieldID);
+       s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
 
-       return l;
+    return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
 }
 
 
-jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       float f;
-
-       STATISTICS(jniinvokation());
-
-       f = GET_FIELD(obj, float, fieldID);
-
-       return f;
-}
+/****************** returns the utf8 length in bytes of a string *******************/
 
+jsize _Jv_JNI_GetStringUTFLength(JNIEnv *env, jstring string)
+{   
+       java_lang_String *s;
+       s4                length;
 
-jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       double d;
+       TRACEJNICALLS("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string);
 
-       STATISTICS(jniinvokation());
+       s = (java_lang_String *) string;
 
-       d = GET_FIELD(obj, double, fieldID);
+       length = u2_utflength(LLNI_field_direct(s, value)->data, LLNI_field_direct(s, count));
 
-       return d;
+       return length;
 }
 
 
-/* Set<type>Field Routines *****************************************************
+/* GetStringUTFChars ***********************************************************
 
-   This family of accessor routines sets the value of an instance
-   (nonstatic) field of an object. The field to access is specified by
-   a field ID obtained by calling GetFieldID().
+   Returns a pointer to an array of UTF-8 characters of the
+   string. This array is valid until it is released by
+   ReleaseStringUTFChars().
 
 *******************************************************************************/
 
-void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, java_objectheader*, fieldID, value);
-}
-
-
-void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, s4, fieldID, value);
-}
-
-
-void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, s4, fieldID, value);
-}
-
-
-void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, s4, fieldID, value);
-}
-
-
-void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value)
+const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
+                                                                         jboolean *isCopy)
 {
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, s4, fieldID, value);
-}
-
+       utf *u;
 
-void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value)
-{
        STATISTICS(jniinvokation());
 
-       SET_FIELD(obj, s4, fieldID, value);
-}
+       if (string == NULL)
+               return "";
 
+       if (isCopy)
+               *isCopy = JNI_TRUE;
+       
+       u = javastring_toutf((java_handle_t *) string, false);
 
-void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value)
-{
-       STATISTICS(jniinvokation());
+       if (u != NULL)
+               return u->text;
 
-       SET_FIELD(obj, s8, fieldID, value);
+       return "";
 }
 
 
-void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value)
-{
-       STATISTICS(jniinvokation());
+/* ReleaseStringUTFChars *******************************************************
 
-       SET_FIELD(obj, float, fieldID, value);
-}
+   Informs the VM that the native code no longer needs access to
+   utf. The utf argument is a pointer derived from string using
+   GetStringUTFChars().
 
+*******************************************************************************/
 
-void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value)
+void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
 {
        STATISTICS(jniinvokation());
 
-       SET_FIELD(obj, double, fieldID, value);
+    /* XXX we don't release utf chars right now, perhaps that should be done 
+          later. Since there is always one reference the garbage collector will
+          never get them */
 }
 
 
-/* Calling Static Methods *****************************************************/
-
-/* GetStaticMethodID ***********************************************************
+/* Array Operations ***********************************************************/
 
-   Returns the method ID for a static method of a class. The method is
-   specified by its name and signature.
+/* GetArrayLength **************************************************************
 
-   GetStaticMethodID() causes an uninitialized class to be
-   initialized.
+   Returns the number of elements in the array.
 
 *******************************************************************************/
 
-jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
-                                                       const char *sig)
+jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
 {
-       classinfo  *c;
-       utf        *uname;
-       utf        *udesc;
-       methodinfo *m;
+       java_handle_t *a;
+       jsize          size;
 
        STATISTICS(jniinvokation());
 
-       c = (classinfo *) clazz;
-
-       if (!c)
-               return NULL;
-
-       if (!(c->state & CLASS_INITIALIZED))
-               if (!initialize_class(c))
-                       return NULL;
-
-       /* try to get the static method of the class */
-
-       uname = utf_new_char((char *) name);
-       udesc = utf_new_char((char *) sig);
-
-       m = class_resolvemethod(c, uname, udesc);
-
-       if ((m == NULL) || !(m->flags & ACC_STATIC)) {
-               exceptions_throw_nosuchmethoderror(c, uname, udesc);
+       a = (java_handle_t *) array;
 
-               return NULL;
-       }
+       size = LLNI_array_size(a);
 
-       return m;
+       return size;
 }
 
 
-jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       java_objectheader *ret;
-       va_list            ap;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallObjectMethod(NULL, NULL, methodID, ap);
-       va_end(ap);
-
-       return NewLocalRef(env, ret);
-}
-
-
-jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       java_objectheader *ret;
-
-       ret = _Jv_jni_CallObjectMethod(NULL, NULL, methodID, args);
-
-       return NewLocalRef(env, ret);
-}
-
-
-jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticObjectMethodA: IMPLEMENT ME!");
-
-       return NewLocalRef(env, NULL);
-}
-
-
-jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list  ap;
-       jboolean ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap,
-                                                               PRIMITIVETYPE_BOOLEAN);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       jboolean ret;
-
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args,
-                                                               PRIMITIVETYPE_BOOLEAN);
-
-       return ret;
-}
-
-
-jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticBooleanMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jbyte   ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_BYTE);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       jbyte ret;
-
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_BYTE);
-
-       return ret;
-}
-
-
-jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticByteMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jchar   ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_CHAR);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       jchar ret;
-
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_CHAR);
-
-       return ret;
-}
-
-
-jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticCharMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jshort  ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_SHORT);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       jshort ret;
-
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args,
-                                                               PRIMITIVETYPE_SHORT);
-
-       return ret;
-}
-
-
-jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticShortMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jint    ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_INT);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       jint ret;
-
-       ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_INT);
-
-       return ret;
-}
-
-
-jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticIntMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jlong   ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallLongMethod(NULL, NULL, methodID, ap);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
-                                                       va_list args)
-{
-       jlong ret;
-       
-       ret = _Jv_jni_CallLongMethod(NULL, NULL, methodID, args);
-
-       return ret;
-}
-
-
-jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticLongMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-
-jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jfloat  ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallFloatMethod(NULL, NULL, methodID, ap);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       jfloat ret;
-
-       ret = _Jv_jni_CallFloatMethod(NULL, NULL, methodID, args);
-
-       return ret;
-}
-
-
-jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticFloatMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-       jdouble ret;
-
-       va_start(ap, methodID);
-       ret = _Jv_jni_CallDoubleMethod(NULL, NULL, methodID, ap);
-       va_end(ap);
-
-       return ret;
-}
-
-
-jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       jdouble ret;
-
-       ret = _Jv_jni_CallDoubleMethod(NULL, NULL, methodID, args);
-
-       return ret;
-}
-
-
-jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       log_text("JNI-Call: CallStaticDoubleMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list ap;
-
-       va_start(ap, methodID);
-       _Jv_jni_CallVoidMethod(NULL, NULL, methodID, ap);
-       va_end(ap);
-}
-
-
-void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       _Jv_jni_CallVoidMethod(NULL, NULL, methodID, args);
-}
-
-
-void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue * args)
-{
-       log_text("JNI-Call: CallStaticVoidMethodA: IMPLEMENT ME!");
-}
-
-
-/* Accessing Static Fields ****************************************************/
-
-/* GetStaticFieldID ************************************************************
-
-   Returns the field ID for a static field of a class. The field is
-   specified by its name and signature. The GetStatic<type>Field and
-   SetStatic<type>Field families of accessor functions use field IDs
-   to retrieve static fields.
-
-*******************************************************************************/
-
-jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
-{
-       jfieldID f;
-
-       STATISTICS(jniinvokation());
-
-       f = class_findfield(clazz,
-                                               utf_new_char((char *) name),
-                                               utf_new_char((char *) sig));
-       
-       if (!f)
-               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);
-
-       return f;
-}
-
-
-/* GetStatic<type>Field ********************************************************
-
-   This family of accessor routines returns the value of a static
-   field of an object.
-
-*******************************************************************************/
-
-jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return NULL;
-
-       return NewLocalRef(env, fieldID->value.a);
-}
-
-
-jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return false;
-
-       return fieldID->value.i;       
-}
-
-
-jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return 0;
-
-       return fieldID->value.i;       
-}
-
-
-jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return 0;
-
-       return fieldID->value.i;       
-}
-
-
-jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return 0;
-
-       return fieldID->value.i;       
-}
-
-
-jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return 0;
-
-       return fieldID->value.i;       
-}
-
-
-jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return 0;
-
-       return fieldID->value.l;
-}
-
-
-jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return 0.0;
-
-       return fieldID->value.f;
-}
-
-
-jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return 0.0;
-
-       return fieldID->value.d;
-}
-
-
-/*  SetStatic<type>Field *******************************************************
-
-       This family of accessor routines sets the value of a static field
-       of an object.
-
-*******************************************************************************/
-
-void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.a = value;
-}
-
-
-void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.i = value;
-}
-
-
-void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.i = value;
-}
-
-
-void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.i = value;
-}
-
-
-void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.i = value;
-}
-
-
-void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.i = value;
-}
-
-
-void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.l = value;
-}
-
-
-void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.f = value;
-}
-
-
-void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value)
-{
-       STATISTICS(jniinvokation());
-
-       if (!(clazz->state & CLASS_INITIALIZED))
-               if (!initialize_class(clazz))
-                       return;
-
-       fieldID->value.d = value;
-}
-
-
-/* String Operations **********************************************************/
-
-/* NewString *******************************************************************
-
-   Create new java.lang.String object from an array of Unicode
-   characters.
-
-*******************************************************************************/
-
-jstring NewString(JNIEnv *env, const jchar *buf, jsize len)
-{
-       java_lang_String *s;
-       java_chararray   *a;
-       u4                i;
-
-       STATISTICS(jniinvokation());
-       
-       s = (java_lang_String *) builtin_new(class_java_lang_String);
-       a = builtin_newarray_char(len);
-
-       /* javastring or characterarray could not be created */
-       if (!a || !s)
-               return NULL;
-
-       /* copy text */
-       for (i = 0; i < len; i++)
-               a->data[i] = buf[i];
-
-       s->value = a;
-       s->offset = 0;
-       s->count = len;
-
-       return (jstring) NewLocalRef(env, (jobject) s);
-}
-
-
-static jchar emptyStringJ[]={0,0};
-
-/* GetStringLength *************************************************************
-
-   Returns the length (the count of Unicode characters) of a Java
-   string.
-
-*******************************************************************************/
-
-jsize GetStringLength(JNIEnv *env, jstring str)
-{
-       return ((java_lang_String *) str)->count;
-}
-
-
-/********************  convertes javastring to u2-array ****************************/
-       
-u2 *javastring_tou2(jstring so) 
-{
-       java_lang_String *s;
-       java_chararray   *a;
-       u2               *stringbuffer;
-       u4                i;
-
-       STATISTICS(jniinvokation());
-       
-       s = (java_lang_String *) so;
-
-       if (!s)
-               return NULL;
-
-       a = s->value;
-
-       if (!a)
-               return NULL;
-
-       /* allocate memory */
-
-       stringbuffer = MNEW(u2, s->count + 1);
-
-       /* copy text */
-
-       for (i = 0; i < s->count; i++)
-               stringbuffer[i] = a->data[s->offset + i];
-       
-       /* terminate string */
-
-       stringbuffer[i] = '\0';
-
-       return stringbuffer;
-}
-
-
-/* GetStringChars **************************************************************
-
-   Returns a pointer to the array of Unicode characters of the
-   string. This pointer is valid until ReleaseStringchars() is called.
-
-*******************************************************************************/
-
-const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
-{      
-       jchar *jc;
-
-       STATISTICS(jniinvokation());
-
-       jc = javastring_tou2(str);
-
-       if (jc) {
-               if (isCopy)
-                       *isCopy = JNI_TRUE;
-
-               return jc;
-       }
-
-       if (isCopy)
-               *isCopy = JNI_TRUE;
-
-       return emptyStringJ;
-}
-
-
-/* ReleaseStringChars **********************************************************
-
-   Informs the VM that the native code no longer needs access to
-   chars. The chars argument is a pointer obtained from string using
-   GetStringChars().
-
-*******************************************************************************/
-
-void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
-{
-       STATISTICS(jniinvokation());
-
-       if (chars == emptyStringJ)
-               return;
-
-       MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1);
-}
-
-
-/* NewStringUTF ****************************************************************
-
-   Constructs a new java.lang.String object from an array of UTF-8 characters.
-
-*******************************************************************************/
-
-jstring NewStringUTF(JNIEnv *env, const char *bytes)
-{
-       java_lang_String *s;
-
-       STATISTICS(jniinvokation());
-
-       s = javastring_new(utf_new_char(bytes));
-
-    return (jstring) NewLocalRef(env, (jobject) s);
-}
-
-
-/****************** returns the utf8 length in bytes of a string *******************/
-
-jsize GetStringUTFLength (JNIEnv *env, jstring string)
-{   
-    java_lang_String *s = (java_lang_String*) string;
-
-       STATISTICS(jniinvokation());
-
-    return (jsize) u2_utflength(s->value->data, s->count); 
-}
-
-
-/* GetStringUTFChars ***********************************************************
-
-   Returns a pointer to an array of UTF-8 characters of the
-   string. This array is valid until it is released by
-   ReleaseStringUTFChars().
-
-*******************************************************************************/
-
-const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)
-{
-       utf *u;
-
-       STATISTICS(jniinvokation());
-
-       if (!string)
-               return "";
-
-       if (isCopy)
-               *isCopy = JNI_TRUE;
-       
-       u = javastring_toutf((java_lang_String *) string, false);
-
-       if (u)
-               return u->text;
-
-       return "";
-}
-
-
-/* ReleaseStringUTFChars *******************************************************
-
-   Informs the VM that the native code no longer needs access to
-   utf. The utf argument is a pointer derived from string using
-   GetStringUTFChars().
-
-*******************************************************************************/
-
-void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
-{
-       STATISTICS(jniinvokation());
-
-    /* XXX we don't release utf chars right now, perhaps that should be done 
-          later. Since there is always one reference the garbage collector will
-          never get them */
-}
-
-
-/* Array Operations ***********************************************************/
-
-/* GetArrayLength **************************************************************
-
-   Returns the number of elements in the array.
-
-*******************************************************************************/
-
-jsize GetArrayLength(JNIEnv *env, jarray array)
-{
-       STATISTICS(jniinvokation());
-
-       return array->size;
-}
-
-
-/* NewObjectArray **************************************************************
-
-   Constructs a new array holding objects in class elementClass. All
-   elements are initially set to initialElement.
-
-*******************************************************************************/
-
-jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)
-{
-       java_objectarray *oa;
-       s4                i;
-
-       STATISTICS(jniinvokation());
-
-       if (length < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-    oa = builtin_anewarray(length, elementClass);
-
-       if (!oa)
-               return NULL;
-
-       /* set all elements to initialElement */
-
-       for (i = 0; i < length; i++)
-               oa->data[i] = initialElement;
-
-       return (jobjectArray) NewLocalRef(env, (jobject) oa);
-}
-
-
-jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
-{
-    jobject o;
-
-       STATISTICS(jniinvokation());
-
-       if (index >= array->header.size) {
-               exceptions_throw_arrayindexoutofboundsexception();
-               return NULL;
-       }
-
-       o = array->data[index];
-    
-    return NewLocalRef(env, o);
-}
-
-
-void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val)
-{
-       java_objectarray  *oa;
-       java_objectheader *o;
-
-       STATISTICS(jniinvokation());
-
-       oa = (java_objectarray *) array;
-       o  = (java_objectheader *) val;
-
-    if (index >= array->header.size) {
-               exceptions_throw_arrayindexoutofboundsexception();
-               return;
-       }
-
-       /* check if the class of value is a subclass of the element class
-          of the array */
-
-       if (!builtin_canstore(oa, o)) {
-               *exceptionptr = new_exception(string_java_lang_ArrayStoreException);
-
-               return;
-       }
-
-       array->data[index] = val;
-}
-
-
-jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
-{
-       java_booleanarray *ba;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       ba = builtin_newarray_boolean(len);
-
-       return (jbooleanArray) NewLocalRef(env, (jobject) ba);
-}
-
-
-jbyteArray NewByteArray(JNIEnv *env, jsize len)
-{
-       java_bytearray *ba;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       ba = builtin_newarray_byte(len);
-
-       return (jbyteArray) NewLocalRef(env, (jobject) ba);
-}
-
-
-jcharArray NewCharArray(JNIEnv *env, jsize len)
-{
-       java_chararray *ca;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       ca = builtin_newarray_char(len);
-
-       return (jcharArray) NewLocalRef(env, (jobject) ca);
-}
-
-
-jshortArray NewShortArray(JNIEnv *env, jsize len)
-{
-       java_shortarray *sa;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       sa = builtin_newarray_short(len);
-
-       return (jshortArray) NewLocalRef(env, (jobject) sa);
-}
-
-
-jintArray NewIntArray(JNIEnv *env, jsize len)
-{
-       java_intarray *ia;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       ia = builtin_newarray_int(len);
-
-       return (jintArray) NewLocalRef(env, (jobject) ia);
-}
-
-
-jlongArray NewLongArray(JNIEnv *env, jsize len)
-{
-       java_longarray *la;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       la = builtin_newarray_long(len);
-
-       return (jlongArray) NewLocalRef(env, (jobject) la);
-}
-
-
-jfloatArray NewFloatArray(JNIEnv *env, jsize len)
-{
-       java_floatarray *fa;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       fa = builtin_newarray_float(len);
-
-       return (jfloatArray) NewLocalRef(env, (jobject) fa);
-}
-
-
-jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
-{
-       java_doublearray *da;
-
-       STATISTICS(jniinvokation());
-
-       if (len < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       da = builtin_newarray_double(len);
-
-       return (jdoubleArray) NewLocalRef(env, (jobject) da);
-}
-
-
-/* Get<PrimitiveType>ArrayElements *********************************************
-
-   A family of functions that returns the body of the primitive array.
-
-*******************************************************************************/
-
-jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array,
-                                                                 jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
-                                                               jboolean *isCopy)
-{
-       STATISTICS(jniinvokation());
-
-    if (isCopy)
-               *isCopy = JNI_FALSE;
-
-    return array->data;
-}
-
-
-/* Release<PrimitiveType>ArrayElements *****************************************
-
-   A family of functions that informs the VM that the native code no
-   longer needs access to elems. The elems argument is a pointer
-   derived from array using the corresponding
-   Get<PrimitiveType>ArrayElements() function. If necessary, this
-   function copies back all changes made to elems to the original
-   array.
-
-*******************************************************************************/
-
-void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
-                                                                jboolean *elems, jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems,
-                                                         jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems,
-                                                         jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems,
-                                                          jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
-                                                        jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems,
-                                                         jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems,
-                                                          jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
-                                                               jdouble *elems, jint mode)
-{
-       STATISTICS(jniinvokation());
-
-       if (elems != array->data) {
-               switch (mode) {
-               case JNI_COMMIT:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       break;
-               case 0:
-                       MCOPY(array->data, elems, jboolean, array->header.size);
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               case JNI_ABORT:
-                       /* XXX TWISTI how should it be freed? */
-                       break;
-               }
-       }
-}
-
-
-/*  Get<PrimitiveType>ArrayRegion **********************************************
-
-       A family of functions that copies a region of a primitive array
-       into a buffer.
-
-*******************************************************************************/
-
-void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
-                                                  jsize len, jboolean *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jboolean, len);
-}
-
-
-void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
-                                               jbyte *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size) 
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jbyte, len);
-}
+/* NewObjectArray **************************************************************
 
+   Constructs a new array holding objects in class elementClass. All
+   elements are initially set to initialElement.
+
+*******************************************************************************/
 
-void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
-                                               jchar *buf)
+jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
+                                                                       jclass elementClass, jobject initialElement)
 {
+       classinfo                 *c;
+       java_handle_t             *o;
+       java_handle_objectarray_t *oa;
+       s4                         i;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jchar, len);
-}
+       c = LLNI_classinfo_unwrap(elementClass);
+       o = (java_handle_t *) initialElement;
 
+       if (length < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
-void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
-                                                jsize len, jshort *buf)
-{
-       STATISTICS(jniinvokation());
+    oa = builtin_anewarray(length, c);
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else       
-               MCOPY(buf, &array->data[start], jshort, len);
-}
+       if (oa == NULL)
+               return NULL;
 
+       /* set all elements to initialElement */
 
-void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
-                                          jint *buf)
-{
-       STATISTICS(jniinvokation());
+       for (i = 0; i < length; i++)
+               LLNI_objectarray_element_set(oa, i, o);
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jint, len);
+       return (jobjectArray) _Jv_JNI_NewLocalRef(env, (jobject) oa);
 }
 
 
-void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len,
-                                               jlong *buf)
+jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
+                                                                         jsize index)
 {
+       java_handle_objectarray_t *oa;
+       java_handle_t             *o;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jlong, len);
-}
+       oa = (java_handle_objectarray_t *) array;
 
+       if (index >= LLNI_array_size(oa)) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return NULL;
+       }
 
-void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
-                                                jsize len, jfloat *buf)
-{
-       STATISTICS(jniinvokation());
+       LLNI_objectarray_element_get(oa, index, o);
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jfloat, len);
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
-                                                 jsize len, jdouble *buf)
+void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
+                                                                  jsize index, jobject val)
 {
+       java_handle_objectarray_t *oa;
+       java_handle_t             *o;
+
        STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start+len>array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jdouble, len);
-}
+       oa = (java_handle_objectarray_t *) array;
+       o  = (java_handle_t *) val;
 
+       if (index >= LLNI_array_size(oa)) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return;
+       }
 
-/*  Set<PrimitiveType>ArrayRegion **********************************************
+       /* check if the class of value is a subclass of the element class
+          of the array */
 
-       A family of functions that copies back a region of a primitive
-       array from a buffer.
+       if (!builtin_canstore(oa, o))
+               return;
 
-*******************************************************************************/
+       LLNI_objectarray_element_set(oa, index, o);
+}
 
-void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
-                                                  jsize len, jboolean *buf)
-{
-       STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jboolean, len);
+#define JNI_NEW_ARRAY(name, type, intern)                \
+type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
+{                                                        \
+       java_handle_##intern##array_t *a;                    \
+                                                         \
+       STATISTICS(jniinvokation());                         \
+                                                         \
+       if (len < 0) {                                       \
+               exceptions_throw_negativearraysizeexception();   \
+               return NULL;                                     \
+       }                                                    \
+                                                         \
+       a = builtin_newarray_##intern(len);                  \
+                                                         \
+       return (type) _Jv_JNI_NewLocalRef(env, (jobject) a); \
 }
 
+JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
+JNI_NEW_ARRAY(Byte,    jbyteArray,    byte)
+JNI_NEW_ARRAY(Char,    jcharArray,    char)
+JNI_NEW_ARRAY(Short,   jshortArray,   byte)
+JNI_NEW_ARRAY(Int,     jintArray,     int)
+JNI_NEW_ARRAY(Long,    jlongArray,    long)
+JNI_NEW_ARRAY(Float,   jfloatArray,   float)
+JNI_NEW_ARRAY(Double,  jdoubleArray,  double)
 
-void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
-                                               jbyte *buf)
-{
-       STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jbyte, len);
-}
+/* Get<PrimitiveType>ArrayElements *********************************************
 
+   A family of functions that returns the body of the primitive array.
 
-void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
-                                               jchar *buf)
-{
-       STATISTICS(jniinvokation());
+*******************************************************************************/
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jchar, len);
-}
+#define JNI_GET_ARRAY_ELEMENTS(name, type, intern)                     \
+type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
+                                                                                jboolean *isCopy)             \
+{                                                                      \
+       java_handle_##intern##array_t *a;                                  \
+                                                                       \
+       STATISTICS(jniinvokation());                                       \
+                                                                       \
+       a = (java_handle_##intern##array_t *) array;                       \
+                                                                       \
+       if (isCopy)                                                        \
+               *isCopy = JNI_FALSE;                                           \
+                                                                       \
+       return LLNI_array_data(a);                                         \
+}
+
+JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
+JNI_GET_ARRAY_ELEMENTS(Byte,    jbyte,    byte)
+JNI_GET_ARRAY_ELEMENTS(Char,    jchar,    char)
+JNI_GET_ARRAY_ELEMENTS(Short,   jshort,   short)
+JNI_GET_ARRAY_ELEMENTS(Int,     jint,     int)
+JNI_GET_ARRAY_ELEMENTS(Long,    jlong,    long)
+JNI_GET_ARRAY_ELEMENTS(Float,   jfloat,   float)
+JNI_GET_ARRAY_ELEMENTS(Double,  jdouble,  double)
 
 
-void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
-                                                jsize len, jshort *buf)
-{
-       STATISTICS(jniinvokation());
+/* Release<PrimitiveType>ArrayElements *****************************************
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jshort, len);
-}
+   A family of functions that informs the VM that the native code no
+   longer needs access to elems. The elems argument is a pointer
+   derived from array using the corresponding
+   Get<PrimitiveType>ArrayElements() function. If necessary, this
+   function copies back all changes made to elems to the original
+   array.
 
+*******************************************************************************/
 
-void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
-                                          jint *buf)
-{
-       STATISTICS(jniinvokation());
+#define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2)            \
+void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
+                                                                                 type *elems, jint mode)          \
+{                                                                          \
+       java_handle_##intern##array_t *a;                                      \
+                                                                           \
+       STATISTICS(jniinvokation());                                           \
+                                                                           \
+       a = (java_handle_##intern##array_t *) array;                           \
+                                                                           \
+       if (elems != LLNI_array_data(a)) {                                     \
+               switch (mode) {                                                    \
+               case JNI_COMMIT:                                                   \
+                       MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
+                       break;                                                         \
+               case 0:                                                            \
+                       MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
+                       /* XXX TWISTI how should it be freed? */                       \
+                       break;                                                         \
+               case JNI_ABORT:                                                    \
+                       /* XXX TWISTI how should it be freed? */                       \
+                       break;                                                         \
+               }                                                                  \
+       }                                                                      \
+}
+
+JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
+JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    s1)
+JNI_RELEASE_ARRAY_ELEMENTS(Char,    jchar,    char,    u2)
+JNI_RELEASE_ARRAY_ELEMENTS(Short,   jshort,   short,   s2)
+JNI_RELEASE_ARRAY_ELEMENTS(Int,     jint,     int,     s4)
+JNI_RELEASE_ARRAY_ELEMENTS(Long,    jlong,    long,    s8)
+JNI_RELEASE_ARRAY_ELEMENTS(Float,   jfloat,   float,   float)
+JNI_RELEASE_ARRAY_ELEMENTS(Double,  jdouble,  double,  double)
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jint, len);
-}
 
+/*  Get<PrimitiveType>ArrayRegion **********************************************
 
-void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len,
-                                               jlong *buf)
-{
-       STATISTICS(jniinvokation());
+       A family of functions that copies a region of a primitive array
+       into a buffer.
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jlong, len);
-}
+*******************************************************************************/
 
+#define JNI_GET_ARRAY_REGION(name, type, intern, intern2)               \
+void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
+                                                                       jsize start, jsize len, type *buf)  \
+{                                                                       \
+       java_handle_##intern##array_t *a;                                   \
+                                                                        \
+       STATISTICS(jniinvokation());                                        \
+                                                                        \
+       a = (java_handle_##intern##array_t *) array;                        \
+                                                                        \
+       if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
+               exceptions_throw_arrayindexoutofboundsexception();              \
+       else                                                                \
+               MCOPY(buf, &LLNI_array_direct(a, start), intern2, len);         \
+}
+
+JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
+JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
+JNI_GET_ARRAY_REGION(Char,    jchar,    char,    u2)
+JNI_GET_ARRAY_REGION(Short,   jshort,   short,   s2)
+JNI_GET_ARRAY_REGION(Int,     jint,     int,     s4)
+JNI_GET_ARRAY_REGION(Long,    jlong,    long,    s8)
+JNI_GET_ARRAY_REGION(Float,   jfloat,   float,   float)
+JNI_GET_ARRAY_REGION(Double,  jdouble,  double,  double)
 
-void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
-                                                jsize len, jfloat *buf)
-{
-       STATISTICS(jniinvokation());
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jfloat, len);
-}
+/*  Set<PrimitiveType>ArrayRegion **********************************************
 
+       A family of functions that copies back a region of a primitive
+       array from a buffer.
 
-void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
-                                                 jsize len, jdouble *buf)
-{
-       STATISTICS(jniinvokation());
+*******************************************************************************/
 
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jdouble, len);
-}
+#define JNI_SET_ARRAY_REGION(name, type, intern, intern2)                    \
+void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
+                                                                       jsize start, jsize len, const type *buf) \
+{                                                                            \
+       java_handle_##intern##array_t *a;                                        \
+                                                                             \
+       STATISTICS(jniinvokation());                                             \
+                                                                             \
+       a = (java_handle_##intern##array_t *) array;                             \
+                                                                             \
+       if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a)))      \
+               exceptions_throw_arrayindexoutofboundsexception();                   \
+       else                                                                     \
+               MCOPY(&LLNI_array_direct(a, start), buf, intern2, len);              \
+}
+
+JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
+JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
+JNI_SET_ARRAY_REGION(Char,    jchar,    char,    u2)
+JNI_SET_ARRAY_REGION(Short,   jshort,   short,   s2)
+JNI_SET_ARRAY_REGION(Int,     jint,     int,     s4)
+JNI_SET_ARRAY_REGION(Long,    jlong,    long,    s8)
+JNI_SET_ARRAY_REGION(Float,   jfloat,   float,   float)
+JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
 
 
 /* Registering Native Methods *************************************************/
@@ -4278,12 +3130,20 @@ void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
 
 *******************************************************************************/
 
-jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
-                                        jint nMethods)
+jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
+                                                        const JNINativeMethod *methods, jint nMethods)
 {
+       classinfo *c;
+
        STATISTICS(jniinvokation());
 
-    log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!");
+       c = LLNI_classinfo_unwrap(clazz);
+
+       /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
+       if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
+       */
+
+       native_method_register(c->name, methods, nMethods);
 
     return 0;
 }
@@ -4301,7 +3161,7 @@ jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
 
 *******************************************************************************/
 
-jint UnregisterNatives(JNIEnv *env, jclass clazz)
+jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
 {
        STATISTICS(jniinvokation());
 
@@ -4322,18 +3182,16 @@ jint UnregisterNatives(JNIEnv *env, jclass clazz)
 
 *******************************************************************************/
 
-jint MonitorEnter(JNIEnv *env, jobject obj)
+jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
 {
        STATISTICS(jniinvokation());
 
-       if (!obj) {
+       if (obj == NULL) {
                exceptions_throw_nullpointerexception();
                return JNI_ERR;
        }
 
-#if defined(USE_THREADS)
-       builtin_monitorenter(obj);
-#endif
+       LOCK_MONITOR_ENTER(obj);
 
        return JNI_OK;
 }
@@ -4349,18 +3207,16 @@ jint MonitorEnter(JNIEnv *env, jobject obj)
 
 *******************************************************************************/
 
-jint MonitorExit(JNIEnv *env, jobject obj)
+jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
 {
        STATISTICS(jniinvokation());
 
-       if (!obj) {
+       if (obj == NULL) {
                exceptions_throw_nullpointerexception();
                return JNI_ERR;
        }
 
-#if defined(USE_THREADS)
-       builtin_monitorexit(obj);
-#endif
+       LOCK_MONITOR_EXIT(obj);
 
        return JNI_OK;
 }
@@ -4376,29 +3232,81 @@ jint MonitorExit(JNIEnv *env, jobject obj)
 
 *******************************************************************************/
 
-jint GetJavaVM(JNIEnv *env, JavaVM **vm)
+jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **vm)
 {
        STATISTICS(jniinvokation());
 
-    *vm = &ptr_jvm;
+    *vm = (JavaVM *) _Jv_jvm;
 
        return 0;
 }
 
 
-void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
+/* GetStringRegion *************************************************************
+
+   Copies len number of Unicode characters beginning at offset start
+   to the given buffer buf.
+
+   Throws StringIndexOutOfBoundsException on index overflow.
+
+*******************************************************************************/
+
+void _Jv_JNI_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
+                                                        jchar *buf)
 {
+       java_lang_String        *s;
+       java_handle_chararray_t *ca;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: GetStringRegion: IMPLEMENT ME!");
+       s  = (java_lang_String *) str;
+       LLNI_field_get_ref(s, value, ca);
+
+       if ((start < 0) || (len < 0) || (start > LLNI_field_direct(s, count)) ||
+               (start + len > LLNI_field_direct(s, count))) {
+               exceptions_throw_stringindexoutofboundsexception();
+               return;
+       }
+
+       MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
 }
 
 
-void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
+/* GetStringUTFRegion **********************************************************
+
+    Translates len number of Unicode characters beginning at offset
+    start into UTF-8 format and place the result in the given buffer
+    buf.
+
+    Throws StringIndexOutOfBoundsException on index overflow. 
+
+*******************************************************************************/
+
+void _Jv_JNI_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
+                                                               jsize len, char *buf)
 {
-       STATISTICS(jniinvokation());
+       java_lang_String        *s;
+       java_handle_chararray_t *ca;
+       s4                       i;
+       int32_t                  count;
+       int32_t                  offset;
+
+       TRACEJNICALLS("_Jv_JNI_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf);
+
+       s  = (java_lang_String *) str;
+       LLNI_field_get_ref(s, value, ca);
+       LLNI_field_get_val(s, count, count);
+       LLNI_field_get_val(s, offset, offset);
+
+       if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
+               exceptions_throw_stringindexoutofboundsexception();
+               return;
+       }
+
+       for (i = 0; i < len; i++)
+               buf[i] = LLNI_array_direct(ca, offset + start + i);
 
-       log_text("JNI-Call: GetStringUTFRegion: IMPLEMENT ME!");
+       buf[i] = '\0';
 }
 
 
@@ -4408,16 +3316,17 @@ void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char
 
 *******************************************************************************/
 
-void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
+void *_Jv_JNI_GetPrimitiveArrayCritical(JNIEnv *env, jarray array,
+                                                                               jboolean *isCopy)
 {
-       java_bytearray *ba;
-       jbyte          *bp;
+       java_handle_bytearray_t *ba;
+       jbyte                   *bp;
 
-       ba = (java_bytearray *) array;
+       ba = (java_handle_bytearray_t *) array;
 
        /* do the same as Kaffe does */
 
-       bp = GetByteArrayElements(env, ba, isCopy);
+       bp = _Jv_JNI_GetByteArrayElements(env, (jbyteArray) ba, isCopy);
 
        return (void *) bp;
 }
@@ -4429,14 +3338,15 @@ void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
 
 *******************************************************************************/
 
-void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray,
-                                                                  jint mode)
+void _Jv_JNI_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array,
+                                                                                  void *carray, jint mode)
 {
        STATISTICS(jniinvokation());
 
        /* do the same as Kaffe does */
 
-       ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray, mode);
+       _Jv_JNI_ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray,
+                                                                        mode);
 }
 
 
@@ -4447,23 +3357,25 @@ void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray,
 
 *******************************************************************************/
 
-const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)
+const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
+                                                                          jboolean *isCopy)
 {
        STATISTICS(jniinvokation());
 
-       return GetStringChars(env, string, isCopy);
+       return _Jv_JNI_GetStringChars(env, string, isCopy);
 }
 
 
-void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring)
+void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
+                                                                  const jchar *cstring)
 {
        STATISTICS(jniinvokation());
 
-       ReleaseStringChars(env, string, cstring);
+       _Jv_JNI_ReleaseStringChars(env, string, cstring);
 }
 
 
-jweak NewWeakGlobalRef(JNIEnv* env, jobject obj)
+jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
 {
        STATISTICS(jniinvokation());
 
@@ -4473,7 +3385,7 @@ jweak NewWeakGlobalRef(JNIEnv* env, jobject obj)
 }
 
 
-void DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
+void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
 {
        STATISTICS(jniinvokation());
 
@@ -4488,46 +3400,61 @@ void DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
 
 *******************************************************************************/
     
-jobject NewGlobalRef(JNIEnv* env, jobject lobj)
+jobject _Jv_JNI_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                  */
+       java_handle_t *o;
 
        STATISTICS(jniinvokation());
 
-#if defined(USE_THREADS)
-       builtin_monitorenter(*global_ref_table);
-#endif
+       o = (java_handle_t *) obj;
+
+       LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+
+       /* 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 == o) {
+                       /* 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);
-#endif
-                       return NULL;
+                       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+
+                       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);
 
-#if defined(USE_THREADS)
-       builtin_monitorexit(*global_ref_table);
-#endif
+       gre->o    = o;
+       gre->refs = 1;
+
+       /* insert entry into hashtable */
+
+       gre->hashlink = hashtable_global_ref->ptr[slot];
 
-       return lobj;
+       hashtable_global_ref->ptr[slot] = gre;
+
+       /* update number of hashtable-entries */
+
+       hashtable_global_ref->entries++;
+
+       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+
+       return obj;
 }
 
 
@@ -4537,47 +3464,63 @@ jobject NewGlobalRef(JNIEnv* env, jobject lobj)
 
 *******************************************************************************/
 
-void DeleteGlobalRef(JNIEnv* env, jobject globalRef)
+void _Jv_JNI_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                  */
+       java_handle_t              *o;
 
        STATISTICS(jniinvokation());
 
-#if defined(USE_THREADS)
-       builtin_monitorenter(*global_ref_table);
-#endif
+       o = (java_handle_t *) globalRef;
 
-       ASM_CALLJAVAFUNCTION_ADR(o, getmid, *global_ref_table, globalRef, NULL,
-                                                        NULL);
+       LOCK_MONITOR_ENTER(hashtable_global_ref->header);
 
-       refcount = (java_lang_Integer *) o;
+       /* normally addresses are aligned to 4, 8 or 16 bytes */
 
-       if (refcount == NULL) {
-               log_text("JNI-DeleteGlobalRef: unable to find global reference");
-               return;
-       }
+       key  = ((u4) (ptrint) globalRef) >> 4;     /* align to 16-byte boundaries */
+       slot = key & (hashtable_global_ref->size - 1);
+       gre  = hashtable_global_ref->ptr[slot];
 
-       /* we can access the object itself, as we are in a synchronized
-          section */
+       /* initialize prevgre */
 
-       val = refcount->value - 1;
+       prevgre = NULL;
 
-       if (val == 0) {
-               ASM_CALLJAVAFUNCTION(removemid, *global_ref_table, refcount, NULL,
-                                                        NULL);
+       /* search external hash chain for the entry */
 
-       } else {
-               /* we do not create a new object, but set the new value into
-           the old one */
+       while (gre) {
+               if (gre->o == o) {
+                       /* global object found, decrement the reference count */
+
+                       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);
+                       }
+
+                       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
 
-               refcount->value = val;
+                       return;
+               }
+
+               prevgre = gre;                    /* save current pointer for removal */
+               gre     = gre->hashlink;            /* next element in external chain */
        }
 
-#if defined(USE_THREADS)
-       builtin_monitorexit(*global_ref_table);
-#endif
+       log_println("JNI-DeleteGlobalRef: global reference not found");
+
+       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
 }
 
 
@@ -4588,11 +3531,15 @@ void DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 
 *******************************************************************************/
 
-jboolean ExceptionCheck(JNIEnv *env)
+jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
 {
+       java_handle_t *o;
+
        STATISTICS(jniinvokation());
 
-       return *exceptionptr ? JNI_TRUE : JNI_FALSE;
+       o = exceptions_get_exception();
+
+       return (o != NULL) ? JNI_TRUE : JNI_FALSE;
 }
 
 
@@ -4606,41 +3553,50 @@ jboolean ExceptionCheck(JNIEnv *env)
 
 *******************************************************************************/
 
-jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
+jobject _Jv_JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 {
-       java_objectheader       *nbuf;
-#if SIZEOF_VOID_P == 8
+#if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
+       java_handle_t           *nbuf;
+
+# if SIZEOF_VOID_P == 8
        gnu_classpath_Pointer64 *paddress;
-#else
+# else
        gnu_classpath_Pointer32 *paddress;
-#endif
+# endif
 
        STATISTICS(jniinvokation());
 
        /* alocate a gnu.classpath.Pointer{32,64} object */
 
-#if SIZEOF_VOID_P == 8
+# if SIZEOF_VOID_P == 8
        if (!(paddress = (gnu_classpath_Pointer64 *)
                  builtin_new(class_gnu_classpath_Pointer64)))
-#else
+# else
        if (!(paddress = (gnu_classpath_Pointer32 *)
                  builtin_new(class_gnu_classpath_Pointer32)))
-#endif
+# endif
                return NULL;
 
        /* fill gnu.classpath.Pointer{32,64} with address */
 
-       paddress->data = (ptrint) address;
+       LLNI_field_set_val(paddress, data, (ptrint) address);
 
        /* 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 */
 
-       return NewLocalRef(env, nbuf);
+       return _Jv_JNI_NewLocalRef(env, nbuf);
+#else
+       vm_abort("_Jv_JNI_NewDirectByteBuffer: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
 }
 
 
@@ -4651,14 +3607,16 @@ jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 
 *******************************************************************************/
 
-void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
+void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
 {
+#if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
        java_nio_DirectByteBufferImpl *nbuf;
-#if SIZEOF_VOID_P == 8
-       gnu_classpath_Pointer64       *address;
-#else
-       gnu_classpath_Pointer32       *address;
-#endif
+# if SIZEOF_VOID_P == 8
+       gnu_classpath_Pointer64       *paddress;
+# else
+       gnu_classpath_Pointer32       *paddress;
+# endif
+       void                          *address;
 
        STATISTICS(jniinvokation());
 
@@ -4667,13 +3625,28 @@ void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
 
        nbuf = (java_nio_DirectByteBufferImpl *) buf;
 
-#if SIZEOF_VOID_P == 8
-       address = (gnu_classpath_Pointer64 *) nbuf->address;
+# if SIZEOF_VOID_P == 8
+       LLNI_field_get_ref(nbuf, address, paddress);
+       /* this was the cast to avaoid warning: (gnu_classpath_Pointer64 *) nbuf->address; */
+# else
+       LLNI_field_get_ref(nbuf, address, paddress); 
+       /* this was the cast to avaoid warning: (gnu_classpath_Pointer32 *) nbuf->address; */
+# endif
+
+       if (paddress == NULL)
+               return NULL;
+
+       LLNI_field_get_val(paddress, data, address);
+       /* this was the cast to avaoid warning: (void *) paddress->data */
+
+       return address;
 #else
-       address = (gnu_classpath_Pointer32 *) nbuf->address;
-#endif
+       vm_abort("_Jv_JNI_GetDirectBufferAddress: not implemented in this configuration");
+
+       /* keep compiler happy */
 
-       return (void *) address->data;
+       return NULL;
+#endif
 }
 
 
@@ -4684,28 +3657,52 @@ void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
 
 *******************************************************************************/
 
-jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf)
+jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
 {
+#if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
+       java_handle_t   *o;
        java_nio_Buffer *nbuf;
+       jlong            capacity;
 
        STATISTICS(jniinvokation());
 
-       if (!builtin_instanceof(buf, class_java_nio_DirectByteBufferImpl))
+       o = (java_handle_t *) buf;
+
+       if (!builtin_instanceof(o, class_java_nio_DirectByteBufferImpl))
                return -1;
 
-       nbuf = (java_nio_Buffer *) buf;
+       nbuf = (java_nio_Buffer *) o;
+
+       LLNI_field_get_val(nbuf, cap, capacity);
+
+       return capacity;
+#else
+       vm_abort("_Jv_JNI_GetDirectBufferCapacity: not implemented in this configuration");
+
+       /* keep compiler happy */
 
-       return (jlong) nbuf->cap;
+       return 0;
+#endif
 }
 
 
-jint DestroyJavaVM(JavaVM *vm)
+/* 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 _Jv_JNI_DestroyJavaVM(JavaVM *vm)
 {
+       s4 status;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: DestroyJavaVM: IMPLEMENT ME!");
+    status = vm_destroy(vm);
 
-       return 0;
+       return status;
 }
 
 
@@ -4723,31 +3720,76 @@ jint DestroyJavaVM(JavaVM *vm)
 
 *******************************************************************************/
 
-jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args)
+static s4 jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
 {
-       STATISTICS(jniinvokation());
+       JavaVMAttachArgs *vm_aargs;
 
-       log_text("JNI-Call: AttachCurrentThread: IMPLEMENT ME!");
+#if defined(ENABLE_THREADS)
+       if (threads_get_current_threadobject() == NULL) {
+               vm_aargs = (JavaVMAttachArgs *) thr_args;
 
-#if !defined(HAVE___THREAD)
-/*     cacao_thread_attach();*/
-#else
-       #error "No idea how to implement that. Perhaps Stefan knows"
+               if (vm_aargs != NULL) {
+                       if ((vm_aargs->version != JNI_VERSION_1_2) &&
+                               (vm_aargs->version != JNI_VERSION_1_4))
+                               return JNI_EVERSION;
+               }
+
+               if (!threads_attach_current_thread(vm_aargs, false))
+                       return JNI_ERR;
+
+               if (!localref_table_init())
+                       return JNI_ERR;
+       }
 #endif
 
-       *env = &ptr_env;
+       *p_env = _Jv_env;
 
-       return 0;
+       return JNI_OK;
 }
 
 
-jint DetachCurrentThread(JavaVM *vm)
+jint _Jv_JNI_AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args)
 {
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: DetachCurrentThread: IMPLEMENT ME!");
+       return jni_attach_current_thread(p_env, thr_args, false);
+}
+
 
-       return 0;
+/* DetachCurrentThread *********************************************************
+
+   Detaches the current thread from a Java VM. All Java monitors held
+   by this thread are released. All Java threads waiting for this
+   thread to die are notified.
+
+   In JDK 1.1, the main thread cannot be detached from the VM. It must
+   call DestroyJavaVM to unload the entire VM.
+
+   In the JDK, the main thread can be detached from the VM.
+
+   The main thread, which is the thread that created the Java VM,
+   cannot be detached from the VM. Instead, the main thread must call
+   JNI_DestroyJavaVM() to unload the entire VM.
+
+*******************************************************************************/
+
+jint _Jv_JNI_DetachCurrentThread(JavaVM *vm)
+{
+#if defined(ENABLE_THREADS)
+       threadobject *thread;
+
+       STATISTICS(jniinvokation());
+
+       thread = threads_get_current_threadobject();
+
+       if (thread == NULL)
+               return JNI_ERR;
+
+       if (!threads_detach_thread(thread))
+               return JNI_ERR;
+#endif
+
+       return JNI_OK;
 }
 
 
@@ -4760,28 +3802,36 @@ jint DetachCurrentThread(JavaVM *vm)
 
 *******************************************************************************/
 
-jint GetEnv(JavaVM *vm, void **env, jint version)
+jint _Jv_JNI_GetEnv(JavaVM *vm, void **env, jint version)
 {
        STATISTICS(jniinvokation());
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       if (thread_getself() == NULL) {
+#if defined(ENABLE_THREADS)
+       if (threads_get_current_threadobject() == NULL) {
                *env = NULL;
 
                return JNI_EDETACHED;
        }
 #endif
 
-       if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) ||
-               (version == JNI_VERSION_1_4)) {
-               *env = &ptr_env;
+       /* check the JNI version */
 
+       switch (version) {
+       case JNI_VERSION_1_1:
+       case JNI_VERSION_1_2:
+       case JNI_VERSION_1_4:
+               *env = _Jv_env;
                return JNI_OK;
+
+       default:
+               ;
        }
 
 #if defined(ENABLE_JVMTI)
-       if (version == JVMTI_VERSION_1_0) {
-               *env = (void *) new_jvmtienv();
+       if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE) 
+               == JVMTI_VERSION_INTERFACE_JVMTI) {
+
+               *env = (void *) jvmti_new_environment();
 
                if (env != NULL)
                        return JNI_OK;
@@ -4794,302 +3844,312 @@ jint GetEnv(JavaVM *vm, void **env, jint version)
 }
 
 
+/* AttachCurrentThreadAsDaemon *************************************************
+
+   Same semantics as AttachCurrentThread, but the newly-created
+   java.lang.Thread instance is a daemon.
 
-jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
+   If the thread has already been attached via either
+   AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
+   simply sets the value pointed to by penv to the JNIEnv of the
+   current thread. In this case neither AttachCurrentThread nor this
+   routine have any effect on the daemon status of the thread.
+
+*******************************************************************************/
+
+jint _Jv_JNI_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)
 {
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: AttachCurrentThreadAsDaemon: IMPLEMENT ME!");
-
-       return 0;
+       return jni_attach_current_thread(penv, args, true);
 }
 
 
 /* JNI invocation table *******************************************************/
 
-const struct JNIInvokeInterface JNI_JavaVMTable = {
+const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
        NULL,
        NULL,
        NULL,
 
-       DestroyJavaVM,
-       AttachCurrentThread,
-       DetachCurrentThread,
-       GetEnv,
-       AttachCurrentThreadAsDaemon
+       _Jv_JNI_DestroyJavaVM,
+       _Jv_JNI_AttachCurrentThread,
+       _Jv_JNI_DetachCurrentThread,
+       _Jv_JNI_GetEnv,
+       _Jv_JNI_AttachCurrentThreadAsDaemon
 };
 
 
 /* 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,
+       _Jv_JNI_GetVersion,
+
+       _Jv_JNI_DefineClass,
+       _Jv_JNI_FindClass,
+       _Jv_JNI_FromReflectedMethod,
+       _Jv_JNI_FromReflectedField,
+       _Jv_JNI_ToReflectedMethod,
+       _Jv_JNI_GetSuperclass,
+       _Jv_JNI_IsAssignableFrom,
+       _Jv_JNI_ToReflectedField,
+
+       _Jv_JNI_Throw,
+       _Jv_JNI_ThrowNew,
+       _Jv_JNI_ExceptionOccurred,
+       _Jv_JNI_ExceptionDescribe,
+       _Jv_JNI_ExceptionClear,
+       _Jv_JNI_FatalError,
+       _Jv_JNI_PushLocalFrame,
+       _Jv_JNI_PopLocalFrame,
+
+       _Jv_JNI_NewGlobalRef,
+       _Jv_JNI_DeleteGlobalRef,
+       _Jv_JNI_DeleteLocalRef,
+       _Jv_JNI_IsSameObject,
+       _Jv_JNI_NewLocalRef,
+       _Jv_JNI_EnsureLocalCapacity,
+
+       _Jv_JNI_AllocObject,
+       _Jv_JNI_NewObject,
+       _Jv_JNI_NewObjectV,
+       _Jv_JNI_NewObjectA,
+
+       _Jv_JNI_GetObjectClass,
+       _Jv_JNI_IsInstanceOf,
+
+       _Jv_JNI_GetMethodID,
+
+       _Jv_JNI_CallObjectMethod,
+       _Jv_JNI_CallObjectMethodV,
+       _Jv_JNI_CallObjectMethodA,
+       _Jv_JNI_CallBooleanMethod,
+       _Jv_JNI_CallBooleanMethodV,
+       _Jv_JNI_CallBooleanMethodA,
+       _Jv_JNI_CallByteMethod,
+       _Jv_JNI_CallByteMethodV,
+       _Jv_JNI_CallByteMethodA,
+       _Jv_JNI_CallCharMethod,
+       _Jv_JNI_CallCharMethodV,
+       _Jv_JNI_CallCharMethodA,
+       _Jv_JNI_CallShortMethod,
+       _Jv_JNI_CallShortMethodV,
+       _Jv_JNI_CallShortMethodA,
+       _Jv_JNI_CallIntMethod,
+       _Jv_JNI_CallIntMethodV,
+       _Jv_JNI_CallIntMethodA,
+       _Jv_JNI_CallLongMethod,
+       _Jv_JNI_CallLongMethodV,
+       _Jv_JNI_CallLongMethodA,
+       _Jv_JNI_CallFloatMethod,
+       _Jv_JNI_CallFloatMethodV,
+       _Jv_JNI_CallFloatMethodA,
+       _Jv_JNI_CallDoubleMethod,
+       _Jv_JNI_CallDoubleMethodV,
+       _Jv_JNI_CallDoubleMethodA,
+       _Jv_JNI_CallVoidMethod,
+       _Jv_JNI_CallVoidMethodV,
+       _Jv_JNI_CallVoidMethodA,
+
+       _Jv_JNI_CallNonvirtualObjectMethod,
+       _Jv_JNI_CallNonvirtualObjectMethodV,
+       _Jv_JNI_CallNonvirtualObjectMethodA,
+       _Jv_JNI_CallNonvirtualBooleanMethod,
+       _Jv_JNI_CallNonvirtualBooleanMethodV,
+       _Jv_JNI_CallNonvirtualBooleanMethodA,
+       _Jv_JNI_CallNonvirtualByteMethod,
+       _Jv_JNI_CallNonvirtualByteMethodV,
+       _Jv_JNI_CallNonvirtualByteMethodA,
+       _Jv_JNI_CallNonvirtualCharMethod,
+       _Jv_JNI_CallNonvirtualCharMethodV,
+       _Jv_JNI_CallNonvirtualCharMethodA,
+       _Jv_JNI_CallNonvirtualShortMethod,
+       _Jv_JNI_CallNonvirtualShortMethodV,
+       _Jv_JNI_CallNonvirtualShortMethodA,
+       _Jv_JNI_CallNonvirtualIntMethod,
+       _Jv_JNI_CallNonvirtualIntMethodV,
+       _Jv_JNI_CallNonvirtualIntMethodA,
+       _Jv_JNI_CallNonvirtualLongMethod,
+       _Jv_JNI_CallNonvirtualLongMethodV,
+       _Jv_JNI_CallNonvirtualLongMethodA,
+       _Jv_JNI_CallNonvirtualFloatMethod,
+       _Jv_JNI_CallNonvirtualFloatMethodV,
+       _Jv_JNI_CallNonvirtualFloatMethodA,
+       _Jv_JNI_CallNonvirtualDoubleMethod,
+       _Jv_JNI_CallNonvirtualDoubleMethodV,
+       _Jv_JNI_CallNonvirtualDoubleMethodA,
+       _Jv_JNI_CallNonvirtualVoidMethod,
+       _Jv_JNI_CallNonvirtualVoidMethodV,
+       _Jv_JNI_CallNonvirtualVoidMethodA,
+
+       _Jv_JNI_GetFieldID,
+
+       _Jv_JNI_GetObjectField,
+       _Jv_JNI_GetBooleanField,
+       _Jv_JNI_GetByteField,
+       _Jv_JNI_GetCharField,
+       _Jv_JNI_GetShortField,
+       _Jv_JNI_GetIntField,
+       _Jv_JNI_GetLongField,
+       _Jv_JNI_GetFloatField,
+       _Jv_JNI_GetDoubleField,
+       _Jv_JNI_SetObjectField,
+       _Jv_JNI_SetBooleanField,
+       _Jv_JNI_SetByteField,
+       _Jv_JNI_SetCharField,
+       _Jv_JNI_SetShortField,
+       _Jv_JNI_SetIntField,
+       _Jv_JNI_SetLongField,
+       _Jv_JNI_SetFloatField,
+       _Jv_JNI_SetDoubleField,
+
+       _Jv_JNI_GetStaticMethodID,
+
+       _Jv_JNI_CallStaticObjectMethod,
+       _Jv_JNI_CallStaticObjectMethodV,
+       _Jv_JNI_CallStaticObjectMethodA,
+       _Jv_JNI_CallStaticBooleanMethod,
+       _Jv_JNI_CallStaticBooleanMethodV,
+       _Jv_JNI_CallStaticBooleanMethodA,
+       _Jv_JNI_CallStaticByteMethod,
+       _Jv_JNI_CallStaticByteMethodV,
+       _Jv_JNI_CallStaticByteMethodA,
+       _Jv_JNI_CallStaticCharMethod,
+       _Jv_JNI_CallStaticCharMethodV,
+       _Jv_JNI_CallStaticCharMethodA,
+       _Jv_JNI_CallStaticShortMethod,
+       _Jv_JNI_CallStaticShortMethodV,
+       _Jv_JNI_CallStaticShortMethodA,
+       _Jv_JNI_CallStaticIntMethod,
+       _Jv_JNI_CallStaticIntMethodV,
+       _Jv_JNI_CallStaticIntMethodA,
+       _Jv_JNI_CallStaticLongMethod,
+       _Jv_JNI_CallStaticLongMethodV,
+       _Jv_JNI_CallStaticLongMethodA,
+       _Jv_JNI_CallStaticFloatMethod,
+       _Jv_JNI_CallStaticFloatMethodV,
+       _Jv_JNI_CallStaticFloatMethodA,
+       _Jv_JNI_CallStaticDoubleMethod,
+       _Jv_JNI_CallStaticDoubleMethodV,
+       _Jv_JNI_CallStaticDoubleMethodA,
+       _Jv_JNI_CallStaticVoidMethod,
+       _Jv_JNI_CallStaticVoidMethodV,
+       _Jv_JNI_CallStaticVoidMethodA,
+
+       _Jv_JNI_GetStaticFieldID,
+
+       _Jv_JNI_GetStaticObjectField,
+       _Jv_JNI_GetStaticBooleanField,
+       _Jv_JNI_GetStaticByteField,
+       _Jv_JNI_GetStaticCharField,
+       _Jv_JNI_GetStaticShortField,
+       _Jv_JNI_GetStaticIntField,
+       _Jv_JNI_GetStaticLongField,
+       _Jv_JNI_GetStaticFloatField,
+       _Jv_JNI_GetStaticDoubleField,
+       _Jv_JNI_SetStaticObjectField,
+       _Jv_JNI_SetStaticBooleanField,
+       _Jv_JNI_SetStaticByteField,
+       _Jv_JNI_SetStaticCharField,
+       _Jv_JNI_SetStaticShortField,
+       _Jv_JNI_SetStaticIntField,
+       _Jv_JNI_SetStaticLongField,
+       _Jv_JNI_SetStaticFloatField,
+       _Jv_JNI_SetStaticDoubleField,
+
+       _Jv_JNI_NewString,
+       _Jv_JNI_GetStringLength,
+       _Jv_JNI_GetStringChars,
+       _Jv_JNI_ReleaseStringChars,
+
+       _Jv_JNI_NewStringUTF,
+       _Jv_JNI_GetStringUTFLength,
+       _Jv_JNI_GetStringUTFChars,
+       _Jv_JNI_ReleaseStringUTFChars,
+
+       _Jv_JNI_GetArrayLength,
+
+       _Jv_JNI_NewObjectArray,
+       _Jv_JNI_GetObjectArrayElement,
+       _Jv_JNI_SetObjectArrayElement,
+
+       _Jv_JNI_NewBooleanArray,
+       _Jv_JNI_NewByteArray,
+       _Jv_JNI_NewCharArray,
+       _Jv_JNI_NewShortArray,
+       _Jv_JNI_NewIntArray,
+       _Jv_JNI_NewLongArray,
+       _Jv_JNI_NewFloatArray,
+       _Jv_JNI_NewDoubleArray,
+
+       _Jv_JNI_GetBooleanArrayElements,
+       _Jv_JNI_GetByteArrayElements,
+       _Jv_JNI_GetCharArrayElements,
+       _Jv_JNI_GetShortArrayElements,
+       _Jv_JNI_GetIntArrayElements,
+       _Jv_JNI_GetLongArrayElements,
+       _Jv_JNI_GetFloatArrayElements,
+       _Jv_JNI_GetDoubleArrayElements,
+
+       _Jv_JNI_ReleaseBooleanArrayElements,
+       _Jv_JNI_ReleaseByteArrayElements,
+       _Jv_JNI_ReleaseCharArrayElements,
+       _Jv_JNI_ReleaseShortArrayElements,
+       _Jv_JNI_ReleaseIntArrayElements,
+       _Jv_JNI_ReleaseLongArrayElements,
+       _Jv_JNI_ReleaseFloatArrayElements,
+       _Jv_JNI_ReleaseDoubleArrayElements,
+
+       _Jv_JNI_GetBooleanArrayRegion,
+       _Jv_JNI_GetByteArrayRegion,
+       _Jv_JNI_GetCharArrayRegion,
+       _Jv_JNI_GetShortArrayRegion,
+       _Jv_JNI_GetIntArrayRegion,
+       _Jv_JNI_GetLongArrayRegion,
+       _Jv_JNI_GetFloatArrayRegion,
+       _Jv_JNI_GetDoubleArrayRegion,
+       _Jv_JNI_SetBooleanArrayRegion,
+       _Jv_JNI_SetByteArrayRegion,
+       _Jv_JNI_SetCharArrayRegion,
+       _Jv_JNI_SetShortArrayRegion,
+       _Jv_JNI_SetIntArrayRegion,
+       _Jv_JNI_SetLongArrayRegion,
+       _Jv_JNI_SetFloatArrayRegion,
+       _Jv_JNI_SetDoubleArrayRegion,
+
+       _Jv_JNI_RegisterNatives,
+       _Jv_JNI_UnregisterNatives,
+
+       _Jv_JNI_MonitorEnter,
+       _Jv_JNI_MonitorExit,
+
+       _Jv_JNI_GetJavaVM,
 
        /* new JNI 1.2 functions */
 
-       &GetStringRegion,
-       &GetStringUTFRegion,
+       _Jv_JNI_GetStringRegion,
+       _Jv_JNI_GetStringUTFRegion,
 
-       &GetPrimitiveArrayCritical,
-       &ReleasePrimitiveArrayCritical,
+       _Jv_JNI_GetPrimitiveArrayCritical,
+       _Jv_JNI_ReleasePrimitiveArrayCritical,
 
-       &GetStringCritical,
-       &ReleaseStringCritical,
+       _Jv_JNI_GetStringCritical,
+       _Jv_JNI_ReleaseStringCritical,
 
-       &NewWeakGlobalRef,
-       &DeleteWeakGlobalRef,
+       _Jv_JNI_NewWeakGlobalRef,
+       _Jv_JNI_DeleteWeakGlobalRef,
 
-       &ExceptionCheck,
+       _Jv_JNI_ExceptionCheck,
 
        /* new JNI 1.4 functions */
 
-       &NewDirectByteBuffer,
-       &GetDirectBufferAddress,
-       &GetDirectBufferCapacity
+       _Jv_JNI_NewDirectByteBuffer,
+       _Jv_JNI_GetDirectBufferAddress,
+       _Jv_JNI_GetDirectBufferCapacity
 };
 
 
@@ -5103,12 +4163,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;
 }
 
@@ -5124,9 +4200,17 @@ jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
 
 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 {
-       log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!");
+       TRACEJNICALLS("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs);
 
-       return 0;
+       if (bufLen <= 0)
+               return JNI_ERR;
+
+       /* We currently only support 1 VM running. */
+
+       vmBuf[0] = (JavaVM *) _Jv_jvm;
+       *nVMs    = 1;
+
+    return JNI_OK;
 }
 
 
@@ -5137,18 +4221,16 @@ 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;
+       TRACEJNICALLS("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args);
 
-       vm = &JNI_JavaVMTable;
-       env = &JNI_JNIEnvTable;
+       /* actually create the JVM */
 
-       *p_vm = (JavaVM *) vm;
-       *p_env = (JNIEnv *) env;
+       if (!vm_createjvm(p_vm, p_env, vm_args))
+               return JNI_ERR;
 
-       return 0;
+       return JNI_OK;
 }
 
 
@@ -5163,4 +4245,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:
  */