* Removed all Id tags.
[cacao.git] / src / native / jni.c
index e90b3f21e82cf11afef980662600c718b2849a43..a28cd68df14fa8481bda0f7a7d8034280a0b197d 100644 (file)
@@ -1,9 +1,9 @@
 /* src/native/jni.c - implementation of the Java Native Interface functions
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 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
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Rainhard Grafl
-            Roman Obermaisser
-
-   Changes: Joseph Wenninger
-            Martin Platter
-            Christian Thalinger
-
-   $Id: jni.c 4213 2006-01-15 23:32:36Z twisti $
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 */
 
 #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, 1);
-
-       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,717 +216,896 @@ 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")) ||
+                 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)
-{
-       typedesc *paramtypes;
-       s4        i;
-
-       paramtypes = descr->paramtypes;
-
-       /* if method is non-static fill first block and skip `this' pointer */
-
-       i = 0;
-
-       if (obj) {
-               /* the `this' pointer */
-               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;
+/* _Jv_jni_CallObjectMethod ****************************************************
 
-               case PRIMITIVETYPE_DOUBLE:
-                       blk[i].itemtype = TYPE_DBL;
-                       *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
-                       break;
+   Internal function to call Java Object methods.
 
-               case TYPE_ADR: 
-                       blk[i].itemtype = TYPE_ADR;
-                       blk[i].item = PTR_TO_ITEM(va_arg(data, void*));
-                       break;
-               }
-       }
+*******************************************************************************/
 
-       /* The standard doesn't say anything about return value checking, but it  */
-       /* appears to be useful.                                                  */
+static java_handle_t *_Jv_jni_CallObjectMethod(java_handle_t *o,
+                                                                                          vftbl_t *vftbl,
+                                                                                          methodinfo *m, va_list ap)
+{
+       methodinfo    *resm;
+       java_handle_t *ro;
 
-       if (rettype != descr->returntype.decltype)
-               log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
-}
+       STATISTICS(jniinvokation());
 
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
 
-/* XXX it could be considered if we should do typechecking here in the future */
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-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;
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       paramcount = descr->paramcount;
-       paramtypes = descr->paramtypes;
+               if (o != NULL)
+                       o = NULL;
 
-       /* if method is non-static fill first block and skip `this' pointer */
+               /* for convenience */
 
-       i = 0;
+               resm = m;
 
-       if (obj) {
-               /* this pointer */
-               blk[0].itemtype = TYPE_ADR;
-               blk[0].item = PTR_TO_ITEM(obj);
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-               paramtypes++;
-               paramcount--;
-               i++;
+               resm = method_vftbl_lookup(vftbl, m);
        }
 
-       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;
+       STATISTICS(jnicallXmethodnvokation());
 
-                       /* internally used data type */
-                       blk[i].itemtype = paramtypes->type;
+       ro = vm_call_method_valist(resm, o, ap);
 
-                       /* convert the value according to its declared type */
+       return ro;
+}
 
-                       c = param->vftbl->class;
 
-                       switch (paramtypes->decltype) {
-                       case PRIMITIVETYPE_BOOLEAN:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Boolean *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
+/* _Jv_jni_CallObjectMethodA ***************************************************
 
-                       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;
+   Internal function to call Java Object methods.
 
-                       case PRIMITIVETYPE_CHAR:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Character *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_SHORT:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_INT:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_LONG:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Long *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Integer *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Short *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
-                                       blk[i].item = (s8) ((java_lang_Byte *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
+*******************************************************************************/
 
-                       case PRIMITIVETYPE_FLOAT:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
-
-                       case PRIMITIVETYPE_DOUBLE:
-                               if (c == primitivetype_table[paramtypes->decltype].class_wrap)
-                                       *((jdouble *) (&blk[i].item)) = (jdouble) ((java_lang_Float *) param)->value;
-                               else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
-                                       *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
-                               else
-                                       goto illegal_arg;
-                               break;
+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;
 
-                       default:
-                               goto illegal_arg;
-                       } /* end declared type switch */
-                       break;
-               
-                       case TYPE_ADDRESS:
-                               if (!resolve_class_from_typedesc(paramtypes, true, true, &c))
-                                       return false;
+       STATISTICS(jniinvokation());
 
-                               if (params->data[j] != 0) {
-                                       if (paramtypes->arraydim > 0) {
-                                               if (!builtin_arrayinstanceof(params->data[j], c))
-                                                       goto illegal_arg;
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
 
-                                       } 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;                  
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-                       default:
-                               goto illegal_arg;
-               } /* end param type switch */
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       } /* end param loop */
+               if (o != NULL)
+                       o = NULL;
 
-/*     if (rettype) */
-/*             *rettype = descr->returntype.decltype; */
+               /* for convenience */
 
-       return true;
+               resm = m;
 
-illegal_arg:
-       exceptions_throw_illegalargumentexception();
-       return false;
-}
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-static jmethodID get_virtual(jobject obj, jmethodID methodID)
-{
-       if (obj->vftbl->class == methodID->class)
-               return methodID;
+       STATISTICS(jnicallXmethodnvokation());
+
+       ro = vm_call_method_jvalue(resm, o, args);
 
-       return class_resolvemethod(obj->vftbl->class, methodID->name,
-                                                          methodID->descriptor);
+       return ro;
 }
 
 
-static jmethodID get_nonvirtual(jclass clazz, jmethodID methodID)
-{
-       if (clazz == methodID->class)
-               return methodID;
+/* _Jv_jni_CallIntMethod *******************************************************
 
-       /* class_resolvemethod -> classfindmethod? (JOWENN) */
-       return class_resolvemethod(clazz, methodID->name, methodID->descriptor);
-}
+   Internal function to call Java integer class methods (boolean,
+   byte, char, short, int).
 
+*******************************************************************************/
 
-static jobject callObjectMethod(jobject obj, jmethodID methodID, va_list args)
-{      
-       int argcount;
-       jni_callblock *blk;
-       jobject ret;
+static jint _Jv_jni_CallIntMethod(java_handle_t *o, vftbl_t *vftbl,
+                                                                 methodinfo *m, va_list ap)
+{
+       methodinfo *resm;
+       jint        i;
 
-       if (methodID == 0) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
-               return 0;
-       }
+       STATISTICS(jniinvokation());
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
-               ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
                return 0;
        }
+        
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       if (obj && !builtin_instanceof(obj, methodID->class)) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
-       }
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       argcount = methodID->parseddesc->paramcount;
+               if (o != NULL)
+                       o = NULL;
 
-       blk = MNEW(jni_callblock, argcount);
+               /* for convenience */
 
-       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_ADR);
+               resm = m;
 
-       STATISTICS(jnicallXmethodnvokation());
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       ASM_CALLJAVAFUNCTION2_ADR(ret, methodID, argcount,
-                                                         argcount * sizeof(jni_callblock),
-                                                         blk);
+       STATISTICS(jnicallXmethodnvokation());
 
-       MFREE(blk, jni_callblock, argcount);
+       i = vm_call_method_int_valist(resm, o, ap);
 
-       return ret;
+       return i;
 }
 
 
-/*
-  core function for integer class methods (bool, byte, short, integer)
-  This is basically needed for i386
-*/
-static jint callIntegerMethod(jobject obj, jmethodID methodID, int retType, va_list args)
+/* _Jv_jni_CallIntMethodA ******************************************************
+
+   Internal function to call Java integer class methods (boolean,
+   byte, char, short, int).
+
+*******************************************************************************/
+
+static jint _Jv_jni_CallIntMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                  methodinfo *m, const jvalue *args)
 {
-       int argcount;
-       jni_callblock *blk;
-       jint ret;
+       methodinfo *resm;
+       jint        i;
 
        STATISTICS(jniinvokation());
 
-        /*
-        log_text("JNI-Call: CallObjectMethodV");
-        utf_display(methodID->name);
-        utf_display(methodID->descriptor);
-        printf("\nParmaeter count: %d\n",argcount);
-        utf_display(obj->vftbl->class->name);
-        printf("\n");
-        */
-       if (methodID == 0) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
                return 0;
        }
         
-       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
-               ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
-       }
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       if (obj && !builtin_instanceof(obj, methodID->class)) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
-       }
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       argcount = methodID->parseddesc->paramcount;
+               if (o != NULL)
+                       o = NULL;
 
-       blk = MNEW(jni_callblock, argcount);
+               /* for convenience */
 
-       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType);
+               resm = m;
 
-       STATISTICS(jnicallXmethodnvokation());
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       ASM_CALLJAVAFUNCTION2_INT(ret, methodID, argcount,
-                                                         argcount * sizeof(jni_callblock),
-                                                         blk);
+       STATISTICS(jnicallXmethodnvokation());
 
-       MFREE(blk, jni_callblock, argcount);
+       i = vm_call_method_int_jvalue(resm, o, args);
 
-       return ret;
+       return i;
 }
 
 
-/* callLongMethod **************************************************************
+/* _Jv_jni_CallLongMethod ******************************************************
 
-   Core function for long class functions.
+   Internal function to call Java long methods.
 
 *******************************************************************************/
 
-static jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
+static jlong _Jv_jni_CallLongMethod(java_handle_t *o, vftbl_t *vftbl,
+                                                                       methodinfo *m, va_list ap)
 {
-       s4             argcount;
-       jni_callblock *blk;
-       jlong          ret;
+       methodinfo *resm;
+       jlong       l;
 
        STATISTICS(jniinvokation());
 
-       if (methodID == 0) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
                return 0;
        }
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
-                  ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
-       }
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       if (obj && !builtin_instanceof(obj, methodID->class)) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return 0;
-       }
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       argcount = methodID->parseddesc->paramcount;
+               if (o != NULL)
+                       o = NULL;
 
-       blk = MNEW(jni_callblock, argcount);
+               /* for convenience */
 
-       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_LNG);
+               resm = m;
 
-       STATISTICS(jnicallXmethodnvokation());
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
+
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       ASM_CALLJAVAFUNCTION2_LONG(ret, methodID, argcount,
-                                                          argcount * sizeof(jni_callblock),
-                                                          blk);
+       STATISTICS(jnicallXmethodnvokation());
 
-       MFREE(blk, jni_callblock, argcount);
+       l = vm_call_method_long_valist(resm, o, ap);
 
-       return ret;
+       return l;
 }
 
 
-/*core function for float class methods (float,double)*/
-static jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,int retType)
+/* _Jv_jni_CallLongMethodA *****************************************************
+
+   Internal function to call Java long methods.
+
+*******************************************************************************/
+
+static jlong _Jv_jni_CallLongMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                        methodinfo *m, const jvalue *args)
 {
-       int argcount = methodID->parseddesc->paramcount;
-       jni_callblock *blk;
-       jdouble ret;
+       methodinfo *resm;
+       jlong       l;
 
        STATISTICS(jniinvokation());
 
-       assert(0);
-
-       if (argcount > 3) {
-               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
-               log_text("Too many arguments. CallObjectMethod does not support that");
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
                return 0;
        }
 
-       blk = MNEW(jni_callblock, /*4 */ argcount+2);
-
-       fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType);
-
-       STATISTICS(jnicallXmethodnvokation());
-
-       ASM_CALLJAVAFUNCTION2_DOUBLE(ret, methodID, argcount + 1,
-                                                                (argcount + 1) * sizeof(jni_callblock),
-                                                                blk);
-
-       MFREE(blk, jni_callblock, argcount + 1);
-
-       return ret;
-}
+       /* 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. */
 
-static void cacao_jni_CallVoidMethod(jobject obj, jmethodID m, va_list ap)
-{      
-       s4             paramcount;
-       jni_callblock *blk;
+               if (o != NULL)
+                       o = NULL;
 
-       if (m == 0) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
-               return;
-       }
+               /* for convenience */
 
-       if (!( ((m->flags & ACC_STATIC) && (obj == 0)) ||
-               ((!(m->flags & ACC_STATIC)) && (obj != 0)) )) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return;
+               resm = m;
        }
+       else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       if (obj && !builtin_instanceof(obj, m->class)) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-               return;
+               resm = method_vftbl_lookup(vftbl, m);
        }
 
-       paramcount = m->parseddesc->paramcount;
-
-/* #error XXX does not work on intrp, but on JIT */
-       if (!(m->flags & ACC_STATIC))
-               paramcount++;
-
-       blk = MNEW(jni_callblock, paramcount);
-
-       fill_callblock_from_vargs(obj, m->parseddesc, blk, ap, TYPE_VOID);
-
        STATISTICS(jnicallXmethodnvokation());
 
-       ASM_CALLJAVAFUNCTION2(m, paramcount,
-                                                 paramcount * sizeof(jni_callblock),
-                                                 blk);
+       l = vm_call_method_long_jvalue(resm, o, args);
 
-       MFREE(blk, jni_callblock, paramcount);
-
-       return;
+       return l;
 }
 
 
-/* GetVersion ******************************************************************
+/* _Jv_jni_CallFloatMethod *****************************************************
 
-   Returns the major version number in the higher 16 bits and the
-   minor version number in the lower 16 bits.
+   Internal function to call Java float methods.
 
 *******************************************************************************/
 
-jint GetVersion(JNIEnv *env)
+static jfloat _Jv_jni_CallFloatMethod(java_handle_t *o, vftbl_t *vftbl,
+                                                                         methodinfo *m, va_list ap)
 {
-       STATISTICS(jniinvokation());
-
-       /* we support JNI 1.4 */
+       methodinfo *resm;
+       jfloat      f;
 
-       return JNI_VERSION_1_4;
-}
+       /* 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. */
 
-/* Class Operations ***********************************************************/
-
-/* DefineClass *****************************************************************
+               if (o != NULL)
+                       o = NULL;
 
-   Loads a class from a buffer of raw class data. The buffer
-   containing the raw class data is not referenced by the VM after the
-   DefineClass call returns, and it may be discarded if desired.
+               /* for convenience */
 
-*******************************************************************************/
+               resm = m;
 
-jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
-                                  const jbyte *buf, jsize bufLen)
-{
-       java_lang_ClassLoader *cl;
-       java_lang_String      *s;
-       java_bytearray        *ba;
-       jclass                 c;
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       STATISTICS(jniinvokation());
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       cl = (java_lang_ClassLoader *) loader;
-       s = javastring_new_char(name);
-       ba = (java_bytearray *) buf;
+       STATISTICS(jnicallXmethodnvokation());
 
-       c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
-                                                                                                                 0, bufLen, NULL);
+       f = vm_call_method_float_valist(resm, o, ap);
 
-       return (jclass) NewLocalRef(env, (jobject) c);
+       return f;
 }
 
 
-/* FindClass *******************************************************************
+/* _Jv_jni_CallFloatMethodA ****************************************************
 
-   This function loads a locally-defined class. It searches the
-   directories and zip files specified by the CLASSPATH environment
-   variable for the class with the specified name.
+   Internal function to call Java float methods.
 
 *******************************************************************************/
 
-jclass FindClass(JNIEnv *env, const char *name)
+static jfloat _Jv_jni_CallFloatMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                          methodinfo *m, const jvalue *args)
 {
-       utf               *u;
-       classinfo         *c;
-       java_objectheader *cl;
+       methodinfo *resm;
+       jfloat      f;
 
-       STATISTICS(jniinvokation());
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       u = utf_new_char_classname((char *) name);
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       /* check stacktrace for classloader, if one found use it, otherwise use */
-       /* the system classloader */
+               if (o != NULL)
+                       o = NULL;
 
-#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__)
-       /* these JITs support stacktraces, and so does the interpreter */
+               /* for convenience */
 
-       cl = cacao_currentClassLoader();
-#else
-# if defined(ENABLE_INTRP)
-       /* the interpreter supports stacktraces, even if the JIT does not */
+               resm = m;
+       }
+       else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       if (opt_intrp)
-               cl = cacao_currentClassLoader();
-       else
-# endif
-               cl = NULL;
-#endif
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       if (!(c = load_class_from_classloader(u, cl)))
-               return NULL;
+       STATISTICS(jnicallXmethodnvokation());
 
-       if (!link_class(c))
-               return NULL;
+       f = vm_call_method_float_jvalue(resm, o, args);
 
-       return (jclass) NewLocalRef(env, (jobject) c);
+       return f;
 }
-  
 
-/* FromReflectedMethod *********************************************************
 
-   Converts java.lang.reflect.Method or java.lang.reflect.Constructor
-   object to a method ID.
-  
+/* _Jv_jni_CallDoubleMethod ****************************************************
+
+   Internal function to call Java double methods.
+
 *******************************************************************************/
-  
-jmethodID FromReflectedMethod(JNIEnv *env, jobject method)
+
+static jdouble _Jv_jni_CallDoubleMethod(java_handle_t *o, vftbl_t *vftbl,
+                                                                               methodinfo *m, va_list ap)
 {
-       methodinfo *mi;
-       classinfo  *c;
-       s4          slot;
+       methodinfo *resm;
+       jdouble     d;
 
-       STATISTICS(jniinvokation());
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       if (method == NULL)
-               return NULL;
-       
-       if (builtin_instanceof(method, class_java_lang_reflect_Method)) {
-               java_lang_reflect_Method *rm;
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-               rm = (java_lang_reflect_Method *) method;
-               c = (classinfo *) (rm->declaringClass);
-               slot = rm->slot;
+               if (o != NULL)
+                       o = NULL;
 
-       } else if (builtin_instanceof(method, class_java_lang_reflect_Constructor)) {
-               java_lang_reflect_Constructor *rc;
+               /* for convenience */
 
-               rc = (java_lang_reflect_Constructor *) method;
-               c = (classinfo *) (rc->clazz);
-               slot = rc->slot;
+               resm = m;
 
-       } else
-               return NULL;
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       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);
+               resm = method_vftbl_lookup(vftbl, m);
        }
 
-       mi = &(c->methods[slot]);
+       d = vm_call_method_double_valist(resm, o, ap);
 
-       return mi;
+       return d;
 }
 
 
-/* GetSuperclass ***************************************************************
+/* _Jv_jni_CallDoubleMethodA ***************************************************
 
-   If clazz represents any class other than the class Object, then
-   this function returns the object that represents the superclass of
-   the class specified by clazz.
+   Internal function to call Java double methods.
 
 *******************************************************************************/
-jclass GetSuperclass(JNIEnv *env, jclass sub)
+
+static jdouble _Jv_jni_CallDoubleMethodA(java_handle_t *o, vftbl_t *vftbl,
+                                                                                methodinfo *m, const jvalue *args)
 {
-       classinfo *c;
+       methodinfo *resm;
+       jdouble     d;
 
-       STATISTICS(jniinvokation());
+       /* Class initialization is done by the JIT compiler.  This is ok
+          since a static method always belongs to the declaring class. */
 
-       c = ((classinfo *) sub)->super.cls;
+       if (m->flags & ACC_STATIC) {
+               /* For static methods we reset the object. */
 
-       if (!c)
-               return NULL;
+               if (o != NULL)
+                       o = NULL;
 
-       return (jclass) NewLocalRef(env, (jobject) c);
-}
-  
-/* IsAssignableFrom ************************************************************
+               /* for convenience */
 
-   Determines whether an object of sub can be safely cast to sup.
+               resm = m;
+       }
+       else {
+               /* For instance methods we make a virtual function table lookup. */
 
-*******************************************************************************/
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
-{
-       STATISTICS(jniinvokation());
+       d = vm_call_method_double_jvalue(resm, o, args);
 
-       return Java_java_lang_VMClass_isAssignableFrom(env,
-                                                                                                  NULL,
-                                                                                                  (java_lang_Class *) sup,
-                                                                                                  (java_lang_Class *) sub);
+       return d;
 }
 
 
-/* Throw ***********************************************************************
+/* _Jv_jni_CallVoidMethod ******************************************************
 
-   Causes a java.lang.Throwable object to be thrown.
+   Internal function to call Java void methods.
 
 *******************************************************************************/
 
-jint Throw(JNIEnv *env, jthrowable obj)
-{
-       STATISTICS(jniinvokation());
+static void _Jv_jni_CallVoidMethod(java_handle_t *o, vftbl_t *vftbl,
+                                                                  methodinfo *m, va_list ap)
+{      
+       methodinfo *resm;
 
-       *exceptionptr = (java_objectheader *) obj;
+       if (m == NULL) {
+               exceptions_throw_nullpointerexception();
+               return;
+       }
 
-       return JNI_OK;
-}
+       /* 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. */
 
-/* ThrowNew ********************************************************************
+               if (o != NULL)
+                       o = NULL;
 
-   Constructs an exception object from the specified class with the
-   message specified by message and causes that exception to be
-   thrown.
+               /* for convenience */
 
-*******************************************************************************/
+               resm = m;
 
-jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
-{
-       java_lang_Throwable *o;
-       java_lang_String    *s;
+       } else {
+               /* For instance methods we make a virtual function table lookup. */
 
-       STATISTICS(jniinvokation());
+               resm = method_vftbl_lookup(vftbl, m);
+       }
 
-       s = (java_lang_String *) javastring_new_char(msg);
+       STATISTICS(jnicallXmethodnvokation());
 
-       /* instantiate exception object */
+       (void) vm_call_method_valist(resm, o, ap);
+}
+
+
+/* _Jv_jni_CallVoidMethodA *****************************************************
+
+   Internal function to call Java void methods.
+
+*******************************************************************************/
+
+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;
+       }
+
+       /* 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());
+
+       (void) vm_call_method_jvalue(resm, o, args);
+}
+
+
+/* _Jv_jni_invokeNative ********************************************************
+
+   Invoke a method on the given object with the given arguments.
+
+   For instance methods OBJ must be != NULL and the method is looked up
+   in the vftbl of the object.
+
+   For static methods, OBJ is ignored.
+
+*******************************************************************************/
+
+java_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;
+
+       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--;
+
+       /* For instance methods the object has to be an instance of the
+          class the method belongs to. For static methods the obj
+          parameter is ignored. */
+
+       if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) {
+               exceptions_throw_illegalargumentexception();
+               return NULL;
+       }
+
+       /* check if we got the right number of arguments */
+
+       if (((params == NULL) && (paramcount != 0)) ||
+               (params && (LLNI_array_size(params) != paramcount))) 
+       {
+               exceptions_throw_illegalargumentexception();
+               return NULL;
+       }
+
+       /* for instance methods we need an object */
+
+       if (!(m->flags & ACC_STATIC) && (o == NULL)) {
+               /* XXX not sure if that is the correct exception */
+               exceptions_throw_nullpointerexception();
+               return NULL;
+       }
+
+       /* for static methods, zero object to make subsequent code simpler */
+       if (m->flags & ACC_STATIC)
+               o = NULL;
+
+       if (o != NULL) {
+               /* for instance methods we must do a vftbl lookup */
+               resm = method_vftbl_lookup(o->vftbl, m);
+       }
+       else {
+               /* for static methods, just for convenience */
+               resm = m;
+       }
+
+       /* mark start of dump memory area */
+
+       dumpsize = dump_size();
+
+       /* Fill the argument array from a object-array. */
+
+       array = vm_array_from_objectarray(resm, o, params);
+
+       /* 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. */
+
+       if ((array == NULL) && (exceptions_get_exception() != NULL)) {
+               /* release dump area */
+
+               dump_release(dumpsize);
+
+               return NULL;
+       }
+
+       switch (resm->parseddesc->returntype.decltype) {
+       case TYPE_VOID:
+               (void) vm_call_array(resm, array);
+               ro = NULL;
+               break;
+
+       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;
+
+       case PRIMITIVETYPE_LONG:
+               value.l = vm_call_long_array(resm, array);
+               ro = primitive_box(resm->parseddesc->returntype.decltype, value);
+               break;
+
+       case PRIMITIVETYPE_FLOAT:
+               value.f = vm_call_float_array(resm, array);
+               ro = primitive_box(resm->parseddesc->returntype.decltype, value);
+               break;
+
+       case PRIMITIVETYPE_DOUBLE:
+               value.d = vm_call_double_array(resm, array);
+               ro = primitive_box(resm->parseddesc->returntype.decltype, value);
+               break;
+
+       case TYPE_ADR:
+               ro = vm_call_array(resm, array);
+               break;
+
+       default:
+               vm_abort("_Jv_jni_invokeNative: invalid return type %d", resm->parseddesc->returntype.decltype);
+       }
+
+       xptr = exceptions_get_exception();
+
+       if (xptr != NULL) {
+               /* clear exception pointer, we are calling JIT code again */
+
+               exceptions_clear_exception();
+
+               exceptions_throw_invocationtargetexception(xptr);
+       }
+
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+       return ro;
+}
+
+
+/* GetVersion ******************************************************************
+
+   Returns the major version number in the higher 16 bits and the
+   minor version number in the lower 16 bits.
+
+*******************************************************************************/
+
+jint _Jv_JNI_GetVersion(JNIEnv *env)
+{
+       STATISTICS(jniinvokation());
+
+       /* we support JNI 1.4 */
+
+       return JNI_VERSION_1_4;
+}
+
+
+/* Class Operations ***********************************************************/
+
+/* DefineClass *****************************************************************
+
+   Loads a class from a buffer of raw class data. The buffer
+   containing the raw class data is not referenced by the VM after the
+   DefineClass call returns, and it may be discarded if desired.
+
+*******************************************************************************/
+
+jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
+                                                  const jbyte *buf, jsize bufLen)
+{
+#if defined(ENABLE_JAVASE)
+       utf         *u;
+       classloader *cl;
+       classinfo   *c;
+
+       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;
+
+       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");
+
+       /* keep compiler happy */
+
+       return 0;
+#endif
+}
+
+
+/* FindClass *******************************************************************
+
+   This function loads a locally-defined class. It searches the
+   directories and zip files specified by the CLASSPATH environment
+   variable for the class with the specified name.
+
+*******************************************************************************/
+
+jclass _Jv_JNI_FindClass(JNIEnv *env, const char *name)
+{
+#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. */
+
+       /* 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
+               c = load_class_from_classloader(u, cc->classloader);
+
+       if (c == NULL)
+               return NULL;
+
+       if (!link_class(c))
+               return NULL;
+
+       return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
+#else
+       vm_abort("_Jv_JNI_FindClass: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
+}
+  
+
+/* GetSuperclass ***************************************************************
+
+   If clazz represents any class other than the class Object, then
+   this function returns the object that represents the superclass of
+   the class specified by clazz.
+
+*******************************************************************************/
+jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
+{
+       classinfo *c;
+       classinfo *super;
+
+       TRACEJNICALLS("_Jv_JNI_GetSuperclass(env=%p, sub=%p)", env, sub);
+
+       c = LLNI_classinfo_unwrap(sub);
+
+       if (c == NULL)
+               return NULL;
 
-       o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz,
-                                                                                                                  s);
+       super = class_get_superclass(c);
 
-       if (!o)
+       return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) super);
+}
+  
+/* IsAssignableFrom ************************************************************
+
+   Determines whether an object of sub can be safely cast to 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 _Jv_java_lang_Class_isAssignableFrom(csup, csub);
+}
+
+
+/* Throw ***********************************************************************
+
+   Causes a java.lang.Throwable object to be thrown.
+
+*******************************************************************************/
+
+jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
+{
+       java_handle_t *o;
+
+       STATISTICS(jniinvokation());
+
+       o = (java_handle_t *) obj;
+
+       exceptions_set_exception(o);
+
+       return JNI_OK;
+}
+
+
+/* ThrowNew ********************************************************************
+
+   Constructs an exception object from the specified class with the
+   message specified by message and causes that exception to be
+   thrown.
+
+*******************************************************************************/
+
+jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
+{
+       classinfo     *c;
+       java_handle_t *o;
+       java_handle_t *s;
+
+       STATISTICS(jniinvokation());
+
+       c = LLNI_classinfo_unwrap(clazz);
+       if (msg == NULL)
+               msg = "";
+       s = javastring_new_from_utf_string(msg);
+
+       /* instantiate exception object */
+
+       o = native_new_and_init_string(c, s);
+
+       if (o == NULL)
                return -1;
 
-       *exceptionptr = (java_objectheader *) o;
+       exceptions_set_exception(o);
 
        return 0;
 }
@@ -944,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);
 }
 
 
@@ -964,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);
        }
 }
 
@@ -1004,11 +1179,11 @@ void ExceptionDescribe(JNIEnv *env)
 
 *******************************************************************************/
 
-void ExceptionClear(JNIEnv *env)
+void _Jv_JNI_ExceptionClear(JNIEnv *env)
 {
        STATISTICS(jniinvokation());
 
-       *exceptionptr = NULL;
+       exceptions_clear_exception();
 }
 
 
@@ -1019,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);
 }
 
 
@@ -1034,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
@@ -1053,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);
 }
 
 
@@ -1073,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;
+                       }
                }
        }
 
@@ -1102,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");
 }
 
 
@@ -1112,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());
 
@@ -1129,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;
@@ -1143,17 +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");
+       if (lrt->used == lrt->capacity) {
+               if (_Jv_JNI_EnsureLocalCapacity(env, 16) != 0)
+                       return NULL;
 
-       /* insert the reference */
+               /* 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;
@@ -1177,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;
 
@@ -1189,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;
 }
@@ -1205,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);
 }
 
 
@@ -1233,62 +1426,106 @@ 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);
-       cacao_jni_CallVoidMethod(o, methodID, ap);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
        va_end(ap);
 
-       return NewLocalRef(env, o);
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-/*********************************************************************************** 
+/* NewObjectV ******************************************************************
 
-       Constructs a new Java object
-       arguments that are to be passed to the constructor are placed in va_list args 
+   Programmers place all arguments that are to be passed to the
+   constructor in an args argument of type va_list that immediately
+   follows the methodID argument. NewObjectV() accepts these
+   arguments, and, in turn, passes them to the Java method that the
+   programmer wishes to invoke.
 
-***********************************************************************************/
+*******************************************************************************/
 
-jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
+jobject _Jv_JNI_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
+                                                  va_list args)
 {
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: NewObjectV: 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_CallVoidMethod(o, o->vftbl, m, args);
 
-       return NewLocalRef(env, NULL);
+       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);
 }
 
 
@@ -1298,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);
 }
 
 
@@ -1319,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
 }
 
 
@@ -1364,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
 }
 
 
@@ -1381,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());
 
@@ -1405,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;
@@ -1415,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))
@@ -1429,2044 +1762,1215 @@ 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 || (m->flags & ACC_STATIC)) {
-               *exceptionptr = exceptions_new_nosuchmethoderror(c, uname, udesc);
+       if ((m == NULL) || (m->flags & ACC_STATIC)) {
+               exceptions_throw_nosuchmethoderror(c, uname, udesc);
 
                return NULL;
        }
 
-       return m;
-}
-
-
-/******************** JNI-functions for calling instance methods ******************/
-
-jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       java_objectheader* ret;
-       va_list            vaargs;
-
-       STATISTICS(jniinvokation());
+       return (jmethodID) m;
+}
+
+
+/* JNI-functions for calling instance methods *********************************/
+
+#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(vaargs, methodID);
-       ret = callObjectMethod(obj, methodID, vaargs);
-       va_end(vaargs);
+       va_start(ap, methodID);
+       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;
+       java_handle_t *o;
+       methodinfo    *m;
+       java_handle_t *ret;
 
-       STATISTICS(jniinvokation());
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
 
-       ret = callObjectMethod(obj, methodID, args);
+       ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, args);
 
-       return NewLocalRef(env, ret);
+       return _Jv_JNI_NewLocalRef(env, (jobject) ret);
 }
 
 
-jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+                                                                 const jvalue *args)
 {
-       STATISTICS(jniinvokation());
+       java_handle_t *o;
+       methodinfo    *m;
+       java_handle_t *ret;
 
-       log_text("JNI-Call: CallObjectMethodA: IMPLEMENT ME!");
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
 
-       return NewLocalRef(env, NULL);
-}
+       ret = _Jv_jni_CallObjectMethodA(o, o->vftbl, m, args);
 
+       return _Jv_JNI_NewLocalRef(env, (jobject) ret);
+}
 
 
 
-jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       jboolean ret;
-       va_list vaargs;
-
-       STATISTICS(jniinvokation());
-
-/*     log_text("JNI-Call: CallBooleanMethod");*/
+       java_handle_t *o;
+       methodinfo    *m;
+       va_list        ap;
 
-       va_start(vaargs,methodID);
-       ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BOOLEAN,vaargs);
-       va_end(vaargs);
-       return ret;
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
 
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
+       va_end(ap);
 }
 
-jboolean CallBooleanMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BOOLEAN,args);
 
+void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+                                                        va_list args)
+{
+       java_handle_t *o;
+       methodinfo    *m;
+
+       o = (java_handle_t *) obj;
+       m = (methodinfo *) methodID;
+
+       _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
 }
 
-jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
-{
-       STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: CallBooleanMethodA");
+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);
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 
-       return 0;
+       return _Jv_JNI_NewLocalRef(env, (jobject) r);
 }
 
-jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       jbyte ret;
-       va_list vaargs;
 
-       STATISTICS(jniinvokation());
+jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
+                                                                                       jclass clazz, jmethodID methodID,
+                                                                                       va_list args)
+{
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+       java_handle_t *r;
 
-/*     log_text("JNI-Call: CallVyteMethod");*/
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BYTE,vaargs);
-       va_end(vaargs);
-       return ret;
+       r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
 
+       return _Jv_JNI_NewLocalRef(env, (jobject) r);
 }
 
-jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-/*     log_text("JNI-Call: CallByteMethodV");*/
 
-       STATISTICS(jniinvokation());
+jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
+                                                                                       jclass clazz, jmethodID methodID,
+                                                                                       const jvalue *args)
+{
+       log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
 
-       return callIntegerMethod(obj,methodID,PRIMITIVETYPE_BYTE,args);
+       return _Jv_JNI_NewLocalRef(env, NULL);
 }
 
 
-jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
+                                                                         jmethodID methodID, ...)
 {
-       STATISTICS(jniinvokation());
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+       va_list        ap;
 
-       log_text("JNI-Call: CallByteMethodA: IMPLEMENT ME!");
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
-       return 0;
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
+       va_end(ap);
 }
 
 
-jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
+                                                                          jmethodID methodID, va_list args)
 {
-       jchar ret;
-       va_list vaargs;
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
 
-       STATISTICS(jniinvokation());
-
-/*     log_text("JNI-Call: CallCharMethod");*/
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_CHAR, vaargs);
-       va_end(vaargs);
-
-       return ret;
+       _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
 }
 
 
-jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
+void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
+                                                                          jmethodID methodID, const jvalue * args)
+{      
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
 
-/*     log_text("JNI-Call: CallCharMethodV");*/
+       o = (java_handle_t *) obj;
+       c = LLNI_classinfo_unwrap(clazz);
+       m = (methodinfo *) methodID;
 
-       return callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_CHAR,args);
+       _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
 }
 
 
-jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
+/* Accessing Fields of Objects ************************************************/
 
-       log_text("JNI-Call: CallCharMethodA: IMPLEMENT ME!");
+/* GetFieldID ******************************************************************
 
-       return 0;
-}
+   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 CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
+                                                       const char *sig)
 {
-       jshort ret;
-       va_list vaargs;
+       classinfo *c;
+       fieldinfo *f;
+       utf       *uname;
+       utf       *udesc;
 
        STATISTICS(jniinvokation());
 
-/*     log_text("JNI-Call: CallShortMethod");*/
+       c = LLNI_classinfo_unwrap(clazz);
 
-       va_start(vaargs, methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_SHORT, vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
+       /* XXX NPE check? */
 
+       uname = utf_new_char((char *) name);
+       udesc = utf_new_char((char *) sig);
 
-jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
+       f = class_findfield(c, uname, udesc); 
+       
+       if (f == NULL)
+               exceptions_throw_nosuchfielderror(c, uname);  
 
-       return callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_SHORT, args);
+       return (jfieldID) f;
 }
 
 
-jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
+/* Get<type>Field Routines *****************************************************
 
-       log_text("JNI-Call: CallShortMethodA: IMPLEMENT ME!");
+   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().
 
-       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)
 
 
-jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
 {
-       jint ret;
-       va_list vaargs;
+       java_handle_t *o;
 
        STATISTICS(jniinvokation());
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_INT, vaargs);
-       va_end(vaargs);
+#warning this needs to be fixed
+       o = GET_FIELD(obj, java_handle_t*, fieldID);
 
-       return ret;
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_INT, args);
-}
-
+/* Set<type>Field Routines *****************************************************
 
-jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
+   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().
 
-       log_text("JNI-Call: CallIntMethodA: IMPLEMENT ME!");
+*******************************************************************************/
 
-       return 0;
+#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 CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
-       jlong ret;
-       va_list vaargs;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs,methodID);
-       ret = callLongMethod(obj,get_virtual(obj, methodID),vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
+                                                       jobject value)
 {
        STATISTICS(jniinvokation());
 
-       return  callLongMethod(obj,get_virtual(obj, methodID),args);
+#warning this needs to be fixed
+       SET_FIELD(obj, java_handle_t*, fieldID, value);
 }
 
 
-jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
+/* Calling Static Methods *****************************************************/
 
-       log_text("JNI-Call: CallLongMethodA: IMPLEMENT ME!");
+/* GetStaticMethodID ***********************************************************
 
-       return 0;
-}
+   Returns the method ID for a static method of a class. The method is
+   specified by its name and signature.
 
+   GetStaticMethodID() causes an uninitialized class to be
+   initialized.
 
+*******************************************************************************/
 
-jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
+                                                                       const char *sig)
 {
-       jfloat ret;
-       va_list vaargs;
+       classinfo  *c;
+       utf        *uname;
+       utf        *udesc;
+       methodinfo *m;
 
        STATISTICS(jniinvokation());
 
-/*     log_text("JNI-Call: CallFloatMethod");*/
+       c = LLNI_classinfo_unwrap(clazz);
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, PRIMITIVETYPE_FLOAT);
-       va_end(vaargs);
+       if (!c)
+               return NULL;
 
-       return ret;
-}
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return NULL;
 
+       /* try to get the static method of the class */
 
-jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
+       uname = utf_new_char((char *) name);
+       udesc = utf_new_char((char *) sig);
 
-/*     log_text("JNI-Call: CallFloatMethodV"); */
+       m = class_resolvemethod(c, uname, udesc);
 
-       return callFloatMethod(obj, get_virtual(obj, methodID), args, PRIMITIVETYPE_FLOAT);
-}
+       if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+               exceptions_throw_nosuchmethoderror(c, uname, udesc);
 
+               return NULL;
+       }
 
-jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
+       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;
 
-       log_text("JNI-Call: CallFloatMethodA: IMPLEMENT ME!");
+       va_start(ap, methodID);
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
+       va_end(ap);
 
-       return 0;
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-
-jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
+                                                                               jmethodID methodID, va_list args)
 {
-       jdouble ret;
-       va_list vaargs;
-
-       STATISTICS(jniinvokation());
+       methodinfo    *m;
+       java_handle_t *o;
 
-/*     log_text("JNI-Call: CallDoubleMethod");*/
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, PRIMITIVETYPE_DOUBLE);
-       va_end(vaargs);
+       o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
 
-       return ret;
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
+                                                                               jmethodID methodID, const jvalue *args)
 {
-       STATISTICS(jniinvokation());
+       methodinfo    *m;
+       java_handle_t *o;
 
-/*     log_text("JNI-Call: CallDoubleMethodV"); */
+       m = (methodinfo *) methodID;
 
-       return callFloatMethod(obj, get_virtual(obj, methodID), args, PRIMITIVETYPE_DOUBLE);
+       o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
+
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
+                                                                 jmethodID methodID, ...)
 {
-       STATISTICS(jniinvokation());
+       methodinfo *m;
+       va_list     ap;
 
-       log_text("JNI-Call: CallDoubleMethodA: IMPLEMENT ME!");
+       m = (methodinfo *) methodID;
 
-       return 0;
+       va_start(ap, methodID);
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
+       va_end(ap);
 }
 
 
-
-void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
+                                                                  jmethodID methodID, va_list args)
 {
-       va_list vaargs;
+       methodinfo *m;
 
-       STATISTICS(jniinvokation());
+       m = (methodinfo *) methodID;
 
-       va_start(vaargs,methodID);
-       (void) callIntegerMethod(obj, get_virtual(obj, methodID),TYPE_VOID, vaargs);
-       va_end(vaargs);
+       _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
 }
 
 
-void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
+                                                                  jmethodID methodID, const jvalue * args)
 {
-       STATISTICS(jniinvokation());
+       methodinfo *m;
 
-/*     log_text("JNI-Call: CallVoidMethodV"); */
+       m = (methodinfo *) methodID;
 
-       (void) callIntegerMethod(obj, get_virtual(obj, methodID), TYPE_VOID,args);
+       _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
 }
 
 
-void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
+/* Accessing Static Fields ****************************************************/
 
-       log_text("JNI-Call: CallVoidMethodA: IMPLEMENT ME!");
-}
+/* 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.
 
+*******************************************************************************/
 
-jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
+                                                                 const char *sig)
 {
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallNonvirtualObjectMethod: IMPLEMENT ME!");
-
-       return NewLocalRef(env, NULL);
-}
-
+       classinfo *c;
+       fieldinfo *f;
+       utf       *uname;
+       utf       *usig;
 
-jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: CallNonvirtualObjectMethodV: IMPLEMENT ME!");
+       c = LLNI_classinfo_unwrap(clazz);
 
-       return NewLocalRef(env, NULL);
-}
+       uname = utf_new_char((char *) name);
+       usig  = utf_new_char((char *) sig);
 
+       f = class_findfield(c, uname, usig);
+       
+       if (f == NULL)
+               exceptions_throw_nosuchfielderror(c, uname);
 
-jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
+       return (jfieldID) f;
+}
 
-       log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
 
-       return NewLocalRef(env, NULL);
-}
+/* GetStatic<type>Field ********************************************************
 
+   This family of accessor routines returns the value of a static
+   field of an object.
 
+*******************************************************************************/
 
-jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+#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)
 {
-       jboolean ret;
-       va_list vaargs;
+       classinfo *c;
+       fieldinfo *f;
 
        STATISTICS(jniinvokation());
 
-/*     log_text("JNI-Call: CallNonvirtualBooleanMethod");*/
-
-       va_start(vaargs,methodID);
-       ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BOOLEAN,vaargs);
-       va_end(vaargs);
-
-       return ret;
+       c = LLNI_classinfo_unwrap(clazz);
+       f = (fieldinfo *) fieldID;
 
-}
-
-
-jboolean CallNonvirtualBooleanMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-/*     log_text("JNI-Call: CallNonvirtualBooleanMethodV");*/
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return NULL;
 
-       return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BOOLEAN,args);
+       return _Jv_JNI_NewLocalRef(env, f->value->a);
 }
 
 
-jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallNonvirtualBooleanMethodA: IMPLEMENT ME!");
+/*  SetStatic<type>Field *******************************************************
 
-       return 0;
-}
+       This family of accessor routines sets the value of a static field
+       of an object.
 
+*******************************************************************************/
 
-jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+#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)
 {
-       jbyte ret;
-       va_list vaargs;
+       classinfo *c;
+       fieldinfo *f;
 
        STATISTICS(jniinvokation());
 
-/*     log_text("JNI-Call: CallNonvirutalByteMethod");*/
-
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BYTE,vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
+       c = LLNI_classinfo_unwrap(clazz);
+       f = (fieldinfo *) fieldID;
 
-jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       /*log_text("JNI-Call: CallNonvirtualByteMethodV"); */
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return;
 
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BYTE,args);
+       f->value->a = value;
 }
 
 
-jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallNonvirtualByteMethodA: IMPLEMENT ME!");
+/* String Operations **********************************************************/
 
-       return 0;
-}
+/* NewString *******************************************************************
 
+   Create new java.lang.String object from an array of Unicode
+   characters.
 
+*******************************************************************************/
 
-jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jstring _Jv_JNI_NewString(JNIEnv *env, const jchar *buf, jsize len)
 {
-       jchar ret;
-       va_list vaargs;
+       java_lang_String        *s;
+       java_handle_chararray_t *a;
+       u4                       i;
 
        STATISTICS(jniinvokation());
+       
+       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       a = builtin_newarray_char(len);
 
-/*     log_text("JNI-Call: CallNonVirtualCharMethod");*/
-
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_CHAR,vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
+       /* javastring or characterarray could not be created */
+       if ((a == NULL) || (s == NULL))
+               return NULL;
 
-jchar CallNonvirtualCharMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
+       /* copy text */
+       for (i = 0; i < len; i++)
+               LLNI_array_direct(a, i) = buf[i];
 
-       /*log_text("JNI-Call: CallNonvirtualCharMethodV");*/
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , len);
 
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_CHAR,args);
+       return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
 }
 
 
-jchar CallNonvirtualCharMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallNonvirtualCharMethodA: IMPLEMENT ME!");
+static jchar emptyStringJ[]={0,0};
 
-       return 0;
-}
+/* GetStringLength *************************************************************
 
+   Returns the length (the count of Unicode characters) of a Java
+   string.
 
+*******************************************************************************/
 
-jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+jsize _Jv_JNI_GetStringLength(JNIEnv *env, jstring str)
 {
-       jshort ret;
-       va_list vaargs;
+       java_lang_String *s;
+       jsize             len;
 
-       STATISTICS(jniinvokation());
+       TRACEJNICALLS("_Jv_JNI_GetStringLength(env=%p, str=%p)", env, str);
 
-       /*log_text("JNI-Call: CallNonvirtualShortMethod");*/
+       s = (java_lang_String *) str;
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_SHORT,vaargs);
-       va_end(vaargs);
+       LLNI_field_get_val(s, count, len);
 
-       return ret;
+       return len;
 }
 
 
-jshort CallNonvirtualShortMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
+/********************  convertes javastring to u2-array ****************************/
+       
+u2 *javastring_tou2(jstring so) 
 {
-       STATISTICS(jniinvokation());
-
-       /*log_text("JNI-Call: CallNonvirtualShortMethodV");*/
-
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_SHORT,args);
-}
+       java_lang_String        *s;
+       java_handle_chararray_t *a;
+       u2                      *stringbuffer;
+       u4                       i;
+       int32_t                  count;
+       int32_t                  offset;
 
-
-jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
        STATISTICS(jniinvokation());
+       
+       s = (java_lang_String *) so;
 
-       log_text("JNI-Call: CallNonvirtualShortMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
+       if (!s)
+               return NULL;
 
-jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       jint ret;
-       va_list vaargs;
+       LLNI_field_get_ref(s, value, a);
 
-       STATISTICS(jniinvokation());
+       if (!a)
+               return NULL;
 
-       /*log_text("JNI-Call: CallNonvirtualIntMethod");*/
+       LLNI_field_get_val(s, count, count);
+       LLNI_field_get_val(s, offset, offset);
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_INT,vaargs);
-       va_end(vaargs);
+       /* allocate memory */
 
-       return ret;
-}
+       stringbuffer = MNEW(u2, count + 1);
 
+       /* copy text */
 
-jint CallNonvirtualIntMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
+       for (i = 0; i < count; i++)
+               stringbuffer[i] = LLNI_array_direct(a, offset + i);
+       
+       /* terminate string */
 
-       /*log_text("JNI-Call: CallNonvirtualIntMethodV");*/
+       stringbuffer[i] = '\0';
 
-       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_INT,args);
+       return stringbuffer;
 }
 
 
-jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallNonvirtualIntMethodA: IMPLEMENT ME!");
+/* GetStringChars **************************************************************
 
-       return 0;
-}
+   Returns a pointer to the array of Unicode characters of the
+   string. This pointer is valid until ReleaseStringChars() is called.
 
+*******************************************************************************/
 
+const jchar *_Jv_JNI_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
+{      
+       jchar *jc;
 
-jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: CallNonvirtualLongMethod: IMPLEMENT ME!");
-
-       return 0;
-}
+       jc = javastring_tou2(str);
 
+       if (jc) {
+               if (isCopy)
+                       *isCopy = JNI_TRUE;
 
-jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
+               return jc;
+       }
 
-       log_text("JNI-Call: CallNonvirtualLongMethodV: IMPLEMENT ME!");
+       if (isCopy)
+               *isCopy = JNI_TRUE;
 
-       return 0;
+       return emptyStringJ;
 }
 
 
-jlong CallNonvirtualLongMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
+/* 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().
 
+*******************************************************************************/
 
-jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
+void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
 {
-       jfloat ret;
-       va_list vaargs;
+       java_lang_String *s;
 
        STATISTICS(jniinvokation());
 
-       /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/
+       if (chars == emptyStringJ)
+               return;
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,PRIMITIVETYPE_FLOAT);
-       va_end(vaargs);
+       s = (java_lang_String *) str;
 
-       return ret;
+       MFREE(((jchar *) chars), jchar, LLNI_field_direct(s, count) + 1);
 }
 
 
-jfloat CallNonvirtualFloatMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-/*     log_text("JNI-Call: CallNonvirtualFloatMethodV"); */
+/* NewStringUTF ****************************************************************
 
-       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,PRIMITIVETYPE_FLOAT);
-}
+   Constructs a new java.lang.String object from an array of UTF-8
+   characters.
 
+*******************************************************************************/
 
-jfloat CallNonvirtualFloatMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
 {
-       STATISTICS(jniinvokation());
+       java_lang_String *s;
 
-       log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!");
+       TRACEJNICALLS("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes);
 
-       return 0;
+       s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
+
+    return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
 }
 
 
+/****************** returns the utf8 length in bytes of a string *******************/
 
-jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       jdouble ret;
-       va_list vaargs;
+jsize _Jv_JNI_GetStringUTFLength(JNIEnv *env, jstring string)
+{   
+       java_lang_String *s;
+       s4                length;
 
-       STATISTICS(jniinvokation());
+       TRACEJNICALLS("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string);
 
-/*     log_text("JNI-Call: CallNonvirtualDoubleMethod"); */
+       s = (java_lang_String *) string;
 
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,PRIMITIVETYPE_DOUBLE);
-       va_end(vaargs);
+       length = u2_utflength(LLNI_field_direct(s, value)->data, LLNI_field_direct(s, count));
 
-       return ret;
+       return length;
 }
 
 
-jdouble CallNonvirtualDoubleMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-/*     log_text("JNI-Call: CallNonvirtualDoubleMethodV");*/
+/* GetStringUTFChars ***********************************************************
 
-       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,PRIMITIVETYPE_DOUBLE);
-}
+   Returns a pointer to an array of UTF-8 characters of the
+   string. This array is valid until it is released by
+   ReleaseStringUTFChars().
 
+*******************************************************************************/
 
-jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
+const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
+                                                                         jboolean *isCopy)
 {
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
+       utf *u;
 
+       STATISTICS(jniinvokation());
 
-void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
+       if (string == NULL)
+               return "";
 
-       STATISTICS(jniinvokation());
+       if (isCopy)
+               *isCopy = JNI_TRUE;
+       
+       u = javastring_toutf((java_handle_t *) string, false);
 
-/*      log_text("JNI-Call: CallNonvirtualVoidMethod");*/
+       if (u != NULL)
+               return u->text;
 
-       va_start(vaargs,methodID);
-       (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),TYPE_VOID,vaargs);
-       va_end(vaargs);
+       return "";
 }
 
 
-void CallNonvirtualVoidMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-/*     log_text("JNI-Call: CallNonvirtualVoidMethodV");*/
+/* ReleaseStringUTFChars *******************************************************
 
-       (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),TYPE_VOID,args);
-}
+   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 CallNonvirtualVoidMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
+void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
 {
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: CallNonvirtualVoidMethodA: IMPLEMENT ME!");
+    /* 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 */
 }
 
 
-/* Accessing Fields of Objects ************************************************/
+/* Array Operations ***********************************************************/
 
-/* GetFieldID ******************************************************************
+/* GetArrayLength **************************************************************
 
-   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.
+   Returns the number of elements in the array.
 
 *******************************************************************************/
 
-jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name,
-                                       const char *sig) 
+jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
 {
-       fieldinfo *f;
-       utf       *uname;
-       utf       *udesc;
+       java_handle_t *a;
+       jsize          size;
 
        STATISTICS(jniinvokation());
 
-       uname = utf_new_char((char *) name);
-       udesc = utf_new_char((char *) sig);
+       a = (java_handle_t *) array;
 
-       f = class_findfield(clazz, uname, udesc); 
-       
-       if (!f)
-               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
+       size = LLNI_array_size(a);
 
-       return f;
+       return size;
 }
 
 
-/* Get<type>Field Routines *****************************************************
+/* NewObjectArray **************************************************************
 
-   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 array holding objects in class elementClass. All
+   elements are initially set to initialElement.
 
 *******************************************************************************/
 
-jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
+jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
+                                                                       jclass elementClass, jobject initialElement)
 {
-       java_objectheader *o;
+       classinfo                 *c;
+       java_handle_t             *o;
+       java_handle_objectarray_t *oa;
+       s4                         i;
 
        STATISTICS(jniinvokation());
 
-       o = GET_FIELD(obj, java_objectheader*, fieldID);
+       c = LLNI_classinfo_unwrap(elementClass);
+       o = (java_handle_t *) initialElement;
 
-       return NewLocalRef(env, o);
-}
+       if (length < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
 
+    oa = builtin_anewarray(length, c);
 
-jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       s4 i;
+       if (oa == NULL)
+               return NULL;
 
-       STATISTICS(jniinvokation());
+       /* set all elements to initialElement */
 
-       i = GET_FIELD(obj, s4, fieldID);
+       for (i = 0; i < length; i++)
+               LLNI_objectarray_element_set(oa, i, o);
 
-       return (jboolean) i;
+       return (jobjectArray) _Jv_JNI_NewLocalRef(env, (jobject) oa);
 }
 
 
-jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID)
+jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
+                                                                         jsize index)
 {
-       s4 i;
+       java_handle_objectarray_t *oa;
+       java_handle_t             *o;
 
        STATISTICS(jniinvokation());
 
-       i = GET_FIELD(obj, s4, fieldID);
-
-       return (jbyte) i;
-}
-
-
-jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       s4 i;
+       oa = (java_handle_objectarray_t *) array;
 
-       STATISTICS(jniinvokation());
+       if (index >= LLNI_array_size(oa)) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return NULL;
+       }
 
-       i = GET_FIELD(obj, s4, fieldID);
+       LLNI_objectarray_element_get(oa, index, o);
 
-       return (jchar) i;
+       return _Jv_JNI_NewLocalRef(env, (jobject) o);
 }
 
 
-jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID)
+void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
+                                                                  jsize index, jobject val)
 {
-       s4 i;
+       java_handle_objectarray_t *oa;
+       java_handle_t             *o;
 
        STATISTICS(jniinvokation());
 
-       i = GET_FIELD(obj, s4, fieldID);
+       oa = (java_handle_objectarray_t *) array;
+       o  = (java_handle_t *) val;
 
-       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)
-{
-       s8 l;
-
-       STATISTICS(jniinvokation());
-
-       l = GET_FIELD(obj, s8, fieldID);
-
-       return l;
-}
-
-
-jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       float f;
-
-       STATISTICS(jniinvokation());
-
-       f = GET_FIELD(obj, float, fieldID);
-
-       return f;
-}
-
-
-jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
-       double d;
-
-       STATISTICS(jniinvokation());
-
-       d = GET_FIELD(obj, double, fieldID);
-
-       return d;
-}
-
-
-/* Set<type>Field Routines *****************************************************
-
-   This family of accessor routines sets the value of an instance
-   (nonstatic) field of an object. The field to access is specified by
-   a field ID obtained by calling GetFieldID().
-
-*******************************************************************************/
-
-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)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, s4, fieldID, value);
-}
-
-
-void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, s4, fieldID, value);
-}
-
-
-void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, s8, fieldID, value);
-}
-
-
-void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, float, fieldID, value);
-}
-
-
-void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value)
-{
-       STATISTICS(jniinvokation());
-
-       SET_FIELD(obj, double, fieldID, value);
-}
-
-
-/* Calling Static Methods *****************************************************/
-
-/* GetStaticMethodID ***********************************************************
-
-   Returns the method ID for a static method of a class. The method is
-   specified by its name and signature.
-
-   GetStaticMethodID() causes an uninitialized class to be
-   initialized.
-
-*******************************************************************************/
-
-jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
-                                                       const char *sig)
-{
-       classinfo  *c;
-       utf        *uname;
-       utf        *udesc;
-       methodinfo *m;
-
-       STATISTICS(jniinvokation());
-
-       c = (classinfo *) clazz;
-
-       if (!c)
-               return NULL;
-
-       if (!(c->state & CLASS_INITIALIZED))
-               if (!initialize_class(c))
-                       return NULL;
-
-       /* try to get the 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 || !(m->flags & ACC_STATIC)) {
-               *exceptionptr = exceptions_new_nosuchmethoderror(c, uname, udesc);
-
-               return NULL;
-       }
-
-       return m;
-}
-
-
-jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       java_objectheader *ret;
-       va_list            vaargs;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = callObjectMethod(0, methodID, vaargs);
-       va_end(vaargs);
-
-       return NewLocalRef(env, ret);
-}
-
-
-jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       java_objectheader *ret;
-
-       STATISTICS(jniinvokation());
-       
-       ret = callObjectMethod(0, methodID, args);
-
-       return NewLocalRef(env, ret);
-}
-
-
-jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticObjectMethodA: IMPLEMENT ME!");
-
-       return NewLocalRef(env, NULL);
-}
-
-
-jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list  vaargs;
-       jboolean ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = (jboolean) callIntegerMethod(0, methodID, PRIMITIVETYPE_BOOLEAN, vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return (jboolean) callIntegerMethod(0, methodID, PRIMITIVETYPE_BOOLEAN, args);
-}
-
-
-jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticBooleanMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
-       jbyte   ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = (jbyte) callIntegerMethod(0, methodID, PRIMITIVETYPE_BYTE, vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return (jbyte) callIntegerMethod(0, methodID, PRIMITIVETYPE_BYTE, args);
-}
-
-
-jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticByteMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
-       jchar   ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = (jchar) callIntegerMethod(0, methodID, PRIMITIVETYPE_CHAR, vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return (jchar) callIntegerMethod(0, methodID, PRIMITIVETYPE_CHAR, args);
-}
-
-
-jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticCharMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
-       jshort  ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = (jshort) callIntegerMethod(0, methodID, PRIMITIVETYPE_SHORT, vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return (jshort) callIntegerMethod(0, methodID, PRIMITIVETYPE_SHORT, args);
-}
-
-
-jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticShortMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
-       jint    ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = callIntegerMethod(0, methodID, PRIMITIVETYPE_INT, vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return callIntegerMethod(0, methodID, PRIMITIVETYPE_INT, args);
-}
-
-
-jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticIntMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
-       jlong   ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = callLongMethod(0, methodID, vaargs);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
-                                                       va_list args)
-{
-       STATISTICS(jniinvokation());
-       
-       return callLongMethod(0, methodID, args);
-}
-
-
-jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticLongMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-
-jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
-       jfloat  ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       ret = callFloatMethod(0, methodID, vaargs, PRIMITIVETYPE_FLOAT);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return callFloatMethod(0, methodID, args, PRIMITIVETYPE_FLOAT);
-
-}
-
-
-jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticFloatMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
-       va_list vaargs;
-       jdouble ret;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs,methodID);
-       ret = callFloatMethod(0, methodID, vaargs, PRIMITIVETYPE_DOUBLE);
-       va_end(vaargs);
-
-       return ret;
-}
-
-
-jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       return callFloatMethod(0, methodID, args, PRIMITIVETYPE_DOUBLE);
-}
-
-
-jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
-{
-       STATISTICS(jniinvokation());
-
-       log_text("JNI-Call: CallStaticDoubleMethodA: IMPLEMENT ME!");
-
-       return 0;
-}
-
-
-void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)
-{
-       va_list vaargs;
-
-       STATISTICS(jniinvokation());
-
-       va_start(vaargs, methodID);
-       (void) callIntegerMethod(0, methodID, TYPE_VOID, vaargs);
-       va_end(vaargs);
-}
-
-
-void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)
-{
-       STATISTICS(jniinvokation());
-
-       (void) callIntegerMethod(0, methodID, TYPE_VOID, args);
-}
-
-
-void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args)
-{
-       STATISTICS(jniinvokation());
-
-       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) {
+       if (index >= LLNI_array_size(oa)) {
                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;
-       }
+       /* check if the class of value is a subclass of the element class
+          of the array */
 
-       la = builtin_newarray_long(len);
+       if (!builtin_canstore(oa, o))
+               return;
 
-       return (jlongArray) NewLocalRef(env, (jobject) la);
+       LLNI_objectarray_element_set(oa, index, o);
 }
 
 
-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);
+#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); \
 }
 
-
-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);
-}
+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)
 
 
 /* Get<PrimitiveType>ArrayElements *********************************************
@@ -3475,94 +2979,30 @@ jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
 
 *******************************************************************************/
 
-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;
-}
+#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)
 
 
 /* Release<PrimitiveType>ArrayElements *****************************************
@@ -3576,180 +3016,40 @@ jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray 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;
-               }
-       }
-}
+#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)
 
 
 /*  Get<PrimitiveType>ArrayRegion **********************************************
@@ -3759,203 +3059,63 @@ void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
 
 *******************************************************************************/
 
-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);
-}
-
-
-void GetCharArrayRegion(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(buf, &array->data[start], jchar, len);
-}
-
-
-void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
-                                                jsize len, jshort *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else       
-               MCOPY(buf, &array->data[start], jshort, len);
-}
-
-
-void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
-                                          jint *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jint, len);
-}
-
-
-void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len,
-                                               jlong *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(buf, &array->data[start], jlong, len);
-}
-
-
-void GetFloatArrayRegion(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(buf, &array->data[start], jfloat, len);
-}
-
-
-void GetDoubleArrayRegion(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(buf, &array->data[start], jdouble, 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)
 
 
 /*  Set<PrimitiveType>ArrayRegion **********************************************
 
        A family of functions that copies back a region of a primitive
-       array from a buffer.
-
-*******************************************************************************/
-
-void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
-                                                  jsize len, jboolean *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jboolean, len);
-}
-
-
-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);
-}
-
-
-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);
-}
-
-
-void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
-                                                jsize len, jshort *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jshort, len);
-}
-
-
-void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
-                                          jint *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jint, len);
-}
-
-
-void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len,
-                                               jlong *buf)
-{
-       STATISTICS(jniinvokation());
-
-    if (start < 0 || len < 0 || start + len > array->header.size)
-               exceptions_throw_arrayindexoutofboundsexception();
-    else
-               MCOPY(&array->data[start], buf, jlong, len);
-}
-
-
-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);
-}
-
+       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 *************************************************/
@@ -3970,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;
 }
@@ -3993,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());
 
@@ -4014,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;
 }
@@ -4041,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;
 }
@@ -4068,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';
 }
 
 
@@ -4100,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;
 }
@@ -4121,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);
 }
 
 
@@ -4139,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());
 
@@ -4165,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());
 
@@ -4180,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;
 }
 
 
@@ -4229,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);
 }
 
 
@@ -4280,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;
 }
 
 
@@ -4298,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
 }
 
 
@@ -4343,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());
 
@@ -4359,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
 }
 
 
@@ -4376,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;
 }
 
 
@@ -4415,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;
 }
 
 
@@ -4452,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;
@@ -4486,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
 };
 
 
@@ -4795,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;
 }
 
@@ -4816,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;
 }
 
 
@@ -4829,260 +4221,16 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 
 *******************************************************************************/
 
-jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args)
-{
-       const struct JNIInvokeInterface *vm;
-       struct JNINativeInterface *env;
-
-       vm = &JNI_JavaVMTable;
-       env = &JNI_JNIEnvTable;
-
-       *p_vm = (JavaVM *) vm;
-       *p_env = (JNIEnv *) env;
-
-       return 0;
-}
-
-
-jobject *jni_method_invokeNativeHelper(JNIEnv *env, methodinfo *methodID,
-                                                                          jobject obj, java_objectarray *params)
+jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
 {
-       jni_callblock *blk;
-       jobject        o;
-       s4             argcount;
-       s4             paramcount;
-
-       if (methodID == 0) {
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
-               return NULL;
-       }
-
-       argcount = methodID->parseddesc->paramcount;
-       paramcount = argcount;
-
-       /* if method is non-static, remove the `this' pointer */
-
-       if (!(methodID->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 (!(methodID->flags & ACC_STATIC) && obj &&
-               (!builtin_instanceof((java_objectheader *) obj, methodID->class))) {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_IllegalArgumentException,
-                                                                                         "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
-               return NULL;
-       }
-
-       if (((params == NULL) && (paramcount != 0)) ||
-               (params && (params->header.size != paramcount))) {
-               *exceptionptr =
-                       new_exception(string_java_lang_IllegalArgumentException);
-               return NULL;
-       }
+       TRACEJNICALLS("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args);
 
+       /* actually create the JVM */
 
-       if (!(methodID->flags & ACC_STATIC) && !obj)  {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NullPointerException,
-                                                                 "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
-               return NULL;
-       }
-
-       if ((methodID->flags & ACC_STATIC) && (obj))
-               obj = NULL;
-
-       if (obj) {
-               if ((methodID->flags & ACC_ABSTRACT) ||
-                       (methodID->class->flags & ACC_INTERFACE)) {
-                       methodID = get_virtual(obj, methodID);
-               }
-       }
-
-       blk = MNEW(jni_callblock, argcount);
-
-       if (!fill_callblock_from_objectarray(obj, methodID->parseddesc, blk,
-                                                                                params))
-               return NULL;
-
-       switch (methodID->parseddesc->returntype.decltype) {
-       case TYPE_VOID:
-               ASM_CALLJAVAFUNCTION2(methodID, argcount,
-                                                         argcount * sizeof(jni_callblock),
-                                                         blk);
-               o = NULL; /*native_new_and_init(loader_load(utf_new_char("java/lang/Void")));*/
-               break;
-
-       case PRIMITIVETYPE_INT: {
-               s4 i;
-               ASM_CALLJAVAFUNCTION2_INT(i, methodID, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
-
-               o = native_new_and_init_int(class_java_lang_Integer, i);
-       }
-       break;
-
-       case PRIMITIVETYPE_BYTE: {
-               s4 i;
-               ASM_CALLJAVAFUNCTION2_INT(i, methodID, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
-
-/*             o = native_new_and_init_int(class_java_lang_Byte, i); */
-               o = builtin_new(class_java_lang_Byte);
-               CallVoidMethod(env,
-                                          o,
-                                          class_resolvemethod(o->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_byte__void),
-                                          i);
-       }
-       break;
-
-       case PRIMITIVETYPE_CHAR: {
-               s4 i;
-
-               ASM_CALLJAVAFUNCTION2_INT(i, methodID, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
-
-               o = builtin_new(class_java_lang_Character);
-
-               CallVoidMethod(env,
-                                          o,
-                                          class_resolvemethod(o->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_char__void),
-                                          i);
-       }
-       break;
-
-       case PRIMITIVETYPE_SHORT: {
-               s4 i;
-
-               ASM_CALLJAVAFUNCTION2_INT(i, methodID, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
-
-               o = builtin_new(class_java_lang_Short);
-
-               CallVoidMethod(env,
-                                          o,
-                                          class_resolvemethod(o->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_short__void),
-                                          i);
-       }
-       break;
-
-       case PRIMITIVETYPE_BOOLEAN: {
-               s4 i;
-
-               ASM_CALLJAVAFUNCTION2_INT(i, methodID, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
-
-               o = builtin_new(class_java_lang_Boolean);
-
-               CallVoidMethod(env,
-                                          o,
-                                          class_resolvemethod(o->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_boolean__void),
-                                          i);
-       }
-       break;
-
-       case PRIMITIVETYPE_LONG: {
-               s8 l;
-
-               ASM_CALLJAVAFUNCTION2_LONG(l, methodID, argcount,
-                                                                  argcount * sizeof(jni_callblock),
-                                                                  blk);
-
-               o = builtin_new(class_java_lang_Long);
-
-               CallVoidMethod(env,
-                                          o,
-                                          class_resolvemethod(o->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_long__void),
-                                          l);
-       }
-       break;
-
-       case PRIMITIVETYPE_FLOAT: {
-               float f;
-
-               ASM_CALLJAVAFUNCTION2_FLOAT(f, methodID, argcount,
-                                                                       argcount * sizeof(jni_callblock),
-                                                                       blk);
-
-               o = builtin_new(class_java_lang_Float);
-
-               CallVoidMethod(env,
-                                          o,
-                                          class_resolvemethod(o->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_float__void),
-                                          f);
-       }
-       break;
-
-       case PRIMITIVETYPE_DOUBLE: {
-               double d;
-
-               ASM_CALLJAVAFUNCTION2_DOUBLE(d, methodID, argcount,
-                                                                        argcount * sizeof(jni_callblock),
-                                                                        blk);
-
-               o = builtin_new(class_java_lang_Double);
-
-               CallVoidMethod(env,
-                                          o,
-                                          class_resolvemethod(o->vftbl->class,
-                                                                                  utf_init,
-                                                                                  utf_double__void),
-                                          d);
-       }
-       break;
-
-       case TYPE_ADR:
-               ASM_CALLJAVAFUNCTION2_ADR(o, methodID, argcount,
-                                                                 argcount * sizeof(jni_callblock),
-                                                                 blk);
-               break;
-
-       default:
-               /* if this happens the exception has already been set by              */
-               /* fill_callblock_from_objectarray                                    */
-
-               MFREE(blk, jni_callblock, argcount);
-
-               return (jobject *) 0;
-       }
-
-       MFREE(blk, jni_callblock, argcount);
-
-       if (*exceptionptr) {
-               java_objectheader *cause;
-
-               cause = *exceptionptr;
-
-               /* clear exception pointer, we are calling JIT code again */
-
-               *exceptionptr = NULL;
-
-               *exceptionptr =
-                       new_exception_throwable(string_java_lang_reflect_InvocationTargetException,
-                                                                       (java_lang_Throwable *) cause);
-       }
+       if (!vm_createjvm(p_vm, p_env, vm_args))
+               return JNI_ERR;
 
-       return (jobject *) o;
+       return JNI_OK;
 }
 
 
@@ -5097,4 +4245,5 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, methodinfo *methodID,
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */