< prev index next >

src/hotspot/share/interpreter/interpreterRuntime.cpp

Print this page

        

@@ -378,16 +378,23 @@
   return (type2size[field_type] + type2size[T_OBJECT]) * AbstractInterpreter::stackElementSize;
 JRT_END
 
 JRT_ENTRY(void, InterpreterRuntime::uninitialized_static_value_field(JavaThread* thread, oopDesc* mirror, int index))
   // The interpreter tries to access a flattenable static field that has not been initialized.
-  // This situation can happen only if the load or initialization of the field failed during step 8 of
-  // the initialization of the holder of the field. The code below tries to load and initialize
-  // the field's class again in order to throw likely the same exception or error as the one that caused
-  // the field initialization to fail.
+  // This situation can happen in different scenarios:
+  //   1 - if the load or initialization of the field failed during step 8 of
+  //       the initialization of the holder of the field, in this case the access to the field
+  //       must fail
+  //   2 - it can also happen when the initialization of the holder class triggered the initialization of
+  //       another class which accesses this field in its static initializer, in this case the
+  //       access must succeed to allow circularity
+  // The code below tries to load and initialize the field's class again before returning the default value.
+  // If the field was not initialized because of an error, a exception should be thrown.
+  // If the class is being initialized, the default value is returned.
   instanceHandle mirror_h(THREAD, (instanceOop)mirror);
   InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
+  if (klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD)) {
   int offset = klass->field_offset(index);
   Klass* field_k = klass->get_value_field_klass_or_null(index);
   if (field_k == NULL) {
     field_k = SystemDictionary::resolve_or_fail(klass->field_signature(index)->fundamental_name(THREAD),
         Handle(THREAD, klass->class_loader()),

@@ -395,11 +402,31 @@
         true, CHECK);
     assert(field_k != NULL, "Should have been loaded or an exception thrown above");
     klass->set_value_field_klass(index, field_k);
   }
   field_k->initialize(CHECK);
-  fatal("An exception should have been thrown above");
+    oop defaultvalue = ValueKlass::cast(field_k)->default_value();
+    // It is safe to initialized the static field because 1) the current thread is the initializing thread
+    // and is the only one that can access it, and 2) the field is actually not initialized (i.e. null)
+    // otherwise the JVM should not be executing this code.
+    mirror->obj_field_put(offset, defaultvalue);
+    thread->set_vm_result(defaultvalue);
+  } else {
+    assert(klass->is_in_error_state(), "If not initializing, initialization must have failed to get there");
+    ResourceMark rm(THREAD);
+    const char* desc = "Could not initialize class ";
+    const char* className = klass->external_name();
+    size_t msglen = strlen(desc) + strlen(className) + 1;
+    char* message = NEW_RESOURCE_ARRAY(char, msglen);
+    if (NULL == message) {
+      // Out of memory: can't create detailed error message
+      THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
+    } else {
+      jio_snprintf(message, msglen, "%s%s", desc, className);
+      THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
+    }
+  }
 JRT_END
 
 JRT_ENTRY(void, InterpreterRuntime::uninitialized_instance_value_field(JavaThread* thread, oopDesc* obj, int index))
   instanceHandle obj_h(THREAD, (instanceOop)obj);
   InstanceKlass* klass = InstanceKlass::cast(obj_h()->klass());
< prev index next >