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

Reply via email to