< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page
*** 791,21 ***
    assert(lock != nullptr || !is_not_initialized(), // initialized or in_error state
           "only fully initialized state can have a null lock");
    return lock;
  }
  
! // Set the initialization lock to null so the object can be GC'ed.  Any racing
  // threads to get this lock will see a null lock and will not lock.
  // That's okay because they all check for initialized state after getting
! // the lock and return.
  void InstanceKlass::fence_and_clear_init_lock() {
    // make sure previous stores are all done, notably the init_state.
    OrderAccess::storestore();
    java_lang_Class::clear_init_lock(java_mirror());
    assert(!is_not_initialized(), "class must be initialized now");
  }
  
  
  // See "The Virtual Machine Specification" section 2.16.5 for a detailed explanation of the class initialization
  // process. The step comments refers to the procedure described in that section.
  // Note: implementation moved to static method to expose the this pointer.
  void InstanceKlass::initialize(TRAPS) {
--- 791,30 ---
    assert(lock != nullptr || !is_not_initialized(), // initialized or in_error state
           "only fully initialized state can have a null lock");
    return lock;
  }
  
! // Set the initialization lock to null so the object can be GC'ed. Any racing
  // threads to get this lock will see a null lock and will not lock.
  // That's okay because they all check for initialized state after getting
! // the lock and return. For preempted vthreads we keep the oop protected
+ // in the ObjectMonitor (see ObjectMonitor::set_object_strong()).
  void InstanceKlass::fence_and_clear_init_lock() {
    // make sure previous stores are all done, notably the init_state.
    OrderAccess::storestore();
    java_lang_Class::clear_init_lock(java_mirror());
    assert(!is_not_initialized(), "class must be initialized now");
  }
  
+ void InstanceKlass::initialize_preemptable(TRAPS) {
+   if (this->should_be_initialized()) {
+     PREEMPT_ON_INIT_SUPPORTED_ONLY(PreemptableInitCall pic(THREAD, this);)
+     initialize_impl(THREAD);
+   } else {
+     assert(is_initialized(), "sanity check");
+   }
+ }
  
  // See "The Virtual Machine Specification" section 2.16.5 for a detailed explanation of the class initialization
  // process. The step comments refers to the procedure described in that section.
  // Note: implementation moved to static method to expose the this pointer.
  void InstanceKlass::initialize(TRAPS) {

*** 978,11 ***
  
    // verification & rewriting
    {
      HandleMark hm(THREAD);
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, jt);
      // rewritten will have been set if loader constraint error found
      // on an earlier link attempt
      // don't verify or rewrite if already rewritten
      //
  
--- 987,16 ---
  
    // verification & rewriting
    {
      HandleMark hm(THREAD);
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, CHECK_PREEMPTABLE_false);
+     // Don't allow preemption if we link/initialize classes below,
+     // since that would release this monitor while we are in the
+     // middle of linking this class.
+     NoPreemptMark npm(THREAD);
+ 
      // rewritten will have been set if loader constraint error found
      // on an earlier link attempt
      // don't verify or rewrite if already rewritten
      //
  

*** 1191,11 ***
  
    // refer to the JVM book page 47 for description of steps
    // Step 1
    {
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, jt);
  
      // Step 2
      // If we were to use wait() instead of waitInterruptibly() then
      // we might end up throwing IE from link/symbol resolution sites
      // that aren't expected to throw.  This would wreak havoc.  See 6320309.
--- 1205,11 ---
  
    // refer to the JVM book page 47 for description of steps
    // Step 1
    {
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, CHECK_PREEMPTABLE);
  
      // Step 2
      // If we were to use wait() instead of waitInterruptibly() then
      // we might end up throwing IE from link/symbol resolution sites
      // that aren't expected to throw.  This would wreak havoc.  See 6320309.

*** 1204,13 ***
          ResourceMark rm(jt);
          log_debug(class, init)("Thread \"%s\" waiting for initialization of %s by thread \"%s\"",
                                 jt->name(), external_name(), init_thread_name());
        }
        wait = true;
!       jt->set_class_to_be_initialized(this);
!       ol.wait_uninterruptibly(jt);
-       jt->set_class_to_be_initialized(nullptr);
      }
  
      // Step 3
      if (is_being_initialized() && is_reentrant_initialization(jt)) {
        if (debug_logging_enabled) {
--- 1218,12 ---
          ResourceMark rm(jt);
          log_debug(class, init)("Thread \"%s\" waiting for initialization of %s by thread \"%s\"",
                                 jt->name(), external_name(), init_thread_name());
        }
        wait = true;
!       ThreadWaitingForClassInit twcl(THREAD, this);
!       ol.wait_uninterruptibly(CHECK_PREEMPTABLE);
      }
  
      // Step 3
      if (is_being_initialized() && is_reentrant_initialization(jt)) {
        if (debug_logging_enabled) {

*** 1264,10 ***
--- 1277,14 ---
                                 jt->name(), external_name());
        }
      }
    }
  
+   // Block preemption once we are the initializer thread. Unmounting now
+   // would complicate the reentrant case (identity is platform thread).
+   NoPreemptMark npm(THREAD);
+ 
    // Step 7
    // Next, if C is a class rather than an interface, initialize it's super class and super
    // interfaces.
    if (!is_interface()) {
      Klass* super_klass = super();
< prev index next >