Merged revisions 7766-7796 via svnmerge from
[cacao.git] / src / native / jni.c
index bce898f4bc3f5bd0bbd0e79ecb40d082117d8291..a011a0f0fe38b729ba56b189f2ebd184a4a47fab 100644 (file)
@@ -1,6 +1,6 @@
 /* src/native/jni.c - implementation of the Java Native Interface functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Rainhard Grafl
-            Roman Obermaisser
-
-   Changes: Joseph Wenninger
-            Martin Platter
-            Christian Thalinger
-                       Edwin Steiner
-
-   $Id: jni.c 5698 2006-10-05 17:28:13Z twisti $
+   $Id: jni.c 7723 2007-04-16 18:03:08Z michi $
 
 */
 
 
 #include "vm/types.h"
 
-#include "mm/boehm.h"
+#include "mm/gc-common.h"
 #include "mm/memory.h"
 #include "native/jni.h"
 #include "native/native.h"
 
-#include "native/include/gnu_classpath_Pointer.h"
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_GNU)
+#  include "native/include/gnu_classpath_Pointer.h"
 
-#if SIZEOF_VOID_P == 8
-# include "native/include/gnu_classpath_Pointer64.h"
-#else
-# include "native/include/gnu_classpath_Pointer32.h"
+#  if SIZEOF_VOID_P == 8
+#   include "native/include/gnu_classpath_Pointer64.h"
+#  else
+#   include "native/include/gnu_classpath_Pointer32.h"
+#  endif
+# endif
 #endif
 
 #include "native/include/java_lang_Object.h"
 #include "native/include/java_lang_Long.h"
 #include "native/include/java_lang_Float.h"
 #include "native/include/java_lang_Double.h"
+#include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
-#include "native/include/java_lang_reflect_Method.h"
-#include "native/include/java_lang_reflect_Constructor.h"
-#include "native/include/java_lang_reflect_Field.h"
 
-#include "native/include/java_lang_Class.h" /* for java_lang_VMClass.h */
-#include "native/include/java_lang_VMClass.h"
-#include "native/include/java_lang_VMClassLoader.h"
-#include "native/include/java_nio_Buffer.h"
-#include "native/include/java_nio_DirectByteBufferImpl.h"
+#if defined(ENABLE_JAVASE)
+# include "native/include/java_lang_ClassLoader.h"
+
+# include "native/include/java_lang_reflect_Constructor.h"
+# include "native/include/java_lang_reflect_Field.h"
+# include "native/include/java_lang_reflect_Method.h"
+
+# include "native/include/java_nio_Buffer.h"
+# include "native/include/java_nio_DirectByteBufferImpl.h"
+#endif
 
 #if defined(ENABLE_JVMTI)
 # include "native/jvmti/cacaodbg.h"
 #endif
 
+#include "native/vm/java_lang_Class.h"
+
+#if defined(ENABLE_JAVASE)
+# include "native/vm/java_lang_ClassLoader.h"
+#endif
+
 #if defined(ENABLE_THREADS)
 # include "threads/native/lock.h"
 # include "threads/native/threads.h"
 #else
 # include "threads/none/lock.h"
+# include "threads/none/threads.h"
 #endif
 
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/initialize.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/resolve.h"
-#include "vm/statistics.h"
 #include "vm/stringlocal.h"
+#include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
-#include "vm/statistics.h"
-#include "vm/vm.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vm/resolve.h"
+#include "vmcore/statistics.h"
 
 
 /* global variables ***********************************************************/
 
 #define HASHTABLE_GLOBAL_REF_SIZE    64 /* initial size of globalref-hash     */
 
-static hashtable *hashtable_global_ref; /* hashtable for globalrefs           */
+hashtable *hashtable_global_ref;        /* hashtable for globalrefs           */
 
 
 /* direct buffer stuff ********************************************************/
 
+#if defined(ENABLE_JAVASE)
 static classinfo *class_java_nio_Buffer;
 static classinfo *class_java_nio_DirectByteBufferImpl;
 static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
-#if SIZEOF_VOID_P == 8
+
+# if defined(WITH_CLASSPATH_GNU)
+#  if SIZEOF_VOID_P == 8
 static classinfo *class_gnu_classpath_Pointer64;
-#else
+#  else
 static classinfo *class_gnu_classpath_Pointer32;
-#endif
+#  endif
+# endif
 
 static methodinfo *dbbirw_init;
+#endif
 
 
 /* local reference table ******************************************************/
@@ -166,6 +178,7 @@ bool jni_init(void)
        hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
 
 
+#if defined(ENABLE_JAVASE)
        /* direct buffer stuff */
 
        if (!(class_java_nio_Buffer =
@@ -189,17 +202,20 @@ bool jni_init(void)
                                                        utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
                return false;
 
-#if SIZEOF_VOID_P == 8
+# if defined(WITH_CLASSPATH_GNU)
+#  if SIZEOF_VOID_P == 8
        if (!(class_gnu_classpath_Pointer64 =
                  load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
                !link_class(class_gnu_classpath_Pointer64))
                return false;
-#else
+#  else
        if (!(class_gnu_classpath_Pointer32 =
                  load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
                !link_class(class_gnu_classpath_Pointer32))
                return false;
-#endif
+#  endif
+# endif
+#endif /* defined(ENABLE_JAVASE) */
 
        return true;
 }
@@ -211,11 +227,17 @@ bool jni_init(void)
 
 *******************************************************************************/
 
-static bool jni_init_localref_table(void)
+bool jni_init_localref_table(void)
 {
        localref_table *lrt;
 
+#if defined(ENABLE_GC_CACAO)
+       /* XXX this one will never get freed for the main thread;
+          call jni_free_localref_table() if you want to do it! */
+       lrt = NEW(localref_table);
+#else
        lrt = GCNEW(localref_table);
+#endif
 
        if (lrt == NULL)
                return false;
@@ -235,6 +257,31 @@ static bool jni_init_localref_table(void)
 }
 
 
+/* jni_init_localref_table *****************************************************
+
+   Frees the local references table of the current thread.
+
+*******************************************************************************/
+
+bool jni_free_localref_table(void)
+{
+       localref_table *lrt;
+
+#if defined(ENABLE_GC_CACAO)
+       lrt = LOCALREFTABLE;
+
+       assert(lrt);
+       assert(lrt->prev == NULL);
+
+       FREE(lrt, localref_table);
+
+       LOCALREFTABLE = NULL;
+#endif
+
+       return true;
+}
+
+
 /* _Jv_jni_vmargs_from_objectarray *********************************************
 
    XXX
@@ -824,8 +871,9 @@ java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
        java_objectheader *ro;
        s4                 argcount;
        s4                 paramcount;
+       java_objectheader *xptr;
 
-       if (!m) {
+       if (m == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
@@ -843,9 +891,7 @@ java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
           parameter is ignored. */
 
        if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_IllegalArgumentException,
-                                                                 "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
+               exceptions_throw_illegalargumentexception();
                return NULL;
        }
 
@@ -854,17 +900,15 @@ java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
        if (((params == NULL) && (paramcount != 0)) ||
                (params && (params->header.size != paramcount))) 
        {
-               *exceptionptr =
-                       new_exception(string_java_lang_IllegalArgumentException);
+               exceptions_throw_illegalargumentexception();
                return NULL;
        }
 
        /* for instance methods we need an object */
 
        if (!(m->flags & ACC_STATIC) && (o == NULL)) {
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NullPointerException,
-                                                                 "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
+               /* XXX not sure if that is the correct exception */
+               exceptions_throw_nullpointerexception();
                return NULL;
        }
 
@@ -875,16 +919,18 @@ java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
        if (o != NULL) {
                /* for instance methods we must do a vftbl lookup */
                resm = method_vftbl_lookup(o->vftbl, m);
-
-       else {
+       }
+       else {
                /* for static methods, just for convenience */
                resm = m;
        }
 
        vmargs = MNEW(vm_arg, argcount);
 
-       if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params))
+       if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params)) {
+               MFREE(vmargs, vm_arg, argcount);
                return NULL;
+       }
 
        switch (resm->parseddesc->returntype.decltype) {
        case TYPE_VOID:
@@ -1028,18 +1074,14 @@ java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
 
        MFREE(vmargs, vm_arg, argcount);
 
-       if (*exceptionptr) {
-               java_objectheader *cause;
-
-               cause = *exceptionptr;
+       xptr = exceptions_get_exception();
 
+       if (xptr != NULL) {
                /* clear exception pointer, we are calling JIT code again */
 
-               *exceptionptr = NULL;
+               exceptions_clear_exception();
 
-               *exceptionptr =
-                       new_exception_throwable(string_java_lang_reflect_InvocationTargetException,
-                                                                       (java_lang_Throwable *) cause);
+               exceptions_throw_invocationtargetexception(xptr);
        }
 
        return ro;
@@ -1076,6 +1118,7 @@ jint _Jv_JNI_GetVersion(JNIEnv *env)
 jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
                                                   const jbyte *buf, jsize bufLen)
 {
+#if defined(ENABLE_JAVASE)
        java_lang_ClassLoader *cl;
        java_lang_String      *s;
        java_bytearray        *ba;
@@ -1084,13 +1127,20 @@ jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
        STATISTICS(jniinvokation());
 
        cl = (java_lang_ClassLoader *) loader;
-       s  = javastring_new_from_utf_string(name);
+       s  = (java_lang_String *) javastring_new_from_utf_string(name);
        ba = (java_bytearray *) buf;
 
-       c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
-                                                                                                                 0, bufLen, NULL);
+       c = (jclass) _Jv_java_lang_ClassLoader_defineClass(cl, s, ba, 0, bufLen,
+                                                                                                          NULL);
 
        return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
+#else
+       vm_abort("_Jv_JNI_DefineClass: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return 0;
+#endif
 }
 
 
@@ -1104,6 +1154,7 @@ jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
 
 jclass _Jv_JNI_FindClass(JNIEnv *env, const char *name)
 {
+#if defined(ENABLE_JAVASE)
        utf       *u;
        classinfo *cc;
        classinfo *c;
@@ -1140,6 +1191,13 @@ jclass _Jv_JNI_FindClass(JNIEnv *env, const char *name)
                return NULL;
 
        return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
+#else
+       vm_abort("_Jv_JNI_FindClass: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
 }
   
 
@@ -1174,12 +1232,15 @@ jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
 
 jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
 {
+       java_lang_Class *csup;
+       java_lang_Class *csub;
+
+       csup = (java_lang_Class *) sup;
+       csub = (java_lang_Class *) sub;
+
        STATISTICS(jniinvokation());
 
-       return Java_java_lang_VMClass_isAssignableFrom(env,
-                                                                                                  NULL,
-                                                                                                  (java_lang_Class *) sup,
-                                                                                                  (java_lang_Class *) sub);
+       return _Jv_java_lang_Class_isAssignableFrom(csup, csub);
 }
 
 
@@ -1191,9 +1252,13 @@ jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
 
 jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
 {
+       java_objectheader *o;
+
        STATISTICS(jniinvokation());
 
-       *exceptionptr = (java_objectheader *) obj;
+       o = (java_objectheader *) obj;
+
+       exceptions_set_exception(o);
 
        return JNI_OK;
 }
@@ -1209,23 +1274,23 @@ jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
 
 jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
 {
-       classinfo           *c;
-       java_lang_Throwable *o;
-       java_lang_String    *s;
+       classinfo         *c;
+       java_objectheader *o;
+       java_objectheader *s;
 
        STATISTICS(jniinvokation());
 
        c = (classinfo *) clazz;
-       s = (java_lang_String *) javastring_new_from_utf_string(msg);
+       s = javastring_new_from_utf_string(msg);
 
        /* instantiate exception object */
 
-       o = (java_lang_Throwable *) native_new_and_init_string(c, s);
+       o = native_new_and_init_string(c, s);
 
        if (o == NULL)
                return -1;
 
-       *exceptionptr = (java_objectheader *) o;
+       exceptions_set_exception(o);
 
        return 0;
 }
@@ -1241,13 +1306,13 @@ jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
 
 jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
 {
-       java_objectheader *e;
+       java_objectheader *o;
 
        STATISTICS(jniinvokation());
 
-       e = *exceptionptr;
+       o = exceptions_get_exception();
 
-       return _Jv_JNI_NewLocalRef(env, (jthrowable) e);
+       return _Jv_JNI_NewLocalRef(env, (jthrowable) o);
 }
 
 
@@ -1261,33 +1326,33 @@ jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
 
 void _Jv_JNI_ExceptionDescribe(JNIEnv *env)
 {
-       java_objectheader *e;
+       java_objectheader *o;
        methodinfo        *m;
 
        STATISTICS(jniinvokation());
 
-       e = *exceptionptr;
+       o = exceptions_get_exception();
 
-       if (e) {
+       if (o == NULL) {
                /* clear exception, because we are calling jit code again */
 
-               *exceptionptr = NULL;
+               exceptions_clear_exception();
 
                /* get printStackTrace method from exception class */
 
-               m = class_resolveclassmethod(e->vftbl->class,
+               m = class_resolveclassmethod(o->vftbl->class,
                                                                         utf_printStackTrace,
                                                                         utf_void__void,
                                                                         NULL,
                                                                         true);
 
-               if (!m)
+               if (m == NULL)
                        /* XXX what should we do? */
                        return;
 
                /* print the stacktrace */
 
-               (void) vm_call_method(m, e);
+               (void) vm_call_method(m, o);
        }
 }
 
@@ -1303,7 +1368,7 @@ void _Jv_JNI_ExceptionClear(JNIEnv *env)
 {
        STATISTICS(jniinvokation());
 
-       *exceptionptr = NULL;
+       exceptions_clear_exception();
 }
 
 
@@ -1318,7 +1383,9 @@ void _Jv_JNI_FatalError(JNIEnv *env, const char *msg)
 {
        STATISTICS(jniinvokation());
 
-       throw_cacao_exception_exit(string_java_lang_InternalError, msg);
+       /* this seems to be the best way */
+
+       vm_abort(msg);
 }
 
 
@@ -1348,7 +1415,11 @@ jint _Jv_JNI_PushLocalFrame(JNIEnv* env, jint capacity)
        else
                additionalrefs = 0;
 
+#if defined(ENABLE_GC_CACAO)
+       nlrt = MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#else
        nlrt = GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#endif
 
        if (nlrt == NULL)
                return -1;
@@ -1386,6 +1457,7 @@ jobject _Jv_JNI_PopLocalFrame(JNIEnv* env, jobject result)
        localref_table *lrt;
        localref_table *plrt;
        s4              localframes;
+       s4              additionalrefs;
 
        STATISTICS(jniinvokation());
 
@@ -1415,6 +1487,18 @@ jobject _Jv_JNI_PopLocalFrame(JNIEnv* env, jobject result)
 
                lrt->prev = NULL;
 
+#if defined(ENABLE_GC_CACAO)
+               /* for the exact GC local reference tables are not on the heap,
+                  so we need to free them explicitly here. */
+
+               if (lrt->capacity > LOCALREFTABLE_CAPACITY)
+                       additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
+               else
+                       additionalrefs = 0;
+
+               MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#endif
+
                /* set new local references table */
 
                lrt = plrt;
@@ -1556,8 +1640,6 @@ jint _Jv_JNI_EnsureLocalCapacity(JNIEnv* env, jint capacity)
 {
        localref_table *lrt;
 
-       log_text("JNI-Call: EnsureLocalCapacity");
-
        STATISTICS(jniinvokation());
 
        /* get local reference table (thread specific) */
@@ -1590,9 +1672,7 @@ jobject _Jv_JNI_AllocObject(JNIEnv *env, jclass clazz)
        c = (classinfo *) clazz;
 
        if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_InstantiationException,
-                                                                        c->name);
+               exceptions_throw_instantiationexception(c);
                return NULL;
        }
                
@@ -1740,12 +1820,15 @@ jclass _Jv_JNI_GetObjectClass(JNIEnv *env, jobject obj)
 
 jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
 {
+       java_lang_Class  *c;
+       java_lang_Object *o;
+
        STATISTICS(jniinvokation());
 
-       return Java_java_lang_VMClass_isInstance(env,
-                                                                                        NULL,
-                                                                                        (java_lang_Class *) clazz,
-                                                                                        (java_lang_Object *) obj);
+       c = (java_lang_Class *) clazz;
+       o = (java_lang_Object *) obj;
+
+       return _Jv_java_lang_Class_isInstance(c, o);
 }
 
 
@@ -1760,6 +1843,7 @@ jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
   
 jmethodID _Jv_JNI_FromReflectedMethod(JNIEnv *env, jobject method)
 {
+#if defined(ENABLE_JAVASE)
        methodinfo *mi;
        classinfo  *c;
        s4          slot;
@@ -1789,6 +1873,13 @@ jmethodID _Jv_JNI_FromReflectedMethod(JNIEnv *env, jobject method)
        mi = &(c->methods[slot]);
 
        return (jmethodID) mi;
+#else
+       vm_abort("_Jv_JNI_FromReflectedMethod: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
 }
 
 
@@ -1800,6 +1891,7 @@ jmethodID _Jv_JNI_FromReflectedMethod(JNIEnv *env, jobject method)
  
 jfieldID _Jv_JNI_FromReflectedField(JNIEnv* env, jobject field)
 {
+#if defined(ENABLE_JAVASE)
        java_lang_reflect_Field *rf;
        classinfo               *c;
        fieldinfo               *f;
@@ -1816,6 +1908,13 @@ jfieldID _Jv_JNI_FromReflectedField(JNIEnv* env, jobject field)
        f = &(c->fields[rf->slot]);
 
        return (jfieldID) f;
+#else
+       vm_abort("_Jv_JNI_FromReflectedField: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
 }
 
 
@@ -2876,19 +2975,22 @@ void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
 jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
                                                        const char *sig) 
 {
+       classinfo *c;
        fieldinfo *f;
        utf       *uname;
        utf       *udesc;
 
        STATISTICS(jniinvokation());
 
+       c = (classinfo *) clazz;
+
        uname = utf_new_char((char *) name);
        udesc = utf_new_char((char *) sig);
 
        f = class_findfield(clazz, uname, udesc); 
        
-       if (!f)
-               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
+       if (f == NULL)
+               exceptions_throw_nosuchfielderror(c, uname);  
 
        return (jfieldID) f;
 }
@@ -3567,19 +3669,22 @@ void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
 jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
                                                                  const char *sig)
 {
+       classinfo *c;
        fieldinfo *f;
        utf       *uname;
        utf       *usig;
 
        STATISTICS(jniinvokation());
 
+       c = (classinfo *) clazz;
+
        uname = utf_new_char((char *) name);
        usig  = utf_new_char((char *) sig);
 
        f = class_findfield(clazz, uname, usig);
        
        if (f == NULL)
-               *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);
+               exceptions_throw_nosuchfielderror(c, uname);
 
        return (jfieldID) f;
 }
@@ -4027,7 +4132,7 @@ u2 *javastring_tou2(jstring so)
 /* GetStringChars **************************************************************
 
    Returns a pointer to the array of Unicode characters of the
-   string. This pointer is valid until ReleaseStringchars() is called.
+   string. This pointer is valid until ReleaseStringChars() is called.
 
 *******************************************************************************/
 
@@ -4074,7 +4179,8 @@ void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
 
 /* NewStringUTF ****************************************************************
 
-   Constructs a new java.lang.String object from an array of UTF-8 characters.
+   Constructs a new java.lang.String object from an array of UTF-8
+   characters.
 
 *******************************************************************************/
 
@@ -4084,7 +4190,7 @@ jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
 
        STATISTICS(jniinvokation());
 
-       s = javastring_new(utf_new_char(bytes));
+       s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
 
     return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
 }
@@ -4123,7 +4229,7 @@ const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
        if (isCopy)
                *isCopy = JNI_TRUE;
        
-       u = javastring_toutf((java_lang_String *) string, false);
+       u = javastring_toutf((java_objectheader *) string, false);
 
        if (u != NULL)
                return u->text;
@@ -4244,11 +4350,8 @@ void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
        /* check if the class of value is a subclass of the element class
           of the array */
 
-       if (!builtin_canstore(oa, o)) {
-               *exceptionptr = new_exception(string_java_lang_ArrayStoreException);
-
+       if (!builtin_canstore(oa, o))
                return;
-       }
 
        oa->data[index] = val;
 }
@@ -5394,9 +5497,13 @@ void _Jv_JNI_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 
 jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
 {
+       java_objectheader *o;
+
        STATISTICS(jniinvokation());
 
-       return *exceptionptr ? JNI_TRUE : JNI_FALSE;
+       o = exceptions_get_exception();
+
+       return (o != NULL) ? JNI_TRUE : JNI_FALSE;
 }
 
 
@@ -5412,24 +5519,25 @@ jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
 
 jobject _Jv_JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 {
+#if defined(ENABLE_JAVASE)
        java_objectheader       *nbuf;
-#if SIZEOF_VOID_P == 8
+# if SIZEOF_VOID_P == 8
        gnu_classpath_Pointer64 *paddress;
-#else
+# else
        gnu_classpath_Pointer32 *paddress;
-#endif
+# endif
 
        STATISTICS(jniinvokation());
 
        /* alocate a gnu.classpath.Pointer{32,64} object */
 
-#if SIZEOF_VOID_P == 8
+# if SIZEOF_VOID_P == 8
        if (!(paddress = (gnu_classpath_Pointer64 *)
                  builtin_new(class_gnu_classpath_Pointer64)))
-#else
+# else
        if (!(paddress = (gnu_classpath_Pointer32 *)
                  builtin_new(class_gnu_classpath_Pointer32)))
-#endif
+# endif
                return NULL;
 
        /* fill gnu.classpath.Pointer{32,64} with address */
@@ -5445,6 +5553,13 @@ jobject _Jv_JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
        /* add local reference and return the value */
 
        return _Jv_JNI_NewLocalRef(env, nbuf);
+#else
+       vm_abort("_Jv_JNI_NewDirectByteBuffer: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
 }
 
 
@@ -5457,12 +5572,13 @@ jobject _Jv_JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 
 void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
 {
+#if defined(ENABLE_JAVASE)
        java_nio_DirectByteBufferImpl *nbuf;
-#if SIZEOF_VOID_P == 8
+# if SIZEOF_VOID_P == 8
        gnu_classpath_Pointer64       *address;
-#else
+# else
        gnu_classpath_Pointer32       *address;
-#endif
+# endif
 
        STATISTICS(jniinvokation());
 
@@ -5471,16 +5587,23 @@ void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
 
        nbuf = (java_nio_DirectByteBufferImpl *) buf;
 
-#if SIZEOF_VOID_P == 8
+# if SIZEOF_VOID_P == 8
        address = (gnu_classpath_Pointer64 *) nbuf->address;
-#else
+# else
        address = (gnu_classpath_Pointer32 *) nbuf->address;
-#endif
+# endif
 
        if (address == NULL)
                return NULL;
 
        return (void *) address->data;
+#else
+       vm_abort("_Jv_JNI_GetDirectBufferAddress: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return NULL;
+#endif
 }
 
 
@@ -5493,6 +5616,7 @@ void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
 
 jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
 {
+#if defined(ENABLE_JAVASE)
        java_nio_Buffer *nbuf;
 
        STATISTICS(jniinvokation());
@@ -5503,6 +5627,13 @@ jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
        nbuf = (java_nio_Buffer *) buf;
 
        return (jlong) nbuf->cap;
+#else
+       vm_abort("_Jv_JNI_GetDirectBufferCapacity: not implemented in this configuration");
+
+       /* keep compiler happy */
+
+       return 0;
+#endif
 }
 
 
@@ -5595,6 +5726,7 @@ jint _Jv_JNI_AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args)
 
 jint _Jv_JNI_DetachCurrentThread(JavaVM *vm)
 {
+#if defined(ENABLE_THREADS)
        threadobject *thread;
 
        STATISTICS(jniinvokation());
@@ -5604,8 +5736,12 @@ jint _Jv_JNI_DetachCurrentThread(JavaVM *vm)
        if (thread == NULL)
                return JNI_ERR;
 
+       if (!jni_free_localref_table())
+               return JNI_ERR;
+
        if (!threads_detach_thread(thread))
                return JNI_ERR;
+#endif
 
        return JNI_OK;
 }
@@ -6033,57 +6169,12 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 
 jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
 {
-       JavaVMInitArgs *_vm_args;
-       _Jv_JNIEnv     *env;
-       _Jv_JavaVM     *vm;
-
-       /* get the arguments for the new JVM */
-
-       _vm_args = (JavaVMInitArgs *) vm_args;
-
-       /* get the VM and Env tables (must be set before vm_create) */
-
-       env = NEW(_Jv_JNIEnv);
-       env->env = &_Jv_JNINativeInterface;
-
-       /* XXX Set the global variable.  Maybe we should do that differently. */
-
-       _Jv_env = env;
-
-       /* create and fill a JavaVM structure */
-
-       vm = NEW(_Jv_JavaVM);
-       vm->functions = &_Jv_JNIInvokeInterface;
-
-       /* XXX Set the global variable.  Maybe we should do that differently. */
-       /* XXX JVMTI Agents needs a JavaVM  */
-
-       _Jv_jvm = vm;
-
        /* actually create the JVM */
 
-       if (!vm_create(_vm_args))
-               goto error;
-
-       /* setup the local ref table (must be created after vm_create) */
-
-       if (!jni_init_localref_table())
-               goto error;
-
-       /* now return the values */
-
-       *p_vm  = (JavaVM *) vm;
-       *p_env = (void *) env;
+       if (!vm_createjvm(p_vm, p_env, vm_args))
+               return JNI_ERR;
 
        return JNI_OK;
-
- error:
-       /* release allocated memory */
-
-       FREE(env, _Jv_JNIEnv);
-       FREE(vm, _Jv_JavaVM);
-
-       return JNI_ERR;
 }