When a class was loaded with name in a dot form and if another time classloader would be asked about the same class but in a slash form then classloader will try to load the class again. We should convert class names to slash names at classloader_load() entry to avoid loading the same class twice.
This bug led to infinite loop of initialization of "gnu/java/awt/peer/gtk/GtkComponentPeer" because it is referenced from somewhere in its initialization code with a dot form name: "gnu.java.awt.peer.gtk.GtkComponentPeer". Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- vm/classloader.c | 31 ++++++++++++++++++++++--------- vm/jato.c | 5 ++++- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/vm/classloader.c b/vm/classloader.c index b612c86..173dd78 100644 --- a/vm/classloader.c +++ b/vm/classloader.c @@ -188,6 +188,18 @@ static int lookup_class(const char *class_name) return -1; } +static char *dots_to_slash(const char *name) +{ + char *result = strdup(name); + + for (unsigned int i = 0, n = strlen(name); i < n; ++i) { + if (result[i] == '.') + result[i] = '/'; + } + + return result; +} + static char *class_name_to_file_name(const char *class_name) { char *filename; @@ -197,11 +209,6 @@ static char *class_name_to_file_name(const char *class_name) return NULL; } - for (unsigned int i = 0, n = strlen(class_name); i < n; ++i) { - if (filename[i] == '.') - filename[i] = '/'; - } - return filename; } @@ -450,6 +457,12 @@ struct vm_class *classloader_load(const char *class_name) trace_push(class_name); + char *slash_class_name = dots_to_slash(class_name); + if (!slash_class_name) { + trace_pop(); + return NULL; + } + pthread_mutex_lock(&classloader_mutex); /* @@ -457,8 +470,7 @@ struct vm_class *classloader_load(const char *class_name) * while we're loading a class or waiting for a class to get * loaded the classes array might get relocated. */ - class_index = lookup_class(class_name); - + class_index = lookup_class(slash_class_name); if (class_index >= 0) { /* If class is being loaded by another thread then wait * until loading is completed. */ @@ -492,7 +504,7 @@ struct vm_class *classloader_load(const char *class_name) class_index = nr_classes++; classes[class_index].loaded = false; - classes[class_index].class_name = class_name; + classes[class_index].class_name = slash_class_name; pthread_mutex_unlock(&classloader_mutex); @@ -501,7 +513,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(class_name); + vmc = load_class(slash_class_name); if (!vmc) { NOT_IMPLEMENTED; vmc = NULL; @@ -521,6 +533,7 @@ struct vm_class *classloader_load(const char *class_name) pthread_mutex_unlock(&classloader_mutex); out: + free(slash_class_name); trace_pop(); return vmc; } diff --git a/vm/jato.c b/vm/jato.c index e8f62fa..4a82048 100644 --- a/vm/jato.c +++ b/vm/jato.c @@ -440,7 +440,7 @@ native_vmclass_forname(struct vm_object *name, jboolean initialize, goto throw; } - const char *class_name = vm_string_to_cstr(name); + char *class_name = vm_string_to_cstr(name); if (!class_name) { NOT_IMPLEMENTED; return NULL; @@ -448,6 +448,9 @@ native_vmclass_forname(struct vm_object *name, jboolean initialize, /* TODO: use @loader to load the class. */ struct vm_class *class = classloader_load(class_name); + + free(class_name); + if (!class) { signal_new_exception(vm_java_lang_ClassNotFoundException, class_name); -- 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