x86_64 include added
[cacao.git] / jni.c
diff --git a/jni.c b/jni.c
index bedd4b8f88a3f19577dcbc72a97a01c23351c32d..265a28a8c9c01c4ec6ba15b9347703c461285667 100644 (file)
--- a/jni.c
+++ b/jni.c
@@ -1,12 +1,76 @@
-/********************************** jni.c *****************************************
-
-       implementation of the Java Native Interface functions                             
-       which are used in the JNI function table                                         
+/* jni.c - implementation of the Java Native Interface functions
+
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
+   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
+   P. Tomsich, J. Wenninger, M. Platter
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: ?
+
+   Changes: Joseph Wenninger, Martin Platter
+
+   $Id: jni.c 1384 2004-08-02 11:41:26Z motse $
+
+*/
+
+
+#include <string.h>
+#include "exceptions.h"
+#include "main.h"
+#include "jni.h"
+#include "global.h"
+#include "loader.h"
+#include "tables.h"
+#include "native.h"
+#include "builtin.h"
+#include "options.h"
+#include "statistics.h"
+#include "threads/thread.h"
+#include "toolbox/logging.h"
+#include "toolbox/memory.h"
+#include "nat/java_lang_Byte.h"
+#include "nat/java_lang_Character.h"
+#include "nat/java_lang_Short.h"
+#include "nat/java_lang_Integer.h"
+#include "nat/java_lang_Boolean.h"
+#include "nat/java_lang_Long.h"
+#include "nat/java_lang_Float.h"
+#include "nat/java_lang_Double.h"
+#include "nat/java_lang_Throwable.h"
+#include "jit/jit.h"
+#include "asmpart.h"   
+#define JNI_VERSION       0x00010002
 
-***********************************************************************************/
 
+#define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
 
-#define JNI_VERSION       0x00010002
+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 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     */
+       u4 parametercount = 0;
+
+       /* skip '(' */
+       utf_nextu2(&utf_ptr);
+
+    /* determine number of parameters */
+       while (*utf_ptr != ')') {
+               get_type(&utf_ptr, desc_end, true);
+               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     */
+    int cnt;
+    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;
+    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;
+       }
+
+       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);
+}
+
+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;
+       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");
+       */
+
+       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 = new_exception(string_java_lang_NoSuchMethodError);
+               return 0;
+       }
+       
+       if (obj && !builtin_instanceof(obj, methodID->class)) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+               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*/);
+
+       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;
+}
+
+
+/*
+  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);*/
+
+        /*
+        log_text("JNI-Call: CallObjectMethodV");
+        utf_display(methodID->name);
+        utf_display(methodID->descriptor);
+        printf("\nParmaeter count: %d\n",argcount);
+        utf_display(obj->vftbl->class->name);
+        printf("\n");
+        */
+       if (methodID == 0) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
+               return 0;
+       }
+        
+       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 = new_exception(string_java_lang_NoSuchMethodError);
+               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*/);
+
+       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;
+}
+
+
+/*core function for long class functions*/
+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 = 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 = new_exception(string_java_lang_NoSuchMethodError);
+               return 0;
+       }
+
+       if (obj && !builtin_instanceof(obj,methodID->class)) {
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+               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*/);
+
+       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;
+}
+
+
+/*core function for float class methods (float,double)*/
+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");
+        utf_display(methodID->name);
+        utf_display(methodID->descriptor);
+        printf("\nParmaeter count: %d\n",argcount);
+        utf_display(obj->vftbl->class->name);
+        printf("\n");
+        */
+
+       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*/);
+
+       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;
+}
+
+
 /*************************** function: jclass_findfield ****************************
        
        searches for field with specified name and type in a 'classinfo'-structur
 fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc)
 {
        s4 i;
-       for (i = 0; i < c->fieldscount; i++) {
+/*     printf(" FieldCount: %d\n",c->fieldscount);
+       utf_display(c->name); */
+               for (i = 0; i < c->fieldscount; i++) {
+/*             utf_display(c->fields[i].name);
+               printf("\n");
+               utf_display(c->fields[i].descriptor);
+               printf("\n");*/
                if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
                        return &(c->fields[i]);
                }
 
+       if (c->super) return jclass_findfield(c->super,name,desc);
+
        return NULL;
 }
 
@@ -40,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;
 }
@@ -60,13 +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;  
   
-       c = loader_load(utf_new_char ((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;
 }
@@ -79,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");
+       /* 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");
+       /* 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);        
 }
@@ -168,7 +955,7 @@ void ExceptionDescribe (JNIEnv* env)
 
 void ExceptionClear (JNIEnv* env) 
 {
-       exceptionptr = NULL;    
+       *exceptionptr = NULL;   
 }
 
 
@@ -181,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;
 }
 
@@ -262,9 +1052,36 @@ jobject AllocObject (JNIEnv* env, jclass clazz)
 
 jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: NewObject");
+       java_objectheader *o;
+       void* args[3];
+       int argcount=get_parametercount(methodID);
+       int i;
+       va_list vaargs;
+
+       /* log_text("JNI-Call: NewObject"); */
+
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+               log_text("Too many arguments. NewObject does not support that");
+               return 0;
+       }
+
+       
+       o = builtin_new (clazz);         /*          create object */
+       
+       if (!o) return NULL;
+
+       va_start(vaargs,methodID);
+       for (i=0;i<argcount;i++) {
+               args[i]=va_arg(vaargs,void*);
+       }
+       va_end(vaargs);
+       asm_calljavafunction(methodID,o,args[0],args[1],args[2]);
+
+       return o;
 }
 
+
 /*********************************************************************************** 
 
        Constructs a new Java object
@@ -272,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");
+       /* log_text("JNI-Call: NewObjectV"); */
+
+       return NULL;
 }
 
+
 /*********************************************************************************** 
 
        Constructs a new Java object
@@ -285,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");
+       /* 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 
@@ -322,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;
 
@@ -339,30 +1170,39 @@ 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, ...)
 {
-       log_text("JNI-Call: CallObjectMethod");
+       jobject ret;
+       va_list vaargs;
 
-       return NULL;
+/*     log_text("JNI-Call: CallObjectMethod");*/
+
+       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)
 {
-       log_text("JNI-Call: CallObjectMethodV");
-
-       return NULL;
+       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");
 
@@ -370,18 +1210,26 @@ jobject CallObjectMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue
 }
 
 
+
+
 jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallBooleanMethod");
+       jboolean ret;
+       va_list vaargs;
+
+/*     log_text("JNI-Call: CallBooleanMethod");*/
+
+       va_start(vaargs,methodID);
+       ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',vaargs);
+       va_end(vaargs);
+       return ret;
 
-       return 0;
 }
 
 jboolean CallBooleanMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallBooleanMethodV");
+       return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',args);
 
-       return 0;
 }
 
 jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
@@ -393,20 +1241,26 @@ jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalu
 
 jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallByteMethod");
+       jbyte ret;
+       va_list vaargs;
+
+/*     log_text("JNI-Call: CallVyteMethod");*/
+
+       va_start(vaargs,methodID);
+       ret = callIntegerMethod(obj,get_virtual(obj,methodID),'B',vaargs);
+       va_end(vaargs);
+       return ret;
 
-       return 0;
 }
 
 jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallByteMethodV");
-
-       return 0;
+/*     log_text("JNI-Call: CallByteMethodV");*/
+       return callIntegerMethod(obj,methodID,'B',args);
 }
 
 
-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");
 
@@ -414,22 +1268,29 @@ jbyte CallByteMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *arg
 }
 
 
-jchar CallCharMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallCharMethod");
+       jchar ret;
+       va_list vaargs;
 
-       return 0;
+/*     log_text("JNI-Call: CallCharMethod");*/
+
+       va_start(vaargs,methodID);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'C', vaargs);
+       va_end(vaargs);
+
+       return ret;
 }
 
-jchar CallCharMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
-{
-       log_text("JNI-Call: CallCharMethodV");
 
-       return 0;
+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");
 
@@ -437,23 +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, ...)
 {
-       log_text("JNI-Call: CallShortMethod");
+       jshort ret;
+       va_list vaargs;
 
-       return 0;
+/*     log_text("JNI-Call: CallShortMethod");*/
+
+       va_start(vaargs, methodID);
+       ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'S', vaargs);
+       va_end(vaargs);
+
+       return ret;
 }
 
 
-jshort CallShortMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
+jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallShortMethodV");
-
-       return 0;
+       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");
 
@@ -462,23 +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, ...)
 {
-       log_text("JNI-Call: CallIntMethod");
+       jint ret;
+       va_list vaargs;
 
-       return 0;
+       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)
 {
-       log_text("JNI-Call: CallIntMethodV");
-
-       return 0;
+       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");
 
@@ -487,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");
 
@@ -512,23 +1384,29 @@ 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, ...)
 {
-       log_text("JNI-Call: CallFloatMethod");
+       jfloat ret;
+       va_list vaargs;
 
-       return 0;
+/*     log_text("JNI-Call: CallFloatMethod");*/
+
+       va_start(vaargs,methodID);
+       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 0;
+       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");
 
@@ -537,49 +1415,58 @@ 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, ...)
 {
-       log_text("JNI-Call: CallDoubleMethod");
+       jdouble ret;
+       va_list vaargs;
 
-       return 0;
+/*     log_text("JNI-Call: CallDoubleMethod");*/
+
+       va_start(vaargs,methodID);
+       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 0;
+       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;
 }
 
 
 
-void CallVoidMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...)
+void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallVoidMethod");
+       va_list vaargs;
+
+/*      log_text("JNI-Call: CallVoidMethod");*/
 
+       va_start(vaargs,methodID);
+       (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs);
+       va_end(vaargs);
 }
 
 
 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");
-
 }
 
 
@@ -611,17 +1498,23 @@ jobject CallNonvirtualObjectMethodA (JNIEnv *env, jobject obj, jclass clazz, jme
 
 jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallNonvirtualBooleanMethod");
+       jboolean ret;
+       va_list vaargs;
+
+/*     log_text("JNI-Call: CallNonvirtualBooleanMethod");*/
+
+       va_start(vaargs,methodID);
+       ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',vaargs);
+       va_end(vaargs);
+       return ret;
 
-       return 0;
 }
 
 
 jboolean CallNonvirtualBooleanMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualBooleanMethodV");
-
-       return 0;
+/*     log_text("JNI-Call: CallNonvirtualBooleanMethodV");*/
+       return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',args);
 }
 
 
@@ -636,17 +1529,23 @@ jboolean CallNonvirtualBooleanMethodA (JNIEnv *env, jobject obj, jclass clazz, j
 
 jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallNonvirtualByteMethod");
+       jbyte ret;
+       va_list vaargs;
 
-       return 0;
+/*     log_text("JNI-Call: CallNonvirutalByteMethod");*/
+
+       va_start(vaargs,methodID);
+       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',vaargs);
+       va_end(vaargs);
+       return ret;
 }
 
 
 jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualByteMethodV");
+       /*log_text("JNI-Call: CallNonvirtualByteMethodV"); */
+       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',args);
 
-       return 0;
 }
 
 
@@ -661,17 +1560,22 @@ jbyte CallNonvirtualByteMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethod
 
 jchar CallNonvirtualCharMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallNonvirtualCharMethod");
+       jchar ret;
+       va_list vaargs;
 
-       return 0;
+/*     log_text("JNI-Call: CallNonVirtualCharMethod");*/
+
+       va_start(vaargs,methodID);
+       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',vaargs);
+       va_end(vaargs);
+       return ret;
 }
 
 
 jchar CallNonvirtualCharMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualCharMethodV");
-
-       return 0;
+       /*log_text("JNI-Call: CallNonvirtualCharMethodV");*/
+       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',args);
 }
 
 
@@ -686,17 +1590,22 @@ jchar CallNonvirtualCharMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethod
 
 jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallNonvirtualShortMethod");
+       jshort ret;
+       va_list vaargs;
 
-       return 0;
+       /*log_text("JNI-Call: CallNonvirtualShortMethod");*/
+
+       va_start(vaargs,methodID);
+       ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',vaargs);
+       va_end(vaargs);
+       return ret;
 }
 
 
 jshort CallNonvirtualShortMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualShortMethodV");
-
-       return 0;
+       /*log_text("JNI-Call: CallNonvirtualShortMethodV");*/
+       return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',args);
 }
 
 
@@ -711,17 +1620,23 @@ jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmeth
 
 jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallNonvirtualIntMethod");
 
-       return 0;
+        jint ret;
+        va_list vaargs;
+
+       /*log_text("JNI-Call: CallNonvirtualIntMethod");*/
+
+        va_start(vaargs,methodID);
+        ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',vaargs);
+        va_end(vaargs);
+        return ret;
 }
 
 
 jint CallNonvirtualIntMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualIntMethodV");
-
-       return 0;
+       /*log_text("JNI-Call: CallNonvirtualIntMethodV");*/
+        return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',args);
 }
 
 
@@ -761,17 +1676,24 @@ jlong CallNonvirtualLongMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethod
 
 jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallNonvirtualFloatMethod");
+       jfloat ret;
+       va_list vaargs;
+
+       /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/
+
+
+       va_start(vaargs,methodID);
+       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'F');
+       va_end(vaargs);
+       return ret;
 
-       return 0;
 }
 
 
 jfloat CallNonvirtualFloatMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
        log_text("JNI-Call: CallNonvirtualFloatMethodV");
-
-       return 0;
+       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'F');
 }
 
 
@@ -786,17 +1708,22 @@ jfloat CallNonvirtualFloatMethodA (JNIEnv *env, jobject obj, jclass clazz, jmeth
 
 jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
+       jdouble ret;
+       va_list vaargs;
        log_text("JNI-Call: CallNonvirtualDoubleMethod");
 
-       return 0;
+       va_start(vaargs,methodID);
+       ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'D');
+       va_end(vaargs);
+       return ret;
+
 }
 
 
 jdouble CallNonvirtualDoubleMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualDoubleMethodV");
-
-       return 0;
+/*     log_text("JNI-Call: CallNonvirtualDoubleMethodV");*/
+       return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'D');
 }
 
 
@@ -811,13 +1738,23 @@ jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jme
 
 void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallNonvirtualVoidMethod");
+        va_list vaargs;
+
+/*      log_text("JNI-Call: CallNonvirtualVoidMethod");*/
+
+        va_start(vaargs,methodID);
+        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',vaargs);
+        va_end(vaargs);
+
 }
 
 
 void CallNonvirtualVoidMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallNonvirtualVoidMethodV");
+/*     log_text("JNI-Call: CallNonvirtualVoidMethodV");*/
+
+        (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',args);
+
 }
 
 
@@ -832,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 = env->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;
 }
 
@@ -956,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");
 
@@ -997,23 +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, ...)
 {
-       log_text("JNI-Call: CallStaticBooleanMethod");
+       jboolean ret;
+       va_list vaargs;
 
-       return 0;
+       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)
 {
-       log_text("JNI-Call: CallStaticBooleanMethodV");
-
-       return 0;
+       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");
 
@@ -1021,46 +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, ...)
 {
-       log_text("JNI-Call: CallStaticByteMethod");
+       jbyte ret;
+       va_list vaargs;
 
-       return 0;
+       /*      log_text("JNI-Call: CallStaticByteMethod");*/
+
+       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)
 {
-       log_text("JNI-Call: CallStaticByteMethodV");
-
-       return 0;
+       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, ...)
 {
-       log_text("JNI-Call: CallStaticCharMethod");
+       jchar ret;
+       va_list vaargs;
 
-       return 0;
+       /*      log_text("JNI-Call: CallStaticByteMethod");*/
+
+       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)
 {
-       log_text("JNI-Call: CallStaticCharMethodV");
-
-       return 0;
+       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");
 
@@ -1069,23 +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, ...)
 {
-       log_text("JNI-Call: CallStaticShortMethod");
+       jshort ret;
+       va_list vaargs;
 
-       return 0;
+       /*      log_text("JNI-Call: CallStaticByteMethod");*/
+
+       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 0;
+       /*log_text("JNI-Call: CallStaticShortMethodV");*/
+       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");
 
@@ -1094,23 +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, ...)
 {
-       log_text("JNI-Call: CallStaticIntMethod");
+       jint ret;
+       va_list vaargs;
 
-       return 0;
+       /*      log_text("JNI-Call: CallStaticIntMethod");*/
+
+       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 0;
+       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");
 
@@ -1119,23 +2111,30 @@ 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, ...)
 {
-       log_text("JNI-Call: CallStaticLongMethod");
+       jlong ret;
+       va_list vaargs;
 
-       return 0;
+       /*      log_text("JNI-Call: CallStaticLongMethod");*/
+
+       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");
-
-       return 0;
+       
+       return callLongMethod(0,methodID,args);
 }
 
 
-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");
 
@@ -1144,23 +2143,30 @@ 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, ...)
 {
-       log_text("JNI-Call: CallStaticFloatMethod");
+       jfloat ret;
+       va_list vaargs;
 
-       return 0;
+       /*      log_text("JNI-Call: CallStaticLongMethod");*/
+
+       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)
 {
-       log_text("JNI-Call: CallStaticFloatMethodV");
 
-       return 0;
+       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");
 
@@ -1169,23 +2175,30 @@ jfloat CallStaticFloatMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jv
 
 
 
-jdouble CallStaticDoubleMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallStaticDoubleMethod");
+       jdouble ret;
+       va_list vaargs;
 
-       return 0;
+       /*      log_text("JNI-Call: CallStaticDoubleMethod");*/
+
+       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 0;
+       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");
 
@@ -1193,27 +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, ...)
 {
-       log_text("JNI-Call: CallStaticVoidMethod");
+       va_list vaargs;
+
+/*      log_text("JNI-Call: CallStaticVoidMethod");*/
 
+       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 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) 
@@ -1225,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;
 }
@@ -1381,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)
@@ -1419,21 +2440,30 @@ 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 **********/
 
 jstring NewStringUTF (JNIEnv *env, const char *utf)
 {
-    log_text("NewStringUTF called");
+/*    log_text("NewStringUTF called");*/
+    return (jstring) javastring_new(utf_new_char((char *) utf));
 }
 
 /****************** returns the utf8 length in bytes of a string *******************/
@@ -1445,123 +2475,207 @@ 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)
 {
-    return javastring_toutf((java_lang_String*) string,false)->text;
+    utf *u;
+
+    u = javastring_toutf((java_lang_String *) string, false);
+
+    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));
+       */
 }
 
 /************************** 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_instanceof(val, array->elementtype))
-           exceptionptr = proto_java_lang_ArrayStoreException;
-       else
-           array->data[index] = val;
+               else
+                       array->data[index] = val;
     }
 }
 
 
 
-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;
 }
 
@@ -1670,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");
@@ -1844,12 +2979,16 @@ jint MonitorExit (JNIEnv* env, jobject obj)
 
 
 /************************************* JavaVM interface ****************************/
-
+#ifdef __cplusplus
+#error CPP mode not supported yet
+#else
 jint GetJavaVM (JNIEnv* env, JavaVM **vm)
 {
     log_text("JNI-Call: GetJavaVM");
+    *vm=&javaVM;
     return 0;
 }
+#endif /*__cplusplus*/
 
 void GetStringRegion (JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
 {
@@ -1863,26 +3002,16 @@ 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)
 {
-       java_arrayheader *s = (java_arrayheader*) array;
-
-       switch (s->arraytype) {
-               case ARRAYTYPE_BYTE:    return (((java_bytearray*)    array)->data);
-               case ARRAYTYPE_BOOLEAN: return (((java_booleanarray*) array)->data);
-               case ARRAYTYPE_CHAR:    return (((java_chararray*)    array)->data);
-               case ARRAYTYPE_SHORT:   return (((java_shortarray*)   array)->data);
-               case ARRAYTYPE_INT:     return (((java_intarray*)     array)->data);
-               case ARRAYTYPE_LONG:    return (((java_longarray*)    array)->data);
-               case ARRAYTYPE_FLOAT:   return (((java_floatarray*)   array)->data);
-               case ARRAYTYPE_DOUBLE:  return (((java_doublearray*)  array)->data);
-               case ARRAYTYPE_OBJECT:  return (((java_objectarray*)  array)->data); 
-               case ARRAYTYPE_ARRAY:   return (((java_arrayarray*)   array)->data);
-       }
+       java_objectheader *s = (java_objectheader*) array;
+       arraydescriptor *desc = s->vftbl->arraydesc;
 
-       return NULL;
+       if (!desc) return NULL;
+
+       return ((u1*)s) + desc->dataoffset;
 }
 
 
@@ -1893,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)
 {
@@ -1902,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)
 {
@@ -1931,17 +3060,77 @@ 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;
+}
+
+
+
+
+
+
+jint DestroyJavaVM(JavaVM *vm)
+{
+       log_text("DestroyJavaVM called");
+
+       return 0;
+}
+
+
+jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2)
+{
+       log_text("AttachCurrentThread called");
+
+       return 0;
+}
+
+
+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 ******************************/
+
+struct _JavaVM javaVMTable={
+   NULL,
+   NULL,
+   NULL,
+   &DestroyJavaVM,
+   &AttachCurrentThread,
+   &DetachCurrentThread,
+   &GetEnv,
+   &AttachCurrentThreadAsDaemon
+};
+
+JavaVM javaVM = &javaVMTable;
+
+
 /********************************* JNI function table ******************************/
 
-JNIEnv env =     
-   {   
+struct JNI_Table envTable = {   
     NULL,
     NULL,
     NULL,
@@ -2171,7 +3360,235 @@ JNIEnv env =
     &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);
+
+       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;
+}
+
 
 /*
  * These are local overrides for various environment variables in Emacs.