exceptionptr update for native threads
[cacao.git] / jni.c
diff --git a/jni.c b/jni.c
index 63f377e8871e0476f8f4328769b09c0e370a90f0..289e01556125e136545b6e11edfda9e03c876b28 100644 (file)
--- a/jni.c
+++ b/jni.c
@@ -1,4 +1,4 @@
-/* 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,
 
    Authors: ?
 
-   $Id: jni.c 676 2003-11-24 20:50:23Z twisti $
+   Changes: Joseph Wenninger
+
+   $Id: jni.c 862 2004-01-06 23:42:01Z stefan $
 
 */
 
 
+#include <string.h>
 #include "jni.h"
-#include "types.h"
-#include "jit.h"
-#include "builtin.h"
+#include "global.h"
 #include "loader.h"
-#include "native.h"
 #include "tables.h"
-#include "asmpart.h"
+#include "native.h"
+#include "builtin.h"
+#include "threads/thread.h"
+#include "toolbox/loging.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 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;
 
 
 /********************* accessing instance-fields **********************************/
 
+#define setField(obj,typ,var,val) *((typ*) ((long int) obj + (long int) var->offset))=val;  
+#define getField(obj,typ,var)     *((typ*) ((long int) obj + (long int) var->offset))
+#define setfield_critical(clazz,obj,name,sig,jdatatype,val) setField(obj,jdatatype,getFieldID_critical(env,clazz,name,sig),val); 
+
+
+
 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     */
-    int parametercount = 0;
+       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;
 
-    /* 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;
 }
 
 
 
-/* XXX it could be considered if we should do typechecking here in the future */
 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);
+    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;
+       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' : {
+                       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=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;
 
     u4 dummy;
     char c;
+    char *cp;
+    intsDisable();
+       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");
+       }
+    intsRestore();
+
        /*
          log_text("fill_callblock");
          utf_display(descr);
@@ -88,92 +236,244 @@ void fill_callblock(void *obj, utf *descr, jni_callblock blk[], va_list data, ch
     /* determine number of parameters */
        if (obj) {
                blk[0].itemtype = TYPE_ADR;
-               blk[0].item = (u8)(u4)obj;
+               blk[0].item = PTR_TO_ITEM(obj);
                cnt=1;
 
        } else {
                cnt = 0;
        }
 
+       cnts=0;
        while (**utf_ptr != ')') {
                if (*utf_ptr >= desc_end)
                panic("illegal method descriptor");
 
                /* primitive types */
                switch (utf_nextu2(utf_ptr)) {
-               case 'B':
+               case 'B':       
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               if (param->vftbl->class->name==utf_byte) {
+                                       blk[cnt].itemtype=TYPE_INT;
+                                       blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value;
+                               } else  {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               break;
                case 'C':
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               if (param->vftbl->class->name==utf_char) {
+                                       blk[cnt].itemtype=TYPE_INT;
+                                       blk[cnt].item = (u8) ((struct java_lang_Character * )param)->value;
+                               } else  {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               break;
+
                case 'S': 
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               if (param->vftbl->class->name==utf_short) {
+                                       blk[cnt].itemtype=TYPE_INT;
+                                       blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value;
+                               } else  {
+                                       if (param->vftbl->class->name==utf_byte) {
+                                               blk[cnt].itemtype=TYPE_INT;
+                                               blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value;
+                                       } else {
+                                               *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                               return 0;
+                                       }
+                               }
+                               break;
+
                case 'Z':
-                       blk[cnt].itemtype = TYPE_INT;
-                       blk[cnt].item = (u8) va_arg(data, int);
-                       break;
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               if (param->vftbl->class->name==utf_bool) {
+                                       blk[cnt].itemtype=TYPE_INT;
+                                       blk[cnt].item = (u8) ((struct java_lang_Boolean * )param)->value;
+                               } else  {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               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;
-
+                               /*log_text("fill_callblock_objA: param 'I'");*/
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               if (param->vftbl->class->name==utf_int) {
+                                       blk[cnt].itemtype=TYPE_INT;
+                                       blk[cnt].item = (u8) ((struct 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) ((struct java_lang_Short* )param)->value;
+                                       } else  {
+                                               if (param->vftbl->class->name==utf_byte) {
+                                                       blk[cnt].itemtype=TYPE_INT;
+                                                       blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value;
+
+                                               } else  {
+                                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                                       return 0;
+                                               }
+                                       }
+                               }
+                               break;
                case 'J':
-                       blk[cnt].itemtype = TYPE_LNG;
-                       blk[cnt].item = (u8) va_arg(data, jlong);
-                       break;
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               if (param->vftbl->class->name==utf_long) {
+                                       blk[cnt].itemtype=TYPE_LNG;
+                                       blk[cnt].item = (u8) ((struct java_lang_Long * )param)->value;
+                               } else  {
+                                       if (param->vftbl->class->name==utf_int) {
+                                               blk[cnt].itemtype=TYPE_LNG;
+                                               blk[cnt].item = (u8) ((struct java_lang_Integer * )param)->value;
+                                       } else {
+                                               if (param->vftbl->class->name==utf_short) {
+                                                       blk[cnt].itemtype=TYPE_LNG;
+                                                       blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value;
+                                               } else  {
+                                                       if (param->vftbl->class->name==utf_byte) {
+                                                               blk[cnt].itemtype=TYPE_LNG;
+                                                               blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value;
+                                                       } else  {
+                                                               *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                                               return 0;
+                                                       }
+                                               }
+                                       }
 
-               case 'F':
-                       blk[cnt].itemtype = TYPE_FLT;
-                       *((jfloat*) (&blk[cnt].item)) = ((jfloat) va_arg(data, jdouble));
-                       break;
+                               }
+                               break;
 
-               case 'D':
-                       blk[cnt].itemtype = TYPE_DBL;
-                       *((jdouble*) (&blk[cnt].item)) = (jdouble) va_arg(data, jdouble);
-                       break;
+               case 'F' : 
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
 
+                               if (param->vftbl->class->name==utf_float) {
+                                       blk[cnt].itemtype=TYPE_FLT;
+                                       *((jfloat*)(&blk[cnt].item))=(jfloat) ((struct java_lang_Float*)param)->value;
+                               } else  {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+                               break;
+               case 'D' : 
+                               param=params->data[cnts];
+                               if (param==0) {
+                                       *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                               }
+
+                               if (param->vftbl->class->name==utf_double) {
+                                       blk[cnt].itemtype=TYPE_DBL;
+                                       *((jdouble*)(&blk[cnt].item))=(jdouble) ((struct java_lang_Float*)param)->value;
+                               } else  {
+                                       if (param->vftbl->class->name==utf_float) {
+                                               blk[cnt].itemtype=TYPE_DBL;
+                                               *((jdouble*)(&blk[cnt].item))=(jdouble) ((struct java_lang_Float*)param)->value;
+                                       } else  {
+                                               *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                               return 0;
+                                       }
+                               }
+                               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 = (u8)(u4) va_arg(data, void*);
-                       break;                  
-
-               case '[' : {
-                       /* XXX need arrayclass change? no.*/
-                       /* arrayclass */
-                       char ch;
-                       while ((ch = utf_nextu2(utf_ptr)) == '[')
-                               if (ch == 'L') {
-                                       while (utf_nextu2(utf_ptr) != ';') {}
+               case 'L': {
+                               char *start=(*utf_ptr)-1;
+                               char *end;
+
+                               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=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                               return 0;
+                                       }                       
                                }
-                       
-                       ch = utf_nextu2(utf_ptr);
-                       blk[cnt].itemtype = TYPE_ADR;
-                       blk[cnt].item = (u8)(u4) va_arg(data, void*);
-                       break;
-               }
+                               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=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+                                       return 0;
+                                       
+                               }
+       
+                               blk[cnt].itemtype = TYPE_ADR;
+                               blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
+                               break;
+                       }
                }
                cnt++;
+               cnts++;
        }
 
-       /*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====");
+       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);
@@ -184,6 +484,8 @@ jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) {
        return class_resolvemethod (clazz, methodID->name, methodID->descriptor);
 }
 
+
+
 jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
 {      
        int argcount;
@@ -199,36 +501,41 @@ jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
          printf("\n");
        */
 
-       if (methodID==0) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); 
+       if (methodID == 0) {
+               *exceptionptr = native_new_and_init(class_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 = native_new_and_init(class_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 = native_new_and_init(class_java_lang_NoSuchMethodError);
                return 0;
        }
 
-       if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+       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*/);
 
-       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);
+       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;
 }
@@ -255,26 +562,26 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar
         printf("\n");
         */
        if (methodID == 0) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); 
+               *exceptionptr = native_new_and_init(class_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);
+       if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
+               ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
+               *exceptionptr = native_new_and_init(class_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 = native_new_and_init(class_java_lang_NoSuchMethodError);
                return 0;
        }
 
 
-       if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+       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;
        }
@@ -311,37 +618,42 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
         utf_display(obj->vftbl->class->name);
         printf("\n");
         */
-       if (methodID==0) {
-               exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); 
+       if (methodID == 0) {
+               *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); 
                return 0;
        }
-       argcount=get_parametercount(methodID);
 
-       if (!( ((methodID->flags & ACC_STATIC) && (obj==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);
+               *exceptionptr = native_new_and_init(class_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 = native_new_and_init(class_java_lang_NoSuchMethodError);
                return 0;
        }
 
 
-       if  (argcount>3) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+       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*/);
 
-       fill_callblock(obj,methodID->descriptor,blk,args,'L');
+       fill_callblock(obj, methodID->descriptor, blk, args, 'L');
 
        /*      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);
+       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;
@@ -349,9 +661,9 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
 
 
 /*core function for float class methods (float,double)*/
-jdouble callFloatMethod (jobject obj, jmethodID methodID, va_list args,char retType)
+jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType)
 {
-       int argcount=get_parametercount(methodID);
+       int argcount = get_parametercount(methodID);
        jni_callblock *blk;
        jdouble ret;
 
@@ -363,19 +675,24 @@ 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")));
+
+       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*/);
 
-       fill_callblock(obj,methodID->descriptor,blk,args,retType);
+       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);
+       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;
@@ -445,7 +762,7 @@ jclass FindClass (JNIEnv* env, const char *name)
        else*/
                c = loader_load(utf_new_char_classname ((char *) name));
 
-       if (!c) exceptionptr = native_new_and_init(class_java_lang_ClassFormatError);
+       if (!c) *exceptionptr = native_new_and_init(class_java_lang_ClassFormatError);
 
        return c;
 }
@@ -504,7 +821,7 @@ jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isS
 
 jint Throw(JNIEnv* env, jthrowable obj)
 {
-       exceptionptr = (java_objectheader*) obj;
+       *exceptionptr = (java_objectheader*) obj;
 
        return 0;
 }
@@ -517,8 +834,7 @@ jint Throw(JNIEnv* env, jthrowable obj)
 
  **********************************************************************************/   
 
-
-jint ThrowNew (JNIEnv* env, jclass clazz, const char *msg) 
+jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
 {
        java_lang_Throwable *o;
 
@@ -529,22 +845,24 @@ jint ThrowNew (JNIEnv* env, jclass clazz, const 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);        
 }
@@ -554,7 +872,7 @@ void ExceptionDescribe (JNIEnv* env)
 
 void ExceptionClear (JNIEnv* env) 
 {
-       exceptionptr = NULL;    
+       *exceptionptr = NULL;   
 }
 
 
@@ -588,8 +906,6 @@ jobject PopLocalFrame(JNIEnv* env, jobject result)
     
 jobject NewGlobalRef(JNIEnv* env, jobject lobj)
 {
-       heap_addreference((void**) &lobj);
-
        return lobj;
 }
 
@@ -662,7 +978,7 @@ 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")));
+               *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
                log_text("Too many arguments. NewObject does not support that");
                return 0;
        }
@@ -677,7 +993,7 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
                args[i]=va_arg(vaargs,void*);
        }
        va_end(vaargs);
-       exceptionptr=asm_calljavamethod(methodID,o,args[0],args[1],args[2]);
+       asm_calljavafunction(methodID,o,args[0],args[1],args[2]);
 
        return o;
 }
@@ -719,8 +1035,11 @@ jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
 jclass GetObjectClass(JNIEnv* env, jobject obj)
 {
        classinfo *c = obj->vftbl->class;
+/*     log_text("GetObjectClass");
+       utf_display(obj->vftbl->class->name);*/
        use_class_as_object(c);
 
+       /*printf("\nPointer: %p\n",c);*/
        return c;
 }
 
@@ -770,7 +1089,7 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *s
                utf_new_char ((char*) sig)
        );
 
-       if (!m) exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);          
+       if (!m) *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError);         
 
        return m;
 }
@@ -1375,7 +1694,7 @@ jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *si
 /*             utf_display(clazz->name);
                log_text(name);
                log_text(sig);*/
-               exceptionptr =  native_new_and_init(class_java_lang_NoSuchFieldError);  
+               *exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldError);  
        }
        return f;
 }
@@ -1504,23 +1823,24 @@ 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 = native_new_and_init(class_java_lang_NoSuchMethodError);
 
        return m;
 }
 
+
 jobject CallStaticObjectMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
        log_text("JNI-Call: CallStaticObjectMethod");
@@ -1826,7 +2146,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 = native_new_and_init(class_java_lang_NoSuchFieldError);  
 
        return f;
 }
@@ -1984,6 +2304,7 @@ jstring NewString (JNIEnv *env, const jchar *buf, jsize len)
 
 
 static char emptyString[]="";
+static jchar emptyStringJ[]={0,0};
 
 /******************* returns the length of a Java string ***************************/
 
@@ -2030,14 +2351,14 @@ const jchar *GetStringChars (JNIEnv *env, jstring str, jboolean *isCopy)
                return jc;
        }
        if (isCopy) *isCopy=JNI_TRUE;
-       return emptyString;
+       return emptyStringJ;
 }
 
 /**************** native code no longer needs access to chars **********************/
 
 void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars)
 {
-       if (chars==emptyString) return;
+       if (chars==emptyStringJ) return;
        MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1);
 }
 
@@ -2046,7 +2367,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 *******************/
@@ -2095,8 +2416,13 @@ jsize GetArrayLength (JNIEnv *env, jarray array)
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_anewarray (len, clazz);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
@@ -2105,9 +2431,9 @@ jobject GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
     jobject j = NULL;
 
     if (index<array->header.size)      
-       j = array->data[index];
+               j = array->data[index];
     else
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
     
     return j;
 }
@@ -2115,13 +2441,13 @@ jobject GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
 void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobject val)
 {
     if (index>=array->header.size)     
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
     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 = proto_java_lang_ArrayStoreException;
+                       *exceptionptr = proto_java_lang_ArrayStoreException;
                else
                        array->data[index] = val;
     }
@@ -2131,64 +2457,104 @@ void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobjec
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_boolean(len);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_byte(len);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_char(len);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_short(len);   
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_int(len);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_long(len);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_float(len);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
 
 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=proto_java_lang_NegativeArraySizeException;
+               return NULL;
+    }
+    j = builtin_newarray_double(len);
+    if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError;
     return j;
 }
 
@@ -2300,99 +2666,99 @@ void ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems
 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;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size) 
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)      
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)      
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)      
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size) 
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
     else
-       memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
+               memcpy(&array->data[start],buf,len*sizeof(array->data[0]));     
 
 }
 
@@ -2400,45 +2766,45 @@ void SetCharArrayRegion (JNIEnv* env, jcharArray array, jsize start, jsize len,
 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;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
 {
     if (start<0 || len<0 || start+len>array->header.size)
-       exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+               *exceptionptr = proto_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)
@@ -2556,7 +2922,7 @@ jboolean ExceptionCheck(JNIEnv* env)
 {
        log_text("JNI-Call: ExceptionCheck");
 
-       return exceptionptr ? JNI_TRUE : JNI_FALSE;
+       return *exceptionptr ? JNI_TRUE : JNI_FALSE;
 }
 
 
@@ -2604,15 +2970,6 @@ jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
 }
 
 
-
-
-
-
-
-
-
-
-
 /********************************* JNI invocation table ******************************/
 
 struct _JavaVM javaVMTable={
@@ -2863,10 +3220,240 @@ struct JNI_Table envTable = {
     &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 = native_new_and_init(class_java_lang_NoSuchMethodError); 
+               return 0;
+       }
+       argcount = get_parametercount(methodID);
+
+       if (obj && (!builtin_instanceof((java_objectheader*)obj, methodID->class))) {
+               (*env)->ThrowNew(env, loader_load(utf_new_char("java/lang/IllegalArgumentException")),
+                                                "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
+               return 0;
+       }
+
+
+
+       if  (argcount > 3) {
+               *exceptionptr = native_new_and_init(loader_load(utf_new_char("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 = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+               return 0;
+       }
+
+
+       if (!(methodID->flags & ACC_STATIC) && (!obj))  {
+               (*env)->ThrowNew(env, loader_load(utf_new_char("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(loader_load_sysclass(NULL,
+                                                                                                 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(loader_load_sysclass(NULL,
+                                                                                                 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(loader_load_sysclass(NULL,
+                                                                                                 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(loader_load_sysclass(NULL,
+                                                                                                 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(loader_load_sysclass(NULL,
+                                                                                                 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(loader_load_sysclass(NULL,
+                                                                                                 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(loader_load_sysclass(NULL,
+                                                                                                 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(loader_load_sysclass(NULL,
+                                                                                                 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 = loader_load_sysclass(NULL,
+                                                                                               utf_new_char("java/lang/reflect/InvocationTargetException"));
+               java_objectheader* 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;
+}
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where