* src/native/jni.cpp: [OPENJDK] Implemented jni_GetDirectBufferCapacity.
[cacao.git] / src / native / jni.cpp
index fa529f5263eaef9a9e5c79bba39f08934a9cdf91..661780662a239c07a46fd157f4ccce0377900621 100644 (file)
@@ -1,6 +1,6 @@
 /* src/native/jni.cpp - implementation of the Java Native Interface functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "vm/types.h"
 
 #include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
-#include "native/jni.h"
+#include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-#  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"
-#  endif
-# endif
-#endif
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Throwable.h"
-
-#if defined(ENABLE_JAVASE)
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-#  include "native/include/java_nio_ByteBuffer.h"       /* required by j.l.CL */
-# endif
-
-/* java_lang_ClassLoader is used in java_lang_Class and vice versa, so
-   we pre-define it here to prevent a compiler warning for Sun
-   configurations. */
-
-struct java_lang_ClassLoader;
-
-# include "native/include/java_lang_Class.h"
-# 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"
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-#  include "native/include/java_lang_reflect_VMConstructor.h"
-#  include "native/include/java_lang_reflect_VMField.h"
-#  include "native/include/java_lang_reflect_VMMethod.h"
-
-#  include "native/include/java_nio_DirectByteBufferImpl.h"
-# endif
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-# include "native/include/java_lang_Class.h"
-#endif
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
 #if defined(ENABLE_JVMTI)
 # include "native/jvmti/cacaodbg.h"
 #endif
 
-#if defined(ENABLE_JAVASE)
-# include "native/vm/reflect.h"
-#endif
-
-#include "threads/lock-common.h"
-#include "threads/thread.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
 
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
 
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/initialize.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.hpp"
+#include "vm/options.h"
 #include "vm/primitive.hpp"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
+#include "vm/resolve.hpp"
+#include "vm/statistics.h"
+#include "vm/string.hpp"
 #include "vm/vm.hpp"
 
-#include "vm/jit/argument.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/stacktrace.hpp"
 
 
 /* debug **********************************************************************/
@@ -844,9 +793,7 @@ jint _Jv_JNI_GetVersion(JNIEnv *env)
 {
        TRACEJNICALLS(("_Jv_JNI_GetVersion(env=%p)", env));
 
-       /* We support JNI 1.6. */
-
-       return JNI_VERSION_1_6;
+       return JNI_VERSION_SUPPORTED;
 }
 
 
@@ -860,29 +807,28 @@ jint _Jv_JNI_GetVersion(JNIEnv *env)
 
 *******************************************************************************/
 
-jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
-                                                  const jbyte *buf, jsize bufLen)
+jclass jni_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen)
 {
 #if defined(ENABLE_JAVASE)
-       utf             *u;
-       classloader_t   *cl;
-       classinfo       *c;
-       java_lang_Class *co;
+       utf           *u;
+       classloader_t *cl;
+       classinfo     *c;
+       java_handle_t* h;
 
-       TRACEJNICALLS(("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen));
+       TRACEJNICALLS(("jni_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen));
 
        u  = utf_new_char(name);
        cl = loader_hashtable_classloader_add((java_handle_t *) loader);
 
        c = class_define(u, cl, bufLen, (uint8_t *) buf, NULL);
 
-       co = LLNI_classinfo_wrap(c);
+       h = LLNI_classinfo_wrap(c);
 
-       return (jclass) jni_NewLocalRef(env, (jobject) co);
+       return (jclass) jni_NewLocalRef(env, (jobject) h);
 #else
-       vm_abort("_Jv_JNI_DefineClass: not implemented in this configuration");
+       vm_abort("jni_DefineClass: Not implemented in this configuration");
 
-       /* keep compiler happy */
+       // Keep compiler happy.
 
        return 0;
 #endif
@@ -901,10 +847,10 @@ jclass jni_FindClass(JNIEnv *env, const char *name)
 {
 #if defined(ENABLE_JAVASE)
 
-       utf             *u;
-       classinfo       *cc;
-       classinfo       *c;
-       java_lang_Class *co;
+       utf*       u;    
+       classinfocc;
+       classinfoc;
+       java_handle_t* h;
 
        TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
 
@@ -946,9 +892,9 @@ jclass jni_FindClass(JNIEnv *env, const char *name)
        if (!link_class(c))
                return NULL;
 
-       co = LLNI_classinfo_wrap(c);
+       h = LLNI_classinfo_wrap(c);
 
-       return (jclass) jni_NewLocalRef(env, (jobject) co);
+       return (jclass) jni_NewLocalRef(env, (jobject) h);
 
 #elif defined(ENABLE_JAVAME_CLDC1_1)
 
@@ -988,13 +934,12 @@ jclass jni_FindClass(JNIEnv *env, const char *name)
 
 *******************************************************************************/
  
-jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
+jclass jni_GetSuperclass(JNIEnv *env, jclass sub)
 {
-       classinfo       *c;
-       classinfo       *super;
-       java_lang_Class *co;
+       classinfo* c;
+       classinfo* super;
 
-       TRACEJNICALLS(("_Jv_JNI_GetSuperclass(env=%p, sub=%p)", env, sub));
+       TRACEJNICALLS(("jni_GetSuperclass(env=%p, sub=%p)", env, sub));
 
        c = LLNI_classinfo_unwrap(sub);
 
@@ -1003,9 +948,9 @@ jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
 
        super = class_get_superclass(c);
 
-       co = LLNI_classinfo_wrap(super);
+       java_handle_t* h = LLNI_classinfo_wrap(super);
 
-       return (jclass) jni_NewLocalRef(env, (jobject) co);
+       return (jclass) jni_NewLocalRef(env, (jobject) h);
 }
   
  
@@ -1448,13 +1393,12 @@ jobject _Jv_JNI_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
 
 *******************************************************************************/
 
-jclass _Jv_JNI_GetObjectClass(JNIEnv *env, jobject obj)
+jclass jni_GetObjectClass(JNIEnv *env, jobject obj)
 {
-       java_handle_t   *o;
-       classinfo       *c;
-       java_lang_Class *co;
+       java_handle_t* o;
+       classinfo*     c;
 
-       STATISTICS(jniinvokation());
+       TRACEJNICALLS(("jni_GetObjectClass(env=%p, obj=%p)", env, obj));
 
        o = (java_handle_t *) obj;
 
@@ -1463,9 +1407,9 @@ jclass _Jv_JNI_GetObjectClass(JNIEnv *env, jobject obj)
 
        LLNI_class_get(o, c);
 
-       co = LLNI_classinfo_wrap(c);
+       java_handle_t* h = LLNI_classinfo_wrap(c);
 
-       return (jclass) jni_NewLocalRef(env, (jobject) co);
+       return (jclass) jni_NewLocalRef(env, (jobject) h);
 }
 
 
@@ -1502,72 +1446,31 @@ jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
 jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
 {
 #if defined(ENABLE_JAVASE)
-       java_handle_t                   *o;
-       java_lang_reflect_Method        *rm;
-       java_lang_reflect_Constructor   *rc;
-       classinfo                       *c;
-       methodinfo                      *m;
-       int32_t                          slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       java_lang_reflect_VMMethod      *rvmm;
-       java_lang_reflect_VMConstructor *rvmc;
-#endif
+       methodinfo*    m;
 
        TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
 
-       o = (java_handle_t *) method;
+       java_lang_Object o(method);
 
-       if (o == NULL)
+       if (o.is_null())
                return NULL;
 
-       if (o->vftbl->clazz == class_java_lang_reflect_Constructor) {
-               rc = (java_lang_reflect_Constructor *) method;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-               LLNI_field_get_ref(rc,   cons , rvmc);
-               LLNI_field_get_cls(rvmc, clazz, c);
-               LLNI_field_get_val(rvmc, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-               LLNI_field_get_cls(rc, clazz, c);
-               LLNI_field_get_val(rc, slot , slot);
-
-#else
-# error unknown configuration
-#endif
+       if (o.get_Class() == class_java_lang_reflect_Constructor) {
+               java_lang_reflect_Constructor rc(method);
+               m = rc.get_method();
        }
        else {
-               assert(o->vftbl->clazz == class_java_lang_reflect_Method);
-
-               rm = (java_lang_reflect_Method *) method;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-               LLNI_field_get_ref(rm,   m ,    rvmm);
-               LLNI_field_get_cls(rvmm, clazz, c);
-               LLNI_field_get_val(rvmm, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-               LLNI_field_get_cls(rm, clazz, c);
-               LLNI_field_get_val(rm, slot , slot);
+               assert(o.get_Class() == class_java_lang_reflect_Method);
 
-#else
-# error unknown configuration
-#endif
+               java_lang_reflect_Method rm(method);
+               m = rm.get_method();
        }
 
-       m = &(c->methods[slot]);
-
        return (jmethodID) m;
 #else
        vm_abort("jni_FromReflectedMethod: Not implemented in this configuration.");
 
-       /* Keep compiler happy. */
-
+       // Keep compiler happy.
        return NULL;
 #endif
 }
@@ -1582,45 +1485,21 @@ jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
 jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
 {
 #if defined(ENABLE_JAVASE)
-       java_lang_reflect_Field   *rf;
-       classinfo                 *c;
-       fieldinfo                 *f;
-       int32_t                    slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       java_lang_reflect_VMField *rvmf;
-#endif
 
        TRACEJNICALLS(("jni_FromReflectedField(env=%p, field=%p)", env, field));
 
-       rf = (java_lang_reflect_Field *) field;
+       java_lang_reflect_Field rf(field);
 
-       if (rf == NULL)
+       if (rf.is_null())
                return NULL;
 
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       LLNI_field_get_ref(rf,   f,     rvmf);
-       LLNI_field_get_cls(rvmf, clazz, c);
-       LLNI_field_get_val(rvmf, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       LLNI_field_get_cls(rf, clazz, c);
-       LLNI_field_get_val(rf, slot , slot);
-
-#else
-# error unknown configuration
-#endif
-
-       f = &(c->fields[slot]);
+       fieldinfo* f = rf.get_field();
 
        return (jfieldID) f;
 #else
        vm_abort("jni_FromReflectedField: Not implemented in this configuration.");
 
-       /* Keep compiler happy. */
-
+       // Keep compiler happy.
        return NULL;
 #endif
 }
@@ -1634,34 +1513,29 @@ jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
 
 *******************************************************************************/
 
-jobject _Jv_JNI_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
-                                                                 jboolean isStatic)
+jobject jni_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
 {
 #if defined(ENABLE_JAVASE)
-       methodinfo                    *m;
-       java_lang_reflect_Constructor *rc;
-       java_lang_reflect_Method      *rm;
+       TRACEJNICALLS(("jni_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
 
-       TRACEJNICALLS(("_Jv_JNI_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
-
-       m = (methodinfo *) methodID;
+       methodinfo* m = (methodinfo *) methodID;
 
        /* HotSpot does the same assert. */
 
        assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
 
-       if (m->name == utf_init) {
-               rc = reflect_constructor_new(m);
+       java_handle_t* h;
 
-               return (jobject) rc;
+       if (m->name == utf_init) {
+               h = java_lang_reflect_Constructor(m).get_handle();
        }
        else {
-               rm = reflect_method_new(m);
-
-               return (jobject) rm;
+               h = java_lang_reflect_Method(m).get_handle();
        }
+
+       return (jobject) h;
 #else
-       vm_abort("_Jv_JNI_ToReflectedMethod: not implemented in this configuration");
+       vm_abort("jni_ToReflectedMethod: Not implemented in this configuration.");
 
        /* keep compiler happy */
 
@@ -2195,6 +2069,8 @@ jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
 #define SET_FIELD(o,type,f,value) \
     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
 
+#define GET_FIELDINFO(f) ((fieldinfo*) (f))
+
 #define JNI_SET_FIELD(name, type, intern)                                  \
 void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID,  \
                                                          type value)                                  \
@@ -2205,7 +2081,10 @@ void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID,  \
                                                                            \
        SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
                                                                               \
-       LLNI_CRITICAL_START;                                                   \
+       LLNI_CRITICAL_END;                                                     \
+                                                                                                                                                  \
+       if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE)                      \
+               Atomic::memory_barrier();                                          \
 }
 
 JNI_SET_FIELD(Boolean, jboolean, s4)
@@ -2228,6 +2107,9 @@ void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
        SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
 
        LLNI_CRITICAL_END;
+
+       if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE)
+               Atomic::memory_barrier();
 }
 
 
@@ -2379,7 +2261,7 @@ jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
        methodinfo    *m;
        java_handle_t *o;
 
-       TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+       TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p)", env, clazz, methodID));
 
        m = (methodinfo *) methodID;
 
@@ -2426,7 +2308,7 @@ void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
 {
        methodinfo *m;
 
-       TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+       TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p)", env, clazz, methodID));
 
        m = (methodinfo *) methodID;
 
@@ -2565,6 +2447,9 @@ void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
                        return;                                            \
                                                                \
        f->value->field = value;                                   \
+                                                                                                                          \
+       if (f->flags & ACC_VOLATILE)                               \
+               Atomic::memory_barrier();                              \
 }
 
 JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
@@ -2593,6 +2478,9 @@ void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
                        return;
 
        f->value->a = LLNI_UNWRAP((java_handle_t *) value);
+
+       if (f->flags & ACC_VOLATILE)
+               Atomic::memory_barrier();
 }
 
 
@@ -2605,30 +2493,30 @@ void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
 
 *******************************************************************************/
 
-jstring _Jv_JNI_NewString(JNIEnv *env, const jchar *buf, jsize len)
+jstring jni_NewString(JNIEnv *env, const jchar *buf, jsize len)
 {
-       java_lang_String        *s;
-       java_handle_chararray_t *a;
-       int32_t                  i;
+       TRACEJNICALLS(("jni_NewString(env=%p, buf=%p, len=%d)", env, buf, len));
 
-       STATISTICS(jniinvokation());
-       
-       s = (java_lang_String *) builtin_new(class_java_lang_String);
-       a = builtin_newarray_char(len);
+       CharArray ca(len);
 
-       /* javastring or characterarray could not be created */
-       if ((a == NULL) || (s == NULL))
+       if (ca.is_null())
                return NULL;
 
        /* copy text */
-       for (i = 0; i < len; i++)
-               LLNI_array_direct(a, i) = buf[i];
 
-       LLNI_field_set_ref(s, value , a);
-       LLNI_field_set_val(s, offset, 0);
-       LLNI_field_set_val(s, count , len);
+       // XXX: Fix me!
+       uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
+       for (jsize i = 0; i < len; i++)
+               ptr[i] = buf[i];
+
+       java_handle_t* h = builtin_new(class_java_lang_String);
+
+       if (h == NULL)
+               return NULL;
+
+       java_lang_String s(h, ca.get_handle(), len, 0);
 
-       return (jstring) jni_NewLocalRef(env, (jobject) s);
+       return (jstring) jni_NewLocalRef(env, (jobject) s.get_handle());
 }
 
 
@@ -2641,18 +2529,16 @@ static jchar emptyStringJ[]={0,0};
 
 *******************************************************************************/
 
-jsize _Jv_JNI_GetStringLength(JNIEnv *env, jstring str)
+jsize jni_GetStringLength(JNIEnv *env, jstring str)
 {
-       java_lang_String *s;
-       jsize             len;
-
-       TRACEJNICALLS(("_Jv_JNI_GetStringLength(env=%p, str=%p)", env, str));
+       TRACEJNICALLSENTER(("jni_GetStringLength(env=%p, str=%p)", env, str));
 
-       s = (java_lang_String *) str;
+       java_lang_String s(str);
+       jsize count = s.get_count();
 
-       LLNI_field_get_val(s, count, len);
+       TRACEJNICALLSEXIT(("->%d)", count));
 
-       return len;
+       return count;
 }
 
 
@@ -2665,12 +2551,8 @@ jsize _Jv_JNI_GetStringLength(JNIEnv *env, jstring str)
 
 const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
 {      
-       java_lang_String        *s;
-       java_handle_chararray_t *a;
-       u2                      *stringbuffer;
-       int32_t                  count;
-       int32_t                  offset;
-       int32_t                  i;
+       u2      *stringbuffer;
+       int32_t  i;
 
        TRACEJNICALLS(("jni_GetStringChars(env=%p, str=%p, isCopy=%p)", env, str, isCopy));
 
@@ -2678,24 +2560,26 @@ const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
                // FIXME This is really ugly.
                return emptyStringJ;
 
-       s = (java_lang_String *) str;
+       java_lang_String s(str);
 
-       LLNI_field_get_ref(s, value, a);
+       CharArray ca(s.get_value());
 
-       if (a == NULL)
+       int32_t count  = s.get_count();
+       int32_t offset = s.get_offset();
+       
+       if (ca.is_null())
                return NULL;
 
-       LLNI_field_get_val(s, count, count);
-       LLNI_field_get_val(s, offset, offset);
-
        /* allocate memory */
 
        stringbuffer = MNEW(u2, count + 1);
 
        /* copy text */
 
+       // XXX: Fix me!
+       uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
        for (i = 0; i < count; i++)
-               stringbuffer[i] = LLNI_array_direct(a, offset + i);
+               stringbuffer[i] = ptr[offset + i];
        
        /* terminate string */
 
@@ -2718,16 +2602,16 @@ const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
 
 void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
 {
-       java_lang_String *s;
-
-       STATISTICS(jniinvokation());
+       TRACEJNICALLS(("jni_ReleaseStringChars(env=%p, str=%p, chars=%p)", env, str, chars));
 
+       // FIXME
        if (chars == emptyStringJ)
                return;
 
-       s = (java_lang_String *) str;
+       java_lang_String s(str);
+       int32_t count = s.get_count();
 
-       MFREE(((jchar *) chars), jchar, LLNI_field_direct(s, count) + 1);
+       MFREE(((jchar*) chars), jchar, count + 1);
 }
 
 
@@ -2738,30 +2622,29 @@ void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
 
 *******************************************************************************/
 
-jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
+jstring jni_NewStringUTF(JNIEnv *env, const char *bytes)
 {
-       java_lang_String *s;
-
-       TRACEJNICALLS(("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes));
+       TRACEJNICALLS(("jni_NewStringUTF(env=%p, bytes=%s)", env, bytes));
 
-       s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
+       java_handle_t *h = javastring_safe_new_from_utf8(bytes);
 
-    return (jstring) jni_NewLocalRef(env, (jobject) s);
+    return (jstring) jni_NewLocalRef(env, (jobject) h);
 }
 
 
 /****************** returns the utf8 length in bytes of a string *******************/
 
-jsize _Jv_JNI_GetStringUTFLength(JNIEnv *env, jstring string)
+jsize jni_GetStringUTFLength(JNIEnv *env, jstring string)
 {   
-       java_lang_String *s;
-       s4                length;
-
-       TRACEJNICALLS(("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string));
+       TRACEJNICALLS(("jni_GetStringUTFLength(env=%p, string=%p)", env, string));
 
-       s = (java_lang_String *) string;
+       java_lang_String s(string);
+       CharArray        ca(s.get_value());
+       int32_t          count = s.get_count();
 
-       length = u2_utflength(LLNI_field_direct(s, value)->data, LLNI_field_direct(s, count));
+       // FIXME GC critical section!
+       uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
+       int32_t length = u2_utflength(ptr, count);
 
        return length;
 }
@@ -2825,14 +2708,11 @@ void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
 
 jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
 {
-       java_handle_t *a;
-       jsize          size;
-
        TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array));
 
-       a = (java_handle_t *) array;
+       Array a(array);
 
-       size = LLNI_array_size(a);
+       jsize size = a.get_length();
 
        return size;
 }
@@ -2848,10 +2728,9 @@ jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
 jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
                                                                        jclass elementClass, jobject initialElement)
 {
-       classinfo                 *c;
-       java_handle_t             *o;
-       java_handle_objectarray_t *oa;
-       s4                         i;
+       classinfo*     c;
+       java_handle_t* o;
+       s4             i;
 
        STATISTICS(jniinvokation());
 
@@ -2863,36 +2742,33 @@ jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
                return NULL;
        }
 
-    oa = builtin_anewarray(length, c);
+       ObjectArray oa(length, c);
 
-       if (oa == NULL)
+       if (oa.is_null())
                return NULL;
 
        /* set all elements to initialElement */
 
        for (i = 0; i < length; i++)
-               array_objectarray_element_set(oa, i, o);
+               oa.set_element(i, o);
 
-       return (jobjectArray) jni_NewLocalRef(env, (jobject) oa);
+       return (jobjectArray) jni_NewLocalRef(env, (jobject) oa.get_handle());
 }
 
 
 jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
                                                                          jsize index)
 {
-       java_handle_objectarray_t *oa;
-       java_handle_t             *o;
-
        STATISTICS(jniinvokation());
 
-       oa = (java_handle_objectarray_t *) array;
+       ObjectArray oa(array);
 
-       if (index >= LLNI_array_size(oa)) {
+       if (index >= oa.get_length()) {
                exceptions_throw_arrayindexoutofboundsexception();
                return NULL;
        }
 
-       o = array_objectarray_element_get(oa, index);
+       java_handle_t* o = oa.get_element(index);
 
        return jni_NewLocalRef(env, (jobject) o);
 }
@@ -2901,15 +2777,11 @@ jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
 void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
                                                                   jsize index, jobject val)
 {
-       java_handle_objectarray_t *oa;
-       java_handle_t             *o;
-
        STATISTICS(jniinvokation());
 
-       oa = (java_handle_objectarray_t *) array;
-       o  = (java_handle_t *) val;
+       ObjectArray oa(array);
 
-       if (index >= LLNI_array_size(oa)) {
+       if (index >= oa.get_length()) {
                exceptions_throw_arrayindexoutofboundsexception();
                return;
        }
@@ -2917,18 +2789,18 @@ 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))
+       java_handle_t* o  = (java_handle_t *) val;
+
+       if (!builtin_canstore(oa.get_handle(), o))
                return;
 
-       array_objectarray_element_set(oa, index, o);
+       oa.set_element(index, o);
 }
 
 
-#define JNI_NEW_ARRAY(name, type, intern)                \
+#define JNI_NEW_ARRAY(name, type)                        \
 type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
 {                                                        \
-       java_handle_##intern##array_t *a;                    \
-                                                         \
        STATISTICS(jniinvokation());                         \
                                                          \
        if (len < 0) {                                       \
@@ -2936,19 +2808,20 @@ type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
                return NULL;                                     \
        }                                                    \
                                                          \
-       a = builtin_newarray_##intern(len);                  \
+       name##Array a(len);                                  \
                                                          \
-       return (type) jni_NewLocalRef(env, (jobject) a); \
+       return (type) jni_NewLocalRef(env,                   \
+                       (jobject) a.get_handle());                   \
 }
 
-JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
-JNI_NEW_ARRAY(Byte,    jbyteArray,    byte)
-JNI_NEW_ARRAY(Char,    jcharArray,    char)
-JNI_NEW_ARRAY(Short,   jshortArray,   short)
-JNI_NEW_ARRAY(Int,     jintArray,     int)
-JNI_NEW_ARRAY(Long,    jlongArray,    long)
-JNI_NEW_ARRAY(Float,   jfloatArray,   float)
-JNI_NEW_ARRAY(Double,  jdoubleArray,  double)
+JNI_NEW_ARRAY(Boolean, jbooleanArray)
+JNI_NEW_ARRAY(Byte,    jbyteArray)
+JNI_NEW_ARRAY(Char,    jcharArray)
+JNI_NEW_ARRAY(Short,   jshortArray)
+JNI_NEW_ARRAY(Int,     jintArray)
+JNI_NEW_ARRAY(Long,    jlongArray)
+JNI_NEW_ARRAY(Float,   jfloatArray)
+JNI_NEW_ARRAY(Double,  jdoubleArray)
 
 
 /* Get<PrimitiveType>ArrayElements *********************************************
@@ -2961,16 +2834,14 @@ JNI_NEW_ARRAY(Double,  jdoubleArray,  double)
 type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
                                                                                 jboolean *isCopy)             \
 {                                                                      \
-       java_handle_##intern##array_t *a;                                  \
-                                                                       \
        TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \
                                                                        \
-       a = (java_handle_##intern##array_t *) array;                       \
+       name##Array a(array);                                              \
                                                                        \
        if (isCopy)                                                        \
                *isCopy = JNI_FALSE;                                           \
                                                                        \
-       return (type *) LLNI_array_data(a);                                \
+       return (type *) a.get_raw_data_ptr();                              \
 }
 
 JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
@@ -2998,19 +2869,17 @@ JNI_GET_ARRAY_ELEMENTS(Double,  jdouble,  double)
 void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
                                                                                  type *elems, jint mode)          \
 {                                                                          \
-       java_handle_##intern##array_t *a;                                      \
-                                                                           \
        STATISTICS(jniinvokation());                                           \
                                                                            \
-       a = (java_handle_##intern##array_t *) array;                           \
+       name##Array a(array);                                                  \
                                                                            \
-       if (elems != (type *) LLNI_array_data(a)) {                            \
+       if (elems != (type *) a.get_raw_data_ptr()) {                          \
                switch (mode) {                                                    \
                case JNI_COMMIT:                                                   \
-                       MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
+                       a.set_region(0, a.get_length(), (intern2 *) elems);            \
                        break;                                                         \
                case 0:                                                            \
-                       MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
+                       a.set_region(0, a.get_length(), (intern2 *) elems);            \
                        /* XXX TWISTI how should it be freed? */                       \
                        break;                                                         \
                case JNI_ABORT:                                                    \
@@ -3041,16 +2910,14 @@ JNI_RELEASE_ARRAY_ELEMENTS(Double,  jdouble,  double,  double)
 void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
                                                                        jsize start, jsize len, type *buf)  \
 {                                                                       \
-       java_handle_##intern##array_t *a;                                   \
-                                                                        \
        TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \
                                                                         \
-       a = (java_handle_##intern##array_t *) array;                        \
+       name##Array a(array);                                               \
                                                                         \
-       if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
+       if ((start < 0) || (len < 0) || (start + len > a.get_length()))     \
                exceptions_throw_arrayindexoutofboundsexception();              \
        else                                                                \
-               MCOPY(buf, &LLNI_array_direct(a, start), intern2, len);         \
+               a.get_region(start, len, (intern2 *) buf);                      \
 }
 
 JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
@@ -3074,16 +2941,14 @@ JNI_GET_ARRAY_REGION(Double,  jdouble,  double,  double)
 void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
                                                                        jsize start, jsize len, const type *buf) \
 {                                                                            \
-       java_handle_##intern##array_t *a;                                        \
-                                                                             \
        STATISTICS(jniinvokation());                                             \
                                                                              \
-       a = (java_handle_##intern##array_t *) array;                             \
+       name##Array a(array);                                                    \
                                                                              \
-       if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a)))      \
+       if ((start < 0) || (len < 0) || (start + len > a.get_length()))          \
                exceptions_throw_arrayindexoutofboundsexception();                   \
        else                                                                     \
-               MCOPY(&LLNI_array_direct(a, start), buf, intern2, len);              \
+               a.set_region(start, len, (intern2 *) buf);                           \
 }
 
 JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
@@ -3108,22 +2973,16 @@ JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
 
 *******************************************************************************/
 
-jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
-                                                        const JNINativeMethod *methods, jint nMethods)
+jint jni_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods)
 {
-       classinfo *c;
-
-       STATISTICS(jniinvokation());
-
-       c = LLNI_classinfo_unwrap(clazz);
+       TRACEJNICALLS(("jni_RegisterNatives(env=%p, clazz=%p, methods=%p, nMethods=%d)", env, clazz, methods, nMethods));
 
-       /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
-       if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
-       */
+       classinfo* c = LLNI_classinfo_unwrap(clazz);
 
-       native_method_register(c->name, methods, nMethods);
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(c->name, methods, nMethods);
 
-    return 0;
+       return 0;
 }
 
 
@@ -3214,7 +3073,7 @@ jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm)
 {
        STATISTICS(jniinvokation());
 
-    *javavm = vm->get_javavm();
+    *javavm = VM::get_current()->get_javavm();
 
        return 0;
 }
@@ -3229,24 +3088,18 @@ jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm)
 
 *******************************************************************************/
 
-void _Jv_JNI_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
-                                                        jchar *buf)
+void jni_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
 {
-       java_lang_String        *s;
-       java_handle_chararray_t *ca;
-
-       STATISTICS(jniinvokation());
+       java_lang_String s(str);
+       CharArray        ca(s.get_value());
+       int32_t          count = s.get_count();
 
-       s  = (java_lang_String *) str;
-       LLNI_field_get_ref(s, value, ca);
-
-       if ((start < 0) || (len < 0) || (start > LLNI_field_direct(s, count)) ||
-               (start + len > LLNI_field_direct(s, count))) {
+       if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
                exceptions_throw_stringindexoutofboundsexception();
                return;
        }
 
-       MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
+       ca.get_region(start, len, buf);
 }
 
 
@@ -3260,29 +3113,28 @@ void _Jv_JNI_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
 
 *******************************************************************************/
 
-void _Jv_JNI_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
-                                                               jsize len, char *buf)
+void jni_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
 {
-       java_lang_String        *s;
-       java_handle_chararray_t *ca;
-       s4                       i;
-       int32_t                  count;
-       int32_t                  offset;
+       TRACEJNICALLS(("jni_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
+
+       java_lang_String s(str);
 
-       TRACEJNICALLS(("_Jv_JNI_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
+       CharArray ca(s.get_value());
 
-       s  = (java_lang_String *) str;
-       LLNI_field_get_ref(s, value, ca);
-       LLNI_field_get_val(s, count, count);
-       LLNI_field_get_val(s, offset, offset);
+       int32_t count  = s.get_count();
+       int32_t offset = s.get_offset();
 
        if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
                exceptions_throw_stringindexoutofboundsexception();
                return;
        }
 
+       int32_t i;
+
+       // XXX: Fix me!
+       uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
        for (i = 0; i < len; i++)
-               buf[i] = LLNI_array_direct(ca, offset + start + i);
+               buf[i] = ptr[offset + start + i];
 
        buf[i] = '\0';
 }
@@ -3388,7 +3240,7 @@ void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
    argument.
 
 *******************************************************************************/
-    
+
 jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
 {
        hashtable_global_ref_entry *gre;
@@ -3400,7 +3252,7 @@ jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
 
        o = (java_handle_t *) obj;
 
-       LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->lock();
 
        LLNI_CRITICAL_START;
 
@@ -3429,7 +3281,7 @@ jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
        /* global ref not found, create a new one */
 
        if (gre == NULL) {
-               gre = GCNEW_UNCOLLECTABLE(hashtable_global_ref_entry, 1);
+               gre = (hashtable_global_ref_entry*) heap_alloc_uncollectable(sizeof(hashtable_global_ref_entry));
 
 #if defined(ENABLE_GC_CACAO)
                /* register global ref with the GC */
@@ -3455,7 +3307,7 @@ jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
                hashtable_global_ref->entries++;
        }
 
-       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->unlock();
 
 #if defined(ENABLE_HANDLES)
        return gre;
@@ -3483,7 +3335,7 @@ void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 
        o = (java_handle_t *) globalRef;
 
-       LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->lock();
 
        LLNI_CRITICAL_START;
 
@@ -3521,12 +3373,12 @@ void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
                                gc_reference_unregister(&(gre->o));
 #endif
 
-                               GCFREE(gre);
+                               heap_free(gre);
                        }
 
                        LLNI_CRITICAL_END;
 
-                       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+                       hashtable_global_ref->mutex->unlock();
 
                        return;
                }
@@ -3539,7 +3391,7 @@ void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 
        LLNI_CRITICAL_END;
 
-       LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+       hashtable_global_ref->mutex->unlock();
 }
 
 
@@ -3576,38 +3428,29 @@ jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 {
 #if defined(ENABLE_JAVASE)
 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       java_handle_t           *nbuf;
-
-# if SIZEOF_VOID_P == 8
-       gnu_classpath_Pointer64 *paddress;
-# else
-       gnu_classpath_Pointer32 *paddress;
-# endif
-
        TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
 
-       /* alocate a gnu.classpath.Pointer{32,64} object */
+       // Allocate a gnu.classpath.Pointer{32,64} object.
 
 # if SIZEOF_VOID_P == 8
-       if (!(paddress = (gnu_classpath_Pointer64 *)
-                 builtin_new(class_gnu_classpath_Pointer64)))
+       java_handle_t* h = builtin_new(class_gnu_classpath_Pointer64);
 # else
-       if (!(paddress = (gnu_classpath_Pointer32 *)
-                 builtin_new(class_gnu_classpath_Pointer32)))
+       java_handle_t* h = builtin_new(class_gnu_classpath_Pointer32);
 # endif
-               return NULL;
 
-       /* fill gnu.classpath.Pointer{32,64} with address */
+       if (h == NULL)
+               return NULL;
 
-       LLNI_field_set_val(paddress, data, (ptrint) address);
+       gnu_classpath_Pointer p(h, address);
 
-       /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
+       // Create a java.nio.DirectByteBufferImpl$ReadWrite object.
 
-       nbuf = (java_handle_t*) jni_NewObject(env, (jclass) class_java_nio_DirectByteBufferImpl_ReadWrite,
-                                                                                 (jmethodID) dbbirw_init, NULL, paddress,
-                                                                                 (jint) capacity, (jint) capacity, (jint) 0);
+       java_handle_t* nbuf =
+               (java_handle_t*) jni_NewObject(env, (jclass) class_java_nio_DirectByteBufferImpl_ReadWrite,
+                                                                          (jmethodID) dbbirw_init, NULL, p.get_handle(),
+                                                                          (jint) capacity, (jint) capacity, (jint) 0);
 
-       /* add local reference and return the value */
+       // Add a local reference and return the value.
 
        TRACEJNICALLSEXIT(("->%p", nbuf));
 
@@ -3656,74 +3499,47 @@ jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
 
 *******************************************************************************/
 
-void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
+void* jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)
 {
 #if defined(ENABLE_JAVASE)
-       java_handle_t                 *h;
-
 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 
-       java_nio_DirectByteBufferImpl *nbuf;
-       gnu_classpath_Pointer         *po;
-#  if SIZEOF_VOID_P == 8
-       gnu_classpath_Pointer64       *paddress;
-       int64_t                        address;
-#  else
-       gnu_classpath_Pointer32       *paddress;
-       int32_t                        address;
-#  endif
-       void                          *p;
-
-       TRACEJNICALLS(("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
+       TRACEJNICALLSENTER(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
 
        /* Prevent compiler warning. */
 
-       h = (java_handle_t *) buf;
+       java_handle_t* h = (java_handle_t *) buf;
 
        if ((h != NULL) && !builtin_instanceof(h, class_java_nio_Buffer))
                return NULL;
 
-       nbuf = (java_nio_DirectByteBufferImpl *) buf;
-
-       LLNI_field_get_ref(nbuf, address, po);
-
-#  if SIZEOF_VOID_P == 8
-       paddress = (gnu_classpath_Pointer64 *) po;
-#  else
-       paddress = (gnu_classpath_Pointer32 *) po;
-#  endif
+       java_nio_DirectByteBufferImpl dbb(buf);
+       java_handle_t* address = dbb.get_address();
 
-       if (paddress == NULL)
+       if (address == NULL) {
+               TRACEJNICALLSEXIT(("->%p", NULL));
                return NULL;
+       }
 
-       LLNI_field_get_val(paddress, data, address);
+       gnu_classpath_Pointer p(address);
+       void* data = p.get_data();
 
-       p = (void *) (intptr_t) address;
+       TRACEJNICALLSEXIT(("->%p", data));
 
-       return p;
+       return data;
 
 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
-       java_nio_Buffer *o;
-       int64_t          address;
-       void            *p;
+       TRACEJNICALLS(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
 
-       TRACEJNICALLS(("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
+       java_nio_Buffer jnb(buf);
 
-       /* Prevent compiler warning. */
-
-       h = (java_handle_t *) buf;
-
-       if ((h != NULL) && !builtin_instanceof(h, class_sun_nio_ch_DirectBuffer))
+       if (jnb.is_non_null() && !builtin_instanceof(jnb.get_handle(), class_sun_nio_ch_DirectBuffer))
                return NULL;
 
-       o = (java_nio_Buffer *) buf;
-
-       LLNI_field_get_val(o, address, address);
+       void* address = jnb.get_address();
 
-       p = (void *) (intptr_t) address;
-
-       return p;
+       return address;
 
 # else
 #  error unknown classpath configuration
@@ -3731,10 +3547,9 @@ void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
 
 #else
 
-       vm_abort("_Jv_JNI_GetDirectBufferAddress: not implemented in this configuration");
-
-       /* keep compiler happy */
+       vm_abort("jni_GetDirectBufferAddress: Not implemented in this configuration.");
 
+       // Keep compiler happy.
        return NULL;
 
 #endif
@@ -3748,29 +3563,42 @@ void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
 
 *******************************************************************************/
 
-jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
+jlong jni_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
 {
-#if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       java_handle_t   *o;
-       java_nio_Buffer *nbuf;
-       jlong            capacity;
-
-       STATISTICS(jniinvokation());
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       TRACEJNICALLS(("jni_GetDirectBufferCapacity(env=%p, buf=%p)", env, buf));
 
-       o = (java_handle_t *) buf;
+       java_handle_t* h = (java_handle_t *) buf;
 
-       if (!builtin_instanceof(o, class_java_nio_DirectByteBufferImpl))
+       if (!builtin_instanceof(h, class_java_nio_DirectByteBufferImpl))
                return -1;
 
-       nbuf = (java_nio_Buffer *) o;
+       java_nio_Buffer b(h);
+       jlong capacity = b.get_cap();
 
-       LLNI_field_get_val(nbuf, cap, capacity);
+       return capacity;
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       TRACEJNICALLS(("jni_GetDirectBufferCapacity(env=%p, buf=%p)", env, buf));
+
+       java_nio_Buffer jnb(buf);
+
+       if (!builtin_instanceof(jnb.get_handle(), class_sun_nio_ch_DirectBuffer))
+               return -1;
+
+       jlong capacity = jnb.get_capacity();
 
        return capacity;
+
+# else
+#  error unknown classpath configuration
+# endif
+
 #else
-       vm_abort("_Jv_JNI_GetDirectBufferCapacity: not implemented in this configuration");
+       vm_abort("jni_GetDirectBufferCapacity: not implemented in this configuration");
 
-       /* keep compiler happy */
+       // Keep compiler happy.
 
        return 0;
 #endif
@@ -3807,7 +3635,7 @@ jint _Jv_JNI_DestroyJavaVM(JavaVM *javavm)
 
        TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(javavm=%p)", javavm));
 
-       if (vm->is_created() == false)
+       if (VM::get_current()->is_created() == false)
                return JNI_ERR;
 
     status = vm_destroy(javavm);
@@ -3842,7 +3670,7 @@ static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon
        result = thread_current_is_attached();
 
        if (result == true) {
-               *p_env = vm->get_jnienv();
+               *p_env = VM::get_current()->get_jnienv();
                return JNI_OK;
        }
 
@@ -3861,7 +3689,7 @@ static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon
                return JNI_ERR;
 #endif
 
-       *p_env = vm->get_jnienv();
+       *p_env = VM::get_current()->get_jnienv();
 
        return JNI_OK;
 }
@@ -3873,7 +3701,7 @@ jint jni_AttachCurrentThread(JavaVM *javavm, void **p_env, void *thr_args)
 
        TRACEJNICALLS(("jni_AttachCurrentThread(javavm=%p, p_env=%p, thr_args=%p)", javavm, p_env, thr_args));
 
-       if (vm->is_created() == false)
+       if (VM::get_current()->is_created() == false)
                return JNI_ERR;
 
        result = jni_attach_current_thread(p_env, thr_args, false);
@@ -3942,7 +3770,7 @@ jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
 {
        TRACEJNICALLS(("jni_GetEnv(javavm=%p, env=%p, version=%d)", javavm, env, version));
 
-       if (vm->is_created() == false) {
+       if (VM::get_current()->is_created() == false) {
                *env = NULL;
                return JNI_EDETACHED;
        }
@@ -3958,7 +3786,7 @@ jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
        /* Check the JNI version. */
 
        if (jni_version_check(version) == true) {
-               *env = vm->get_jnienv();
+               *env = VM::get_current()->get_jnienv();
                return JNI_OK;
        }
 
@@ -3998,7 +3826,7 @@ jint jni_AttachCurrentThreadAsDaemon(JavaVM *javavm, void **penv, void *args)
 
        TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(javavm=%p, penv=%p, args=%p)", javavm, penv, args));
 
-       if (vm->is_created() == false)
+       if (VM::get_current()->is_created() == false)
                return JNI_ERR;
 
        result = jni_attach_current_thread(penv, args, true);
@@ -4031,12 +3859,12 @@ struct JNINativeInterface_ _Jv_JNINativeInterface = {
        NULL,    
        _Jv_JNI_GetVersion,
 
-       _Jv_JNI_DefineClass,
+       jni_DefineClass,
        jni_FindClass,
        jni_FromReflectedMethod,
        jni_FromReflectedField,
-       _Jv_JNI_ToReflectedMethod,
-       _Jv_JNI_GetSuperclass,
+       jni_ToReflectedMethod,
+       jni_GetSuperclass,
        _Jv_JNI_IsAssignableFrom,
        _Jv_JNI_ToReflectedField,
 
@@ -4061,7 +3889,7 @@ struct JNINativeInterface_ _Jv_JNINativeInterface = {
        _Jv_JNI_NewObjectV,
        _Jv_JNI_NewObjectA,
 
-       _Jv_JNI_GetObjectClass,
+       jni_GetObjectClass,
        _Jv_JNI_IsInstanceOf,
 
        _Jv_JNI_GetMethodID,
@@ -4203,13 +4031,13 @@ struct JNINativeInterface_ _Jv_JNINativeInterface = {
        _Jv_JNI_SetStaticFloatField,
        _Jv_JNI_SetStaticDoubleField,
 
-       _Jv_JNI_NewString,
-       _Jv_JNI_GetStringLength,
+       jni_NewString,
+       jni_GetStringLength,
        jni_GetStringChars,
        _Jv_JNI_ReleaseStringChars,
 
-       _Jv_JNI_NewStringUTF,
-       _Jv_JNI_GetStringUTFLength,
+       jni_NewStringUTF,
+       jni_GetStringUTFLength,
        _Jv_JNI_GetStringUTFChars,
        _Jv_JNI_ReleaseStringUTFChars,
 
@@ -4263,7 +4091,7 @@ struct JNINativeInterface_ _Jv_JNINativeInterface = {
        _Jv_JNI_SetFloatArrayRegion,
        _Jv_JNI_SetDoubleArrayRegion,
 
-       _Jv_JNI_RegisterNatives,
+       jni_RegisterNatives,
        _Jv_JNI_UnregisterNatives,
 
        _Jv_JNI_MonitorEnter,
@@ -4273,8 +4101,8 @@ struct JNINativeInterface_ _Jv_JNINativeInterface = {
 
        /* New JNI 1.2 functions. */
 
-       _Jv_JNI_GetStringRegion,
-       _Jv_JNI_GetStringUTFRegion,
+       jni_GetStringRegion,
+       jni_GetStringUTFRegion,
 
        jni_GetPrimitiveArrayCritical,
        jni_ReleasePrimitiveArrayCritical,
@@ -4290,8 +4118,8 @@ struct JNINativeInterface_ _Jv_JNINativeInterface = {
        /* New JNI 1.4 functions. */
 
        jni_NewDirectByteBuffer,
-       _Jv_JNI_GetDirectBufferAddress,
-       _Jv_JNI_GetDirectBufferCapacity,
+       jni_GetDirectBufferAddress,
+       jni_GetDirectBufferCapacity,
 
        /* New JNI 1.6 functions. */
 
@@ -4316,22 +4144,28 @@ jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
        /* GNU classpath currently supports JNI 1.2 */
 
        switch (_vm_args->version) {
-    case JNI_VERSION_1_1:
+       case JNI_VERSION_1_1:
                _vm_args->version = JNI_VERSION_1_1;
                break;
 
-    case JNI_VERSION_1_2:
-    case JNI_VERSION_1_4:
+       case JNI_VERSION_1_2:
+       case JNI_VERSION_1_4:
                _vm_args->ignoreUnrecognized = JNI_FALSE;
                _vm_args->options = NULL;
                _vm_args->nOptions = 0;
                break;
 
-    default:
-               return -1;
+       case JNI_VERSION_CACAO:
+               // We reveal ourselves by accepting this version number,
+               // this actually means we are using the supported JNI version.
+               _vm_args->version = JNI_VERSION_SUPPORTED;
+               break;
+
+       default:
+               return JNI_ERR;
        }
-  
-       return 0;
+
+       return JNI_OK;
 }
 
 
@@ -4353,7 +4187,7 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
 
        // We currently only support 1 VM running.
 
-       vmBuf[0] = vm->get_javavm();
+       vmBuf[0] = VM::get_current()->get_javavm();
        *nVMs    = 1;
 
     return JNI_OK;
@@ -4388,7 +4222,7 @@ jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
  * Emacs will automagically detect them.
  * ---------------------------------------------------------------------
  * Local variables:
- * mode: c
+ * mode: c++
  * indent-tabs-mode: t
  * c-basic-offset: 4
  * tab-width: 4