Loading a class will finish by trying to execute that class' <clinit> (static initializer) method. However, this method may require other classes to load as well. Prior to this patch, it would be possible that a class would (indirectly) try to load itself, which would deadlock.
This patch introduces a new class state, VM_CLASS_INITIALIZING, which will prevent the classloader from trying to execute the class' <clinit> method from within itself. Signed-off-by: Vegard Nossum <vegard.nos...@gmail.com> --- include/vm/class.h | 1 + vm/class.c | 6 ++++-- vm/classloader.c | 4 +++- vm/jato.c | 5 ++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/vm/class.h b/include/vm/class.h index 362853d..a0a2451 100644 --- a/include/vm/class.h +++ b/include/vm/class.h @@ -13,6 +13,7 @@ struct vm_object; enum vm_class_state { VM_CLASS_LOADED, VM_CLASS_LINKED, + VM_CLASS_INITIALIZING, VM_CLASS_INITIALIZED, }; diff --git a/vm/class.c b/vm/class.c index f2d4fa4..cd19840 100644 --- a/vm/class.c +++ b/vm/class.c @@ -201,6 +201,8 @@ int vm_class_init(struct vm_class *vmc, const struct cafebabe_class *class) */ int vm_class_init_object(struct vm_class *vmc) { + assert(vmc->state == VM_CLASS_INITIALIZING); + vmc->object = vm_object_alloc(vm_java_lang_Class); if (!vmc->object) { NOT_IMPLEMENTED; @@ -212,7 +214,7 @@ int vm_class_init_object(struct vm_class *vmc) int vm_class_run_clinit(struct vm_class *vmc) { - assert(vmc->state == VM_CLASS_LINKED); + assert(vmc->state == VM_CLASS_INITIALIZING); /* XXX: Make sure there's at most one of these. */ for (uint16_t i = 0; i < vmc->class->methods_count; ++i) { @@ -254,7 +256,7 @@ struct vm_class *vm_class_resolve_class(struct vm_class *vmc, uint16_t i) return NULL; } - struct vm_class *class = classloader_load(class_name_str); + struct vm_class *class = classloader_load_and_init(class_name_str); if (!class) { NOT_IMPLEMENTED; return NULL; diff --git a/vm/classloader.c b/vm/classloader.c index ca83f69..1ce3cf9 100644 --- a/vm/classloader.c +++ b/vm/classloader.c @@ -474,7 +474,9 @@ struct vm_class *classloader_load_and_init(const char *class_name) if (!vmc) return NULL; - if (vmc->state != VM_CLASS_INITIALIZED) { + if (vmc->state < VM_CLASS_INITIALIZING) { + vmc->state = VM_CLASS_INITIALIZING; + if (vm_class_init_object(vmc)) { NOT_IMPLEMENTED; return NULL; diff --git a/vm/jato.c b/vm/jato.c index 6724477..0819fec 100644 --- a/vm/jato.c +++ b/vm/jato.c @@ -179,8 +179,11 @@ static 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 = *pe->class; - if (vm_class_init_object(*pe->class)) { + class->state = VM_CLASS_INITIALIZING; + + if (vm_class_init_object(class)) { NOT_IMPLEMENTED; return 1; } -- 1.6.0.4 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel