fix: GetJavaVM now returns a pointer to a global variable ptr_jvm instead of a local...
[cacao.git] / src / native / jni.c
index cae0687476105560d3554deb2bf44f42068e820b..bb77db195f03039325b588d695419e61765b8b27 100644 (file)
@@ -1,9 +1,9 @@
-/* jni.c - implementation of the Java Native Interface functions
+/* native/jni.c - implementation of the Java Native Interface functions
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
-   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger, M. Platter
+   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    Contact: cacao@complang.tuwien.ac.at
 
-   Authors: ?
+   Authors: Rainhard Grafl
+            Roman Obermaisser
 
-   Changes: Joseph Wenninger, Martin Platter
+   Changes: Joseph Wenninger
+            Martin Platter
+            Christian Thalinger
 
-   $Id: jni.c 1424 2004-10-30 11:15:23Z motse $
+   $Id: jni.c 1969 2005-03-01 14:09:25Z motse $
 
 */
 
 
 #include <string.h>
-#include "exceptions.h"
-#include "main.h"
-#include "jni.h"
-#include "global.h"
-#include "loader.h"
-#include "tables.h"
-#include "native.h"
-#include "builtin.h"
-#include "options.h"
-#include "statistics.h"
-#include "threads/thread.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "nat/java_lang_Byte.h"
-#include "nat/java_lang_Character.h"
-#include "nat/java_lang_Short.h"
-#include "nat/java_lang_Integer.h"
-#include "nat/java_lang_Boolean.h"
-#include "nat/java_lang_Long.h"
-#include "nat/java_lang_Float.h"
-#include "nat/java_lang_Double.h"
-#include "nat/java_lang_Throwable.h"
-#include "jit/jit.h"
-#include "asmpart.h"
+
 #include "mm/boehm.h"
-#define JNI_VERSION       0x00010002
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+#include "native/include/java_lang_Byte.h"
+#include "native/include/java_lang_Character.h"
+#include "native/include/java_lang_Short.h"
+#include "native/include/java_lang_Integer.h"
+#include "native/include/java_lang_Boolean.h"
+#include "native/include/java_lang_Long.h"
+#include "native/include/java_lang_Float.h"
+#include "native/include/java_lang_Double.h"
+#include "native/include/java_lang_Throwable.h"
+
+#if defined(USE_THREADS)
+# if defined(NATIVE_THREADS)
+#  include "threads/native/threads.h"
+# else
+#  include "threads/green/threads.h"
+# endif
+#endif
 
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
 
-#define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
 
-static utf* utf_char = 0;
-static utf* utf_bool = 0;
-static utf* utf_byte  =0;
-static utf* utf_short = 0;
-static utf* utf_int = 0;
-static utf* utf_long = 0;
-static utf* utf_float = 0;
-static utf* utf_double = 0;
+/* 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;
+static void* ptr_env = (void*) &JNI_JNIEnvTable;
+
+
+#define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
 
 /* global reference table */
 static jobject *global_ref_table;
+static bool initrunning=false;
 
 /* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/
 static jmethodID getmid = NULL;
@@ -229,23 +241,6 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
     int cnts;
     char c;
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-    intsDisable();
-#endif
-       if (utf_char==0) {
-               utf_char=utf_new_char("java/lang/Character");
-               utf_bool=utf_new_char("java/lang/Boolean");
-               utf_byte=utf_new_char("java/lang/Byte");
-               utf_short=utf_new_char("java/lang/Short");
-               utf_int=utf_new_char("java/lang/Integer");
-               utf_long=utf_new_char("java/lang/Long");
-               utf_float=utf_new_char("java/lang/Float");
-               utf_double=utf_new_char("java/lang/Double");
-       }
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-    intsRestore();
-#endif
-
        /*
          log_text("fill_callblock");
          utf_display(descr);
@@ -274,15 +269,15 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'B':
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
-                       if (param->vftbl->class->name == utf_byte) {
+                       if (param->vftbl->class->name == utf_java_lang_Byte) {
                                blk[cnt].itemtype = TYPE_INT;
                                blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
 
                        } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
                        break;
@@ -290,15 +285,15 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'C':
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
-                       if (param->vftbl->class->name == utf_char) {
+                       if (param->vftbl->class->name == utf_java_lang_Character) {
                                blk[cnt].itemtype = TYPE_INT;
                                blk[cnt].item = (u8) ((java_lang_Character *) param)->value;
 
                        } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
                        break;
@@ -306,20 +301,20 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'S':
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
-                       if (param->vftbl->class->name == utf_short) {
+                       if (param->vftbl->class->name == utf_java_lang_Short) {
                                blk[cnt].itemtype = TYPE_INT;
                                blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
 
                        } else  {
-                               if (param->vftbl->class->name == utf_byte) {
+                               if (param->vftbl->class->name == utf_java_lang_Byte) {
                                        blk[cnt].itemtype = TYPE_INT;
                                        blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
 
                                } else {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                       *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                        return 0;
                                }
                        }
@@ -328,15 +323,15 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'Z':
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
-                       if (param->vftbl->class->name == utf_bool) {
+                       if (param->vftbl->class->name == utf_java_lang_Boolean) {
                                blk[cnt].itemtype = TYPE_INT;
                                blk[cnt].item = (u8) ((java_lang_Boolean *) param)->value;
 
                        } else {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
                        break;
@@ -345,25 +340,25 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                        /*log_text("fill_callblock_objA: param 'I'");*/
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
-                       if (param->vftbl->class->name == utf_int) {
+                       if (param->vftbl->class->name == utf_java_lang_Integer) {
                                blk[cnt].itemtype = TYPE_INT;
                                blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
                                /*printf("INT VALUE :%d\n",((struct java_lang_Integer * )param)->value);*/
                        } else {
-                               if (param->vftbl->class->name == utf_short) {
+                               if (param->vftbl->class->name == utf_java_lang_Short) {
                                        blk[cnt].itemtype = TYPE_INT;
                                        blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
 
                                } else  {
-                                       if (param->vftbl->class->name == utf_byte) {
+                                       if (param->vftbl->class->name == utf_java_lang_Byte) {
                                                blk[cnt].itemtype = TYPE_INT;
                                                blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
 
                                        } else  {
-                                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                                return 0;
                                        }
                                }
@@ -373,29 +368,29 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'J':
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
-                       if (param->vftbl->class->name == utf_long) {
+                       if (param->vftbl->class->name == utf_java_lang_Long) {
                                blk[cnt].itemtype = TYPE_LNG;
                                blk[cnt].item = (u8) ((java_lang_Long *) param)->value;
 
                        } else  {
-                               if (param->vftbl->class->name == utf_int) {
+                               if (param->vftbl->class->name == utf_java_lang_Integer) {
                                        blk[cnt].itemtype = TYPE_LNG;
                                        blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
 
                                } else {
-                                       if (param->vftbl->class->name == utf_short) {
+                                       if (param->vftbl->class->name == utf_java_lang_Short) {
                                                blk[cnt].itemtype = TYPE_LNG;
                                                blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
 
                                        } else  {
-                                               if (param->vftbl->class->name == utf_byte) {
+                                               if (param->vftbl->class->name == utf_java_lang_Byte) {
                                                        blk[cnt].itemtype = TYPE_LNG;
                                                        blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
                                                } else  {
-                                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                                       *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                                        return 0;
                                                }
                                        }
@@ -407,16 +402,16 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'F':
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
 
-                       if (param->vftbl->class->name == utf_float) {
+                       if (param->vftbl->class->name == utf_java_lang_Float) {
                                blk[cnt].itemtype = TYPE_FLT;
                                *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value;
 
                        } else  {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
                        break;
@@ -424,21 +419,21 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'D':
                        param = params->data[cnts];
                        if (param == 0) {
-                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                return 0;
                        }
 
-                       if (param->vftbl->class->name == utf_double) {
+                       if (param->vftbl->class->name == utf_java_lang_Double) {
                                blk[cnt].itemtype = TYPE_DBL;
                                *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
 
                        } else  {
-                               if (param->vftbl->class->name == utf_float) {
+                               if (param->vftbl->class->name == utf_java_lang_Float) {
                                        blk[cnt].itemtype = TYPE_DBL;
                                        *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
 
                                } else  {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                       *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                        return 0;
                                }
                        }
@@ -451,18 +446,17 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case 'L':
                        {
                                char *start = (*utf_ptr) - 1;
-                               char *end = NULL;
+                               /*char *end = NULL;
 
                                while (utf_nextu2(utf_ptr) != ';')
-                                       end = (*utf_ptr) + 1;
+                                       end = (*utf_ptr) + 1;*/
 
-                               if (!builtin_instanceof(params->data[cnts], class_from_descriptor(start, end, 0, CLASSLOAD_LOAD))) {
+                               if (!builtin_instanceof(params->data[cnts], class_from_descriptor(start, desc_end, utf_ptr, CLASSLOAD_LOAD))) {
                                        if (params->data[cnts] != 0) {
-                                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                                return 0;
                                        }                       
                                }
-
                                blk[cnt].itemtype = TYPE_ADR;
                                blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
                                break;                  
@@ -471,8 +465,8 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                case '[':
                        {
                                char *start = (*utf_ptr) - 1;
-                               char *end;
-
+                               /*char *end;
+                               
                                char ch;
                                while ((ch = utf_nextu2(utf_ptr)) == '[')
                                        if (ch == 'L') {
@@ -480,13 +474,13 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
                                        }
 
                                end = (*utf_ptr) - 1;
-                               ch = utf_nextu2(utf_ptr);
+                               ch = utf_nextu2(utf_ptr); */
 
-                               if (!builtin_arrayinstanceof(params->data[cnts], class_from_descriptor(start, end, 0, CLASSLOAD_LOAD)->vftbl)) {
-                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               if (!builtin_arrayinstanceof(params->data[cnts], class_from_descriptor(start, desc_end, utf_ptr, CLASSLOAD_LOAD)->vftbl)) {
+                                       *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                                        return 0;
                                }
-       
+
                                blk[cnt].itemtype = TYPE_ADR;
                                blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
                                break;
@@ -502,24 +496,12 @@ char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_object
 }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
 jmethodID get_virtual(jobject obj,jmethodID methodID) {
        if (obj->vftbl->class==methodID->class) return methodID;
        return class_resolvemethod (obj->vftbl->class, methodID->name, methodID->descriptor);
 }
 
+
 jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) {
        if (clazz==methodID->class) return methodID;
 /*class_resolvemethod -> classfindmethod? (JOWENN)*/
@@ -527,7 +509,6 @@ jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) {
 }
 
 
-
 jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
 {      
        int argcount;
@@ -563,7 +544,7 @@ jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, 'O');
        /*      printf("parameter: obj: %p",blk[0].item); */
@@ -624,15 +605,15 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, retType);
 
        /*      printf("parameter: obj: %p",blk[0].item); */
-       ret = (jint) asm_calljavafunction2(methodID,
-                                                                          argcount + 1,
-                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                          blk);
+       ret = asm_calljavafunction2int(methodID,
+                                                                  argcount + 1,
+                                                                  (argcount + 1) * sizeof(jni_callblock),
+                                                                  blk);
 
        MFREE(blk, jni_callblock, argcount + 1);
        /*      printf("(CallObjectMethodV)-->%p\n",ret); */
@@ -682,7 +663,7 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock,/* 4 */argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, 'J');
 
@@ -723,7 +704,7 @@ jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retTy
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, retType);
 
@@ -766,27 +747,45 @@ fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
        return NULL;
 }
 
-/********************* returns version of native method interface *****************/
 
-jint GetVersion (JNIEnv* env)
+/* GetVersion ******************************************************************
+
+   Returns the major version number in the higher 16 bits and the
+   minor version number in the lower 16 bits.
+
+*******************************************************************************/
+
+jint GetVersion(JNIEnv *env)
 {
-       return JNI_VERSION;
+       /* GNU classpath currently supports JNI 1.2 */
+
+       return JNI_VERSION_1_2;
 }
 
 
-/************** loads a class from a buffer of raw class data *****************/
+/* Class Operations ***********************************************************/
+
+/* DefineClass *****************************************************************
+
+   Loads a class from a buffer of raw class data. The buffer
+   containing the raw class data is not referenced by the VM after the
+   DefineClass call returns, and it may be discarded if desired.
 
-jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *buf, jsize len) 
+*******************************************************************************/
+
+jclass DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen)
 {
-       jclass c; 
+       jclass c;
        jclass r;
        classbuffer *cb;
 
        c = class_new(utf_new_char_classname((char *) name));
 
+#if defined(USE_THREADS)
        /* enter a monitor on the class */
 
        builtin_monitorenter((java_objectheader *) c);
+#endif
 
        /* measure time */
        if (getloadingtime)
@@ -795,7 +794,7 @@ jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *b
        /* build a classbuffer with the given data */
        cb = NEW(classbuffer);
        cb->class = c;
-       cb->size = len;
+       cb->size = bufLen;
        cb->data = (u1 *) buf;
        cb->pos = cb->data - 1;
 
@@ -816,34 +815,43 @@ jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *b
        if (getloadingtime)
                loadingtime_stop();
 
+#if defined(USE_THREADS)
        /* leave the monitor */
 
        builtin_monitorexit((java_objectheader *) c);
+#endif
 
        /* XXX link the class here? */
 /*     if (class_link(c)) */
 /*             return NULL; */
 
-       if (r)
+       if (r) {
                c->classloader = loader;
+               use_class_as_object(r);
+       }
 
        return r;
 }
 
 
-/*********** loads locally defined class with the specified name **************/
+/* FindClass *******************************************************************
+
+   This function loads a locally-defined class. It searches the
+   directories and zip files specified by the CLASSPATH environment
+   variable for the class with the specified name.
 
-jclass FindClass(JNIEnv* env, const char *name) 
+*******************************************************************************/
+
+jclass FindClass(JNIEnv *env, const char *name)
 {
        classinfo *c;  
   
        c = class_new(utf_new_char_classname((char *) name));
 
-       if (!class_load(c))
+       if (!class_load(c) || !class_link(c))
                return NULL;
 
-       if (!class_link(c))
-               return NULL;
+       use_class_as_object(c);
 
        return c;
 }
@@ -858,31 +866,42 @@ jclass FindClass(JNIEnv* env, const char *name)
   
 jmethodID FromReflectedMethod(JNIEnv* env, jobject method)
 {
-       /* log_text("JNI-Call: FromReflectedMethod"); */
+       log_text("JNI-Call: FromReflectedMethod: IMPLEMENT ME!!!");
 
        return 0;
 }
 
 
-/*************** return superclass of the class represented by sub ****************/
+/* GetSuperclass ***************************************************************
+
+   If clazz represents any class other than the class Object, then
+   this function returns the object that represents the superclass of
+   the class specified by clazz.
+
+*******************************************************************************/
  
 jclass GetSuperclass(JNIEnv* env, jclass sub) 
 {
        classinfo *c;
 
-       c = ((classinfo*) sub)->super;
+       c = ((classinfo *) sub)->super;
 
-       if (!c) return NULL; 
+       if (!c)
+               return NULL;
 
        use_class_as_object(c);
 
-       return c;               
+       return c;
 }
   
  
-/*********************** check whether sub can be cast to sup  ********************/
-  
-jboolean IsAssignableForm(JNIEnv* env, jclass sub, jclass sup)
+/* IsAssignableFrom ************************************************************
+
+   Determines whether an object of sub can be safely cast to sup.
+
+*******************************************************************************/
+
+jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
 {
        return builtin_isanysubclass(sub, sup);
 }
@@ -892,26 +911,30 @@ jboolean IsAssignableForm(JNIEnv* env, jclass sub, jclass sup)
 
 jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic)
 {
-       /* log_text("JNI-Call: ToReflectedField"); */
+       log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!!!");
 
        return NULL;
 }
 
 
-/***************** throw java.lang.Throwable object  ******************************/
+/* Throw ***********************************************************************
+
+   Causes a java.lang.Throwable object to be thrown.
+
+*******************************************************************************/
 
-jint Throw(JNIEnvenv, jthrowable obj)
+jint Throw(JNIEnv *env, jthrowable obj)
 {
-       *exceptionptr = (java_objectheader*) obj;
+       *exceptionptr = (java_objectheader *) obj;
 
-       return 0;
+       return JNI_OK;
 }
 
 
-/*******************************************************************************
+/* ThrowNew ********************************************************************
 
-       create exception object from the class clazz with the 
-       specified message and cause it to be thrown
+  Constructs an exception object from the specified class with the message
+  specified by message and causes that exception to be thrown.
 
 *******************************************************************************/
 
@@ -920,11 +943,12 @@ jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
        java_lang_Throwable *o;
 
        /* instantiate exception object */
-       o = (java_lang_Throwable *) native_new_and_init((classinfo*) clazz);
 
-       if (!o) return (-1);
+       o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz,
+                                                                                                                  (java_lang_String *) javastring_new_char(msg));
 
-       o->detailMessage = (java_lang_String *) javastring_new_char((char *) msg);
+       if (!o)
+               return -1;
 
        *exceptionptr = (java_objectheader *) o;
 
@@ -932,38 +956,85 @@ jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
 }
 
 
-/************************* check if exception occured *****************************/
+/* ExceptionOccurred ***********************************************************
+
+   Determines if an exception is being thrown. The exception stays
+   being thrown until either the native code calls ExceptionClear(),
+   or the Java code handles the exception.
 
-jthrowable ExceptionOccurred (JNIEnv* env) 
+*******************************************************************************/
+
+jthrowable ExceptionOccurred(JNIEnv *env)
 {
        return (jthrowable) *exceptionptr;
 }
 
-/********** print exception and a backtrace of the stack (for debugging) **********/
 
-void ExceptionDescribe (JNIEnv* env) 
+/* ExceptionDescribe ***********************************************************
+
+   Prints an exception and a backtrace of the stack to a system
+   error-reporting channel, such as stderr. This is a convenience
+   routine provided for debugging.
+
+*******************************************************************************/
+
+void ExceptionDescribe(JNIEnv *env)
 {
-       utf_display((*exceptionptr)->vftbl->class->name);
-       printf ("\n");
-       fflush (stdout);        
+       java_objectheader *e;
+       methodinfo        *m;
+
+       e = *exceptionptr;
+
+       if (e) {
+               /* clear exception, because we are calling jit code again */
+
+               *exceptionptr = NULL;
+
+               /* get printStackTrace method from exception class */
+
+               m = class_resolveclassmethod(e->vftbl->class,
+                                                                        utf_printStackTrace,
+                                                                        utf_void__void,
+                                                                        NULL,
+                                                                        true);
+
+               if (!m)
+                       /* XXX what should we do? */
+                       return;
+
+               /* print the stacktrace */
+
+               asm_calljavafunction(m, e, NULL, NULL, NULL);
+       }
 }
 
 
-/******************* clear any exception currently being thrown *******************/
+/* ExceptionClear **************************************************************
 
-void ExceptionClear (JNIEnv* env) 
+   Clears any exception that is currently being thrown. If no
+   exception is currently being thrown, this routine has no effect.
+
+*******************************************************************************/
+
+void ExceptionClear(JNIEnv *env)
 {
-       *exceptionptr = NULL;   
+       *exceptionptr = NULL;
 }
 
 
-/********** raises a fatal error and does not expect the VM to recover ************/
+/* FatalError ******************************************************************
+
+   Raises a fatal error and does not expect the VM to recover. This
+   function does not return.
+
+*******************************************************************************/
 
-void FatalError (JNIEnv* env, const char *msg)
+void FatalError(JNIEnv *env, const char *msg)
 {
-       panic((char *) msg);    
+       throw_cacao_exception_exit(string_java_lang_InternalError, msg);
 }
 
+
 /******************* creates a new local reference frame **************************/ 
 
 jint PushLocalFrame(JNIEnv* env, jint capacity)
@@ -992,13 +1063,19 @@ void DeleteLocalRef (JNIEnv* env, jobject localRef)
        /* empty */
 }
 
-/********** Tests whether two references refer to the same Java object ************/
 
-jboolean IsSameObject (JNIEnv* env, jobject obj1, jobject obj2)
+/* IsSameObject ****************************************************************
+
+   Tests whether two references refer to the same Java object.
+
+*******************************************************************************/
+
+jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
 {
-       return (obj1==obj2);
+       return (ref1 == ref2);
 }
 
+
 /***** Creates a new local reference that refers to the same object as ref  *******/
 
 jobject NewLocalRef (JNIEnv* env, jobject ref)
@@ -1019,23 +1096,39 @@ jint EnsureLocalCapacity (JNIEnv* env, jint capacity)
 }
 
 
-/********* Allocates a new Java object without invoking a constructor *************/
+/* AllocObject *****************************************************************
 
-jobject AllocObject (JNIEnv* env, jclass clazz)
+   Allocates a new Java object without invoking any of the constructors for the
+   object. Returns a reference to the object.
+
+*******************************************************************************/
+
+jobject AllocObject(JNIEnv *env, jclass clazz)
 {
-        java_objectheader *o = builtin_new(clazz);     
+       java_objectheader *o;
+
+       if ((clazz->flags & ACC_INTERFACE) || (clazz->flags & ACC_ABSTRACT)) {
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_InstantiationException,
+                                                                        clazz->name);
+               return NULL;
+       }
+               
+       o = builtin_new(clazz);
+
        return o;
 }
 
 
-/*********************************************************************************** 
+/* NewObject *******************************************************************
 
-       Constructs a new Java object
-       arguments that are to be passed to the constructor are placed after methodID
+   Constructs a new Java object. The method ID indicates which constructor
+   method to invoke. This ID must be obtained by calling GetMethodID() with
+   <init> as the method name and void (V) as the return type.
 
-***********************************************************************************/
+*******************************************************************************/
 
-jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
+jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        java_objectheader *o;
        void* args[3];
@@ -1043,8 +1136,6 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
        int i;
        va_list vaargs;
 
-       /* log_text("JNI-Call: NewObject"); */
-
 #ifdef arglimit
        if (argcount > 3) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
@@ -1052,17 +1143,23 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
                return 0;
        }
 #endif
+
+       /* create object */
+
+       o = builtin_new(clazz);
        
-       o = builtin_new (clazz);         /*          create object */
-       
-       if (!o) return NULL;
+       if (!o)
+               return NULL;
 
-       va_start(vaargs,methodID);
-       for (i=0;i<argcount;i++) {
-               args[i]=va_arg(vaargs,void*);
+       va_start(vaargs, methodID);
+       for (i = 0; i < argcount; i++) {
+               args[i] = va_arg(vaargs, void*);
        }
        va_end(vaargs);
-       asm_calljavafunction(methodID,o,args[0],args[1],args[2]);
+
+       /* call constructor */
+
+       asm_calljavafunction(methodID, o, args[0], args[1], args[2]);
 
        return o;
 }
@@ -1144,23 +1241,27 @@ jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean
 }
 
 
-/**************** returns the method ID for an instance method ********************/
+/* GetMethodID *****************************************************************
+
+   returns the method ID for an instance method
+
+*******************************************************************************/
 
 jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *sig)
 {
        jmethodID m;
 
-       m = class_resolvemethod (
-               clazz, 
-               utf_new_char ((char*) name), 
-               utf_new_char ((char*) sig)
-       );
+       m = class_resolvemethod(clazz, 
+                                                       utf_new_char((char *) name), 
+                                                       utf_new_char((char *) sig));
 
-       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-       else if (m->flags & ACC_STATIC)   {
-               m=0;
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       if (!m || (m->flags & ACC_STATIC)) {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoSuchMethodError, name);
+
+               return 0;
        }
+
        return m;
 }
 
@@ -1435,8 +1536,6 @@ void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        va_list vaargs;
 
-/*      log_text("JNI-Call: CallVoidMethod");*/
-
        va_start(vaargs,methodID);
        (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs);
        va_end(vaargs);
@@ -1764,9 +1863,9 @@ jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *si
                            ); 
        
        if (!f) { 
-               utf_display(clazz->name);
+               /*utf_display(clazz->name);
                log_text(name);
-               log_text(sig);
+               log_text(sig);*/
                *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
        }
        return f;
@@ -1793,13 +1892,14 @@ jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig)
 
 jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID)
 {
+       /*
        jobject dbg,dretval,*dpretval;  
        long int dli1, dli2, dli3;
 
-/*     printf("GetObjectField(1): thread: %s obj: %p name: %s desc: %s \n",GetStringUTFChars(env,
+       printf("GetObjectField(1): thread: %s obj: %p name: %s desc: %s \n",GetStringUTFChars(env,
                         ((threadobject *) THREADOBJECT)->o
                         .thread->name,NULL)
-                        ,obj,((fieldinfo*)fieldID)->name->text,(fieldID->descriptor)->text);*/
+                        ,obj,((fieldinfo*)fieldID)->name->text,(fieldID->descriptor)->text);
 
        dbg = getField(obj,jobject,fieldID);
        dli1 = (long int) obj;
@@ -1807,7 +1907,7 @@ jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID)
        dli3 = dli1+dli2;
        dpretval = (jobject*) dli3;
        dretval = *dpretval;
-/*     jclass tmp;
+       jclass tmp;
        jmethodID mid;
        jstring jstr;
 
@@ -1819,7 +1919,9 @@ jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID)
        ,dbg, dli1, dli2, dli3,dpretval, dretval);*/
 
 
-       return dbg;
+/*     return dbg;*/
+
+       return getField(obj,jobject,fieldID);
 }
 
 jboolean GetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID)
@@ -1933,10 +2035,11 @@ jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const c
                                                        utf_new_char((char *) name),
                                                        utf_new_char((char *) sig));
 
-       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
-       else if (!(m->flags & ACC_STATIC))   {
-               m=0;
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       if (!m || !(m->flags & ACC_STATIC)) {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoSuchMethodError, name);
+
+               return NULL;
        }
 
        return m;
@@ -2222,8 +2325,6 @@ void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)
 {
        va_list vaargs;
 
-/*      log_text("JNI-Call: CallStaticVoidMethod");*/
-
        va_start(vaargs, methodID);
        (void) callIntegerMethod(0, methodID, 'V', vaargs);
        va_end(vaargs);
@@ -2470,14 +2571,19 @@ void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars)
        MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1);
 }
 
-/************ create new java.lang.String object from utf8-characterarray **********/
 
-jstring NewStringUTF (JNIEnv *env, const char *utf)
+/* NewStringUTF ****************************************************************
+
+   Constructs a new java.lang.String object from an array of UTF-8 characters.
+
+*******************************************************************************/
+
+jstring NewStringUTF(JNIEnv *env, const char *bytes)
 {
-/*    log_text("NewStringUTF called");*/
-    return (jstring) javastring_new(utf_new_char((char *) utf));
+    return (jstring) javastring_new(utf_new_char(bytes));
 }
 
+
 /****************** returns the utf8 length in bytes of a string *******************/
 
 jsize GetStringUTFLength (JNIEnv *env, jstring string)
@@ -2974,46 +3080,86 @@ jint UnregisterNatives (JNIEnv* env, jclass clazz)
     return 0;
 }
 
-/******************************* monitor operations ********************************/
 
-jint MonitorEnter (JNIEnv* env, jobject obj)
+/* Monitor Operations *********************************************************/
+
+/* MonitorEnter ****************************************************************
+
+   Enters the monitor associated with the underlying Java object
+   referred to by obj.
+
+*******************************************************************************/
+
+jint MonitorEnter(JNIEnv *env, jobject obj)
 {
-    builtin_monitorenter(obj);
-    return 0;
+       if (!obj) {
+               *exceptionptr = new_nullpointerexception();
+               return JNI_ERR;
+       }
+
+#if defined(USE_THREADS)
+       builtin_monitorenter(obj);
+#endif
+
+       return JNI_OK;
 }
 
 
-jint MonitorExit (JNIEnv* env, jobject obj)
+/* MonitorExit *****************************************************************
+
+   The current thread must be the owner of the monitor associated with
+   the underlying Java object referred to by obj. The thread
+   decrements the counter indicating the number of times it has
+   entered this monitor. If the value of the counter becomes zero, the
+   current thread releases the monitor.
+
+*******************************************************************************/
+
+jint MonitorExit(JNIEnv *env, jobject obj)
 {
-    builtin_monitorexit(obj);
-    return 0;
+       if (!obj) {
+               *exceptionptr = new_nullpointerexception();
+               return JNI_ERR;
+       }
+
+#if defined(USE_THREADS)
+       builtin_monitorexit(obj);
+#endif
+
+       return JNI_OK;
 }
 
 
-/************************************* JavaVM interface ****************************/
-#ifdef __cplusplus
-#error CPP mode not supported yet
-#else
-jint GetJavaVM (JNIEnv* env, JavaVM **vm)
+/* JavaVM Interface ***********************************************************/
+
+/* GetJavaVM *******************************************************************
+
+   Returns the Java VM interface (used in the Invocation API)
+   associated with the current thread. The result is placed at the
+   location pointed to by the second argument, vm.
+
+*******************************************************************************/
+
+jint GetJavaVM(JNIEnv *env, JavaVM **vm)
 {
-    log_text("JNI-Call: GetJavaVM");
-    *vm=&javaVM;
-    return 0;
+    *vm = &ptr_jvm;
+
+       return 0;
 }
-#endif /*__cplusplus*/
+
 
 void GetStringRegion (JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
 {
-    log_text("JNI-Call: GetStringRegion");
-
+       log_text("JNI-Call: GetStringRegion");
 }
 
+
 void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
 {
-    log_text("JNI-Call: GetStringUTFRegion");
-
+       log_text("JNI-Call: GetStringUTFRegion");
 }
 
+
 /************** obtain direct pointer to array elements ***********************/
 
 void * GetPrimitiveArrayCritical (JNIEnv* env, jarray array, jboolean *isCopy)
@@ -3072,62 +3218,122 @@ void DeleteWeakGlobalRef (JNIEnv* env, jweak ref)
 /** Creates a new global reference to the object referred to by the obj argument **/
     
 jobject NewGlobalRef(JNIEnv* env, jobject lobj)
-{      
-       MonitorEnter(env,*global_ref_table);
-       jobject refcount = CallObjectMethod(env, *global_ref_table, getmid, lobj);
-       jint val = (refcount == NULL) ? 0 : CallIntMethod(env,refcount,intvalue);
-       jobject newval = NewObject(env,intclass,newint,val+1);
-       if (newval != NULL) {
+{
+       jobject refcount;
+       jint val;
+       jobject newval;
 
-               CallObjectMethod(env, *global_ref_table, putmid, lobj, newval);
+       MonitorEnter(env, *global_ref_table);
+       
+       refcount = CallObjectMethod(env, *global_ref_table, getmid, lobj);
+       val = (refcount == NULL) ? 0 : CallIntMethod(env, refcount, intvalue);
+       newval = NewObject(env, intclass, newint, val + 1);
 
-               MonitorExit(env,*global_ref_table);
+       if (newval != NULL) {
+               CallObjectMethod(env, *global_ref_table, putmid, lobj, newval);
+               MonitorExit(env, *global_ref_table);
                return lobj;
+
        } else {
                log_text("JNI-NewGlobalRef: unable to create new java.lang.Integer");
-               MonitorExit(env,*global_ref_table);
+               MonitorExit(env, *global_ref_table);
                return NULL;
        }
 }
 
 /*************  Deletes the global reference pointed to by globalRef **************/
 
-void DeleteGlobalRef (JNIEnv* env, jobject gref)
+void DeleteGlobalRef(JNIEnv* env, jobject gref)
 {
-       MonitorEnter(env,*global_ref_table);
-       jobject refcount = CallObjectMethod(env, *global_ref_table, getmid, gref);
+       jobject refcount;
+       jint val;
+
+       MonitorEnter(env, *global_ref_table);
+       refcount = CallObjectMethod(env, *global_ref_table, getmid, gref);
+
        if (refcount == NULL) {
                log_text("JNI-DeleteGlobalRef: unable to find global reference");
                return;
        }
-       jint val = CallIntMethod(env,refcount,intvalue);
+
+       val = CallIntMethod(env, refcount, intvalue);
        val--;
+
        if (val == 0) {
                CallObjectMethod(env, *global_ref_table, removemid,refcount);
+
        } else {
-               jobject newval = NewObject(env,intclass,newint,val);
+               jobject newval = NewObject(env, intclass, newint, val);
+
                if (newval != NULL) {
                        CallObjectMethod(env,*global_ref_table, putmid,newval);
+
                } else {
                        log_text("JNI-DeleteGlobalRef: unable to create new java.lang.Integer");
                }
        }
+
        MonitorExit(env,*global_ref_table);
 }
 
-/******************************* check for pending exception ***********************/
 
+/* ExceptionCheck *****************************************************************
 
-jboolean ExceptionCheck(JNIEnv* env)
-{
-       log_text("JNI-Call: ExceptionCheck");
+   check for pending exception
 
+**********************************************************************************/
+
+jboolean ExceptionCheck(JNIEnv *env)
+{
        return *exceptionptr ? JNI_TRUE : JNI_FALSE;
 }
 
 
+/* New JNI 1.4 functions ******************************************************/
+
+/* NewDirectByteBuffer *********************************************************
 
+   Allocates and returns a direct java.nio.ByteBuffer referring to the block of
+   memory starting at the memory address address and extending capacity bytes.
 
+*******************************************************************************/
+
+jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
+{
+       log_text("NewDirectByteBuffer: IMPLEMENT ME!");
+
+       return NULL;
+}
+
+
+/* GetDirectBufferAddress ******************************************************
+
+   Fetches and returns the starting address of the memory region referenced by
+   the given direct java.nio.Buffer.
+
+*******************************************************************************/
+
+void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
+{
+       log_text("GetDirectBufferAddress: IMPLEMENT ME!");
+
+       return NULL;
+}
+
+
+/* GetDirectBufferCapacity *****************************************************
+
+   Fetches and returns the capacity in bytes of the memory region referenced by
+   the given direct java.nio.Buffer.
+
+*******************************************************************************/
+
+jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf)
+{
+       log_text("GetDirectBufferCapacity: IMPLEMENT ME!");
+
+       return 0;
+}
 
 
 jint DestroyJavaVM(JavaVM *vm)
@@ -3154,11 +3360,25 @@ jint DetachCurrentThread(JavaVM *vm)
 }
 
 
-jint GetEnv(JavaVM *vm, void **environment, jint jniversion)
+jint GetEnv(JavaVM *vm, void **env, jint version)
 {
-       *environment = &env;
+       if ((version != JNI_VERSION_1_1) && (version != JNI_VERSION_1_2) &&
+               (version != JNI_VERSION_1_4)) {
+               *env = NULL;
+               return JNI_EVERSION;
+       }
 
-       return 0;
+       /*
+         TODO: If the current thread is not attached to the VM...
+       if (0) {
+               *env = NULL;
+               return JNI_EDETACHED;
+       }
+       */
+
+       *env = &ptr_env;
+
+       return JNI_OK;
 }
 
 
@@ -3169,258 +3389,450 @@ jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
        return 0;
 }
 
+/************* JNI Initialization ****************************************************/
+
+jobject jni_init1(JNIEnv* env, jobject lobj) {
+#if defined(USE_THREADS)
+       while (initrunning) {yieldThread();} /* wait until init is done */
+#endif
+       if (global_ref_table == NULL) {
+               jni_init();
+       } 
+#if defined(USE_THREADS)
+       else {
+               /* wait until jni_init is done */
+               MonitorEnter(env, *global_ref_table) ;
+               MonitorExit(env, *global_ref_table);
+       }
+#endif
+       return NewGlobalRef(env, lobj); 
+}
+void jni_init2(JNIEnv* env, jobject gref) {
+       log_text("DeleteGlobalref called before NewGlobalref");
+#if defined(USE_THREADS)
+       while (initrunning) {yieldThread();} /* wait until init is done */
+#endif
+       if (global_ref_table == NULL) {
+               jni_init();
+       } 
+#if defined(USE_THREADS)
+       else {
+               /* wait until jni_init is done */
+               MonitorEnter(env, *global_ref_table) ;
+               MonitorExit(env, *global_ref_table);
+       }
+#endif
+       DeleteGlobalRef(env, gref); 
+}
+
+void jni_init(){
+       jmethodID mid;
+
+       initrunning = true;
+       log_text("JNI-Init: initialize global_ref_table");
+       /* initalize global reference table */
+       ihmclass = FindClass(NULL, "java/util/IdentityHashMap");
+       
+       if (ihmclass == NULL) {
+               log_text("JNI-Init: unable to find java.util.IdentityHashMap");
+       }
+
+       mid = GetMethodID(NULL, ihmclass, "<init>","()V");
+       if (mid == NULL) {
+               log_text("JNI-Init: unable to find constructor in java.util.IdentityHashMap");
+       }
+       
+       global_ref_table = (jobject*)heap_allocate(sizeof(jobject),true,NULL);
+
+       *global_ref_table = NewObject(NULL,ihmclass,mid);
 
-/********************************* JNI invocation table ******************************/
+       if (*global_ref_table == NULL) {
+               log_text("JNI-Init: unable to create new global_ref_table");
+       }
+
+       initrunning = false;
 
-struct _JavaVM javaVMTable={
-   NULL,
-   NULL,
-   NULL,
-   &DestroyJavaVM,
-   &AttachCurrentThread,
-   &DetachCurrentThread,
-   &GetEnv,
-   &AttachCurrentThreadAsDaemon
+       getmid = GetMethodID(NULL, ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (mid == NULL) {
+               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
+       }
+
+       getmid = GetMethodID(NULL ,ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (getmid == NULL) {
+               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
+       }
+
+       putmid = GetMethodID(NULL, ihmclass, "put","(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+       if (putmid == NULL) {
+               log_text("JNI-Init: unable to find method \"put\" in java.util.IdentityHashMap");
+       }
+
+       intclass = FindClass(NULL, "java/lang/Integer");
+       if (intclass == NULL) {
+               log_text("JNI-Init: unable to find java.lang.Integer");
+       }
+
+       newint = GetMethodID(NULL, intclass, "<init>","(I)V");
+       if (newint == NULL) {
+               log_text("JNI-Init: unable to find constructor in java.lang.Integer");
+       }
+
+       intvalue = GetMethodID(NULL, intclass, "intValue","()I");
+       if (intvalue == NULL) {
+               log_text("JNI-Init: unable to find method \"intValue\" in java.lang.Integer");
+       }
+
+       removemid = GetMethodID(NULL, ihmclass, "remove","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (removemid == NULL) {
+               log_text("JNI-DeleteGlobalRef: unable to find method \"remove\" in java.lang.Object");
+       }
+       
+       /* set NewGlobalRef, DeleteGlobalRef envTable entry to real implementation */
+
+       JNI_JNIEnvTable.NewGlobalRef = &NewGlobalRef;
+       JNI_JNIEnvTable.DeleteGlobalRef = &DeleteGlobalRef;
+}
+
+
+/* JNI invocation table *******************************************************/
+
+const struct JNIInvokeInterface JNI_JavaVMTable = {
+       NULL,
+       NULL,
+       NULL,
+
+       DestroyJavaVM,
+       AttachCurrentThread,
+       DetachCurrentThread,
+       GetEnv,
+       AttachCurrentThreadAsDaemon
 };
 
-JavaVM javaVM = &javaVMTable;
-
-
-/********************************* JNI function table ******************************/
-
-struct JNI_Table envTable = {   
-    NULL,
-    NULL,
-    NULL,
-    NULL,    
-    &GetVersion,
-    &DefineClass,
-    &FindClass,
-    &FromReflectedMethod,
-    &FromReflectedField,
-    &ToReflectedMethod,
-    &GetSuperclass,
-    &IsAssignableForm,
-    &ToReflectedField,
-    &Throw,
-    &ThrowNew,
-    &ExceptionOccurred,
-    &ExceptionDescribe,
-    &ExceptionClear,
-    &FatalError,
-    &PushLocalFrame,
-    &PopLocalFrame,
-    &NewGlobalRef,
-    &DeleteGlobalRef,
-    &DeleteLocalRef,
-    &IsSameObject,
-    &NewLocalRef,
-    &EnsureLocalCapacity,
-    &AllocObject,
-    &NewObject,
-    &NewObjectV,
-    &NewObjectA,
-    &GetObjectClass,
-    &IsInstanceOf,
-    &GetMethodID,
-    &CallObjectMethod,
-    &CallObjectMethodV,
-    &CallObjectMethodA,
-    &CallBooleanMethod,
-    &CallBooleanMethodV,
-    &CallBooleanMethodA,
-    &CallByteMethod,
-    &CallByteMethodV,
-    &CallByteMethodA,
-    &CallCharMethod,
-    &CallCharMethodV,
-    &CallCharMethodA,
-    &CallShortMethod,
-    &CallShortMethodV,
-    &CallShortMethodA,
-    &CallIntMethod,
-    &CallIntMethodV,
-    &CallIntMethodA,
-    &CallLongMethod,
-    &CallLongMethodV,
-    &CallLongMethodA,
-    &CallFloatMethod,
-    &CallFloatMethodV,
-    &CallFloatMethodA,
-    &CallDoubleMethod,
-    &CallDoubleMethodV,
-    &CallDoubleMethodA,
-    &CallVoidMethod,
-    &CallVoidMethodV,
-    &CallVoidMethodA,
-    &CallNonvirtualObjectMethod,
-    &CallNonvirtualObjectMethodV,
-    &CallNonvirtualObjectMethodA,
-    &CallNonvirtualBooleanMethod,
-    &CallNonvirtualBooleanMethodV,
-    &CallNonvirtualBooleanMethodA,
-    &CallNonvirtualByteMethod,
-    &CallNonvirtualByteMethodV,
-    &CallNonvirtualByteMethodA,
-    &CallNonvirtualCharMethod,
-    &CallNonvirtualCharMethodV,
-    &CallNonvirtualCharMethodA,
-    &CallNonvirtualShortMethod,
-    &CallNonvirtualShortMethodV,
-    &CallNonvirtualShortMethodA,
-    &CallNonvirtualIntMethod,
-    &CallNonvirtualIntMethodV,
-    &CallNonvirtualIntMethodA,
-    &CallNonvirtualLongMethod,
-    &CallNonvirtualLongMethodV,
-    &CallNonvirtualLongMethodA,
-    &CallNonvirtualFloatMethod,
-    &CallNonvirtualFloatMethodV,
-    &CallNonvirtualFloatMethodA,
-    &CallNonvirtualDoubleMethod,
-    &CallNonvirtualDoubleMethodV,
-    &CallNonvirtualDoubleMethodA,
-    &CallNonvirtualVoidMethod,
-    &CallNonvirtualVoidMethodV,
-    &CallNonvirtualVoidMethodA,
-    &GetFieldID,
-    &GetObjectField,
-    &GetBooleanField,
-    &GetByteField,
-    &GetCharField,
-    &GetShortField,
-    &GetIntField,
-    &GetLongField,
-    &GetFloatField,
-    &GetDoubleField,
-    &SetObjectField,
-    &SetBooleanField,
-    &SetByteField,
-    &SetCharField,
-    &SetShortField,
-    &SetIntField,
-    &SetLongField,
-    &SetFloatField,
-    &SetDoubleField,
-    &GetStaticMethodID,
-    &CallStaticObjectMethod,
-    &CallStaticObjectMethodV,
-    &CallStaticObjectMethodA,
-    &CallStaticBooleanMethod,
-    &CallStaticBooleanMethodV,
-    &CallStaticBooleanMethodA,
-    &CallStaticByteMethod,
-    &CallStaticByteMethodV,
-    &CallStaticByteMethodA,
-    &CallStaticCharMethod,
-    &CallStaticCharMethodV,
-    &CallStaticCharMethodA,
-    &CallStaticShortMethod,
-    &CallStaticShortMethodV,
-    &CallStaticShortMethodA,
-    &CallStaticIntMethod,
-    &CallStaticIntMethodV,
-    &CallStaticIntMethodA,
-    &CallStaticLongMethod,
-    &CallStaticLongMethodV,
-    &CallStaticLongMethodA,
-    &CallStaticFloatMethod,
-    &CallStaticFloatMethodV,
-    &CallStaticFloatMethodA,
-    &CallStaticDoubleMethod,
-    &CallStaticDoubleMethodV,
-    &CallStaticDoubleMethodA,
-    &CallStaticVoidMethod,
-    &CallStaticVoidMethodV,
-    &CallStaticVoidMethodA,
-    &GetStaticFieldID,
-    &GetStaticObjectField,
-    &GetStaticBooleanField,
-    &GetStaticByteField,
-    &GetStaticCharField,
-    &GetStaticShortField,
-    &GetStaticIntField,
-    &GetStaticLongField,
-    &GetStaticFloatField,
-    &GetStaticDoubleField,
-    &SetStaticObjectField,
-    &SetStaticBooleanField,
-    &SetStaticByteField,
-    &SetStaticCharField,
-    &SetStaticShortField,
-    &SetStaticIntField,
-    &SetStaticLongField,
-    &SetStaticFloatField,
-    &SetStaticDoubleField,
-    &NewString,
-    &GetStringLength,
-    &GetStringChars,
-    &ReleaseStringChars,
-    &NewStringUTF,
-    &GetStringUTFLength,
-    &GetStringUTFChars,
-    &ReleaseStringUTFChars,
-    &GetArrayLength,
-    &NewObjectArray,
-    &GetObjectArrayElement,
-    &SetObjectArrayElement,
-    &NewBooleanArray,
-    &NewByteArray,
-    &NewCharArray,
-    &NewShortArray,
-    &NewIntArray,
-    &NewLongArray,
-    &NewFloatArray,
-    &NewDoubleArray,
-    &GetBooleanArrayElements,
-    &GetByteArrayElements,
-    &GetCharArrayElements,
-    &GetShortArrayElements,
-    &GetIntArrayElements,
-    &GetLongArrayElements,
-    &GetFloatArrayElements,
-    &GetDoubleArrayElements,
-    &ReleaseBooleanArrayElements,
-    &ReleaseByteArrayElements,
-    &ReleaseCharArrayElements,
-    &ReleaseShortArrayElements,
-    &ReleaseIntArrayElements,
-    &ReleaseLongArrayElements,
-    &ReleaseFloatArrayElements,
-    &ReleaseDoubleArrayElements,
-    &GetBooleanArrayRegion,
-    &GetByteArrayRegion,
-    &GetCharArrayRegion,
-    &GetShortArrayRegion,
-    &GetIntArrayRegion,
-    &GetLongArrayRegion,
-    &GetFloatArrayRegion,
-    &GetDoubleArrayRegion,
-    &SetBooleanArrayRegion,
-    &SetByteArrayRegion,
-    &SetCharArrayRegion,
-    &SetShortArrayRegion,
-    &SetIntArrayRegion,
-    &SetLongArrayRegion,
-    &SetFloatArrayRegion,
-    &SetDoubleArrayRegion,
-    &RegisterNatives,
-    &UnregisterNatives,
-    &MonitorEnter,
-    &MonitorExit,
-    &GetJavaVM,
-    &GetStringRegion,
-    &GetStringUTFRegion,
-    &GetPrimitiveArrayCritical,
-    &ReleasePrimitiveArrayCritical,
-    &GetStringCritical,
-    &ReleaseStringCritical,
-    &NewWeakGlobalRef,
-    &DeleteWeakGlobalRef,
-    &ExceptionCheck
+
+/* JNI function table *********************************************************/
+
+struct JNINativeInterface JNI_JNIEnvTable = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,    
+       &GetVersion,
+
+       &DefineClass,
+       &FindClass,
+       &FromReflectedMethod,
+       &FromReflectedField,
+       &ToReflectedMethod,
+       &GetSuperclass,
+       &IsAssignableFrom,
+       &ToReflectedField,
+
+       &Throw,
+       &ThrowNew,
+       &ExceptionOccurred,
+       &ExceptionDescribe,
+       &ExceptionClear,
+       &FatalError,
+       &PushLocalFrame,
+       &PopLocalFrame,
+
+       &jni_init1, /* &NewGlobalRef,    initialize Global_Ref_Table*/
+       &jni_init2, /* &DeleteGlobalRef,*/
+       &DeleteLocalRef,
+       &IsSameObject,
+       &NewLocalRef,
+       &EnsureLocalCapacity,
+
+       &AllocObject,
+       &NewObject,
+       &NewObjectV,
+       &NewObjectA,
+
+       &GetObjectClass,
+       &IsInstanceOf,
+
+       &GetMethodID,
+
+       &CallObjectMethod,
+       &CallObjectMethodV,
+       &CallObjectMethodA,
+       &CallBooleanMethod,
+       &CallBooleanMethodV,
+       &CallBooleanMethodA,
+       &CallByteMethod,
+       &CallByteMethodV,
+       &CallByteMethodA,
+       &CallCharMethod,
+       &CallCharMethodV,
+       &CallCharMethodA,
+       &CallShortMethod,
+       &CallShortMethodV,
+       &CallShortMethodA,
+       &CallIntMethod,
+       &CallIntMethodV,
+       &CallIntMethodA,
+       &CallLongMethod,
+       &CallLongMethodV,
+       &CallLongMethodA,
+       &CallFloatMethod,
+       &CallFloatMethodV,
+       &CallFloatMethodA,
+       &CallDoubleMethod,
+       &CallDoubleMethodV,
+       &CallDoubleMethodA,
+       &CallVoidMethod,
+       &CallVoidMethodV,
+       &CallVoidMethodA,
+
+       &CallNonvirtualObjectMethod,
+       &CallNonvirtualObjectMethodV,
+       &CallNonvirtualObjectMethodA,
+       &CallNonvirtualBooleanMethod,
+       &CallNonvirtualBooleanMethodV,
+       &CallNonvirtualBooleanMethodA,
+       &CallNonvirtualByteMethod,
+       &CallNonvirtualByteMethodV,
+       &CallNonvirtualByteMethodA,
+       &CallNonvirtualCharMethod,
+       &CallNonvirtualCharMethodV,
+       &CallNonvirtualCharMethodA,
+       &CallNonvirtualShortMethod,
+       &CallNonvirtualShortMethodV,
+       &CallNonvirtualShortMethodA,
+       &CallNonvirtualIntMethod,
+       &CallNonvirtualIntMethodV,
+       &CallNonvirtualIntMethodA,
+       &CallNonvirtualLongMethod,
+       &CallNonvirtualLongMethodV,
+       &CallNonvirtualLongMethodA,
+       &CallNonvirtualFloatMethod,
+       &CallNonvirtualFloatMethodV,
+       &CallNonvirtualFloatMethodA,
+       &CallNonvirtualDoubleMethod,
+       &CallNonvirtualDoubleMethodV,
+       &CallNonvirtualDoubleMethodA,
+       &CallNonvirtualVoidMethod,
+       &CallNonvirtualVoidMethodV,
+       &CallNonvirtualVoidMethodA,
+
+       &GetFieldID,
+
+       &GetObjectField,
+       &GetBooleanField,
+       &GetByteField,
+       &GetCharField,
+       &GetShortField,
+       &GetIntField,
+       &GetLongField,
+       &GetFloatField,
+       &GetDoubleField,
+       &SetObjectField,
+       &SetBooleanField,
+       &SetByteField,
+       &SetCharField,
+       &SetShortField,
+       &SetIntField,
+       &SetLongField,
+       &SetFloatField,
+       &SetDoubleField,
+
+       &GetStaticMethodID,
+
+       &CallStaticObjectMethod,
+       &CallStaticObjectMethodV,
+       &CallStaticObjectMethodA,
+       &CallStaticBooleanMethod,
+       &CallStaticBooleanMethodV,
+       &CallStaticBooleanMethodA,
+       &CallStaticByteMethod,
+       &CallStaticByteMethodV,
+       &CallStaticByteMethodA,
+       &CallStaticCharMethod,
+       &CallStaticCharMethodV,
+       &CallStaticCharMethodA,
+       &CallStaticShortMethod,
+       &CallStaticShortMethodV,
+       &CallStaticShortMethodA,
+       &CallStaticIntMethod,
+       &CallStaticIntMethodV,
+       &CallStaticIntMethodA,
+       &CallStaticLongMethod,
+       &CallStaticLongMethodV,
+       &CallStaticLongMethodA,
+       &CallStaticFloatMethod,
+       &CallStaticFloatMethodV,
+       &CallStaticFloatMethodA,
+       &CallStaticDoubleMethod,
+       &CallStaticDoubleMethodV,
+       &CallStaticDoubleMethodA,
+       &CallStaticVoidMethod,
+       &CallStaticVoidMethodV,
+       &CallStaticVoidMethodA,
+
+       &GetStaticFieldID,
+
+       &GetStaticObjectField,
+       &GetStaticBooleanField,
+       &GetStaticByteField,
+       &GetStaticCharField,
+       &GetStaticShortField,
+       &GetStaticIntField,
+       &GetStaticLongField,
+       &GetStaticFloatField,
+       &GetStaticDoubleField,
+       &SetStaticObjectField,
+       &SetStaticBooleanField,
+       &SetStaticByteField,
+       &SetStaticCharField,
+       &SetStaticShortField,
+       &SetStaticIntField,
+       &SetStaticLongField,
+       &SetStaticFloatField,
+       &SetStaticDoubleField,
+
+       &NewString,
+       &GetStringLength,
+       &GetStringChars,
+       &ReleaseStringChars,
+
+       &NewStringUTF,
+       &GetStringUTFLength,
+       &GetStringUTFChars,
+       &ReleaseStringUTFChars,
+
+       &GetArrayLength,
+
+       &NewObjectArray,
+       &GetObjectArrayElement,
+       &SetObjectArrayElement,
+
+       &NewBooleanArray,
+       &NewByteArray,
+       &NewCharArray,
+       &NewShortArray,
+       &NewIntArray,
+       &NewLongArray,
+       &NewFloatArray,
+       &NewDoubleArray,
+
+       &GetBooleanArrayElements,
+       &GetByteArrayElements,
+       &GetCharArrayElements,
+       &GetShortArrayElements,
+       &GetIntArrayElements,
+       &GetLongArrayElements,
+       &GetFloatArrayElements,
+       &GetDoubleArrayElements,
+
+       &ReleaseBooleanArrayElements,
+       &ReleaseByteArrayElements,
+       &ReleaseCharArrayElements,
+       &ReleaseShortArrayElements,
+       &ReleaseIntArrayElements,
+       &ReleaseLongArrayElements,
+       &ReleaseFloatArrayElements,
+       &ReleaseDoubleArrayElements,
+
+       &GetBooleanArrayRegion,
+       &GetByteArrayRegion,
+       &GetCharArrayRegion,
+       &GetShortArrayRegion,
+       &GetIntArrayRegion,
+       &GetLongArrayRegion,
+       &GetFloatArrayRegion,
+       &GetDoubleArrayRegion,
+       &SetBooleanArrayRegion,
+       &SetByteArrayRegion,
+       &SetCharArrayRegion,
+       &SetShortArrayRegion,
+       &SetIntArrayRegion,
+       &SetLongArrayRegion,
+       &SetFloatArrayRegion,
+       &SetDoubleArrayRegion,
+
+       &RegisterNatives,
+       &UnregisterNatives,
+
+       &MonitorEnter,
+       &MonitorExit,
+
+       &GetJavaVM,
+
+       /* new JNI 1.2 functions */
+
+       &GetStringRegion,
+       &GetStringUTFRegion,
+
+       &GetPrimitiveArrayCritical,
+       &ReleasePrimitiveArrayCritical,
+
+       &GetStringCritical,
+       &ReleaseStringCritical,
+
+       &NewWeakGlobalRef,
+       &DeleteWeakGlobalRef,
+
+       &ExceptionCheck,
+
+       /* new JNI 1.4 functions */
+
+       &NewDirectByteBuffer,
+       &GetDirectBufferAddress,
+       &GetDirectBufferCapacity
 };
 
-JNIEnv env = &envTable;
+
+/* Invocation API Functions ***************************************************/
+
+/* JNI_GetDefaultJavaVMInitArgs ************************************************
+
+   Returns a default configuration for the Java VM.
+
+*******************************************************************************/
+
+jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
+{
+       JDK1_1InitArgs *_vm_args = (JDK1_1InitArgs *) vm_args;
+
+       /* GNU classpath currently supports JNI 1.2 */
+
+       _vm_args->version = JNI_VERSION_1_2;
+
+       return 0;
+}
+
+
+/* JNI_GetCreatedJavaVMs *******************************************************
+
+   Returns all Java VMs that have been created. Pointers to VMs are written in
+   the buffer vmBuf in the order they are created. At most bufLen number of
+   entries will be written. The total number of created VMs is returned in
+   *nVMs.
+
+*******************************************************************************/
+
+jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
+{
+       log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!");
+
+       return 0;
+}
+
+
+/* JNI_CreateJavaVM ************************************************************
+
+   Loads and initializes a Java VM. The current thread becomes the main thread.
+   Sets the env argument to the JNI interface pointer of the main thread.
+
+*******************************************************************************/
+
+jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args)
+{
+       *p_vm = (JavaVM *) &JNI_JavaVMTable;
+       *p_env = (JNIEnv *) &JNI_JNIEnvTable;
+
+       return 0;
+}
 
 
 jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, jobject obj, java_objectarray *params)
@@ -3437,7 +3849,11 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
 
        argcount = get_parametercount(methodID);
 
-       if (obj && (!builtin_instanceof((java_objectheader *) obj, methodID->class))) {
+       /* the method is an instance method the obj has to be an instance of the 
+          class the method belongs to. For static methods the obj parameter
+          is ignored. */
+       if (!(methodID->flags & ACC_STATIC) && obj &&
+               (!builtin_instanceof((java_objectheader *) obj, methodID->class))) {
                *exceptionptr = new_exception_message(string_java_lang_IllegalArgumentException,
                                                                                          "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
                return 0;
@@ -3451,22 +3867,28 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                return 0;
        }
 #endif
-
-       if (((!params) && (argcount != 0)) || (params && (params->header.size != argcount))) {
+       if (((params==0) && (argcount != 0)) || (params && (params->header.size != argcount))) {
                *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                return 0;
        }
 
 
-       if (!(methodID->flags & ACC_STATIC) && (!obj))  {
-               *exceptionptr = new_exception_message(string_java_lang_NullPointerException,
-                                                                                         "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
+       if (((methodID->flags & ACC_STATIC)==0) && (0==obj))  {
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NullPointerException,
+                                                                 "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
                return 0;
        }
 
        if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0;
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       if (obj) {
+               if ( (methodID->flags & ACC_ABSTRACT) || (methodID->class->flags & ACC_INTERFACE) ) {
+                       methodID=get_virtual(obj,methodID);
+               }
+       }
+
+       blk = MNEW(jni_callblock, /*4 */argcount+2);
 
        retT = fill_callblock_objA(obj, methodID->descriptor, blk, params);
 
@@ -3480,130 +3902,130 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                break;
 
        case 'I': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Integer")));
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               retVal = builtin_new(class_java_lang_Integer);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(I)V")),
+                                                                                  utf_init,
+                                                                                  utf_int__void),
                                           intVal);
        }
        break;
 
        case 'B': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Byte")));
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               retVal = builtin_new(class_java_lang_Byte);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(B)V")),
+                                                                                  utf_init,
+                                                                                  utf_byte__void),
                                           intVal);
        }
        break;
 
        case 'C': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Character")));
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               retVal = builtin_new(class_java_lang_Character);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(C)V")),
+                                                                                  utf_init,
+                                                                                  utf_char__void),
                                           intVal);
        }
        break;
 
        case 'S': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Short")));
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               retVal = builtin_new(class_java_lang_Short);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(S)V")),
+                                                                                  utf_init,
+                                                                                  utf_short__void),
                                           intVal);
        }
        break;
 
        case 'Z': {
-               s4 intVal;      
-               intVal = (s4) asm_calljavafunction2(methodID,
-                                                                                       argcount + 1,
-                                                                                       (argcount + 1) * sizeof(jni_callblock),
-                                                                                       blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Boolean")));
+               s4 intVal;
+               intVal = asm_calljavafunction2int(methodID,
+                                                                                 argcount + 1,
+                                                                                 (argcount + 1) * sizeof(jni_callblock),
+                                                                                 blk);
+               retVal = builtin_new(class_java_lang_Boolean);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(Z)V")),
+                                                                                  utf_init,
+                                                                                  utf_boolean__void),
                                           intVal);
        }
        break;
 
        case 'J': {
-               jlong intVal;   
-               intVal = asm_calljavafunction2long(methodID,
-                                                                                  argcount + 1,
-                                                                                  (argcount + 1) * sizeof(jni_callblock),
-                                                                                  blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Long")));
+               jlong longVal;
+               longVal = asm_calljavafunction2long(methodID,
+                                                                                       argcount + 1,
+                                                                                       (argcount + 1) * sizeof(jni_callblock),
+                                                                                       blk);
+               retVal = builtin_new(class_java_lang_Long);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(J)V")),
-                                          intVal);
+                                                                                  utf_init,
+                                                                                  utf_long__void),
+                                          longVal);
        }
        break;
 
        case 'F': {
                jdouble floatVal;       
-               floatVal = asm_calljavafunction2double(methodID,
-                                                                                          argcount + 1,
-                                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                                          blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Float")));
+               floatVal = asm_calljavafunction2float(methodID,
+                                                                                         argcount + 1,
+                                                                                         (argcount + 1) * sizeof(jni_callblock),
+                                                                                         blk);
+               retVal = builtin_new(class_java_lang_Float);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(F)V")),
+                                                                                  utf_init,
+                                                                                  utf_float__void),
                                           floatVal);
        }
        break;
 
        case 'D': {
-               jdouble floatVal;       
-               floatVal = asm_calljavafunction2double(methodID,
-                                                                                          argcount + 1,
-                                                                                          (argcount + 1) * sizeof(jni_callblock),
-                                                                                          blk);
-               retVal = builtin_new(class_new(utf_new_char("java/lang/Double")));
+               jdouble doubleVal;
+               doubleVal = asm_calljavafunction2double(methodID,
+                                                                                               argcount + 1,
+                                                                                               (argcount + 1) * sizeof(jni_callblock),
+                                                                                               blk);
+               retVal = builtin_new(class_java_lang_Double);
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
-                                                                                  utf_new_char("<init>"),
-                                                                                  utf_new_char("(D)V")),
-                                          floatVal);
+                                                                                  utf_init,
+                                                                                  utf_double__void),
+                                          doubleVal);
        }
        break;
 
@@ -3617,11 +4039,11 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
 
        default:
                /* if this happens the acception has already been set by fill_callblock_objA*/
-               MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+               MFREE(blk, jni_callblock, /*4 */ argcount+2);
                return (jobject *) 0;
        }
 
-       MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+       MFREE(blk, jni_callblock, /* 4 */ argcount+2);
 
        if (*exceptionptr) {
                java_objectheader *exceptionToWrap = *exceptionptr;
@@ -3648,65 +4070,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
        return (jobject *) retVal;
 }
 
-void jni_init() {
-       jmethodID mid;
-
-       log_text("JNI-Init: initialize global_ref_table");
-       // initalize global reference table
-       ihmclass = FindClass(NULL, "java/util/IdentityHashMap");
-       
-       if (ihmclass == NULL) {
-               log_text("JNI-Init: unable to find java.util.IdentityHashMap");
-       }
-
-       mid = GetMethodID(NULL, ihmclass, "<init>","()V");
-       if (mid == NULL) {
-               log_text("JNI-Init: unable to find constructor in java.util.IdentityHashMap");
-       }
-       
-       global_ref_table = (jobject*)heap_allocate(sizeof(jobject),true,NULL);
-
-       *global_ref_table = NewObject(NULL,ihmclass,mid);
-
-       if (*global_ref_table == NULL) {
-               log_text("JNI-Init: unable to create new global_ref_table");
-       }
-       
-       getmid = GetMethodID(NULL, ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
-       if (mid == NULL) {
-               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
-       }
-
-       getmid = GetMethodID(NULL ,ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
-       if (getmid == NULL) {
-               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
-       }
 
-       putmid = GetMethodID(NULL, ihmclass, "put","(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-       if (putmid == NULL) {
-               log_text("JNI-Init: unable to find method \"put\" in java.util.IdentityHashMap");
-       }
-
-       intclass = FindClass(NULL, "java/lang/Integer");
-       if (intclass == NULL) {
-               log_text("JNI-Init: unable to find java.lang.Integer");
-       }
-
-       newint = GetMethodID(NULL, intclass, "<init>","(I)V");
-       if (newint == NULL) {
-               log_text("JNI-Init: unable to find constructor in java.lang.Integer");
-       }
-
-       intvalue = GetMethodID(NULL, intclass, "intValue","()I");
-       if (intvalue == NULL) {
-               log_text("JNI-Init: unable to find method \"intValue\" in java.lang.Integer");
-       }
-
-       removemid = GetMethodID(NULL, ihmclass, "remove","(Ljava/lang/Object;)Ljava/lang/Object;");
-       if (removemid == NULL) {
-               log_text("JNI-DeleteGlobalRef: unable to find method \"remove\" in java.lang.Object");
-       }
-}
 
 
 /*