This adds support for delegating class loading to other class loaders.
While resolving a class, we must use the class loader of the class from
which resolving originates.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 include/vm/classloader.h |    4 ++-
 jit/object-bc.c          |    5 +---
 vm/class.c               |   15 +++++++----
 vm/classloader.c         |   59 +++++++++++++++++++++++++++++++++++++++------
 vm/jato.c                |   56 +++++++++++--------------------------------
 vm/jni-interface.c       |    3 +-
 vm/object.c              |   16 ++++++------
 vm/preload.c             |    2 +-
 vm/reflection.c          |   17 +++++++-----
 9 files changed, 99 insertions(+), 78 deletions(-)

diff --git a/include/vm/classloader.h b/include/vm/classloader.h
index 505b3db..fe2556f 100644
--- a/include/vm/classloader.h
+++ b/include/vm/classloader.h
@@ -6,13 +6,15 @@
 extern bool opt_trace_classloader;
 
 struct vm_class;
+struct vm_object;
 
 int classloader_add_to_classpath(const char *classpath);
 int try_to_add_zip_to_classpath(const char *zip);
 char *get_classpath(void);
 
 void classloader_init(void);
-struct vm_class *classloader_load(const char *class_name);
+struct vm_class *classloader_load(struct vm_object *loader,
+                                 const char *class_name);
 struct vm_class *classloader_load_primitive(const char *class_name);
 struct vm_class *classloader_find_class(const char *name);
 
diff --git a/jit/object-bc.c b/jit/object-bc.c
index 25b4847..154213c 100644
--- a/jit/object-bc.c
+++ b/jit/object-bc.c
@@ -46,11 +46,8 @@ static struct vm_class *class_to_array_class(struct vm_class 
*class)
        struct vm_class *array_class;
        char *array_class_name;
 
-       /* XXX: This is not entirely right. We need to make sure that we're
-        * using the same class loader as the original class. We don't support
-        * multiple (different) class loaders yet. */
        array_class_name = class_name_to_array_name(class->name);
-       array_class = classloader_load(array_class_name);
+       array_class = classloader_load(class->classloader, array_class_name);
        free(array_class_name);
 
        return array_class;
diff --git a/vm/class.c b/vm/class.c
index e4e099d..e00d7a4 100644
--- a/vm/class.c
+++ b/vm/class.c
@@ -123,6 +123,7 @@ static int vm_class_link_common(struct vm_class *vmc)
                return -err;
 
        vmc->object = NULL;
+       vmc->classloader = NULL;
 
        return 0;
 }
@@ -237,7 +238,7 @@ int vm_class_link(struct vm_class *vmc, const struct 
cafebabe_class *class)
                        super_name->length);
 
                /* XXX: Circularity check */
-               vmc->super = classloader_load(super_name_str);
+               vmc->super = classloader_load(NULL, super_name_str);
                if (!vmc->super) {
                        NOT_IMPLEMENTED;
                        return -1;
@@ -284,7 +285,7 @@ int vm_class_link(struct vm_class *vmc, const struct 
cafebabe_class *class)
                        return -1;
                }
 
-               struct vm_class *vmi = classloader_load(c_name);
+               struct vm_class *vmi = classloader_load(NULL, c_name);
                free(c_name);
                if (!vmi)
                        return -1;
@@ -635,7 +636,8 @@ struct vm_class *vm_class_resolve_class(const struct 
vm_class *vmc, uint16_t i)
                return NULL;
        }
 
-       struct vm_class *class = classloader_load(class_name_str);
+       struct vm_class *class
+               = classloader_load(vmc->classloader, class_name_str);
        if (!class) {
                NOT_IMPLEMENTED;
                return NULL;
@@ -1063,11 +1065,12 @@ struct vm_class *vm_class_get_array_class(struct 
vm_class *element_class)
        struct vm_class *result;
        char *name;
 
-       if (!asprintf(&name, "[%s", element_class->name))
+       if (!asprintf(&name, "[%s", element_class->name)) {
+               signal_new_exception(vm_java_lang_OutOfMemoryError, NULL);
                return NULL;
+       }
 
-       result = classloader_load(name);
-
+       result = classloader_load(element_class->classloader, name);
        free(name);
        return result;
 }
diff --git a/vm/classloader.c b/vm/classloader.c
index 73bfcd7..fecb48f 100644
--- a/vm/classloader.c
+++ b/vm/classloader.c
@@ -8,8 +8,10 @@
 #include "cafebabe/class.h"
 #include "cafebabe/stream.h"
 
+#include "vm/call.h"
 #include "vm/classloader.h"
 #include "vm/preload.h"
+#include "vm/reflection.h"
 #include "vm/class.h"
 #include "vm/die.h"
 #include "vm/backtrace.h"
@@ -18,6 +20,8 @@
 #include "lib/string.h"
 #include "lib/hash-map.h"
 
+#include "jit/exception.h"
+
 bool opt_trace_classloader;
 static __thread int trace_classloader_level = 0;
 
@@ -406,7 +410,8 @@ struct vm_class *classloader_load_primitive(const char 
*class_name)
        return class;
 }
 
-static struct vm_class *load_array_class(const char *class_name)
+static struct vm_class *
+load_array_class(struct vm_object *loader, const char *class_name)
 {
        struct vm_class *array_class;
        char *elem_class_name;
@@ -436,7 +441,7 @@ static struct vm_class *load_array_class(const char 
*class_name)
                        classloader_load_primitive(elem_class_name);
        } else {
                array_class->array_element_class =
-                       classloader_load(elem_class_name);
+                       classloader_load(loader, elem_class_name);
        }
 
        free(elem_class_name);
@@ -444,13 +449,44 @@ static struct vm_class *load_array_class(const char 
*class_name)
        return array_class;
 }
 
-static struct vm_class *load_class(const char *class_name)
+static struct vm_class *
+load_class_with(struct vm_object *loader, const char *name)
+{
+       struct vm_object *name_string;
+       struct vm_object *clazz;
+       struct vm_class *vmc;
+
+       name_string = vm_object_alloc_string_from_c(name);
+       if (!name_string) {
+               signal_new_exception(vm_java_lang_OutOfMemoryError, NULL);
+               return NULL;
+       }
+
+       clazz = vm_call_method_this_object(vm_java_lang_ClassLoader_loadClass,
+                                          loader, name_string);
+       if (!clazz || exception_occurred())
+               return NULL;
+
+       vmc = vm_object_to_vm_class(clazz);
+       if (!vmc)
+               return NULL;
+
+       vmc->classloader = loader;
+
+       return vmc;
+}
+
+static struct vm_class *load_class(struct vm_object *loader,
+                                  const char *class_name)
 {
        struct vm_class *result;
        char *filename;
 
        if (class_name[0] == '[')
-               return load_array_class(class_name);
+               return load_array_class(loader, class_name);
+
+       if (loader)
+               return load_class_with(loader, class_name);
 
        filename = class_name_to_file_name(class_name);
        if (!filename) {
@@ -501,8 +537,15 @@ static struct classloader_class *find_class(const char 
*name)
        return class;
 }
 
-/* XXX: Should use hash table or tree, not linear search. -Vegard */
-struct vm_class *classloader_load(const char *class_name)
+/**
+ * Loads a class of given name. if @loader is not NULL then
+ * loading of a class will be delegated to @loader.
+ *
+ * If @class_name refers to an array class then @loader
+ * will be called only for array element class.
+ */
+struct vm_class *
+classloader_load(struct vm_object *loader, const char *class_name)
 {
        struct vm_class *vmc;
        struct classloader_class *class;
@@ -542,7 +585,7 @@ struct vm_class *classloader_load(const char *class_name)
         * load_class() because for example vm_class_init() might call
         * classloader_load() for superclasses.
         */
-       vmc = load_class(slash_class_name);
+       vmc = load_class(loader, slash_class_name);
        if (!vmc) {
                pthread_mutex_lock(&classloader_mutex);
 
@@ -565,7 +608,7 @@ struct vm_class *classloader_load(const char *class_name)
 
        pthread_mutex_lock(&classloader_mutex);
 
-       vmc->classloader = NULL;
+       vmc->classloader = loader;
 
        class->class = vmc;
        class->status = CLASS_LOADED;
diff --git a/vm/jato.c b/vm/jato.c
index 4d959cd..9c5e0c9 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -144,8 +144,6 @@ static struct vm_object 
*native_vmstackwalker_getclasscontext(void)
                if (vm_class_ensure_init(vmc))
                        return NULL;
 
-               printf("%d: %s.%s\n", idx, vmc->name, cu->method->name);
-
                array_set_field_object(res, idx++, vmc->object);
        }
 
@@ -541,53 +539,27 @@ native_vmclass_forname(struct vm_object *name, jboolean 
initialize,
 
        if (!name) {
                signal_new_exception(vm_java_lang_NullPointerException, NULL);
-               goto throw;
+               return NULL;
        }
 
-       if (loader != NULL) {
-               struct vm_object *obj;
-
-               obj = vm_call_method_object(vm_java_lang_ClassLoader_loadClass,
-                                         loader, name);
-               if (exception_occurred())
-                       return NULL;
-
-               if (!obj)
-                       goto throw;
-
-               class = vm_class_get_class_from_class_object(obj);
-       } else {
-               class_name = vm_string_to_cstr(name);
-               if (!class_name) {
-                       NOT_IMPLEMENTED;
-                       return NULL;
-               }
-
-               class = classloader_load(class_name);
-               free(class_name);
+       class_name = vm_string_to_cstr(name);
+       if (!class_name) {
+               signal_new_exception(vm_java_lang_OutOfMemoryError, NULL);
+               return NULL;
        }
 
+       class = classloader_load(loader, class_name);
        if (!class)
-               goto throw;
+               goto throw_cnf;
 
        if (initialize) {
-               vm_class_ensure_init(class);
-               if (exception_occurred())
-                       goto throw;
+               if (vm_class_ensure_init(class))
+                       goto throw_cnf;
        }
 
        return class->object;
-
- throw:
-       class_name = vm_string_to_cstr(name);
-
-       if (!class_name) {
-               NOT_IMPLEMENTED;
-               return NULL;
-       }
-
-       signal_new_exception(vm_java_lang_ClassNotFoundException,
-                            class_name);
+ throw_cnf:
+       signal_new_exception(vm_java_lang_ClassNotFoundException, class_name);
        free(class_name);
        return NULL;
 }
@@ -823,7 +795,7 @@ native_vmclassloader_loadclass(struct vm_object *name, 
jboolean resolve)
        if (!c_name)
                return NULL;
 
-       vmc = classloader_load(c_name);
+       vmc = classloader_load(NULL, c_name);
        free(c_name);
        if (!vmc)
                return NULL;
@@ -1218,7 +1190,7 @@ static void parse_options(int argc, char *argv[])
 static int
 do_main_class(void)
 {
-       struct vm_class *vmc = classloader_load(classname);
+       struct vm_class *vmc = classloader_load(NULL, classname);
        if (!vmc) {
                fprintf(stderr, "error: %s: could not load\n", classname);
                return -1;
@@ -1274,7 +1246,7 @@ do_jar_file(void)
 static int
 do_method_trace(void)
 {
-       struct vm_class *vmc = classloader_load(method_trace_class_name);
+       struct vm_class *vmc = classloader_load(NULL, method_trace_class_name);
        if (!vmc) {
                NOT_IMPLEMENTED;
                return -1;
diff --git a/vm/jni-interface.c b/vm/jni-interface.c
index 2e35439..d961c52 100644
--- a/vm/jni-interface.c
+++ b/vm/jni-interface.c
@@ -141,7 +141,8 @@ vm_jni_find_class(struct vm_jni_env *env, const char *name)
 
        enter_vm_from_jni();
 
-       class = classloader_load(name);
+       /* XXX: which classloader should we use here? */
+       class = classloader_load(NULL, name);
        if (!class) {
                signal_new_exception(vm_java_lang_NoClassDefFoundError,
                                     name);
diff --git a/vm/object.c b/vm/object.c
index c8ed0fe..1baa966 100644
--- a/vm/object.c
+++ b/vm/object.c
@@ -78,28 +78,28 @@ struct vm_object *vm_object_alloc_primitive_array(int type, 
int count)
 
        switch (type) {
        case T_BOOLEAN:
-               res->class = classloader_load("[Z");
+               res->class = classloader_load(NULL, "[Z");
                break;
        case T_CHAR:
-               res->class = classloader_load("[C");
+               res->class = classloader_load(NULL, "[C");
                break;
        case T_FLOAT:
-               res->class = classloader_load("[F");
+               res->class = classloader_load(NULL, "[F");
                break;
        case T_DOUBLE:
-               res->class = classloader_load("[D");
+               res->class = classloader_load(NULL, "[D");
                break;
        case T_BYTE:
-               res->class = classloader_load("[B");
+               res->class = classloader_load(NULL, "[B");
                break;
        case T_SHORT:
-               res->class = classloader_load("[S");
+               res->class = classloader_load(NULL, "[S");
                break;
        case T_INT:
-               res->class = classloader_load("[I");
+               res->class = classloader_load(NULL, "[I");
                break;
        case T_LONG:
-               res->class = classloader_load("[J");
+               res->class = classloader_load(NULL, "[J");
                break;
        default:
                NOT_IMPLEMENTED;
diff --git a/vm/preload.c b/vm/preload.c
index 8f83aa1..84bea01 100644
--- a/vm/preload.c
+++ b/vm/preload.c
@@ -437,7 +437,7 @@ int preload_vm_classes(void)
        for (unsigned int i = 0; i < ARRAY_SIZE(preload_entries); ++i) {
                const struct preload_entry *pe = &preload_entries[i];
 
-               struct vm_class *class = classloader_load(pe->name);
+               struct vm_class *class = classloader_load(NULL, pe->name);
                if (!class) {
                        printf("%s\n", pe->name);
                        NOT_IMPLEMENTED;
diff --git a/vm/reflection.c b/vm/reflection.c
index dd53135..178fb92 100644
--- a/vm/reflection.c
+++ b/vm/reflection.c
@@ -299,7 +299,9 @@ native_vmclass_get_declared_constructors(struct vm_object 
*clazz,
        return array;
 }
 
-static struct vm_class *vm_type_to_class(char *type_name, enum vm_type type)
+static struct vm_class *
+vm_type_to_class(struct vm_object *classloader, char *type_name,
+                enum vm_type type)
 {
        switch (type) {
        case J_BOOLEAN:
@@ -321,7 +323,7 @@ static struct vm_class *vm_type_to_class(char *type_name, 
enum vm_type type)
        case J_VOID:
                return vm_void_class;
        case J_REFERENCE:
-               return classloader_load(type_name);
+               return classloader_load(classloader, type_name);
        case J_RETURN_ADDRESS:
        case VM_TYPE_MAX:
                error("invalid type");
@@ -352,7 +354,8 @@ static struct vm_object *get_method_parameter_types(struct 
vm_method *vmm)
        while ((type_str = parse_method_args(type_str, &type, &type_name))) {
                struct vm_class *class;
 
-               class = vm_type_to_class(type_name, type);
+               class = vm_type_to_class(vmm->class->classloader, type_name,
+                                        type);
                free(type_name);
 
                if (class)
@@ -801,6 +804,8 @@ native_method_invokenative(struct vm_object *method, struct 
vm_object *o,
 struct vm_object *native_field_gettype(struct vm_object *this)
 {
        struct vm_field *vmf;
+       enum vm_type vmtype;
+       char *type_name;
 
        if (!this) {
                signal_new_exception(vm_java_lang_NullPointerException, NULL);
@@ -811,15 +816,13 @@ struct vm_object *native_field_gettype(struct vm_object 
*this)
        if (!vmf)
                return 0;
 
-       enum vm_type vmtype;
-       char *type_name;
-
        if (!parse_type(vmf->type, &vmtype, &type_name)) {
                warn("type parsing failed");
                return NULL;
        }
 
-       struct vm_class *vmc = vm_type_to_class(type_name, vmtype);
+       struct vm_class *vmc =
+               vm_type_to_class(vmf->class->classloader, type_name, vmtype);
 
        if (vm_class_ensure_init(vmc))
                return NULL;
-- 
1.6.0.6


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to