< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page
rev 59277 : [mq]: v3

@@ -224,22 +224,23 @@
 // set once this method returns.
 // Any errors from nest-host resolution must be preserved so they can be queried
 // from higher-level access checking code, and reported as part of access checking
 // exceptions.
 // VirtualMachineErrors are propagated with a NULL return.
+// Under any conditions where the _nest_host can be set to non-NULL the resulting value
+// of it and, if applicable, _nest_host_res_error, are idempotent. But as we can be
+// executing this code concurrently we need to ensure ordering is maintained so that
+// errors messages can safely be read.
 InstanceKlass* InstanceKlass::nest_host(TRAPS) {
   InstanceKlass* nest_host_k = _nest_host;
   if (nest_host_k != NULL) {
     return nest_host_k;
   }
 
   const bool doLog = log_is_enabled(Trace, class, nestmates);
 
-  // need to resolve and save our nest-host class. This could be attempted
-  // concurrently but as the result is idempotent and we don't use the class
-  // then we do not need any synchronization beyond what is implicitly used
-  // during class loading.
+  // need to resolve and save our nest-host class.
   if (_nest_host_index != 0) { // we have a real nest_host
     // Before trying to resolve check if we're in a suitable context
     if (!THREAD->can_call_java() && !_constants->tag_at(_nest_host_index).is_klass()) {
       if (doLog) {
         ResourceMark rm(THREAD);

@@ -266,10 +267,12 @@
       char* target_host_class = _constants->klass_name_at(_nest_host_index)->as_C_string();
       ss.print("Nest host resolution of %s with host %s failed: ",
                this->external_name(), target_host_class);
       java_lang_Throwable::print(PENDING_EXCEPTION, &ss);
       _nest_host_res_error = ss.as_string(true /* on C-heap */);
+      // ensure we see _nest_host_res_error is set if _nest_host is non-NULL
+      OrderAccess::storestore();
       CLEAR_PENDING_EXCEPTION;
       if (doLog) {
         log_trace(class, nestmates)("%s", _nest_host_res_error);
       }
     } else {

@@ -323,10 +326,12 @@
                  this->class_loader_data()->loader_name_and_id(),
                  k->external_name(),
                  k->class_loader_data()->loader_name_and_id(),
                  error);
         _nest_host_res_error = ss.as_string(true /* on C-heap */);
+        // ensure we see _nest_host_res_error is set if _nest_host is non-NULL
+        OrderAccess::storestore();
 
         if (doLog) {
           log_trace(class, nestmates)("%s", _nest_host_res_error);
         }
       }

@@ -338,11 +343,12 @@
                                   this->external_name());
     }
   }
 
   // Either not in an explicit nest, or else an error occurred, so
-  // the nest-host is set to `this`.
+  // the nest-host is set to `this`. Any thread that sees this assignment
+  // will also see any setting of _nest_host_res_error, if applicable.
   return (_nest_host = this);
 }
 
 // Dynamic nest member support: set this class's nest host to the given class.
 // This occurs as part of the class definition, as soon as the instanceKlass
< prev index next >