x86_64 include added
[cacao.git] / jni.c
diff --git a/jni.c b/jni.c
index 7730cd67b5667f9dd8cb73a08778a9651c26da5a..265a28a8c9c01c4ec6ba15b9347703c461285667 100644 (file)
--- a/jni.c
+++ b/jni.c
@@ -1,9 +1,9 @@
-/* jni.c - implementation of JNI functions
+/* 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
+   P. Tomsich, J. Wenninger, M. Platter
 
    This file is part of CACAO.
 
 
    Authors: ?
 
-   $Id: jni.c 664 2003-11-21 18:24:01Z jowenn $
+   Changes: Joseph Wenninger, Martin Platter
+
+   $Id: jni.c 1384 2004-08-02 11:41:26Z motse $
 
 */
 
 
-#include "types.h"
+#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"   
+#define JNI_VERSION       0x00010002
 
 
-#define JNI_VERSION       0x00010002
+#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;
 
-#include <jit/jit.h>
 
 /********************* accessing instance-fields **********************************/
 
 
 u4 get_parametercount(methodinfo *m)
 {
-    utf  *descr    =  m->descriptor;    /* method-descriptor */
-    char *utf_ptr  =  descr->text;      /* current position in utf-text */
-    char *desc_end =  utf_end(descr);   /* points behind utf string     */
-    java_objectarray* result;
-    int parametercount = 0;
-   int i;
+       utf  *descr    =  m->descriptor;    /* method-descriptor */
+       char *utf_ptr  =  descr->text;      /* current position in utf-text */
+       char *desc_end =  utf_end(descr);   /* points behind utf string     */
+       u4 parametercount = 0;
 
-    /* skip '(' */
-    utf_nextu2(&utf_ptr);
+       /* skip '(' */
+       utf_nextu2(&utf_ptr);
 
     /* determine number of parameters */
-    while ( *utf_ptr != ')' ) {
-        get_type(&utf_ptr,desc_end,true);
-        parametercount++;
-    }
+       while (*utf_ptr != ')') {
+               get_type(&utf_ptr, desc_end, true);
+               parametercount++;
+       }
 
-    return parametercount;
+       return parametercount;
 }
 
 
 
-void fill_callblock(void *obj,utf *descr,jni_callblock blk[], va_list data, char ret) {
-    char *utf__ptr  =  descr->text;      /* current position in utf-text */
-    char **utf_ptr  =  &utf__ptr;
-    char *desc_end =  utf_end(descr);   /* points behind utf string     */
-
+void fill_callblock(void *obj, utf *descr, jni_callblock blk[], va_list data, char ret)
+{
+    char *utf__ptr = descr->text;      /* current position in utf-text */
+    char **utf_ptr = &utf__ptr;
+    char *desc_end = utf_end(descr);   /* points behind utf string     */
     int cnt;
-
-    jdouble d;
-    jlong l;
     u4 dummy;
     char c;
+
        /*
     log_text("fill_callblock");
     utf_display(descr);
@@ -90,86 +120,388 @@ void fill_callblock(void *obj,utf *descr,jni_callblock blk[], va_list data, char
     utf_nextu2(utf_ptr);
 
     /* determine number of parameters */
-   if (obj) {
-          blk[0].itemtype=TYPE_ADR;
-          blk[0].item=(u8)(u4)obj;
-          cnt=1;
-   } else cnt=0;
-   while ( **utf_ptr != ')' ) {
-       if (*utf_ptr>=desc_end)
+       if (obj) {
+               blk[0].itemtype = TYPE_ADR;
+               blk[0].item = PTR_TO_ITEM(obj);
+               cnt = 1;
+       } else cnt = 0;
+
+       while (**utf_ptr != ')') {
+               if (*utf_ptr >= desc_end)
                panic("illegal method descriptor");
 
-       switch (utf_nextu2(utf_ptr)) {
-       /* primitive types */
-             case 'B' :
-             case 'C' :
-             case 'S' : 
-             case 'Z' :
-                        blk[cnt].itemtype=TYPE_INT;
-                        blk[cnt].item=(u8) va_arg(data,int);
-                        break;
-             case 'I' :
-                        blk[cnt].itemtype=TYPE_INT;
-                        dummy=va_arg(data,u4);
-                        /*printf("fill_callblock: pos:%d, value:%d\n",cnt,dummy);*/
-                        blk[cnt].item=(u8)dummy;
-
-                        break;
-
-             case 'J' : 
-                        blk[cnt].itemtype=TYPE_LNG;
-                        blk[cnt].item=(u8)va_arg(data,jlong);
-                                break;
-             case 'F' : 
-                        blk[cnt].itemtype=TYPE_FLT;
-                        *((jfloat*)(&blk[cnt].item))=((jfloat)va_arg(data,jdouble));
-                        break;
-
-             case 'D' : 
-                        blk[cnt].itemtype=TYPE_DBL;
-                        *((jdouble*)(&blk[cnt].item))=(jdouble)va_arg(data,jdouble);
-                        break;
-             case 'V' : panic ("V not allowed as function parameter");
-                        break;
-             case 'L' : {
-                           char *start = *utf_ptr;
-                           while (utf_nextu2(utf_ptr)!=';')
-
-                           blk[cnt].itemtype=TYPE_ADR;
-                           blk[cnt].item=(u8)(u4)va_arg(data,void*);
-                           break;                      
-                        }
-             case '[' : {
-                         /* XXX */
-                           /* arrayclass */
-                                   char *start = *utf_ptr;
-                           char ch;
-                           while ((ch = utf_nextu2(utf_ptr))=='[')
-                           if (ch == 'L') {
-                               while (utf_nextu2(utf_ptr)!=';') {}
-                                   }
+               switch (utf_nextu2(utf_ptr)) {
+                       /* primitive types */
+               case 'B':
+               case 'C':
+               case 'S': 
+               case 'Z':
+                       blk[cnt].itemtype = TYPE_INT;
+                       blk[cnt].item = (u8) va_arg(data, int);
+                       break;
+
+               case 'I':
+                       blk[cnt].itemtype = TYPE_INT;
+                       dummy = va_arg(data, u4);
+                       /*printf("fill_callblock: pos:%d, value:%d\n",cnt,dummy);*/
+                       blk[cnt].item = (u8) dummy;
+                       break;
+
+               case 'J':
+                       blk[cnt].itemtype = TYPE_LNG;
+                       blk[cnt].item = (u8) va_arg(data, jlong);
+                       break;
+
+               case 'F':
+                       blk[cnt].itemtype = TYPE_FLT;
+                       *((jfloat *) (&blk[cnt].item)) = (jfloat) va_arg(data, jdouble);
+                       break;
+
+               case 'D':
+                       blk[cnt].itemtype = TYPE_DBL;
+                       *((jdouble *) (&blk[cnt].item)) = (jdouble) va_arg(data, jdouble);
+                       break;
+
+               case 'V':
+                       panic ("V not allowed as function parameter");
+                       break;
+                       
+               case 'L':
+                       while (utf_nextu2(utf_ptr) != ';')
+                           blk[cnt].itemtype = TYPE_ADR;
+                       blk[cnt].item = PTR_TO_ITEM(va_arg(data, void*));
+                       break;
+                       
+               case '[':
+                       {
+                               /* XXX */
+                               /* arrayclass */
+/*                             char *start = *utf_ptr; */
+                               char ch;
+                               while ((ch = utf_nextu2(utf_ptr)) == '[')
+                                       if (ch == 'L') {
+                                               while (utf_nextu2(utf_ptr) != ';') {}
+                                       }
        
-                            ch=utf_nextu2(utf_ptr);
-                           blk[cnt].itemtype=TYPE_ADR;
-                           blk[cnt].item=(u8)(u4)va_arg(data,void*);
-                           break;                      
-                        }
+                               ch = utf_nextu2(utf_ptr);
+                               blk[cnt].itemtype = TYPE_ADR;
+                               blk[cnt].item = PTR_TO_ITEM(va_arg(data, void*));
+                               break;                  
+                       }
+               }
+               cnt++;
+       }
+
+       /*the standard doesn't say anything about return value checking, but it appears to be usefull*/
+       c = utf_nextu2(utf_ptr);
+       c = utf_nextu2(utf_ptr);
+       /*printf("%c  %c\n",ret,c);*/
+       if (ret == 'O') {
+               if (!((c == 'L') || (c == '[')))
+                       log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
+       } else if (ret != c)
+               log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
+}
+
+
+/* XXX it could be considered if we should do typechecking here in the future */
+char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_objectarray* params)
+{
+    char *utf__ptr = descr->text;      /* current position in utf-text */
+    char **utf_ptr = &utf__ptr;
+    char *desc_end = utf_end(descr);   /* points behind utf string     */
+
+    jobject param;
+    int cnt;
+    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);
+         log_text("====");
+       */
+    /* skip '(' */
+    utf_nextu2(utf_ptr);
+
+    /* determine number of parameters */
+       if (obj) {
+               blk[0].itemtype = TYPE_ADR;
+               blk[0].item = PTR_TO_ITEM(obj);
+               cnt=1;
+
+       } else {
+               cnt = 0;
        }
-       cnt++;
-   }
 
-   /*the standard doesn't say anything about return value checking, but it appears to be usefull*/
-   c=utf_nextu2(utf_ptr);
-   c=utf_nextu2(utf_ptr);
-   /*printf("%c  %c\n",ret,c);*/
-   if (ret=='O') {
-       if (!((c=='L') || (c=='['))) log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
-   } else if (ret != c) log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
+       cnts = 0;
+       while (**utf_ptr != ')') {
+               if (*utf_ptr >= desc_end)
+               panic("illegal method descriptor");
+
+               /* primitive types */
+               switch (utf_nextu2(utf_ptr)) {
+               case 'B':
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       if (param->vftbl->class->name == utf_byte) {
+                               blk[cnt].itemtype = TYPE_INT;
+                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+
+                       } else  {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       break;
+
+               case 'C':
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       if (param->vftbl->class->name == utf_char) {
+                               blk[cnt].itemtype = TYPE_INT;
+                               blk[cnt].item = (u8) ((java_lang_Character *) param)->value;
+
+                       } else  {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       break;
+
+               case 'S':
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       if (param->vftbl->class->name == utf_short) {
+                               blk[cnt].itemtype = TYPE_INT;
+                               blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
+
+                       } else  {
+                               if (param->vftbl->class->name == utf_byte) {
+                                       blk[cnt].itemtype = TYPE_INT;
+                                       blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+
+                               } else {
+                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                       return 0;
+                               }
+                       }
+                       break;
+
+               case 'Z':
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       if (param->vftbl->class->name == utf_bool) {
+                               blk[cnt].itemtype = TYPE_INT;
+                               blk[cnt].item = (u8) ((java_lang_Boolean *) param)->value;
+
+                       } else {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       break;
+
+               case 'I':
+                       /*log_text("fill_callblock_objA: param 'I'");*/
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       if (param->vftbl->class->name == utf_int) {
+                               blk[cnt].itemtype = TYPE_INT;
+                               blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
+                               /*printf("INT VALUE :%d\n",((struct java_lang_Integer * )param)->value);*/
+                       } else {
+                               if (param->vftbl->class->name == utf_short) {
+                                       blk[cnt].itemtype = TYPE_INT;
+                                       blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
+
+                               } else  {
+                                       if (param->vftbl->class->name == utf_byte) {
+                                               blk[cnt].itemtype = TYPE_INT;
+                                               blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+
+                                       } else  {
+                                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                               return 0;
+                                       }
+                               }
+                       }
+                       break;
+
+               case 'J':
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       if (param->vftbl->class->name == utf_long) {
+                               blk[cnt].itemtype = TYPE_LNG;
+                               blk[cnt].item = (u8) ((java_lang_Long *) param)->value;
+
+                       } else  {
+                               if (param->vftbl->class->name == utf_int) {
+                                       blk[cnt].itemtype = TYPE_LNG;
+                                       blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
+
+                               } else {
+                                       if (param->vftbl->class->name == utf_short) {
+                                               blk[cnt].itemtype = TYPE_LNG;
+                                               blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
+
+                                       } else  {
+                                               if (param->vftbl->class->name == utf_byte) {
+                                                       blk[cnt].itemtype = TYPE_LNG;
+                                                       blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+                                               } else  {
+                                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                                       return 0;
+                                               }
+                                       }
+                               }
+
+                       }
+                       break;
+
+               case 'F':
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+
+                       if (param->vftbl->class->name == utf_float) {
+                               blk[cnt].itemtype = TYPE_FLT;
+                               *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value;
+
+                       } else  {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+                       break;
+
+               case 'D':
+                       param = params->data[cnts];
+                       if (param == 0) {
+                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                               return 0;
+                       }
+
+                       if (param->vftbl->class->name == utf_double) {
+                               blk[cnt].itemtype = TYPE_DBL;
+                               *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
+
+                       } else  {
+                               if (param->vftbl->class->name == utf_float) {
+                                       blk[cnt].itemtype = TYPE_DBL;
+                                       *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
+
+                               } else  {
+                                       *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                       return 0;
+                               }
+                       }
+                       break;
+
+               case 'V':
+                       panic("V not allowed as function parameter");
+                       break;
+
+               case 'L':
+                       {
+                               char *start = (*utf_ptr) - 1;
+                               char *end = NULL;
+
+                               while (utf_nextu2(utf_ptr) != ';')
+                                       end = (*utf_ptr) + 1;
+
+                               if (!builtin_instanceof(params->data[cnts], class_from_descriptor(start, end, 0, CLASSLOAD_LOAD))) {
+                                       if (params->data[cnts] != 0) {
+                                               *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+                                               return 0;
+                                       }                       
+                               }
+
+                               blk[cnt].itemtype = TYPE_ADR;
+                               blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
+                               break;                  
+                       }
+
+               case '[':
+                       {
+                               char *start = (*utf_ptr) - 1;
+                               char *end;
+
+                               char ch;
+                               while ((ch = utf_nextu2(utf_ptr)) == '[')
+                                       if (ch == 'L') {
+                                               while (utf_nextu2(utf_ptr) != ';') {}
+                                       }
+
+                               end = (*utf_ptr) - 1;
+                               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");
+                                       return 0;
+                               }
+       
+                               blk[cnt].itemtype = TYPE_ADR;
+                               blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
+                               break;
+                       }
+               }
+               cnt++;
+               cnts++;
+       }
 
+       c = utf_nextu2(utf_ptr);
+       c = utf_nextu2(utf_ptr);
+       return c; /*return type needed usage of the right lowlevel methods*/
 }
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
 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);
@@ -177,67 +509,76 @@ jmethodID get_virtual(jobject obj,jmethodID methodID) {
 
 jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) {
        if (clazz==methodID->class) return methodID;
+/*class_resolvemethod -> classfindmethod? (JOWENN)*/
        return class_resolvemethod (clazz, methodID->name, methodID->descriptor);
 }
 
+
+
 jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
 {      
-        int argcount;
-        int i;
-        jni_callblock *blk;
-        jobject ret;
+       int argcount;
+       jni_callblock *blk;
+       jobject ret;
 
-        /*
-        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");
-        */
+       /*
+         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 = native_new_and_init(class_java_lang_NoSuchMethodError); 
+       if (methodID == 0) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
                return 0;
        }
-        argcount=get_parametercount(methodID);
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj==0)) ||
-               ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);
+       argcount = get_parametercount(methodID);
+
+       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
+               ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
        
-       if (obj && (! builtin_instanceof(obj,methodID->class))) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);
+       if (obj && !builtin_instanceof(obj, methodID->class)) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
 
-        if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
-                log_text("Too many arguments. CallObjectMethod does not support that");
-                return 0;
-        }
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+               log_text("Too many arguments. CallObjectMethod does not support that");
+               return 0;
+       }
 
-        blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
 
-        fill_callblock(obj,methodID->descriptor,blk,args,'O');
+       fill_callblock(obj, methodID->descriptor, blk, args, 'O');
 
-        /*      printf("parameter: obj: %p",blk[0].item); */
-        ret=asm_calljavafunction2(methodID,argcount+1,(argcount+1)*sizeof(jni_callblock),blk);
-        MFREE(blk,jni_callblock,argcount+1);
-        /*      printf("(CallObjectMethodV)-->%p\n",ret); */
-        return ret;
+       /*      printf("parameter: obj: %p",blk[0].item); */
+       ret = asm_calljavafunction2(methodID,
+                                                               argcount + 1,
+                                                               (argcount + 1) * sizeof(jni_callblock),
+                                                               blk);
+
+       MFREE(blk, jni_callblock, argcount + 1);
+       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+       return ret;
 }
 
 
-/*core function for integer class methods (bool,byte,short,integer
-  This is basically needed for i386*/
-jint callIntegerMethod (jobject obj, jmethodID methodID, char retType, va_list args) {
-        int argcount;
-        int i;
-        jni_callblock *blk;
-        jint ret;
+/*
+  core function for integer class methods (bool, byte, short, integer)
+  This is basically needed for i386
+*/
+jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list args)
+{
+       int argcount;
+       jni_callblock *blk;
+       jint ret;
 
 /*     printf("%p,     %c\n",retType,methodID,retType);*/
 
@@ -249,102 +590,111 @@ jint callIntegerMethod (jobject obj, jmethodID methodID, char retType, va_list a
         utf_display(obj->vftbl->class->name);
         printf("\n");
         */
-       if (methodID==0) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); 
+       if (methodID == 0) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
                return 0;
        }
         
-       argcount=get_parametercount(methodID);
+       argcount = get_parametercount(methodID);
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj==0)) ||
-               ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);
+       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
+               ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
 
-       if (obj && (! builtin_instanceof(obj,methodID->class))) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);
+       if (obj && !builtin_instanceof(obj, methodID->class)) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
 
 
-        if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
-                log_text("Too many arguments. CallObjectMethod does not support that");
-                return 0;
-        }
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+               log_text("Too many arguments. CallIntegerMethod does not support that");
+               return 0;
+       }
 
-        blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
 
-        fill_callblock(obj,methodID->descriptor,blk,args,retType);
+       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);
-        MFREE(blk,jni_callblock,argcount+1);
-        /*      printf("(CallObjectMethodV)-->%p\n",ret); */
-        return ret;
+       /*      printf("parameter: obj: %p",blk[0].item); */
+       ret = (jint) asm_calljavafunction2(methodID,
+                                                                          argcount + 1,
+                                                                          (argcount + 1) * sizeof(jni_callblock),
+                                                                          blk);
+
+       MFREE(blk, jni_callblock, argcount + 1);
+       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
 
+       return ret;
 }
 
 
 /*core function for long class functions*/
-jlong callLongMethod (jobject obj, jmethodID methodID, va_list args) {
-        int argcount;
-        int i;
-        jni_callblock *blk;
-        jlong ret;
+jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
+{
+       int argcount;
+       jni_callblock *blk;
+       jlong ret;
 
-        /*
+/*     
         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 = native_new_and_init(class_java_lang_NoSuchMethodError); 
+*/      
+       if (methodID == 0) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
                return 0;
        }
-        argcount=get_parametercount(methodID);
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj==0)) ||
-               ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);
+       argcount = get_parametercount(methodID);
+
+       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
+                  ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
 
-       if (obj && (! builtin_instanceof(obj,methodID->class))) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);
+       if (obj && !builtin_instanceof(obj,methodID->class)) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
                return 0;
        }
 
 
-        if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
-                log_text("Too many arguments. CallObjectMethod does not support that");
-                return 0;
-        }
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+               log_text("Too many arguments. CallObjectMethod does not support that");
+               return 0;
+       }
 
-        blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
 
-        fill_callblock(obj,methodID->descriptor,blk,args,'L');
+       fill_callblock(obj, methodID->descriptor, blk, args, 'J');
 
-        /*      printf("parameter: obj: %p",blk[0].item); */
-        ret=asm_calljavafunction2long(methodID,argcount+1,(argcount+1)*sizeof(jni_callblock),blk);
-        MFREE(blk,jni_callblock,argcount+1);
-        /*      printf("(CallObjectMethodV)-->%p\n",ret); */
-        return ret;
+       /*      printf("parameter: obj: %p",blk[0].item); */
+       ret = asm_calljavafunction2long(methodID,
+                                                                       argcount + 1,
+                                                                       (argcount + 1) * sizeof(jni_callblock),
+                                                                       blk);
 
+       MFREE(blk, jni_callblock, argcount + 1);
+       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+
+       return ret;
 }
 
 
 /*core function for float class methods (float,double)*/
-jdouble callFloatMethod (jobject obj, jmethodID methodID, va_list args,char retType) {
-        int argcount=get_parametercount(methodID);
-        int i;
-        jni_callblock *blk;
-        jdouble ret;
+jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType)
+{
+       int argcount = get_parametercount(methodID);
+       jni_callblock *blk;
+       jdouble ret;
 
         /*
         log_text("JNI-Call: CallObjectMethodV");
@@ -354,22 +704,27 @@ jdouble callFloatMethod (jobject obj, jmethodID methodID, va_list args,char retT
         utf_display(obj->vftbl->class->name);
         printf("\n");
         */
-        if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
-                log_text("Too many arguments. CallObjectMethod does not support that");
-                return 0;
-        }
 
-        blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+               log_text("Too many arguments. CallObjectMethod does not support that");
+               return 0;
+       }
 
-        fill_callblock(obj,methodID->descriptor,blk,args,retType);
+       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
 
-        /*      printf("parameter: obj: %p",blk[0].item); */
-        ret=asm_calljavafunction2double(methodID,argcount+1,(argcount+1)*sizeof(jni_callblock),blk);
-        MFREE(blk,jni_callblock,argcount+1);
-        /*      printf("(CallObjectMethodV)-->%p\n",ret); */
-        return ret;
+       fill_callblock(obj, methodID->descriptor, blk, args, retType);
+
+       /*      printf("parameter: obj: %p",blk[0].item); */
+       ret = asm_calljavafunction2double(methodID,
+                                                                         argcount + 1,
+                                                                         (argcount + 1) * sizeof(jni_callblock),
+                                                                         blk);
 
+       MFREE(blk, jni_callblock, argcount + 1);
+       /*      printf("(CallObjectMethodV)-->%p\n",ret); */
+
+       return ret;
 }
 
 
@@ -394,6 +749,8 @@ fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
                        return &(c->fields[i]);
                }
 
+       if (c->super) return jclass_findfield(c->super,name,desc);
+
        return NULL;
 }
 
@@ -404,19 +761,69 @@ jint GetVersion (JNIEnv* env)
        return JNI_VERSION;
 }
 
+
 /****************** loads a class from a buffer of raw class data *****************/
 
 jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *buf, jsize len) 
 {
-        jclass clazz; 
+       jclass clazz; 
+       classbuffer *cb;
+       s8 starttime;
+       s8 stoptime;
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_lock();
+       tables_lock();
+#else
+       intsDisable();
+#endif
+#endif
+
+       /* measure time */
+       if (getloadingtime)
+               starttime = getcputime();
+
+       clazz = class_new(utf_new_char((char *) name));
+
+       /* build a classbuffer with the given data */
+       cb = NEW(classbuffer);
+       cb->class = clazz;
+       cb->size = len;
+       cb->data = (u1 *) buf;
+       cb->pos = cb->data - 1;
+
+       class_load_intern(cb);
+
+       /* free memory */
+       FREE(cb, classbuffer);
+
+       /* measure time */
+       if (getloadingtime) {
+               stoptime = getcputime();
+               loadingtime += (stoptime - starttime);
+       }
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       tables_unlock();
+       compiler_unlock();
+#else
+       intsRestore();
+#endif
+#endif
+
+       if (*exceptionptr)
+               return NULL;
 
-       /* change suck-mode, so subsequent class_load will read from memory-buffer */
-       classload_buffer( (u1*) buf,len);
+       /* XXX link the class here? */
+       class_link(clazz);
 
-        clazz = loader_load(utf_new_char ((char *) name));
+       if (*exceptionptr)
+               return NULL;
 
-       /* restore old suck-mode */
-       classload_buffer(NULL,0);
+       if (clazz)
+               clazz->classloader = loader;
 
        return clazz;
 }
@@ -424,17 +831,21 @@ jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *b
 
 /*************** loads locally defined class with the specified name **************/
 
-jclass FindClass (JNIEnv* env, const char *name) 
+jclass FindClass(JNIEnv* env, const char *name) 
 {
        classinfo *c;  
   
-       if (strcmp(name,"[B")==0) {
-               c = loader_load(utf_new_char("The_Array_Class"));
-       }
-       else
-               c = loader_load(utf_new_char_classname ((char *) name));
+       c = class_new(utf_new_char_classname((char *) name));
+
+       class_load(c);
+
+       if (*exceptionptr)
+               return NULL;
+
+       class_link(c);
 
-       if (!c) exceptionptr = native_new_and_init(class_java_lang_ClassFormatError);
+       if (*exceptionptr)
+               return NULL;
 
        return c;
 }
@@ -447,86 +858,94 @@ jclass FindClass (JNIEnv* env, const char *name)
   
  **********************************************************************************/   
   
-jmethodID FromReflectedMethod (JNIEnv* env, jobject method)
+jmethodID FromReflectedMethod(JNIEnv* env, jobject method)
 {
        /* log_text("JNI-Call: FromReflectedMethod"); */
+
+       return 0;
 }
 
 
 /*************** return superclass of the class represented by sub ****************/
  
-jclass GetSuperclass (JNIEnv* env, jclass sub) 
+jclass GetSuperclass(JNIEnv* env, jclass sub) 
 {
        classinfo *c;
 
-       c = ((classinfo*) sub) -> super;
+       c = ((classinfo*) sub)->super;
 
        if (!c) return NULL; 
-       use_class_as_object (c);
+
+       use_class_as_object(c);
+
        return c;               
 }
   
  
 /*********************** check whether sub can be cast to sup  ********************/
   
-jboolean IsAssignableForm (JNIEnv* env, jclass sub, jclass sup)
+jboolean IsAssignableForm(JNIEnv* env, jclass sub, jclass sup)
 {
-        return builtin_isanysubclass(sub,sup);
+       return builtin_isanysubclass(sub, sup);
 }
 
 
 /***** converts a field ID derived from cls to a java.lang.reflect.Field object ***/
 
-jobject ToReflectedField (JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic)
+jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic)
 {
        /* log_text("JNI-Call: ToReflectedField"); */
+
+       return NULL;
 }
 
 
 /***************** throw java.lang.Throwable object  ******************************/
 
-jint Throw (JNIEnv* env, jthrowable obj)
+jint Throw(JNIEnv* env, jthrowable obj)
 {
-       exceptionptr = (java_objectheader*) obj;
+       *exceptionptr = (java_objectheader*) obj;
+
        return 0;
 }
 
 
-/*********************************************************************************** 
+/*******************************************************************************
 
        create exception object from the class clazz with the 
        specified message and cause it to be thrown
 
- **********************************************************************************/   
-
+*******************************************************************************/
 
-jint ThrowNew (JNIEnv* env, jclass clazz, const char *msg) 
+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);
+       o = (java_lang_Throwable *) native_new_and_init((classinfo*) clazz);
 
        if (!o) return (-1);
 
-       o->detailMessage = (java_lang_String*) javastring_new_char((char *) msg);
+       o->detailMessage = (java_lang_String *) javastring_new_char((char *) msg);
+
+       *exceptionptr = (java_objectheader *) o;
 
-       exceptionptr = (java_objectheader*) o;  
        return 0;
 }
 
+
 /************************* check if exception occured *****************************/
 
 jthrowable ExceptionOccurred (JNIEnv* env) 
 {
-       return (jthrowable) exceptionptr;
+       return (jthrowable) *exceptionptr;
 }
 
 /********** print exception and a backtrace of the stack (for debugging) **********/
 
 void ExceptionDescribe (JNIEnv* env) 
 {
-       utf_display(exceptionptr->vftbl->class->name);
+       utf_display((*exceptionptr)->vftbl->class->name);
        printf ("\n");
        fflush (stdout);        
 }
@@ -536,7 +955,7 @@ void ExceptionDescribe (JNIEnv* env)
 
 void ExceptionClear (JNIEnv* env) 
 {
-       exceptionptr = NULL;    
+       *exceptionptr = NULL;   
 }
 
 
@@ -549,24 +968,27 @@ void FatalError (JNIEnv* env, const char *msg)
 
 /******************* creates a new local reference frame **************************/ 
 
-jint PushLocalFrame (JNIEnv* env, jint capacity)
+jint PushLocalFrame(JNIEnv* env, jint capacity)
 {
        /* empty */
+
+       return 0;
 }
 
 /**************** Pops off the current local reference frame **********************/
 
-jobject PopLocalFrame (JNIEnv* env, jobject result)
+jobject PopLocalFrame(JNIEnv* env, jobject result)
 {
        /* empty */
+
+       return NULL;
 }
     
 
 /** Creates a new global reference to the object referred to by the obj argument **/
     
-jobject NewGlobalRef (JNIEnv* env, jobject lobj)
+jobject NewGlobalRef(JNIEnv* env, jobject lobj)
 {
-       heap_addreference ( (void**) &lobj);
        return lobj;
 }
 
@@ -630,7 +1052,7 @@ jobject AllocObject (JNIEnv* env, jclass clazz)
 
 jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
 {
-        java_objectheader *o;
+       java_objectheader *o;
        void* args[3];
        int argcount=get_parametercount(methodID);
        int i;
@@ -638,8 +1060,8 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
 
        /* log_text("JNI-Call: NewObject"); */
 
-       if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. NewObject does not support that");
                return 0;
        }
@@ -647,19 +1069,19 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
        
        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_end(vaargs);
-       exceptionptr=asm_calljavamethod(methodID,o,args[0],args[1],args[2]);
-
-        return o;
+       asm_calljavafunction(methodID,o,args[0],args[1],args[2]);
 
+       return o;
 }
 
+
 /*********************************************************************************** 
 
        Constructs a new Java object
@@ -667,11 +1089,14 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
 
 ***********************************************************************************/
 
-jobject NewObjectV (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
+jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
 {
        /* log_text("JNI-Call: NewObjectV"); */
+
+       return NULL;
 }
 
+
 /*********************************************************************************** 
 
        Constructs a new Java object
@@ -680,36 +1105,44 @@ jobject NewObjectV (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
 
 ***********************************************************************************/
 
-jobject NewObjectA (JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
+jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        /* log_text("JNI-Call: NewObjectA"); */
+
+       return NULL;
 }
 
 
 /************************ returns the class of an object **************************/ 
 
-jclass GetObjectClass (JNIEnv* env, jobject obj)
+jclass GetObjectClass(JNIEnv* env, jobject obj)
 {
-       classinfo *c = obj->vftbl -> class;
-       use_class_as_object (c);
+       classinfo *c = obj->vftbl->class;
+
+       use_class_as_object(c);
+
        return c;
 }
 
+
 /************* tests whether an object is an instance of a class ******************/
 
-jboolean IsInstanceOf (JNIEnv* env, jobject obj, jclass clazz)
+jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
 {
-        return builtin_instanceof(obj,clazz);
+       return builtin_instanceof(obj,clazz);
 }
 
 
 /***************** converts a java.lang.reflect.Field to a field ID ***************/
  
-jfieldID FromReflectedField (JNIEnv* env, jobject field)
+jfieldID FromReflectedField(JNIEnv* env, jobject field)
 {
        log_text("JNI-Call: FromReflectedField");
+
+       return 0;
 }
 
+
 /**********************************************************************************
 
        converts a method ID to a java.lang.reflect.Method or 
@@ -717,14 +1150,17 @@ jfieldID FromReflectedField (JNIEnv* env, jobject field)
 
 **********************************************************************************/
 
-jobject ToReflectedMethod (JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
+jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
 {
        log_text("JNI-Call: ToReflectedMethod");
+
+       return NULL;
 }
 
+
 /**************** returns the method ID for an instance method ********************/
 
-jmethodID GetMethodID (JNIEnv* env, jclass clazz, const char *name, const char *sig)
+jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *sig)
 {
        jmethodID m;
 
@@ -734,36 +1170,40 @@ jmethodID GetMethodID (JNIEnv* env, jclass clazz, const char *name, const char *
                utf_new_char ((char*) sig)
        );
 
-       if (!m) exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);          
-
+       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       else if (m->flags & ACC_STATIC)   {
+               m=0;
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       }
        return m;
 }
 
+
 /******************** JNI-functions for calling instance methods ******************/
-jobject CallObjectMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+
+jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jobject ret;
        va_list vaargs;
 
 /*     log_text("JNI-Call: CallObjectMethod");*/
 
-       va_start(vaargs,methodID);
-       ret = callObjectMethod(obj,methodID,vaargs);
+       va_start(vaargs, methodID);
+       ret = callObjectMethod(obj, methodID, vaargs);
        va_end(vaargs);
+
        return ret;
 }
 
 
-jobject CallObjectMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
        return callObjectMethod(obj,methodID,args);
 }
 
 
-jobject CallObjectMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
+jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
 {
-
-
        log_text("JNI-Call: CallObjectMethodA");
 
        return NULL;
@@ -820,13 +1260,15 @@ jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list arg
 }
 
 
-jbyte CallByteMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallByteMethodA");
+
+       return 0;
 }
 
 
-jchar CallCharMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jchar ret;
        va_list vaargs;
@@ -834,20 +1276,21 @@ jchar CallCharMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 /*     log_text("JNI-Call: CallCharMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_virtual(obj,methodID),'C',vaargs);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'C', vaargs);
        va_end(vaargs);
-       return ret;
 
+       return ret;
 }
 
-jchar CallCharMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+
+jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
 /*     log_text("JNI-Call: CallCharMethodV");*/
        return callIntegerMethod(obj,get_virtual(obj,methodID),'C',args);
 }
 
 
-jchar CallCharMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallCharMethodA");
 
@@ -855,28 +1298,28 @@ jchar CallCharMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *arg
 }
 
 
-jshort CallShortMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jshort ret;
        va_list vaargs;
 
 /*     log_text("JNI-Call: CallShortMethod");*/
 
-       va_start(vaargs,methodID);
-       ret = callIntegerMethod(obj,get_virtual(obj,methodID),'S',vaargs);
+       va_start(vaargs, methodID);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'S', vaargs);
        va_end(vaargs);
-       return ret;
 
+       return ret;
 }
 
 
-jshort CallShortMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       return callIntegerMethod(obj,get_virtual(obj,methodID),'S',args);
+       return callIntegerMethod(obj, get_virtual(obj, methodID), 'S', args);
 }
 
 
-jshort CallShortMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallShortMethodA");
 
@@ -885,25 +1328,26 @@ jshort CallShortMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *a
 
 
 
-jint CallIntMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-        jint ret;
-        va_list vaargs;
+       jint ret;
+       va_list vaargs;
 
-        va_start(vaargs,methodID);
-        ret = callIntegerMethod(obj,get_virtual(obj,methodID),'I',vaargs);
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs,methodID);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'I', vaargs);
+       va_end(vaargs);
+
+       return ret;
 }
 
 
-jint CallIntMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       return callIntegerMethod(obj,get_virtual(obj,methodID),'I',args);
+       return callIntegerMethod(obj, get_virtual(obj, methodID), 'I', args);
 }
 
 
-jint CallIntMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallIntMethodA");
 
@@ -912,23 +1356,26 @@ jint CallIntMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 
 
 
-jlong CallLongMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallLongMethod");
+       jlong ret;
+       va_list vaargs;
+       
+       va_start(vaargs,methodID);
+       ret = callLongMethod(obj,get_virtual(obj, methodID),vaargs);
+       va_end(vaargs);
 
-       return 0;
+       return ret;
 }
 
 
-jlong CallLongMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallLongMethodV");
-
-       return 0;
+       return  callLongMethod(obj,get_virtual(obj, methodID),args);
 }
 
 
-jlong CallLongMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallLongMethodA");
 
@@ -937,7 +1384,7 @@ jlong CallLongMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *arg
 
 
 
-jfloat CallFloatMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jfloat ret;
        va_list vaargs;
@@ -945,20 +1392,21 @@ jfloat CallFloatMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 /*     log_text("JNI-Call: CallFloatMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_virtual(obj,methodID),vaargs,'F');
+       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'F');
        va_end(vaargs);
+
        return ret;
 }
 
 
-jfloat CallFloatMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallFloatMethodV");
-       return callFloatMethod(obj,get_virtual(obj,methodID),args,'F');
+       return callFloatMethod(obj, get_virtual(obj, methodID), args, 'F');
 }
 
 
-jfloat CallFloatMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallFloatMethodA");
 
@@ -967,7 +1415,7 @@ jfloat CallFloatMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *a
 
 
 
-jdouble CallDoubleMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
        jdouble ret;
        va_list vaargs;
@@ -975,20 +1423,21 @@ jdouble CallDoubleMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 /*     log_text("JNI-Call: CallDoubleMethod");*/
 
        va_start(vaargs,methodID);
-       ret = callFloatMethod(obj,get_virtual(obj,methodID),vaargs,'D');
+       ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'D');
        va_end(vaargs);
+
        return ret;
 }
 
 
-jdouble CallDoubleMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallDoubleMethodV");
-       return callFloatMethod(obj,get_virtual(obj,methodID),args,'D');
+       return callFloatMethod(obj, get_virtual(obj, methodID), args, 'D');
 }
 
 
-jdouble CallDoubleMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
+jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallDoubleMethodA");
        return 0;
@@ -996,17 +1445,15 @@ jdouble CallDoubleMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue
 
 
 
-void CallVoidMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-        va_list vaargs;
+       va_list vaargs;
 
 /*      log_text("JNI-Call: CallVoidMethod");*/
 
-        va_start(vaargs,methodID);
-        (void)callIntegerMethod(obj,get_virtual(obj,methodID),'V',vaargs);
-        va_end(vaargs);
-
-
+       va_start(vaargs,methodID);
+       (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs);
+       va_end(vaargs);
 }
 
 
@@ -1014,14 +1461,12 @@ void CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args
 {
        log_text("JNI-Call: CallVoidMethodV");
        (void)callIntegerMethod(obj,get_virtual(obj,methodID),'V',args);
-
 }
 
 
 void CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
 {
        log_text("JNI-Call: CallVoidMethodA");
-
 }
 
 
@@ -1324,22 +1769,39 @@ jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *si
 {
        jfieldID f;
 
+/*     log_text("========================= searching for:");
+       log_text(name);
+       log_text(sig);*/
        f = jclass_findfield(clazz,
                            utf_new_char ((char*) name), 
                            utf_new_char ((char*) sig)
                            ); 
        
-       if (!f) exceptionptr =  native_new_and_init(class_java_lang_NoSuchFieldError);  
-
+       if (!f) { 
+/*             utf_display(clazz->name);
+               log_text(name);
+               log_text(sig);*/
+               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
+       }
        return f;
 }
 
 /*************************** retrieve fieldid, abort on error ************************/
 
-jfieldID getFieldID_critical(JNIEnv *env,jclass clazz,const char *name,const char *sig)
+jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig)
 {
-    jfieldID id = GetFieldID(env,clazz,name,sig);     
-    if (!id) panic("setfield_critical failed"); 
+    jfieldID id = GetFieldID(env, clazz, name, sig);
+
+    if (!id) {
+       log_text("class:");
+       utf_display(clazz->name);
+       log_text("\nfield:");
+       log_text(name);
+       log_text("sig:");
+       log_text(sig);
+
+       panic("setfield_critical failed"); 
+    }
     return id;
 }
 
@@ -1448,40 +1910,51 @@ void SetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val)
         setField(obj,jdouble,fieldID,val);
 }
 
+
 /**************** JNI-functions for calling static methods **********************/ 
 
-jmethodID GetStaticMethodID (JNIEnv *env, jclass clazz, const char *name, const char *sig)
+jmethodID GetStaticMethodID(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 =  native_new_and_init(class_java_lang_NoSuchMethodError);  
+       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       else if (!(m->flags & ACC_STATIC))   {
+               m=0;
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       }
 
        return m;
 }
 
-jobject CallStaticObjectMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+
+jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallStaticObjectMethod");
+       jobject ret;
+       va_list vaargs;
 
-       return NULL;
+       /* log_text("JNI-Call: CallStaticObjectMethod");*/
+
+       va_start(vaargs, methodID);
+       ret = callObjectMethod(0, methodID, vaargs);
+       va_end(vaargs);
+
+       return ret;
 }
 
 
-jobject CallStaticObjectMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallStaticObjectMethodV");
-
-       return NULL;
+       /* log_text("JNI-Call: CallStaticObjectMethodV"); */
+       
+       return callObjectMethod(0,methodID,args);
 }
 
 
-jobject CallStaticObjectMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticObjectMethodA");
 
@@ -1489,27 +1962,26 @@ jobject CallStaticObjectMethodA (JNIEnv *env, jclass clazz, jmethodID methodID,
 }
 
 
-jboolean CallStaticBooleanMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-        jboolean ret;
-        va_list vaargs;
-
-/*      log_text("JNI-Call: CallStaticBooleanMethod");*/
+       jboolean ret;
+       va_list vaargs;
 
-        va_start(vaargs,methodID);
-        ret = (jboolean)callIntegerMethod(0,methodID,'Z',vaargs);
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs, methodID);
+       ret = (jboolean) callIntegerMethod(0, methodID, 'Z', vaargs);
+       va_end(vaargs);
 
+       return ret;
 }
 
 
-jboolean CallStaticBooleanMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       return (jboolean)callIntegerMethod(0,methodID,'Z',args);
+       return (jboolean) callIntegerMethod(0, methodID, 'Z', args);
 }
 
-jboolean CallStaticBooleanMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+
+jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticBooleanMethodA");
 
@@ -1517,56 +1989,57 @@ jboolean CallStaticBooleanMethodA (JNIEnv *env, jclass clazz, jmethodID methodID
 }
 
 
-jbyte CallStaticByteMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-        jobject ret;
-        va_list vaargs;
+       jbyte ret;
+       va_list vaargs;
 
-/*      log_text("JNI-Call: CallStaticByteMethod");*/
+       /*      log_text("JNI-Call: CallStaticByteMethod");*/
 
-        va_start(vaargs,methodID);
-        ret = (jbyte)callIntegerMethod(0,methodID,'B',vaargs);
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs, methodID);
+       ret = (jbyte) callIntegerMethod(0, methodID, 'B', vaargs);
+       va_end(vaargs);
 
+       return ret;
 }
 
 
-jbyte CallStaticByteMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       return (jbyte)callIntegerMethod(0,methodID,'B',args);
+       return (jbyte) callIntegerMethod(0, methodID, 'B', args);
 }
 
 
-jbyte CallStaticByteMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticByteMethodA");
 
        return 0;
 }
 
-jchar CallStaticCharMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+
+jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-        jchar ret;
-        va_list vaargs;
+       jchar ret;
+       va_list vaargs;
 
-/*      log_text("JNI-Call: CallStaticByteMethod");*/
+       /*      log_text("JNI-Call: CallStaticByteMethod");*/
 
-        va_start(vaargs,methodID);
-        ret = (jchar)callIntegerMethod(0,methodID,'C',vaargs);
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs, methodID);
+       ret = (jchar) callIntegerMethod(0, methodID, 'C', vaargs);
+       va_end(vaargs);
 
+       return ret;
 }
 
 
-jchar CallStaticCharMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-        return (jchar)callIntegerMethod(0,methodID,'C',args);
+       return (jchar) callIntegerMethod(0, methodID, 'C', args);
 }
 
 
-jchar CallStaticCharMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticCharMethodA");
 
@@ -1575,28 +2048,29 @@ jchar CallStaticCharMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jval
 
 
 
-jshort CallStaticShortMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-        jshort ret;
-        va_list vaargs;
+       jshort ret;
+       va_list vaargs;
 
-/*      log_text("JNI-Call: CallStaticByteMethod");*/
+       /*      log_text("JNI-Call: CallStaticByteMethod");*/
 
-        va_start(vaargs,methodID);
-        ret = (jshort)callIntegerMethod(0,methodID,'S',vaargs);
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs, methodID);
+       ret = (jshort) callIntegerMethod(0, methodID, 'S', vaargs);
+       va_end(vaargs);
+
+       return ret;
 }
 
 
-jshort CallStaticShortMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
        /*log_text("JNI-Call: CallStaticShortMethodV");*/
-       return (jshort)callIntegerMethod(0,methodID,'S',args);
+       return (jshort) callIntegerMethod(0, methodID, 'S', args);
 }
 
 
-jshort CallStaticShortMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticShortMethodA");
 
@@ -1605,30 +2079,30 @@ jshort CallStaticShortMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jv
 
 
 
-jint CallStaticIntMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-        jobject ret;
-        va_list vaargs;
+       jint ret;
+       va_list vaargs;
 
-/*      log_text("JNI-Call: CallStaticIntMethod");*/
+       /*      log_text("JNI-Call: CallStaticIntMethod");*/
 
-        va_start(vaargs,methodID);
-        ret = callIntegerMethod(0,methodID,'I',vaargs);
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs, methodID);
+       ret = callIntegerMethod(0, methodID, 'I', vaargs);
+       va_end(vaargs);
 
+       return ret;
 }
 
 
-jint CallStaticIntMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallStaticIntMethodV");
 
-       return callIntegerMethod(0,methodID,'I',args);
+       return callIntegerMethod(0, methodID, 'I', args);
 }
 
 
-jint CallStaticIntMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticIntMethodA");
 
@@ -1637,21 +2111,22 @@ jint CallStaticIntMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue
 
 
 
-jlong CallStaticLongMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-        jobject ret;
-        va_list vaargs;
+       jlong ret;
+       va_list vaargs;
 
-/*      log_text("JNI-Call: CallStaticLongMethod");*/
+       /*      log_text("JNI-Call: CallStaticLongMethod");*/
 
-        va_start(vaargs,methodID);
-        ret = callLongMethod(0,methodID,vaargs);
-        va_end(vaargs);
-        return ret;
+       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)
+
+jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallStaticLongMethodV");
        
@@ -1659,7 +2134,7 @@ jlong CallStaticLongMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_l
 }
 
 
-jlong CallStaticLongMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticLongMethodA");
 
@@ -1668,62 +2143,62 @@ jlong CallStaticLongMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jval
 
 
 
-jfloat CallStaticFloatMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-        jfloat ret;
-        va_list vaargs;
+       jfloat ret;
+       va_list vaargs;
 
-/*      log_text("JNI-Call: CallStaticLongMethod");*/
+       /*      log_text("JNI-Call: CallStaticLongMethod");*/
 
-        va_start(vaargs,methodID);
-        ret = callFloatMethod(0,methodID,vaargs,'F');
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs, methodID);
+       ret = callFloatMethod(0, methodID, vaargs, 'F');
+       va_end(vaargs);
 
+       return ret;
 }
 
 
-jfloat CallStaticFloatMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
 
-       return callFloatMethod(0,methodID,args,'F');
+       return callFloatMethod(0, methodID, args, 'F');
 
 }
 
 
-jfloat CallStaticFloatMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticFloatMethodA");
 
+       return 0;
 }
 
 
 
-jdouble CallStaticDoubleMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
+       jdouble ret;
+       va_list vaargs;
 
-        jdouble ret;
-        va_list vaargs;
-
-/*      log_text("JNI-Call: CallStaticDoubleMethod");*/
+       /*      log_text("JNI-Call: CallStaticDoubleMethod");*/
 
-        va_start(vaargs,methodID);
-        ret = callFloatMethod(0,methodID,vaargs,'D');
-        va_end(vaargs);
-        return ret;
+       va_start(vaargs,methodID);
+       ret = callFloatMethod(0, methodID, vaargs, 'D');
+       va_end(vaargs);
 
+       return ret;
 }
 
 
-jdouble CallStaticDoubleMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
+jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallStaticDoubleMethodV");
 
-       return callFloatMethod(0,methodID,args,'D');
+       return callFloatMethod(0, methodID, args, 'D');
 }
 
 
-jdouble CallStaticDoubleMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
+jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
 {
        log_text("JNI-Call: CallStaticDoubleMethodA");
 
@@ -1731,34 +2206,31 @@ jdouble CallStaticDoubleMethodA (JNIEnv *env, jclass clazz, jmethodID methodID,
 }
 
 
-
-void CallStaticVoidMethod (JNIEnv *env, jclass cls, jmethodID methodID, ...)
+void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)
 {
-        va_list vaargs;
+       va_list vaargs;
 
 /*      log_text("JNI-Call: CallStaticVoidMethod");*/
 
-        va_start(vaargs,methodID);
-        (void)callIntegerMethod(0,methodID,'V',vaargs);
-        va_end(vaargs);
-
+       va_start(vaargs, methodID);
+       (void) callIntegerMethod(0, methodID, 'V', vaargs);
+       va_end(vaargs);
 }
 
 
-void CallStaticVoidMethodV (JNIEnv *env, jclass cls, jmethodID methodID, va_list args)
+void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallStaticVoidMethodV");
-        (void)callIntegerMethod(0,methodID,'V',args);
-
+       (void)callIntegerMethod(0, methodID, 'V', args);
 }
 
 
-void CallStaticVoidMethodA (JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args)
+void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args)
 {
        log_text("JNI-Call: CallStaticVoidMethodA");
-
 }
 
+
 /****************** JNI-functions for accessing static fields ********************/
 
 jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) 
@@ -1770,7 +2242,7 @@ jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const ch
                            utf_new_char ((char*) sig)
                            ); 
        
-       if (!f) exceptionptr =  native_new_and_init(class_java_lang_NoSuchFieldError);  
+       if (!f) *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
 
        return f;
 }
@@ -1926,6 +2398,10 @@ jstring NewString (JNIEnv *env, const jchar *buf, jsize len)
        return (jstring) s;
 }
 
+
+static char emptyString[]="";
+static jchar emptyStringJ[]={0,0};
+
 /******************* returns the length of a Java string ***************************/
 
 jsize GetStringLength (JNIEnv *env, jstring str)
@@ -1964,14 +2440,22 @@ u2 *javastring_tou2 (jstring so)
 
 const jchar *GetStringChars (JNIEnv *env, jstring str, jboolean *isCopy)
 {      
-       return javastring_tou2(str);
+       jchar *jc=javastring_tou2(str);
+
+       if (jc) {
+               if (isCopy) *isCopy=JNI_TRUE;
+               return jc;
+       }
+       if (isCopy) *isCopy=JNI_TRUE;
+       return emptyStringJ;
 }
 
 /**************** native code no longer needs access to chars **********************/
 
 void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars)
 {
-       MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count);
+       if (chars==emptyStringJ) return;
+       MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1);
 }
 
 /************ create new java.lang.String object from utf8-characterarray **********/
@@ -1979,7 +2463,7 @@ void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars)
 jstring NewStringUTF (JNIEnv *env, const char *utf)
 {
 /*    log_text("NewStringUTF called");*/
-    return javastring_new(utf_new_char(utf));
+    return (jstring) javastring_new(utf_new_char((char *) utf));
 }
 
 /****************** returns the utf8 length in bytes of a string *******************/
@@ -1991,20 +2475,32 @@ jsize GetStringUTFLength (JNIEnv *env, jstring string)
     return (jsize) u2_utflength(s->value->data, s->count); 
 }
 
+
 /************ converts a Javastring to an array of UTF-8 characters ****************/
 
-const char* GetStringUTFChars (JNIEnv *env, jstring string, jboolean *isCopy)
+const char* GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)
 {
-    if (verbose) log_text("GetStringUTFChars:");
+    utf *u;
+
+    u = javastring_toutf((java_lang_String *) string, false);
 
-    return javastring_toutf((java_lang_String*) string,false)->text;
+    if (isCopy)
+               *isCopy = JNI_FALSE;
+       
+    if (u)
+               return u->text;
+
+    return emptyString;
        
 }
 
+
 /***************** native code no longer needs access to utf ***********************/
 
 void ReleaseStringUTFChars (JNIEnv *env, jstring str, const char* chars)
 {
+    /*we don't release utf chars right now, perhaps that should be done later. Since there is always one reference
+       the garbage collector will never get them*/
        /*
     log_text("JNI-Call: ReleaseStringUTFChars");
     utf_display(utf_new_char(chars));
@@ -2013,40 +2509,50 @@ void ReleaseStringUTFChars (JNIEnv *env, jstring str, const char* chars)
 
 /************************** array operations ***************************************/
 
-jsize GetArrayLength (JNIEnv *env, jarray array)
+jsize GetArrayLength(JNIEnv *env, jarray array)
 {
     return array->size;
 }
 
+
 jobjectArray NewObjectArray (JNIEnv *env, jsize len, jclass clazz, jobject init)
 {
-    java_objectarray *j = builtin_anewarray (len, clazz);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_objectarray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_anewarray(len, clazz);
+
     return j;
 }
 
-jobject GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
+
+jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
 {
     jobject j = NULL;
 
-    if (index<array->header.size)      
-       j = array->data[index];
+    if (index < array->header.size)    
+               j = array->data[index];
     else
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
     
     return j;
 }
 
-void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobject val)
+
+void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val)
 {
-    if (index>=array->header.size)     
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
-    else {
+    if (index >= array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
 
-       /* check if the class of value is a subclass of the element class of the array */
+    else {
+               /* check if the class of value is a subclass of the element class of the array */
+               if (!builtin_canstore((java_objectarray *) array, (java_objectheader *) val))
+                       *exceptionptr = new_exception(string_java_lang_ArrayStoreException);
 
-               if (!builtin_canstore((java_objectarray*)array,(java_objectheader*)val))
-                       exceptionptr = proto_java_lang_ArrayStoreException;
                else
                        array->data[index] = val;
     }
@@ -2054,66 +2560,122 @@ void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobjec
 
 
 
-jbooleanArray NewBooleanArray (JNIEnv *env, jsize len)
+jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
 {
-    java_booleanarray *j = builtin_newarray_boolean(len);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_booleanarray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_boolean(len);
+
     return j;
 }
 
 
-jbyteArray NewByteArray (JNIEnv *env, jsize len)
+jbyteArray NewByteArray(JNIEnv *env, jsize len)
 {
-    java_bytearray *j = builtin_newarray_byte(len);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_bytearray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_byte(len);
+
     return j;
 }
 
 
-jcharArray NewCharArray (JNIEnv *env, jsize len)
+jcharArray NewCharArray(JNIEnv *env, jsize len)
 {
-    java_chararray *j = builtin_newarray_char(len);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_chararray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_char(len);
+
     return j;
 }
 
 
-jshortArray NewShortArray (JNIEnv *env, jsize len)
+jshortArray NewShortArray(JNIEnv *env, jsize len)
 {
-    java_shortarray *j = builtin_newarray_short(len);   
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_shortarray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_short(len);
+
     return j;
 }
 
 
-jintArray NewIntArray (JNIEnv *env, jsize len)
+jintArray NewIntArray(JNIEnv *env, jsize len)
 {
-    java_intarray *j = builtin_newarray_int(len);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_intarray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_int(len);
+
     return j;
 }
 
 
-jlongArray NewLongArray (JNIEnv *env, jsize len)
+jlongArray NewLongArray(JNIEnv *env, jsize len)
 {
-    java_longarray *j = builtin_newarray_long(len);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_longarray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_long(len);
+
     return j;
 }
 
 
-jfloatArray NewFloatArray (JNIEnv *env, jsize len)
+jfloatArray NewFloatArray(JNIEnv *env, jsize len)
 {
-    java_floatarray *j = builtin_newarray_float(len);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_floatarray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_float(len);
+
     return j;
 }
 
 
-jdoubleArray NewDoubleArray (JNIEnv *env, jsize len)
+jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
 {
-    java_doublearray *j = builtin_newarray_double(len);
-    if (!j) exceptionptr = proto_java_lang_OutOfMemoryError;
+       java_doublearray *j;
+
+    if (len < 0) {
+               *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
+               return NULL;
+    }
+
+    j = builtin_newarray_double(len);
+
     return j;
 }
 
@@ -2222,150 +2784,171 @@ void ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems
     /* empty */
 }
 
-void GetBooleanArrayRegion (JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf)
+
+void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));     
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void GetByteArrayRegion (JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
+void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size) 
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size) 
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void GetCharArrayRegion (JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
+void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));     
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void GetShortArrayRegion (JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
+void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else       
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));     
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void GetIntArrayRegion (JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
+void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)      
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));     
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void GetLongArrayRegion (JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
+void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)      
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));     
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void GetFloatArrayRegion (JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
+void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)      
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));     
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void GetDoubleArrayRegion (JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
+void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size) 
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start+len>array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(buf,&array->data[start],len*sizeof(array->data[0]));     
+               memcpy(buf, &array->data[start], len * sizeof(array->data[0]));
 }
 
 
-void SetBooleanArrayRegion (JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf)
+void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 }
 
 
-void SetByteArrayRegion (JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
+void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 }
 
 
-void SetCharArrayRegion (JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
+void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 
 }
 
 
-void SetShortArrayRegion (JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
+void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 }
 
 
-void SetIntArrayRegion (JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
+void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 
 }
 
-void SetLongArrayRegion (JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
+
+void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 
 }
 
-void SetFloatArrayRegion (JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
+
+void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 
 }
 
-void SetDoubleArrayRegion (JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
+
+void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf)
 {
-    if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+    if (start < 0 || len < 0 || start + len > array->header.size)
+               *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
+
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start], buf, len * sizeof(array->data[0]));
 }
 
+
 jint RegisterNatives (JNIEnv* env, jclass clazz, const JNINativeMethod *methods, jint nMethods)
 {
     log_text("JNI-Call: RegisterNatives");
@@ -2419,7 +3002,7 @@ void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char
 
 }
 
-/****************** obtain direct pointer to array elements ***********************/
+/************** obtain direct pointer to array elements ***********************/
 
 void * GetPrimitiveArrayCritical (JNIEnv* env, jarray array, jboolean *isCopy)
 {
@@ -2439,7 +3022,7 @@ void ReleasePrimitiveArrayCritical (JNIEnv* env, jarray array, void *carray, jin
        /* empty */
 }
 
-/********* returns a pointer to an array of Unicode characters of the string *******/
+/**** returns a pointer to an array of Unicode characters of the string *******/
 
 const jchar * GetStringCritical (JNIEnv* env, jstring string, jboolean *isCopy)
 {
@@ -2448,7 +3031,7 @@ const jchar * GetStringCritical (JNIEnv* env, jstring string, jboolean *isCopy)
        return GetStringChars(env,string,isCopy);
 }
 
-/**************** native code no longer needs access to chars **********************/
+/*********** native code no longer needs access to chars **********************/
 
 void ReleaseStringCritical (JNIEnv* env, jstring string, const jchar *cstring)
 {
@@ -2477,11 +3060,11 @@ void DeleteWeakGlobalRef (JNIEnv* env, jweak ref)
 /******************************* check for pending exception ***********************/
 
 
-jboolean ExceptionCheck (JNIEnv* env)
+jboolean ExceptionCheck(JNIEnv* env)
 {
        log_text("JNI-Call: ExceptionCheck");
 
-       return exceptionptr ? JNI_TRUE : JNI_FALSE;
+       return *exceptionptr ? JNI_TRUE : JNI_FALSE;
 }
 
 
@@ -2489,35 +3072,44 @@ jboolean ExceptionCheck (JNIEnv* env)
 
 
 
-jint DestroyJavaVM (JavaVM *vm) {
+jint DestroyJavaVM(JavaVM *vm)
+{
        log_text("DestroyJavaVM called");
+
+       return 0;
 }
 
-jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2) {
+
+jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2)
+{
        log_text("AttachCurrentThread called");
-}
 
-jint DetachCurrentThread (JavaVM *vm) {
-       log_text("DetachCurrentThread called");
-}
-   
-jint GetEnv (JavaVM *vm, void **environment, jint jniversion) {
-       *environment=&env;
        return 0;
 }
-   
-jint AttachCurrentThreadAsDaemon (JavaVM *vm, void **par1, void *par2) {
-       log_text("AttachCurrentThreadAsDaemon called");
-}
 
 
+jint DetachCurrentThread(JavaVM *vm)
+{
+       log_text("DetachCurrentThread called");
 
+       return 0;
+}
 
 
+jint GetEnv(JavaVM *vm, void **environment, jint jniversion)
+{
+       *environment = &env;
 
+       return 0;
+}
 
 
+jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
+{
+       log_text("AttachCurrentThreadAsDaemon called");
 
+       return 0;
+}
 
 
 /********************************* JNI invocation table ******************************/
@@ -2531,15 +3123,14 @@ struct _JavaVM javaVMTable={
    &DetachCurrentThread,
    &GetEnv,
    &AttachCurrentThreadAsDaemon
-
 };
 
-JavaVM javaVM=&javaVMTable;
+JavaVM javaVM = &javaVMTable;
+
 
 /********************************* JNI function table ******************************/
 
-struct JNI_Table envTable =     
-   {   
+struct JNI_Table envTable = {   
     NULL,
     NULL,
     NULL,
@@ -2769,10 +3360,234 @@ struct JNI_Table envTable =
     &NewWeakGlobalRef,
     &DeleteWeakGlobalRef,
     &ExceptionCheck
-    };
+};
+
+JNIEnv env = &envTable;
+
+
+jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, jobject obj, java_objectarray *params)
+{
+       int argcount;
+       jni_callblock *blk;
+       char retT;
+       jobject retVal;
+
+       if (methodID == 0) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
+               return NULL;
+       }
 
+       argcount = get_parametercount(methodID);
 
-JNIEnv env=&envTable;
+       if (obj && (!builtin_instanceof((java_objectheader *) obj, methodID->class))) {
+               *exceptionptr = new_exception_message(string_java_lang_IllegalArgumentException,
+                                                                                         "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
+               return 0;
+       }
+
+
+
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+               log_text("Too many arguments. invokeNativeHelper does not support that");
+               return 0;
+       }
+
+       if (((!params) && (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");
+               return 0;
+       }
+
+       if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0;
+
+       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+
+       retT = fill_callblock_objA(obj, methodID->descriptor, blk, params);
+
+       switch (retT) {
+       case 'V':
+               (void) asm_calljavafunction2(methodID,
+                                                                        argcount + 1,
+                                                                        (argcount + 1) * sizeof(jni_callblock),
+                                                                        blk);
+               retVal = NULL; /*native_new_and_init(loader_load(utf_new_char("java/lang/Void")));*/
+               break;
+
+       case 'I': {
+               s4 intVal;      
+               intVal = (s4) asm_calljavafunction2(methodID,
+                                                                                       argcount + 1,
+                                                                                       (argcount + 1) * sizeof(jni_callblock),
+                                                                                       blk);
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Integer")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(I)V")),
+                                          intVal);
+       }
+       break;
+
+       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")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(B)V")),
+                                          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")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(C)V")),
+                                          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")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(S)V")),
+                                          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")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(Z)V")),
+                                          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")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(J)V")),
+                                          intVal);
+       }
+       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")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(F)V")),
+                                          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")));
+               CallVoidMethod(env,
+                                          retVal,
+                                          class_resolvemethod(retVal->vftbl->class,
+                                                                                  utf_new_char("<init>"),
+                                                                                  utf_new_char("(D)V")),
+                                          floatVal);
+       }
+       break;
+
+       case 'L': /* fall through */
+       case '[':
+               retVal = asm_calljavafunction2(methodID,
+                                                                          argcount + 1,
+                                                                          (argcount + 1) * sizeof(jni_callblock),
+                                                                          blk);
+               break;
+
+       default:
+               /* if this happens the acception has already been set by fill_callblock_objA*/
+               MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+               return (jobject *) 0;
+       }
+
+       MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+
+       if (*exceptionptr) {
+               java_objectheader *exceptionToWrap = *exceptionptr;
+               classinfo *ivtec;
+               java_objectheader *ivte;
+
+               *exceptionptr = NULL;
+               ivtec = class_new(utf_new_char("java/lang/reflect/InvocationTargetException"));
+               ivte = builtin_new(ivtec);
+               asm_calljavafunction(class_resolvemethod(ivtec,
+                                                                                                utf_new_char("<init>"),
+                                                                                                utf_new_char("(Ljava/lang/Throwable;)V")),
+                                                        ivte,
+                                                        exceptionToWrap,
+                                                        0,
+                                                        0);
+
+               if (*exceptionptr != NULL)
+                       panic("jni.c: error while creating InvocationTargetException wrapper");
+
+               *exceptionptr = ivte;
+       }
+
+       return (jobject *) retVal;
+}
 
 
 /*