Clean merge -> gc7-branch
[cacao.git] / src / native / vm / gnu / java_lang_VMClassLoader.c
index 282414ac3d56498bfadcef54bf9c6fd645c2e5ea..7df215ca4a8ddbf57f5e43fc34fa53647a1f300d 100644 (file)
@@ -1,9 +1,7 @@
-/* src/native/vm/VMClassLoader.c - java/lang/VMClassLoader
+/* src/native/vm/gnu/java_lang_VMClassLoader.c
 
-   Copyright (C) 1996-2005, 2006 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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Roman Obermaiser
-
-   Changes: Joseph Wenninger
-            Christian Thalinger
-            Edwin Steiner
-
-   $Id: java_lang_VMClassLoader.c 6213 2006-12-18 17:36:06Z twisti $
-
 */
 
 
 #include "config.h"
 
+#include <assert.h>
+#include <stdint.h>
 #include <sys/stat.h>
 
-#include "vm/types.h"
-
 #include "mm/memory.h"
+
 #include "native/jni.h"
+#include "native/llni.h"
 #include "native/native.h"
 #include "native/include/java_lang_Class.h"
 #include "native/include/java_lang_String.h"
+#include "native/include/java_security_ProtectionDomain.h"  /* required by... */
 #include "native/include/java_lang_ClassLoader.h"
-#include "native/include/java_security_ProtectionDomain.h"
 #include "native/include/java_util_Vector.h"
+#include "native/include/java_util_HashMap.h"
+#include "native/include/java_util_Map.h"
+#include "native/include/java_lang_Boolean.h"
+
+#include "native/include/java_lang_VMClassLoader.h"
+
 #include "toolbox/logging.h"
+#include "toolbox/list.h"
+
+#if defined(ENABLE_ASSERTION)
+#include "vm/assertion.h"
+#endif
+
 #include "vm/builtin.h"
-#include "vm/class.h"
-#include "vm/classcache.h"
 #include "vm/exceptions.h"
 #include "vm/initialize.h"
-#include "vm/linker.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
+#include "vm/primitive.h"
 #include "vm/stringlocal.h"
-#include "vm/suck.h"
 #include "vm/vm.h"
-#include "vm/zip.h"
+
 #include "vm/jit/asmpart.h"
 
+#include "vmcore/class.h"
+#include "vmcore/classcache.h"
+#include "vmcore/linker.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vmcore/statistics.h"
+#include "vmcore/suck.h"
+#include "vmcore/zip.h"
+
 #if defined(ENABLE_JVMTI)
 #include "native/jvmti/cacaodbg.h"
 #endif
 
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+       { "defineClass",                "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defineClass                },
+       { "getPrimitiveClass",          "(C)Ljava/lang/Class;",                                                                             (void *) (uintptr_t) &Java_java_lang_VMClassLoader_getPrimitiveClass          },
+       { "resolveClass",               "(Ljava/lang/Class;)V",                                                                             (void *) (uintptr_t) &Java_java_lang_VMClassLoader_resolveClass               },
+       { "loadClass",                  "(Ljava/lang/String;Z)Ljava/lang/Class;",                                                           (void *) (uintptr_t) &Java_java_lang_VMClassLoader_loadClass                  },
+       { "nativeGetResources",         "(Ljava/lang/String;)Ljava/util/Vector;",                                                           (void *) (uintptr_t) &Java_java_lang_VMClassLoader_nativeGetResources         },
+       { "defaultAssertionStatus",     "()Z",                                                                                              (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defaultAssertionStatus     },
+       { "defaultUserAssertionStatus", "()Z",                                                                                              (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defaultUserAssertionStatus },
+       { "packageAssertionStatus0",    "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;",                                          (void *) (uintptr_t) &Java_java_lang_VMClassLoader_packageAssertionStatus0    },
+       { "classAssertionStatus0",      "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;",                                          (void *) (uintptr_t) &Java_java_lang_VMClassLoader_classAssertionStatus0      },
+       { "findLoadedClass",            "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;",                                     (void *) (uintptr_t) &Java_java_lang_VMClassLoader_findLoadedClass            },
+};
+
+
+/* _Jv_java_lang_VMClassLoader_init ********************************************
+
+   Register native functions.
+
+*******************************************************************************/
+
+void _Jv_java_lang_VMClassLoader_init(void)
+{
+       utf *u;
+
+       u = utf_new_char("java/lang/VMClassLoader");
+
+       native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+
 
 /*
  * Class:     java/lang/VMClassLoader
  * Method:    defineClass
  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_bytearray *data, s4 offset, s4 len, java_security_ProtectionDomain *pd)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_handle_bytearray_t *data, int32_t offset, int32_t len, java_security_ProtectionDomain *pd)
 {
-       classinfo   *c;
-       classinfo   *r;
-       classbuffer *cb;
-       utf         *utfname;
+       utf             *utfname;
+       classinfo       *c;
+       classloader_t   *loader;
+       java_lang_Class *o;
+
 #if defined(ENABLE_JVMTI)
        jint new_class_data_len = 0;
        unsigned char* new_class_data = NULL;
@@ -95,112 +132,60 @@ JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIE
 
        /* check the indexes passed */
 
-       if ((offset < 0) || (len < 0) || ((offset + len) > data->header.size)) {
+       if ((offset < 0) || (len < 0) || ((offset + len) > LLNI_array_size(data))) {
                exceptions_throw_arrayindexoutofboundsexception();
                return NULL;
        }
 
-       if (name) {
-               /* convert '.' to '/' in java string */
+       /* add classloader to classloader hashtable */
 
-               utfname = javastring_toutf(name, true);
-               
-               /* check if this class has already been defined */
+       loader = loader_hashtable_classloader_add((java_handle_t *) cl);
 
-               c = classcache_lookup_defined_or_initiated((java_objectheader *) cl, utfname);
-               if (c) {
-                       *exceptionptr =
-                               exceptions_new_linkageerror("duplicate class definition: ",c);
-                       return NULL;
-               }
+       if (name != NULL) {
+               /* convert '.' to '/' in java string */
+
+               utfname = javastring_toutf((java_handle_t *) name, true);
        } 
        else {
                utfname = NULL;
        }
 
-
 #if defined(ENABLE_JVMTI)
+       /* XXX again this will not work because of the indirection cell for classloaders */
+       assert(0);
        /* fire Class File Load Hook JVMTI event */
-       if (jvmti) jvmti_ClassFileLoadHook(utfname, len, (unsigned char*)data->data, 
-                                                       (java_objectheader *)cl, (java_objectheader *)pd, 
-                                                       &new_class_data_len, &new_class_data);
-#endif
-
-
-       /* create a new classinfo struct */
-
-       c = class_create_classinfo(utfname);
-
-#if defined(ENABLE_STATISTICS)
-       /* measure time */
 
-       if (opt_getloadingtime)
-               loadingtime_start();
+       if (jvmti)
+               jvmti_ClassFileLoadHook(utfname, len, (unsigned char *) data->data, 
+                                                               loader, (java_handle_t *) pd, 
+                                                               &new_class_data_len, &new_class_data);
 #endif
 
-       /* build a classbuffer with the given data */
+       /* define the class */
 
-       cb = NEW(classbuffer);
-       cb->class = c;
 #if defined(ENABLE_JVMTI)
        /* check if the JVMTI wants to modify the class */
-       if (new_class_data == NULL) {
-#endif
-       cb->size  = len;
-       cb->data  = (u1 *) &data->data[offset];
-#if defined(ENABLE_JVMTI)
-       } else {
-               cb->size  = new_class_data_len;
-               cb->data  = (u1 *) new_class_data;
-       }
-#endif
-       cb->pos   = cb->data;
-
-       /* preset the defining classloader */
-
-       c->classloader = (java_objectheader *) cl;
-
-       /* load the class from this buffer */
-
-       r = load_class_from_classbuffer(cb);
-
-       /* free memory */
-
-       FREE(cb, classbuffer);
 
-#if defined(ENABLE_STATISTICS)
-       /* measure time */
-
-       if (opt_getloadingtime)
-               loadingtime_stop();
+       if (new_class_data == NULL)
+               c = class_define(utfname, loader, new_class_data_len, new_class_data, pd); 
+       else
 #endif
+               c = class_define(utfname, loader, len, (uint8_t *) &LLNI_array_direct(data, offset), (java_handle_t *) pd);
 
-       if (!r) {
-               /* If return value is NULL, we had a problem and the class is not   */
-               /* loaded. */
-               /* now free the allocated memory, otherwise we could run into a DOS */
-
-               class_free(c);
-
+       if (c == NULL)
                return NULL;
-       }
 
-       /* set ProtectionDomain */
+       /* for convenience */
 
-       c->object.pd = pd;
+       o = LLNI_classinfo_wrap(c);
 
-       /* Store the newly defined class in the class cache. This call also       */
-       /* checks whether a class of the same name has already been defined by    */
-       /* the same defining loader, and if so, replaces the newly created class  */
-       /* by the one defined earlier.                                            */
-       /* Important: The classinfo given to classcache_store must be             */
-       /*            fully prepared because another thread may return this       */
-       /*            pointer after the lookup at to top of this function         */
-       /*            directly after the class cache lock has been released.      */
+#if defined(WITH_CLASSPATH_GNU)
+       /* set ProtectionDomain */
 
-       c = classcache_store((java_objectheader *)cl,c,true);
+       LLNI_field_set_ref(o, pd, pd);
+#endif
 
-       return (java_lang_Class *) c;
+       return o;
 }
 
 
@@ -209,46 +194,18 @@ JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIE
  * Method:    getPrimitiveClass
  * Signature: (C)Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, s4 type)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, int32_t type)
 {
        classinfo *c;
 
-       /* get primitive class */
-
-       switch (type) {
-       case 'I':
-               c = primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
-               break;
-       case 'J':
-               c = primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
-               break;
-       case 'F':
-               c = primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
-               break;
-       case 'D':
-               c = primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
-               break;
-       case 'B':
-               c = primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
-               break;
-       case 'C':
-               c = primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
-               break;
-       case 'S':
-               c = primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
-               break;
-       case 'Z':
-               c = primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
-               break;
-       case 'V':
-               c = primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
-               break;
-       default:
-               *exceptionptr = new_exception(string_java_lang_ClassNotFoundException);
-               c = NULL;
+       c = primitive_class_get_by_char(type);
+
+       if (c == NULL) {
+               exceptions_throw_classnotfoundexception(utf_null);
+               return NULL;
        }
 
-       return (java_lang_Class *) c;
+       return LLNI_classinfo_wrap(c);
 }
 
 
@@ -261,7 +218,7 @@ JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jc
 {
        classinfo *ci;
 
-       ci = (classinfo *) c;
+       ci = LLNI_classinfo_unwrap(c);
 
        if (!ci) {
                exceptions_throw_nullpointerexception();
@@ -282,10 +239,10 @@ JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jc
  * Method:    loadClass
  * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, jboolean resolve)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, int32_t resolve)
 {
        classinfo *c;
-       utf *u;
+       utf       *u;
 
        if (name == NULL) {
                exceptions_throw_nullpointerexception();
@@ -294,37 +251,22 @@ JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv
 
        /* create utf string in which '.' is replaced by '/' */
 
-       u = javastring_toutf(name, true);
+       u = javastring_toutf((java_handle_t *) name, true);
 
        /* load class */
 
-       if (!(c = load_class_bootstrap(u)))
-               goto exception;
+       c = load_class_bootstrap(u);
+
+       if (c == NULL)
+               return NULL;
 
        /* resolve class -- if requested */
 
 /*     if (resolve) */
                if (!link_class(c))
-                       goto exception;
-
-       return (java_lang_Class *) c;
-
- exception:
-       c = (*exceptionptr)->vftbl->class;
-       
-       /* if the exception is a NoClassDefFoundError, we replace it with a
-          ClassNotFoundException, otherwise return the exception */
-
-       if (c == class_java_lang_NoClassDefFoundError) {
-               /* clear exceptionptr, because builtin_new checks for 
-                  ExceptionInInitializerError */
-               *exceptionptr = NULL;
-
-               *exceptionptr =
-                       new_exception_javastring(string_java_lang_ClassNotFoundException, name);
-       }
+                       return NULL;
 
-       return NULL;
+       return LLNI_classinfo_wrap(c);
 }
 
 
@@ -335,33 +277,34 @@ JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv
  */
 JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, java_lang_String *name)
 {
-       jobject               o;         /* vector being created     */
+       java_handle_t        *o;         /* vector being created     */
        methodinfo           *m;         /* "add" method of vector   */
-       java_lang_String     *path;      /* path to be added         */
+       java_handle_t        *path;      /* path to be added         */
        list_classpath_entry *lce;       /* classpath entry          */
        utf                  *utfname;   /* utf to look for          */
        char                 *buffer;    /* char buffer              */
        char                 *namestart; /* start of name to use     */
        char                 *tmppath;   /* temporary buffer         */
-       s4                    namelen;   /* length of name to use    */
-       s4                    searchlen; /* length of name to search */
-       s4                    bufsize;   /* size of buffer allocated */
-       s4                    pathlen;   /* name of path to assemble */
+       int32_t               namelen;   /* length of name to use    */
+       int32_t               searchlen; /* length of name to search */
+       int32_t               bufsize;   /* size of buffer allocated */
+       int32_t               pathlen;   /* name of path to assemble */
        struct stat           buf;       /* buffer for stat          */
        jboolean              ret;       /* return value of "add"    */
 
        /* get the resource name as utf string */
 
-       utfname = javastring_toutf(name, false);
-       if (!utfname)
+       utfname = javastring_toutf((java_handle_t *) name, false);
+
+       if (utfname == NULL)
                return NULL;
 
        /* copy it to a char buffer */
 
-       namelen = utf_bytes(utfname);
+       namelen   = utf_bytes(utfname);
        searchlen = namelen;
-       bufsize = namelen + strlen("0");
-       buffer = MNEW(char, bufsize);
+       bufsize   = namelen + strlen("0");
+       buffer    = MNEW(char, bufsize);
 
        utf_copy(buffer, utfname);
        namestart = buffer;
@@ -392,7 +335,7 @@ JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResour
 
        o = native_new_and_init(class_java_util_Vector);
 
-       if (!o)
+       if (o == NULL)
                goto return_NULL;
 
        /* get Vector.add() method */
@@ -403,7 +346,7 @@ JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResour
                                                                 NULL,
                                                                 true);
 
-       if (!m)
+       if (m == NULL)
                goto return_NULL;
 
        /* iterate over all classpath entries */
@@ -449,10 +392,10 @@ JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResour
 
                /* if a resource was found, add it to the vector */
 
-               if (path) {
+               if (path != NULL) {
                        ret = vm_call_method_int(m, o, path);
 
-                       if (*exceptionptr)
+                       if (exceptions_get_exception() != NULL)
                                goto return_NULL;
 
                        if (ret == 0) 
@@ -476,9 +419,167 @@ return_NULL:
  * Method:    defaultAssertionStatus
  * Signature: ()Z
  */
-JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
+JNIEXPORT int32_t JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
 {
-       return _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus;
+#if defined(ENABLE_ASSERTION)
+       return assertion_system_enabled;
+#else
+       return false;
+#endif
+}
+
+/*
+ * Class:     java/lang/VMClassLoader
+ * Method:    userAssertionStatus
+ * Signature: ()Z
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_VMClassLoader_defaultUserAssertionStatus(JNIEnv *env, jclass clazz)
+{
+#if defined(ENABLE_ASSERTION)
+       return assertion_user_enabled;
+#else
+       return false;
+#endif
+}
+
+/*
+ * Class:     java/lang/VMClassLoader
+ * Method:    packageAssertionStatus
+ * Signature: ()Ljava_util_Map;
+ */
+JNIEXPORT java_util_Map* JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(JNIEnv *env, jclass clazz, java_lang_Boolean *jtrue, java_lang_Boolean *jfalse)
+{
+       java_handle_t     *hm;
+#if defined(ENABLE_ASSERTION)
+       java_handle_t     *js;
+       methodinfo        *m;
+       assertion_name_t  *item;
+#endif
+
+       /* new HashMap() */
+
+       hm = native_new_and_init(class_java_util_HashMap);
+       if (hm == NULL) {
+               return NULL;
+       }
+
+#if defined(ENABLE_ASSERTION)
+       /* if nothing todo, return now */
+
+       if (assertion_package_count == 0) {
+               return (java_util_Map *) hm;
+       }
+
+       /* get HashMap.put method */
+
+       m = class_resolveclassmethod(class_java_util_HashMap,
+                                 utf_put,
+                                 utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+                                 NULL,
+                                 true);
+
+       if (m == NULL) {
+               return NULL;
+       }
+
+       item = (assertion_name_t *)list_first(list_assertion_names);
+
+       while (item != NULL) {
+               if (item->package == false) {
+                       item = (assertion_name_t *)list_next(list_assertion_names, item);
+                       continue;
+               }
+               
+               if (strcmp(item->name, "") == 0) {
+                       /* unnamed package wanted */
+                       js = NULL;
+               }
+               else {
+                       js = javastring_new_from_ascii(item->name);
+                       if (js == NULL) {
+                               return NULL;
+                       }
+               }
+
+               if (item->enabled == true) {
+                       vm_call_method(m, hm, js, jtrue);
+               }
+               else {
+                       vm_call_method(m, hm, js, jfalse);
+               }
+
+               item = (assertion_name_t *)list_next(list_assertion_names, item);
+       }
+#endif
+
+       return (java_util_Map *) hm;
+}
+
+/*
+ * Class:     java/lang/VMClassLoader
+ * Method:    classAssertionStatus
+ * Signature: ()Ljava_util_Map;
+ */
+JNIEXPORT java_util_Map* JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNIEnv *env, jclass clazz, java_lang_Boolean *jtrue, java_lang_Boolean *jfalse)
+{
+       java_handle_t     *hm;
+#if defined(ENABLE_ASSERTION)
+       java_handle_t     *js;
+       methodinfo        *m;
+       assertion_name_t  *item;
+#endif
+
+       /* new HashMap() */
+
+       hm = native_new_and_init(class_java_util_HashMap);
+       if (hm == NULL) {
+               return NULL;
+       }
+
+#if defined(ENABLE_ASSERTION)
+       /* if nothing todo, return now */
+
+       if (assertion_class_count == 0) {
+               return (java_util_Map *) hm;
+       }
+
+       /* get HashMap.put method */
+
+       m = class_resolveclassmethod(class_java_util_HashMap,
+                                 utf_put,
+                                 utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+                                 NULL,
+                                 true);
+
+       if (m == NULL) {
+               return NULL;
+       }
+
+       item = (assertion_name_t *)list_first(list_assertion_names);
+
+       while (item != NULL) {
+               if (item->package == true) {
+                       item = (assertion_name_t *)list_next(list_assertion_names, item);
+                       continue;
+               }
+
+               js = javastring_new_from_ascii(item->name);
+               if (js == NULL) {
+                       return NULL;
+               }
+
+               if (item->enabled == true) {
+                       vm_call_method(m, hm, js, jtrue);
+               }
+               else {
+                       vm_call_method(m, hm, js, jfalse);
+               }
+
+               item = (assertion_name_t *)list_next(list_assertion_names, item);
+       }
+#endif
+
+       return (java_util_Map *) hm;
 }
 
 
@@ -487,25 +588,30 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv
  * Method:    findLoadedClass
  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *loader, java_lang_String *name)
 {
-       classinfo *c;
-       utf       *u;
+       classloader_t *cl;
+       classinfo     *c;
+       utf           *u;
+
+       /* XXX is it correct to add the classloader to the hashtable here? */
+
+       cl = loader_hashtable_classloader_add((java_handle_t *) loader);
 
        /* replace `.' by `/', this is required by the classcache */
 
-       u = javastring_toutf(name, true);
+       u = javastring_toutf((java_handle_t *) name, true);
 
        /* lookup for defining classloader */
 
-       c = classcache_lookup_defined((classloader *) cl, u);
+       c = classcache_lookup_defined(cl, u);
 
        /* if not found, lookup for initiating classloader */
 
        if (c == NULL)
-               c = classcache_lookup((classloader *) cl, u);
+               c = classcache_lookup(cl, u);
 
-       return (java_lang_Class *) c;
+       return LLNI_classinfo_wrap(c);
 }