Merge

Fri, 26 Jan 2018 10:50:22 -0800

author
asaha
date
Fri, 26 Jan 2018 10:50:22 -0800
changeset 9368
161d69083789
parent 9363
a786d379eacb
parent 9367
d2bd0355eb74
child 9370
e3108b56c0cf

Merge

.hgtags file | annotate | diff | comparison | revisions
src/share/vm/oops/klass.cpp file | annotate | diff | comparison | revisions
test/runtime/RedefineFinalizer/RedefineFinalizer.java file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Fri Jan 26 09:59:10 2018 -0800
     1.2 +++ b/.hgtags	Fri Jan 26 10:50:22 2018 -0800
     1.3 @@ -1131,6 +1131,7 @@
     1.4  39e2895b795aded8b584626fb019d35f12e9d1e7 jdk8u162-b11
     1.5  69aec2ca5d905dde1d0f29a89076d02a531808a3 jdk8u162-b12
     1.6  caac74fe3cfa9a8c859c28c97d1046a58252af27 jdk8u162-b31
     1.7 +c9b7abadf150328d2187de05b9e8a9cba2486e47 jdk8u162-b32
     1.8  a17bab9405474602b18cd62e060a09b17d6413ac jdk8u171-b00
     1.9  ebfd57cc21e6b7f0c22b17c666b6b28c9340e207 jdk8u171-b01
    1.10  1acd7c1b80241def8fac90f70b0df16356adad47 jdk8u171-b02
     2.1 --- a/src/share/vm/classfile/metadataOnStackMark.cpp	Fri Jan 26 09:59:10 2018 -0800
     2.2 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp	Fri Jan 26 10:50:22 2018 -0800
     2.3 @@ -41,13 +41,13 @@
     2.4  // Walk metadata on the stack and mark it so that redefinition doesn't delete
     2.5  // it.  Class unloading also walks the previous versions and might try to
     2.6  // delete it, so this class is used by class unloading also.
     2.7 -MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) {
     2.8 +MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) {
     2.9    assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
    2.10    assert(_used_buffers == NULL, "sanity check");
    2.11    NOT_PRODUCT(_is_active = true;)
    2.12  
    2.13    Threads::metadata_do(Metadata::mark_on_stack);
    2.14 -  if (visit_code_cache) {
    2.15 +  if (has_redefined_a_class) {
    2.16      CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
    2.17    }
    2.18    CompileBroker::mark_on_stack();
     3.1 --- a/src/share/vm/classfile/metadataOnStackMark.hpp	Fri Jan 26 09:59:10 2018 -0800
     3.2 +++ b/src/share/vm/classfile/metadataOnStackMark.hpp	Fri Jan 26 10:50:22 2018 -0800
     3.3 @@ -47,7 +47,7 @@
     3.4    static void retire_buffer(MetadataOnStackBuffer* buffer);
     3.5  
     3.6   public:
     3.7 -  MetadataOnStackMark(bool visit_code_cache);
     3.8 +  MetadataOnStackMark(bool has_redefined_a_class);
     3.9     ~MetadataOnStackMark();
    3.10  
    3.11    static void record(Metadata* m, Thread* thread);
     4.1 --- a/src/share/vm/code/nmethod.cpp	Fri Jan 26 09:59:10 2018 -0800
     4.2 +++ b/src/share/vm/code/nmethod.cpp	Fri Jan 26 10:50:22 2018 -0800
     4.3 @@ -2172,7 +2172,7 @@
     4.4                 "metadata must be found in exactly one place");
     4.5          if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
     4.6            Metadata* md = r->metadata_value();
     4.7 -          f(md);
     4.8 +          if (md != _method) f(md);
     4.9          }
    4.10        } else if (iter.type() == relocInfo::virtual_call_type) {
    4.11          // Check compiledIC holders associated with this nmethod
    4.12 @@ -2198,7 +2198,7 @@
    4.13      f(md);
    4.14    }
    4.15  
    4.16 -  // Visit metadata not embedded in the other places.
    4.17 +  // Call function Method*, not embedded in these other places.
    4.18    if (_method != NULL) f(_method);
    4.19  }
    4.20  
     5.1 --- a/src/share/vm/oops/instanceKlass.cpp	Fri Jan 26 09:59:10 2018 -0800
     5.2 +++ b/src/share/vm/oops/instanceKlass.cpp	Fri Jan 26 10:50:22 2018 -0800
     5.3 @@ -2582,16 +2582,6 @@
     5.4      assert(breakpoints() == 0x0, "should have cleared breakpoints");
     5.5    }
     5.6  
     5.7 -  // deallocate information about previous versions
     5.8 -  if (_previous_versions != NULL) {
     5.9 -    for (int i = _previous_versions->length() - 1; i >= 0; i--) {
    5.10 -      PreviousVersionNode * pv_node = _previous_versions->at(i);
    5.11 -      delete pv_node;
    5.12 -    }
    5.13 -    delete _previous_versions;
    5.14 -    _previous_versions = NULL;
    5.15 -  }
    5.16 -
    5.17    // deallocate the cached class file
    5.18    if (_cached_class_file != NULL) {
    5.19      os::free(_cached_class_file, mtClass);
    5.20 @@ -3187,16 +3177,17 @@
    5.21    st->print(BULLET"field type annotations:  "); fields_type_annotations()->print_value_on(st); st->cr();
    5.22    {
    5.23      bool have_pv = false;
    5.24 -    PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
    5.25 -    for (PreviousVersionNode * pv_node = pvw.next_previous_version();
    5.26 -         pv_node != NULL; pv_node = pvw.next_previous_version()) {
    5.27 +    // previous versions are linked together through the InstanceKlass
    5.28 +    for (InstanceKlass* pv_node = _previous_versions;
    5.29 +         pv_node != NULL;
    5.30 +         pv_node = pv_node->previous_versions()) {
    5.31        if (!have_pv)
    5.32          st->print(BULLET"previous version:  ");
    5.33        have_pv = true;
    5.34 -      pv_node->prev_constant_pool()->print_value_on(st);
    5.35 +      pv_node->constants()->print_value_on(st);
    5.36      }
    5.37      if (have_pv) st->cr();
    5.38 -  } // pvw is cleaned up
    5.39 +  }
    5.40  
    5.41    if (generic_signature() != NULL) {
    5.42      st->print(BULLET"generic signature: ");
    5.43 @@ -3610,205 +3601,126 @@
    5.44  // RedefineClasses() support for previous versions:
    5.45  
    5.46  // Purge previous versions
    5.47 -static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) {
    5.48 +void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
    5.49    if (ik->previous_versions() != NULL) {
    5.50      // This klass has previous versions so see what we can cleanup
    5.51      // while it is safe to do so.
    5.52  
    5.53      int deleted_count = 0;    // leave debugging breadcrumbs
    5.54      int live_count = 0;
    5.55 -    ClassLoaderData* loader_data = ik->class_loader_data() == NULL ?
    5.56 -                       ClassLoaderData::the_null_class_loader_data() :
    5.57 -                       ik->class_loader_data();
    5.58 +    ClassLoaderData* loader_data = ik->class_loader_data();
    5.59 +    assert(loader_data != NULL, "should never be null");
    5.60  
    5.61      // RC_TRACE macro has an embedded ResourceMark
    5.62 -    RC_TRACE(0x00000200, ("purge: %s: previous version length=%d",
    5.63 -      ik->external_name(), ik->previous_versions()->length()));
    5.64 -
    5.65 -    for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
    5.66 -      // check the previous versions array
    5.67 -      PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
    5.68 -      ConstantPool* cp_ref = pv_node->prev_constant_pool();
    5.69 -      assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
    5.70 -
    5.71 -      ConstantPool* pvcp = cp_ref;
    5.72 +    RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
    5.73 +
    5.74 +    // previous versions are linked together through the InstanceKlass
    5.75 +    InstanceKlass* pv_node = ik->previous_versions();
    5.76 +    InstanceKlass* last = ik;
    5.77 +    int version = 0;
    5.78 +
    5.79 +    // check the previous versions list
    5.80 +    for (; pv_node != NULL; ) {
    5.81 +
    5.82 +      ConstantPool* pvcp = pv_node->constants();
    5.83 +      assert(pvcp != NULL, "cp ref was unexpectedly cleared");
    5.84 +
    5.85 +
    5.86        if (!pvcp->on_stack()) {
    5.87          // If the constant pool isn't on stack, none of the methods
    5.88 -        // are executing.  Delete all the methods, the constant pool and
    5.89 -        // and this previous version node.
    5.90 -        GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
    5.91 -        if (method_refs != NULL) {
    5.92 -          for (int j = method_refs->length() - 1; j >= 0; j--) {
    5.93 -            Method* method = method_refs->at(j);
    5.94 -            assert(method != NULL, "method ref was unexpectedly cleared");
    5.95 -            method_refs->remove_at(j);
    5.96 -            // method will be freed with associated class.
    5.97 -          }
    5.98 -        }
    5.99 -        // Remove the constant pool
   5.100 -        delete pv_node;
   5.101 -        // Since we are traversing the array backwards, we don't have to
   5.102 -        // do anything special with the index.
   5.103 -        ik->previous_versions()->remove_at(i);
   5.104 +        // are executing.  Unlink this previous_version.
   5.105 +        // The previous version InstanceKlass is on the ClassLoaderData deallocate list
   5.106 +        // so will be deallocated during the next phase of class unloading.
   5.107 +        pv_node = pv_node->previous_versions();
   5.108 +        last->link_previous_versions(pv_node);
   5.109          deleted_count++;
   5.110 +        version++;
   5.111          continue;
   5.112        } else {
   5.113 -        RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i));
   5.114 +        RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
   5.115 +                              pv_node));
   5.116          assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
   5.117          guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
   5.118          live_count++;
   5.119        }
   5.120  
   5.121 -      // At least one method is live in this previous version, clean out
   5.122 -      // the others or mark them as obsolete.
   5.123 -      GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
   5.124 +      // At least one method is live in this previous version so clean its MethodData.
   5.125 +      // Reset dead EMCP methods not to get breakpoints.
   5.126 +      // All methods are deallocated when all of the methods for this class are no
   5.127 +      // longer running.
   5.128 +      Array<Method*>* method_refs = pv_node->methods();
   5.129        if (method_refs != NULL) {
   5.130          RC_TRACE(0x00000200, ("purge: previous methods length=%d",
   5.131            method_refs->length()));
   5.132 -        for (int j = method_refs->length() - 1; j >= 0; j--) {
   5.133 +        for (int j = 0; j < method_refs->length(); j++) {
   5.134            Method* method = method_refs->at(j);
   5.135 -          assert(method != NULL, "method ref was unexpectedly cleared");
   5.136 -
   5.137 -          // Remove the emcp method if it's not executing
   5.138 -          // If it's been made obsolete by a redefinition of a non-emcp
   5.139 -          // method, mark it as obsolete but leave it to clean up later.
   5.140 +
   5.141            if (!method->on_stack()) {
   5.142 -            method_refs->remove_at(j);
   5.143 -          } else if (emcp_method_count == 0) {
   5.144 -            method->set_is_obsolete();
   5.145 +            // no breakpoints for non-running methods
   5.146 +            if (method->is_running_emcp()) {
   5.147 +              method->set_running_emcp(false);
   5.148 +            }
   5.149            } else {
   5.150 +            assert (method->is_obsolete() || method->is_running_emcp(),
   5.151 +                    "emcp method cannot run after emcp bit is cleared");
   5.152              // RC_TRACE macro has an embedded ResourceMark
   5.153              RC_TRACE(0x00000200,
   5.154                ("purge: %s(%s): prev method @%d in version @%d is alive",
   5.155                method->name()->as_C_string(),
   5.156 -              method->signature()->as_C_string(), j, i));
   5.157 +              method->signature()->as_C_string(), j, version));
   5.158 +            if (method->method_data() != NULL) {
   5.159 +              // Clean out any weak method links for running methods
   5.160 +              // (also should include not EMCP methods)
   5.161 +              method->method_data()->clean_weak_method_links();
   5.162 +            }
   5.163            }
   5.164          }
   5.165        }
   5.166 +      // next previous version
   5.167 +      last = pv_node;
   5.168 +      pv_node = pv_node->previous_versions();
   5.169 +      version++;
   5.170      }
   5.171 -    assert(ik->previous_versions()->length() == live_count, "sanity check");
   5.172      RC_TRACE(0x00000200,
   5.173        ("purge: previous version stats: live=%d, deleted=%d", live_count,
   5.174        deleted_count));
   5.175    }
   5.176 +
   5.177 +  // Clean MethodData of this class's methods so they don't refer to
   5.178 +  // old methods that are no longer running.
   5.179 +  Array<Method*>* methods = ik->methods();
   5.180 +  int num_methods = methods->length();
   5.181 +  for (int index2 = 0; index2 < num_methods; ++index2) {
   5.182 +    if (methods->at(index2)->method_data() != NULL) {
   5.183 +      methods->at(index2)->method_data()->clean_weak_method_links();
   5.184 +    }
   5.185 +  }
   5.186  }
   5.187  
   5.188 -// External interface for use during class unloading.
   5.189 -void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
   5.190 -  // Call with >0 emcp methods since they are not currently being redefined.
   5.191 -  purge_previous_versions_internal(ik, 1);
   5.192 -}
   5.193 -
   5.194 -
   5.195 -// Potentially add an information node that contains pointers to the
   5.196 -// interesting parts of the previous version of the_class.
   5.197 -// This is also where we clean out any unused references.
   5.198 -// Note that while we delete nodes from the _previous_versions
   5.199 -// array, we never delete the array itself until the klass is
   5.200 -// unloaded. The has_been_redefined() query depends on that fact.
   5.201 -//
   5.202 -void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
   5.203 -       BitMap* emcp_methods, int emcp_method_count) {
   5.204 -  assert(Thread::current()->is_VM_thread(),
   5.205 -         "only VMThread can add previous versions");
   5.206 -
   5.207 -  if (_previous_versions == NULL) {
   5.208 -    // This is the first previous version so make some space.
   5.209 -    // Start with 2 elements under the assumption that the class
   5.210 -    // won't be redefined much.
   5.211 -    _previous_versions =  new (ResourceObj::C_HEAP, mtClass)
   5.212 -                            GrowableArray<PreviousVersionNode *>(2, true);
   5.213 -  }
   5.214 -
   5.215 -  ConstantPool* cp_ref = ikh->constants();
   5.216 -
   5.217 -  // RC_TRACE macro has an embedded ResourceMark
   5.218 -  RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d "
   5.219 -                        "on_stack=%d",
   5.220 -    ikh->external_name(), _previous_versions->length(), emcp_method_count,
   5.221 -    cp_ref->on_stack()));
   5.222 -
   5.223 -  // If the constant pool for this previous version of the class
   5.224 -  // is not marked as being on the stack, then none of the methods
   5.225 -  // in this previous version of the class are on the stack so
   5.226 -  // we don't need to create a new PreviousVersionNode. However,
   5.227 -  // we still need to examine older previous versions below.
   5.228 -  Array<Method*>* old_methods = ikh->methods();
   5.229 -
   5.230 -  if (cp_ref->on_stack()) {
   5.231 -    PreviousVersionNode * pv_node = NULL;
   5.232 -    if (emcp_method_count == 0) {
   5.233 -      // non-shared ConstantPool gets a reference
   5.234 -      pv_node = new PreviousVersionNode(cp_ref, NULL);
   5.235 -      RC_TRACE(0x00000400,
   5.236 -          ("add: all methods are obsolete; flushing any EMCP refs"));
   5.237 -    } else {
   5.238 -      int local_count = 0;
   5.239 -      GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass)
   5.240 -          GrowableArray<Method*>(emcp_method_count, true);
   5.241 -      for (int i = 0; i < old_methods->length(); i++) {
   5.242 -        if (emcp_methods->at(i)) {
   5.243 -            // this old method is EMCP. Save it only if it's on the stack
   5.244 -            Method* old_method = old_methods->at(i);
   5.245 -            if (old_method->on_stack()) {
   5.246 -              method_refs->append(old_method);
   5.247 -            }
   5.248 -          if (++local_count >= emcp_method_count) {
   5.249 -            // no more EMCP methods so bail out now
   5.250 -            break;
   5.251 -          }
   5.252 -        }
   5.253 -      }
   5.254 -      // non-shared ConstantPool gets a reference
   5.255 -      pv_node = new PreviousVersionNode(cp_ref, method_refs);
   5.256 -    }
   5.257 -    // append new previous version.
   5.258 -    _previous_versions->append(pv_node);
   5.259 -  }
   5.260 -
   5.261 -  // Since the caller is the VMThread and we are at a safepoint, this
   5.262 -  // is a good time to clear out unused references.
   5.263 -
   5.264 -  RC_TRACE(0x00000400, ("add: previous version length=%d",
   5.265 -    _previous_versions->length()));
   5.266 -
   5.267 -  // Purge previous versions not executing on the stack
   5.268 -  purge_previous_versions_internal(this, emcp_method_count);
   5.269 -
   5.270 +void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
   5.271 +                                                int emcp_method_count) {
   5.272    int obsolete_method_count = old_methods->length() - emcp_method_count;
   5.273  
   5.274    if (emcp_method_count != 0 && obsolete_method_count != 0 &&
   5.275 -      _previous_versions->length() > 0) {
   5.276 +      _previous_versions != NULL) {
   5.277      // We have a mix of obsolete and EMCP methods so we have to
   5.278      // clear out any matching EMCP method entries the hard way.
   5.279      int local_count = 0;
   5.280      for (int i = 0; i < old_methods->length(); i++) {
   5.281 -      if (!emcp_methods->at(i)) {
   5.282 +      Method* old_method = old_methods->at(i);
   5.283 +      if (old_method->is_obsolete()) {
   5.284          // only obsolete methods are interesting
   5.285 -        Method* old_method = old_methods->at(i);
   5.286          Symbol* m_name = old_method->name();
   5.287          Symbol* m_signature = old_method->signature();
   5.288  
   5.289 -        // we might not have added the last entry
   5.290 -        for (int j = _previous_versions->length() - 1; j >= 0; j--) {
   5.291 -          // check the previous versions array for non executing obsolete methods
   5.292 -          PreviousVersionNode * pv_node = _previous_versions->at(j);
   5.293 -
   5.294 -          GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
   5.295 -          if (method_refs == NULL) {
   5.296 -            // We have run into a PreviousVersion generation where
   5.297 -            // all methods were made obsolete during that generation's
   5.298 -            // RedefineClasses() operation. At the time of that
   5.299 -            // operation, all EMCP methods were flushed so we don't
   5.300 -            // have to go back any further.
   5.301 -            //
   5.302 -            // A NULL method_refs is different than an empty method_refs.
   5.303 -            // We cannot infer any optimizations about older generations
   5.304 -            // from an empty method_refs for the current generation.
   5.305 -            break;
   5.306 -          }
   5.307 -
   5.308 -          for (int k = method_refs->length() - 1; k >= 0; k--) {
   5.309 +        // previous versions are linked together through the InstanceKlass
   5.310 +        int j = 0;
   5.311 +        for (InstanceKlass* prev_version = _previous_versions;
   5.312 +             prev_version != NULL;
   5.313 +             prev_version = prev_version->previous_versions(), j++) {
   5.314 +
   5.315 +          Array<Method*>* method_refs = prev_version->methods();
   5.316 +          for (int k = 0; k < method_refs->length(); k++) {
   5.317              Method* method = method_refs->at(k);
   5.318  
   5.319              if (!method->is_obsolete() &&
   5.320 @@ -3816,14 +3728,11 @@
   5.321                  method->signature() == m_signature) {
   5.322                // The current RedefineClasses() call has made all EMCP
   5.323                // versions of this method obsolete so mark it as obsolete
   5.324 -              // and remove the reference.
   5.325                RC_TRACE(0x00000400,
   5.326                  ("add: %s(%s): flush obsolete method @%d in version @%d",
   5.327                  m_name->as_C_string(), m_signature->as_C_string(), k, j));
   5.328  
   5.329                method->set_is_obsolete();
   5.330 -              // Leave obsolete methods on the previous version list to
   5.331 -              // clean up later.
   5.332                break;
   5.333              }
   5.334            }
   5.335 @@ -3831,9 +3740,9 @@
   5.336            // The previous loop may not find a matching EMCP method, but
   5.337            // that doesn't mean that we can optimize and not go any
   5.338            // further back in the PreviousVersion generations. The EMCP
   5.339 -          // method for this generation could have already been deleted,
   5.340 +          // method for this generation could have already been made obsolete,
   5.341            // but there still may be an older EMCP method that has not
   5.342 -          // been deleted.
   5.343 +          // been made obsolete.
   5.344          }
   5.345  
   5.346          if (++local_count >= obsolete_method_count) {
   5.347 @@ -3843,30 +3752,67 @@
   5.348        }
   5.349      }
   5.350    }
   5.351 -} // end add_previous_version()
   5.352 -
   5.353 -
   5.354 -// Determine if InstanceKlass has a previous version.
   5.355 -bool InstanceKlass::has_previous_version() const {
   5.356 -  return (_previous_versions != NULL && _previous_versions->length() > 0);
   5.357 -} // end has_previous_version()
   5.358 -
   5.359 -
   5.360 -InstanceKlass* InstanceKlass::get_klass_version(int version) {
   5.361 -  if (constants()->version() == version) {
   5.362 -    return this;
   5.363 +}
   5.364 +
   5.365 +// Save the scratch_class as the previous version if any of the methods are running.
   5.366 +// The previous_versions are used to set breakpoints in EMCP methods and they are
   5.367 +// also used to clean MethodData links to redefined methods that are no longer running.
   5.368 +void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
   5.369 +                                         int emcp_method_count) {
   5.370 +  assert(Thread::current()->is_VM_thread(),
   5.371 +         "only VMThread can add previous versions");
   5.372 +
   5.373 +  // RC_TRACE macro has an embedded ResourceMark
   5.374 +  RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
   5.375 +    scratch_class->external_name(), emcp_method_count));
   5.376 +
   5.377 +  // Clean out old previous versions
   5.378 +  purge_previous_versions(this);
   5.379 +
   5.380 +  // Mark newly obsolete methods in remaining previous versions.  An EMCP method from
   5.381 +  // a previous redefinition may be made obsolete by this redefinition.
   5.382 +  Array<Method*>* old_methods = scratch_class->methods();
   5.383 +  mark_newly_obsolete_methods(old_methods, emcp_method_count);
   5.384 +
   5.385 +  // If the constant pool for this previous version of the class
   5.386 +  // is not marked as being on the stack, then none of the methods
   5.387 +  // in this previous version of the class are on the stack so
   5.388 +  // we don't need to add this as a previous version.
   5.389 +  ConstantPool* cp_ref = scratch_class->constants();
   5.390 +  if (!cp_ref->on_stack()) {
   5.391 +    RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
   5.392 +    return;
   5.393    }
   5.394 -  PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
   5.395 -  for (PreviousVersionNode * pv_node = pvw.next_previous_version();
   5.396 -       pv_node != NULL; pv_node = pvw.next_previous_version()) {
   5.397 -    ConstantPool* prev_cp = pv_node->prev_constant_pool();
   5.398 -    if (prev_cp->version() == version) {
   5.399 -      return prev_cp->pool_holder();
   5.400 +
   5.401 +  if (emcp_method_count != 0) {
   5.402 +    // At least one method is still running, check for EMCP methods
   5.403 +    for (int i = 0; i < old_methods->length(); i++) {
   5.404 +      Method* old_method = old_methods->at(i);
   5.405 +      if (!old_method->is_obsolete() && old_method->on_stack()) {
   5.406 +        // if EMCP method (not obsolete) is on the stack, mark as EMCP so that
   5.407 +        // we can add breakpoints for it.
   5.408 +
   5.409 +        // We set the method->on_stack bit during safepoints for class redefinition and
   5.410 +        // class unloading and use this bit to set the is_running_emcp bit.
   5.411 +        // After the safepoint, the on_stack bit is cleared and the running emcp
   5.412 +        // method may exit.   If so, we would set a breakpoint in a method that
   5.413 +        // is never reached, but this won't be noticeable to the programmer.
   5.414 +        old_method->set_running_emcp(true);
   5.415 +        RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
   5.416 +                              old_method->name_and_sig_as_C_string(), old_method));
   5.417 +      } else if (!old_method->is_obsolete()) {
   5.418 +        RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
   5.419 +                              old_method->name_and_sig_as_C_string(), old_method));
   5.420 +      }
   5.421      }
   5.422    }
   5.423 -  return NULL; // None found
   5.424 -}
   5.425 -
   5.426 +
   5.427 +  // Add previous version if any methods are still running.
   5.428 +  RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
   5.429 +  assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
   5.430 +  scratch_class->link_previous_versions(previous_versions());
   5.431 +  link_previous_versions(scratch_class());
   5.432 +} // end add_previous_version()
   5.433  
   5.434  Method* InstanceKlass::method_with_idnum(int idnum) {
   5.435    Method* m = NULL;
   5.436 @@ -3924,61 +3870,3 @@
   5.437  unsigned char * InstanceKlass::get_cached_class_file_bytes() {
   5.438    return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
   5.439  }
   5.440 -
   5.441 -
   5.442 -// Construct a PreviousVersionNode entry for the array hung off
   5.443 -// the InstanceKlass.
   5.444 -PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool,
   5.445 -  GrowableArray<Method*>* prev_EMCP_methods) {
   5.446 -
   5.447 -  _prev_constant_pool = prev_constant_pool;
   5.448 -  _prev_EMCP_methods = prev_EMCP_methods;
   5.449 -}
   5.450 -
   5.451 -
   5.452 -// Destroy a PreviousVersionNode
   5.453 -PreviousVersionNode::~PreviousVersionNode() {
   5.454 -  if (_prev_constant_pool != NULL) {
   5.455 -    _prev_constant_pool = NULL;
   5.456 -  }
   5.457 -
   5.458 -  if (_prev_EMCP_methods != NULL) {
   5.459 -    delete _prev_EMCP_methods;
   5.460 -  }
   5.461 -}
   5.462 -
   5.463 -// Construct a helper for walking the previous versions array
   5.464 -PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) {
   5.465 -  _thread = thread;
   5.466 -  _previous_versions = ik->previous_versions();
   5.467 -  _current_index = 0;
   5.468 -  _current_p = NULL;
   5.469 -  _current_constant_pool_handle = constantPoolHandle(thread, ik->constants());
   5.470 -}
   5.471 -
   5.472 -
   5.473 -// Return the interesting information for the next previous version
   5.474 -// of the klass. Returns NULL if there are no more previous versions.
   5.475 -PreviousVersionNode* PreviousVersionWalker::next_previous_version() {
   5.476 -  if (_previous_versions == NULL) {
   5.477 -    // no previous versions so nothing to return
   5.478 -    return NULL;
   5.479 -  }
   5.480 -
   5.481 -  _current_p = NULL;  // reset to NULL
   5.482 -  _current_constant_pool_handle = NULL;
   5.483 -
   5.484 -  int length = _previous_versions->length();
   5.485 -
   5.486 -  while (_current_index < length) {
   5.487 -    PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
   5.488 -
   5.489 -    // Save a handle to the constant pool for this previous version,
   5.490 -    // which keeps all the methods from being deallocated.
   5.491 -    _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool());
   5.492 -    _current_p = pv_node;
   5.493 -    return pv_node;
   5.494 -  }
   5.495 -
   5.496 -  return NULL;
   5.497 -} // end next_previous_version()
     6.1 --- a/src/share/vm/oops/instanceKlass.hpp	Fri Jan 26 09:59:10 2018 -0800
     6.2 +++ b/src/share/vm/oops/instanceKlass.hpp	Fri Jan 26 10:50:22 2018 -0800
     6.3 @@ -88,7 +88,6 @@
     6.4  class fieldDescriptor;
     6.5  class DepChange;
     6.6  class nmethodBucket;
     6.7 -class PreviousVersionNode;
     6.8  class JvmtiCachedClassFieldMap;
     6.9  class MemberNameTable;
    6.10  
    6.11 @@ -235,7 +234,8 @@
    6.12      _misc_is_anonymous             = 1 << 3, // has embedded _host_klass field
    6.13      _misc_is_contended             = 1 << 4, // marked with contended annotation
    6.14      _misc_has_default_methods      = 1 << 5, // class/superclass/implemented interfaces has default methods
    6.15 -    _misc_declares_default_methods = 1 << 6  // directly declares default methods (any access)
    6.16 +    _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access)
    6.17 +    _misc_has_been_redefined       = 1 << 7  // class has been redefined
    6.18    };
    6.19    u2              _misc_flags;
    6.20    u2              _minor_version;        // minor version number of class file
    6.21 @@ -250,9 +250,8 @@
    6.22    nmethodBucket*  _dependencies;         // list of dependent nmethods
    6.23    nmethod*        _osr_nmethods_head;    // Head of list of on-stack replacement nmethods for this class
    6.24    BreakpointInfo* _breakpoints;          // bpt lists, managed by Method*
    6.25 -  // Array of interesting part(s) of the previous version(s) of this
    6.26 -  // InstanceKlass. See PreviousVersionWalker below.
    6.27 -  GrowableArray<PreviousVersionNode *>* _previous_versions;
    6.28 +  // Linked instanceKlasses of previous versions
    6.29 +  InstanceKlass* _previous_versions;
    6.30    // JVMTI fields can be moved to their own structure - see 6315920
    6.31    // JVMTI: cached class file, before retransformable agent modified it in CFLH
    6.32    JvmtiCachedClassFileData* _cached_class_file;
    6.33 @@ -669,21 +668,31 @@
    6.34    }
    6.35  
    6.36    // RedefineClasses() support for previous versions:
    6.37 -  void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods,
    6.38 -         int emcp_method_count);
    6.39 -  // If the _previous_versions array is non-NULL, then this klass
    6.40 -  // has been redefined at least once even if we aren't currently
    6.41 -  // tracking a previous version.
    6.42 -  bool has_been_redefined() const { return _previous_versions != NULL; }
    6.43 -  bool has_previous_version() const;
    6.44 +  void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
    6.45 +
    6.46 +  InstanceKlass* previous_versions() const { return _previous_versions; }
    6.47 +
    6.48 +  bool has_been_redefined() const {
    6.49 +    return (_misc_flags & _misc_has_been_redefined) != 0;
    6.50 +  }
    6.51 +  void set_has_been_redefined() {
    6.52 +    _misc_flags |= _misc_has_been_redefined;
    6.53 +  }
    6.54 +
    6.55    void init_previous_versions() {
    6.56      _previous_versions = NULL;
    6.57    }
    6.58 -  GrowableArray<PreviousVersionNode *>* previous_versions() const {
    6.59 -    return _previous_versions;
    6.60 +
    6.61 +
    6.62 +  InstanceKlass* get_klass_version(int version) {
    6.63 +    for (InstanceKlass* ik = this; ik != NULL; ik = ik->previous_versions()) {
    6.64 +      if (ik->constants()->version() == version) {
    6.65 +        return ik;
    6.66 +      }
    6.67 +    }
    6.68 +    return NULL;
    6.69    }
    6.70  
    6.71 -  InstanceKlass* get_klass_version(int version);
    6.72    static void purge_previous_versions(InstanceKlass* ik);
    6.73  
    6.74    // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
    6.75 @@ -1124,6 +1133,10 @@
    6.76  
    6.77    // Free CHeap allocated fields.
    6.78    void release_C_heap_structures();
    6.79 +
    6.80 +  // RedefineClasses support
    6.81 +  void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }
    6.82 +  void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count);
    6.83  public:
    6.84    // CDS support - remove and restore oops from metadata. Oops are not shared.
    6.85    virtual void remove_unshareable_info();
    6.86 @@ -1222,62 +1235,6 @@
    6.87  };
    6.88  
    6.89  
    6.90 -// If breakpoints are more numerous than just JVMTI breakpoints,
    6.91 -// consider compressing this data structure.
    6.92 -// It is currently a simple linked list defined in method.hpp.
    6.93 -
    6.94 -class BreakpointInfo;
    6.95 -
    6.96 -
    6.97 -// A collection point for interesting information about the previous
    6.98 -// version(s) of an InstanceKlass.  A GrowableArray of PreviousVersionNodes
    6.99 -// is attached to the InstanceKlass as needed. See PreviousVersionWalker below.
   6.100 -class PreviousVersionNode : public CHeapObj<mtClass> {
   6.101 - private:
   6.102 -  ConstantPool*    _prev_constant_pool;
   6.103 -
   6.104 -  // If the previous version of the InstanceKlass doesn't have any
   6.105 -  // EMCP methods, then _prev_EMCP_methods will be NULL. If all the
   6.106 -  // EMCP methods have been collected, then _prev_EMCP_methods can
   6.107 -  // have a length of zero.
   6.108 -  GrowableArray<Method*>* _prev_EMCP_methods;
   6.109 -
   6.110 -public:
   6.111 -  PreviousVersionNode(ConstantPool* prev_constant_pool,
   6.112 -                      GrowableArray<Method*>* prev_EMCP_methods);
   6.113 -  ~PreviousVersionNode();
   6.114 -  ConstantPool* prev_constant_pool() const {
   6.115 -    return _prev_constant_pool;
   6.116 -  }
   6.117 -  GrowableArray<Method*>* prev_EMCP_methods() const {
   6.118 -    return _prev_EMCP_methods;
   6.119 -  }
   6.120 -};
   6.121 -
   6.122 -
   6.123 -// Helper object for walking previous versions.
   6.124 -class PreviousVersionWalker : public StackObj {
   6.125 - private:
   6.126 -  Thread*                               _thread;
   6.127 -  GrowableArray<PreviousVersionNode *>* _previous_versions;
   6.128 -  int                                   _current_index;
   6.129 -
   6.130 -  // A pointer to the current node object so we can handle the deletes.
   6.131 -  PreviousVersionNode*                  _current_p;
   6.132 -
   6.133 -  // The constant pool handle keeps all the methods in this class from being
   6.134 -  // deallocated from the metaspace during class unloading.
   6.135 -  constantPoolHandle                    _current_constant_pool_handle;
   6.136 -
   6.137 - public:
   6.138 -  PreviousVersionWalker(Thread* thread, InstanceKlass *ik);
   6.139 -
   6.140 -  // Return the interesting information for the next previous version
   6.141 -  // of the klass. Returns NULL if there are no more previous versions.
   6.142 -  PreviousVersionNode* next_previous_version();
   6.143 -};
   6.144 -
   6.145 -
   6.146  //
   6.147  // nmethodBucket is used to record dependent nmethods for
   6.148  // deoptimization.  nmethod dependencies are actually <klass, method>
     7.1 --- a/src/share/vm/oops/klass.cpp	Fri Jan 26 09:59:10 2018 -0800
     7.2 +++ b/src/share/vm/oops/klass.cpp	Fri Jan 26 10:50:22 2018 -0800
     7.3 @@ -468,6 +468,12 @@
     7.4      if (clean_alive_klasses && current->oop_is_instance()) {
     7.5        InstanceKlass* ik = InstanceKlass::cast(current);
     7.6        ik->clean_weak_instanceklass_links(is_alive);
     7.7 +
     7.8 +      // JVMTI RedefineClasses creates previous versions that are not in
     7.9 +      // the class hierarchy, so process them here.
    7.10 +      while ((ik = ik->previous_versions()) != NULL) {
    7.11 +        ik->clean_weak_instanceklass_links(is_alive);
    7.12 +      }
    7.13      }
    7.14    }
    7.15  }
     8.1 --- a/src/share/vm/oops/method.cpp	Fri Jan 26 09:59:10 2018 -0800
     8.2 +++ b/src/share/vm/oops/method.cpp	Fri Jan 26 10:50:22 2018 -0800
     8.3 @@ -91,6 +91,7 @@
     8.4    set_hidden(false);
     8.5    set_dont_inline(false);
     8.6    set_has_injected_profile(false);
     8.7 +  set_running_emcp(false);
     8.8    set_method_data(NULL);
     8.9    clear_method_counters();
    8.10    set_vtable_index(Method::garbage_vtable_index);
     9.1 --- a/src/share/vm/oops/method.hpp	Fri Jan 26 09:59:10 2018 -0800
     9.2 +++ b/src/share/vm/oops/method.hpp	Fri Jan 26 10:50:22 2018 -0800
     9.3 @@ -111,6 +111,7 @@
     9.4                      _caller_sensitive     : 1,
     9.5                      _force_inline         : 1,
     9.6                      _hidden               : 1,
     9.7 +                    _running_emcp         : 1,
     9.8                      _dont_inline          : 1,
     9.9                      _has_injected_profile : 1,
    9.10                                            : 2;
    9.11 @@ -712,6 +713,21 @@
    9.12    void set_is_obsolete()                            { _access_flags.set_is_obsolete(); }
    9.13    bool is_deleted() const                           { return access_flags().is_deleted(); }
    9.14    void set_is_deleted()                             { _access_flags.set_is_deleted(); }
    9.15 +
    9.16 +  bool is_running_emcp() const {
    9.17 +    // EMCP methods are old but not obsolete or deleted. Equivalent
    9.18 +    // Modulo Constant Pool means the method is equivalent except
    9.19 +    // the constant pool and instructions that access the constant
    9.20 +    // pool might be different.
    9.21 +    // If a breakpoint is set in a redefined method, its EMCP methods that are
    9.22 +    // still running must have a breakpoint also.
    9.23 +    return _running_emcp;
    9.24 +  }
    9.25 +
    9.26 +  void set_running_emcp(bool x) {
    9.27 +    _running_emcp = x;
    9.28 +  }
    9.29 +
    9.30    bool on_stack() const                             { return access_flags().on_stack(); }
    9.31    void set_on_stack(const bool value);
    9.32  
    10.1 --- a/src/share/vm/oops/methodData.cpp	Fri Jan 26 09:59:10 2018 -0800
    10.2 +++ b/src/share/vm/oops/methodData.cpp	Fri Jan 26 10:50:22 2018 -0800
    10.3 @@ -1559,9 +1559,35 @@
    10.4    }
    10.5  }
    10.6  
    10.7 -// Remove SpeculativeTrapData entries that reference an unloaded
    10.8 -// method
    10.9 -void MethodData::clean_extra_data(BoolObjectClosure* is_alive) {
   10.10 +class CleanExtraDataClosure : public StackObj {
   10.11 +public:
   10.12 +  virtual bool is_live(Method* m) = 0;
   10.13 +};
   10.14 +
   10.15 +// Check for entries that reference an unloaded method
   10.16 +class CleanExtraDataKlassClosure : public CleanExtraDataClosure {
   10.17 +private:
   10.18 +  BoolObjectClosure* _is_alive;
   10.19 +public:
   10.20 +  CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {}
   10.21 +  bool is_live(Method* m) {
   10.22 +    return m->method_holder()->is_loader_alive(_is_alive);
   10.23 +  }
   10.24 +};
   10.25 +
   10.26 +// Check for entries that reference a redefined method
   10.27 +class CleanExtraDataMethodClosure : public CleanExtraDataClosure {
   10.28 +public:
   10.29 +  CleanExtraDataMethodClosure() {}
   10.30 +  bool is_live(Method* m) {
   10.31 +    return m->on_stack();
   10.32 +  }
   10.33 +};
   10.34 +
   10.35 +
   10.36 +// Remove SpeculativeTrapData entries that reference an unloaded or
   10.37 +// redefined method
   10.38 +void MethodData::clean_extra_data(CleanExtraDataClosure* cl) {
   10.39    DataLayout* dp  = extra_data_base();
   10.40    DataLayout* end = extra_data_limit();
   10.41  
   10.42 @@ -1572,7 +1598,7 @@
   10.43        SpeculativeTrapData* data = new SpeculativeTrapData(dp);
   10.44        Method* m = data->method();
   10.45        assert(m != NULL, "should have a method");
   10.46 -      if (!m->method_holder()->is_loader_alive(is_alive)) {
   10.47 +      if (!cl->is_live(m)) {
   10.48          // "shift" accumulates the number of cells for dead
   10.49          // SpeculativeTrapData entries that have been seen so
   10.50          // far. Following entries must be shifted left by that many
   10.51 @@ -1603,9 +1629,9 @@
   10.52    }
   10.53  }
   10.54  
   10.55 -// Verify there's no unloaded method referenced by a
   10.56 +// Verify there's no unloaded or redefined method referenced by a
   10.57  // SpeculativeTrapData entry
   10.58 -void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) {
   10.59 +void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) {
   10.60  #ifdef ASSERT
   10.61    DataLayout* dp  = extra_data_base();
   10.62    DataLayout* end = extra_data_limit();
   10.63 @@ -1615,7 +1641,7 @@
   10.64      case DataLayout::speculative_trap_data_tag: {
   10.65        SpeculativeTrapData* data = new SpeculativeTrapData(dp);
   10.66        Method* m = data->method();
   10.67 -      assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist");
   10.68 +      assert(m != NULL && cl->is_live(m), "Method should exist");
   10.69        break;
   10.70      }
   10.71      case DataLayout::bit_data_tag:
   10.72 @@ -1641,6 +1667,19 @@
   10.73      parameters->clean_weak_klass_links(is_alive);
   10.74    }
   10.75  
   10.76 -  clean_extra_data(is_alive);
   10.77 -  verify_extra_data_clean(is_alive);
   10.78 +  CleanExtraDataKlassClosure cl(is_alive);
   10.79 +  clean_extra_data(&cl);
   10.80 +  verify_extra_data_clean(&cl);
   10.81  }
   10.82 +
   10.83 +void MethodData::clean_weak_method_links() {
   10.84 +  for (ProfileData* data = first_data();
   10.85 +       is_valid(data);
   10.86 +       data = next_data(data)) {
   10.87 +    data->clean_weak_method_links();
   10.88 +  }
   10.89 +
   10.90 +  CleanExtraDataMethodClosure cl;
   10.91 +  clean_extra_data(&cl);
   10.92 +  verify_extra_data_clean(&cl);
   10.93 +}
    11.1 --- a/src/share/vm/oops/methodData.hpp	Fri Jan 26 09:59:10 2018 -0800
    11.2 +++ b/src/share/vm/oops/methodData.hpp	Fri Jan 26 10:50:22 2018 -0800
    11.3 @@ -251,6 +251,9 @@
    11.4  
    11.5    // GC support
    11.6    void clean_weak_klass_links(BoolObjectClosure* cl);
    11.7 +
    11.8 +  // Redefinition support
    11.9 +  void clean_weak_method_links();
   11.10  };
   11.11  
   11.12  
   11.13 @@ -508,6 +511,9 @@
   11.14    // GC support
   11.15    virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {}
   11.16  
   11.17 +  // Redefinition support
   11.18 +  virtual void clean_weak_method_links() {}
   11.19 +
   11.20    // CI translation: ProfileData can represent both MethodDataOop data
   11.21    // as well as CIMethodData data. This function is provided for translating
   11.22    // an oop in a ProfileData to the ci equivalent. Generally speaking,
   11.23 @@ -2030,6 +2036,7 @@
   11.24  //
   11.25  
   11.26  CC_INTERP_ONLY(class BytecodeInterpreter;)
   11.27 +class CleanExtraDataClosure;
   11.28  
   11.29  class MethodData : public Metadata {
   11.30    friend class VMStructs;
   11.31 @@ -2183,9 +2190,9 @@
   11.32    static bool profile_parameters_jsr292_only();
   11.33    static bool profile_all_parameters();
   11.34  
   11.35 -  void clean_extra_data(BoolObjectClosure* is_alive);
   11.36 +  void clean_extra_data(CleanExtraDataClosure* cl);
   11.37    void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false);
   11.38 -  void verify_extra_data_clean(BoolObjectClosure* is_alive);
   11.39 +  void verify_extra_data_clean(CleanExtraDataClosure* cl);
   11.40  
   11.41  public:
   11.42    static int header_size() {
   11.43 @@ -2477,6 +2484,8 @@
   11.44    static bool profile_return_jsr292_only();
   11.45  
   11.46    void clean_method_data(BoolObjectClosure* is_alive);
   11.47 +
   11.48 +  void clean_weak_method_links();
   11.49  };
   11.50  
   11.51  #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
    12.1 --- a/src/share/vm/prims/jvmtiImpl.cpp	Fri Jan 26 09:59:10 2018 -0800
    12.2 +++ b/src/share/vm/prims/jvmtiImpl.cpp	Fri Jan 26 10:50:22 2018 -0800
    12.3 @@ -282,39 +282,22 @@
    12.4  void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
    12.5    ((Method*)_method->*meth_act)(_bci);
    12.6  
    12.7 -  // add/remove breakpoint to/from versions of the method that
    12.8 -  // are EMCP. Directly or transitively obsolete methods are
    12.9 -  // not saved in the PreviousVersionNodes.
   12.10 +  // add/remove breakpoint to/from versions of the method that are EMCP.
   12.11    Thread *thread = Thread::current();
   12.12    instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
   12.13    Symbol* m_name = _method->name();
   12.14    Symbol* m_signature = _method->signature();
   12.15  
   12.16    // search previous versions if they exist
   12.17 -  PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh());
   12.18 -  for (PreviousVersionNode * pv_node = pvw.next_previous_version();
   12.19 -       pv_node != NULL; pv_node = pvw.next_previous_version()) {
   12.20 -    GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods();
   12.21 -
   12.22 -    if (methods == NULL) {
   12.23 -      // We have run into a PreviousVersion generation where
   12.24 -      // all methods were made obsolete during that generation's
   12.25 -      // RedefineClasses() operation. At the time of that
   12.26 -      // operation, all EMCP methods were flushed so we don't
   12.27 -      // have to go back any further.
   12.28 -      //
   12.29 -      // A NULL methods array is different than an empty methods
   12.30 -      // array. We cannot infer any optimizations about older
   12.31 -      // generations from an empty methods array for the current
   12.32 -      // generation.
   12.33 -      break;
   12.34 -    }
   12.35 +  for (InstanceKlass* pv_node = ikh->previous_versions();
   12.36 +       pv_node != NULL;
   12.37 +       pv_node = pv_node->previous_versions()) {
   12.38 +    Array<Method*>* methods = pv_node->methods();
   12.39  
   12.40      for (int i = methods->length() - 1; i >= 0; i--) {
   12.41        Method* method = methods->at(i);
   12.42 -      // obsolete methods that are running are not deleted from
   12.43 -      // previous version array, but they are skipped here.
   12.44 -      if (!method->is_obsolete() &&
   12.45 +      // Only set breakpoints in running EMCP methods.
   12.46 +      if (method->is_running_emcp() &&
   12.47            method->name() == m_name &&
   12.48            method->signature() == m_signature) {
   12.49          RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
    13.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Fri Jan 26 09:59:10 2018 -0800
    13.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Fri Jan 26 10:50:22 2018 -0800
    13.3 @@ -3435,13 +3435,12 @@
    13.4      }
    13.5  
    13.6      // the previous versions' constant pool caches may need adjustment
    13.7 -    PreviousVersionWalker pvw(_thread, ik);
    13.8 -    for (PreviousVersionNode * pv_node = pvw.next_previous_version();
    13.9 -         pv_node != NULL; pv_node = pvw.next_previous_version()) {
   13.10 -      other_cp = pv_node->prev_constant_pool();
   13.11 -      cp_cache = other_cp->cache();
   13.12 +    for (InstanceKlass* pv_node = ik->previous_versions();
   13.13 +         pv_node != NULL;
   13.14 +         pv_node = pv_node->previous_versions()) {
   13.15 +      cp_cache = pv_node->constants()->cache();
   13.16        if (cp_cache != NULL) {
   13.17 -        cp_cache->adjust_method_entries(other_cp->pool_holder(), &trace_name_printed);
   13.18 +        cp_cache->adjust_method_entries(pv_node, &trace_name_printed);
   13.19        }
   13.20      }
   13.21    }
   13.22 @@ -3461,9 +3460,8 @@
   13.23    }
   13.24  }
   13.25  
   13.26 -void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
   13.27 -       BitMap *emcp_methods, int * emcp_method_count_p) {
   13.28 -  *emcp_method_count_p = 0;
   13.29 +int VM_RedefineClasses::check_methods_and_mark_as_obsolete() {
   13.30 +  int emcp_method_count = 0;
   13.31    int obsolete_count = 0;
   13.32    int old_index = 0;
   13.33    for (int j = 0; j < _matching_methods_length; ++j, ++old_index) {
   13.34 @@ -3537,9 +3535,9 @@
   13.35        // that we get from effectively overwriting the old methods
   13.36        // when the new methods are attached to the_class.
   13.37  
   13.38 -      // track which methods are EMCP for add_previous_version() call
   13.39 -      emcp_methods->set_bit(old_index);
   13.40 -      (*emcp_method_count_p)++;
   13.41 +      // Count number of methods that are EMCP.  The method will be marked
   13.42 +      // old but not obsolete if it is EMCP.
   13.43 +      emcp_method_count++;
   13.44  
   13.45        // An EMCP method is _not_ obsolete. An obsolete method has a
   13.46        // different jmethodID than the current method. An EMCP method
   13.47 @@ -3589,10 +3587,11 @@
   13.48                            old_method->name()->as_C_string(),
   13.49                            old_method->signature()->as_C_string()));
   13.50    }
   13.51 -  assert((*emcp_method_count_p + obsolete_count) == _old_methods->length(),
   13.52 +  assert((emcp_method_count + obsolete_count) == _old_methods->length(),
   13.53      "sanity check");
   13.54 -  RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", *emcp_method_count_p,
   13.55 +  RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", emcp_method_count,
   13.56      obsolete_count));
   13.57 +  return emcp_method_count;
   13.58  }
   13.59  
   13.60  // This internal class transfers the native function registration from old methods
   13.61 @@ -3973,11 +3972,8 @@
   13.62    old_constants->set_pool_holder(scratch_class());
   13.63  #endif
   13.64  
   13.65 -  // track which methods are EMCP for add_previous_version() call below
   13.66 -  BitMap emcp_methods(_old_methods->length());
   13.67 -  int emcp_method_count = 0;
   13.68 -  emcp_methods.clear();  // clears 0..(length() - 1)
   13.69 -  check_methods_and_mark_as_obsolete(&emcp_methods, &emcp_method_count);
   13.70 +  // track number of methods that are EMCP for add_previous_version() call below
   13.71 +  int emcp_method_count = check_methods_and_mark_as_obsolete();
   13.72    transfer_old_native_function_registrations(the_class);
   13.73  
   13.74    // The class file bytes from before any retransformable agents mucked
   13.75 @@ -4064,9 +4060,10 @@
   13.76      scratch_class->enclosing_method_method_index());
   13.77    scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx);
   13.78  
   13.79 +  the_class->set_has_been_redefined();
   13.80 +
   13.81    // keep track of previous versions of this class
   13.82 -  the_class->add_previous_version(scratch_class, &emcp_methods,
   13.83 -    emcp_method_count);
   13.84 +  the_class->add_previous_version(scratch_class, emcp_method_count);
   13.85  
   13.86    RC_TIMER_STOP(_timer_rsc_phase1);
   13.87    RC_TIMER_START(_timer_rsc_phase2);
    14.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.hpp	Fri Jan 26 09:59:10 2018 -0800
    14.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp	Fri Jan 26 10:50:22 2018 -0800
    14.3 @@ -403,14 +403,9 @@
    14.4    // Change jmethodIDs to point to the new methods
    14.5    void update_jmethod_ids();
    14.6  
    14.7 -  // In addition to marking methods as obsolete, this routine
    14.8 -  // records which methods are EMCP (Equivalent Module Constant
    14.9 -  // Pool) in the emcp_methods BitMap and returns the number of
   14.10 -  // EMCP methods via emcp_method_count_p. This information is
   14.11 -  // used when information about the previous version of the_class
   14.12 -  // is squirreled away.
   14.13 -  void check_methods_and_mark_as_obsolete(BitMap *emcp_methods,
   14.14 -         int * emcp_method_count_p);
   14.15 +  // In addition to marking methods as old and/or obsolete, this routine
   14.16 +  // counts the number of methods that are EMCP (Equivalent Module Constant Pool).
   14.17 +  int check_methods_and_mark_as_obsolete();
   14.18    void transfer_old_native_function_registrations(instanceKlassHandle the_class);
   14.19  
   14.20    // Install the redefinition of a class
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/compiler/profiling/spectrapredefineclass/Agent.java	Fri Jan 26 10:50:22 2018 -0800
    15.3 @@ -0,0 +1,142 @@
    15.4 +/*
    15.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.7 + *
    15.8 + * This code is free software; you can redistribute it and/or modify it
    15.9 + * under the terms of the GNU General Public License version 2 only, as
   15.10 + * published by the Free Software Foundation.
   15.11 + *
   15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   15.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15.15 + * version 2 for more details (a copy is included in the LICENSE file that
   15.16 + * accompanied this code).
   15.17 + *
   15.18 + * You should have received a copy of the GNU General Public License version
   15.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   15.21 + *
   15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   15.23 + * or visit www.oracle.com if you need additional information or have any
   15.24 + * questions.
   15.25 + */
   15.26 +
   15.27 +import java.security.*;
   15.28 +import java.lang.instrument.*;
   15.29 +import java.lang.reflect.*;
   15.30 +import java.lang.management.ManagementFactory;
   15.31 +import com.sun.tools.attach.VirtualMachine;
   15.32 +
   15.33 +class A {
   15.34 +    void m() {
   15.35 +    }
   15.36 +}
   15.37 +
   15.38 +class B extends A {
   15.39 +    void m() {
   15.40 +    }
   15.41 +}
   15.42 +
   15.43 +class C extends A {
   15.44 +    void m() {
   15.45 +    }
   15.46 +}
   15.47 +
   15.48 +class Test {
   15.49 +
   15.50 +    static public void m() throws Exception {
   15.51 +        for (int i = 0; i < 20000; i++) {
   15.52 +            m1(a);
   15.53 +        }
   15.54 +        for (int i = 0; i < 4; i++) {
   15.55 +            m1(b);
   15.56 +        }
   15.57 +    }
   15.58 +
   15.59 +    static boolean m1(A a) {
   15.60 +        boolean res =  Agent.m2(a);
   15.61 +        return res;
   15.62 +    }
   15.63 +
   15.64 +    static public A a = new A();
   15.65 +    static public B b = new B();
   15.66 +    static public C c = new C();
   15.67 +}
   15.68 +
   15.69 +public class Agent implements ClassFileTransformer {
   15.70 +
   15.71 +
   15.72 +    static class MemoryChunk {
   15.73 +        MemoryChunk other;
   15.74 +        long[] array;
   15.75 +        MemoryChunk(MemoryChunk other) {
   15.76 +            other = other;
   15.77 +            array = new long[1024 * 1024 * 1024];
   15.78 +        }
   15.79 +    }
   15.80 +
   15.81 +    static public boolean m2(A a) {
   15.82 +        boolean res = false;
   15.83 +        if (a.getClass() == B.class) {
   15.84 +            a.m();
   15.85 +        } else {
   15.86 +            res = true;
   15.87 +        }
   15.88 +        return res;
   15.89 +    }
   15.90 +
   15.91 +    static public void main(String[] args) throws Exception {
   15.92 +        // Create speculative trap entries
   15.93 +        Test.m();
   15.94 +
   15.95 +        String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
   15.96 +        int p = nameOfRunningVM.indexOf('@');
   15.97 +        String pid = nameOfRunningVM.substring(0, p);
   15.98 +
   15.99 +        // Make the nmethod go away
  15.100 +        for (int i = 0; i < 10; i++) {
  15.101 +            System.gc();
  15.102 +        }
  15.103 +
  15.104 +        // Redefine class
  15.105 +        try {
  15.106 +            VirtualMachine vm = VirtualMachine.attach(pid);
  15.107 +            vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", "");
  15.108 +            vm.detach();
  15.109 +        } catch (Exception e) {
  15.110 +            throw new RuntimeException(e);
  15.111 +        }
  15.112 +
  15.113 +        Test.m();
  15.114 +        // GC will hit dead method pointer
  15.115 +        for (int i = 0; i < 10; i++) {
  15.116 +            System.gc();
  15.117 +        }
  15.118 +    }
  15.119 +
  15.120 +    public synchronized byte[] transform(final ClassLoader classLoader,
  15.121 +                                         final String className,
  15.122 +                                         Class<?> classBeingRedefined,
  15.123 +                                         ProtectionDomain protectionDomain,
  15.124 +                                         byte[] classfileBuffer) {
  15.125 +        System.out.println("Transforming class " + className);
  15.126 +        return classfileBuffer;
  15.127 +    }
  15.128 +
  15.129 +    public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
  15.130 +
  15.131 +        try {
  15.132 +            instrumentation.retransformClasses(to_redefine);
  15.133 +        } catch (Exception e) {
  15.134 +            e.printStackTrace();
  15.135 +        }
  15.136 +
  15.137 +    }
  15.138 +
  15.139 +    public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception {
  15.140 +        Agent transformer = new Agent();
  15.141 +        instrumentation.addTransformer(transformer, true);
  15.142 +
  15.143 +        redefine(agentArgs, instrumentation, Test.class);
  15.144 +    }
  15.145 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/compiler/profiling/spectrapredefineclass/Launcher.java	Fri Jan 26 10:50:22 2018 -0800
    16.3 @@ -0,0 +1,47 @@
    16.4 +/*
    16.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.
   16.11 + *
   16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.15 + * version 2 for more details (a copy is included in the LICENSE file that
   16.16 + * accompanied this code).
   16.17 + *
   16.18 + * You should have received a copy of the GNU General Public License version
   16.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.21 + *
   16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.23 + * or visit www.oracle.com if you need additional information or have any
   16.24 + * questions.
   16.25 + */
   16.26 +import java.io.PrintWriter;
   16.27 +import com.oracle.java.testlibrary.*;
   16.28 +
   16.29 +/*
   16.30 + * @test
   16.31 + * @bug 8038636
   16.32 + * @library /testlibrary
   16.33 + * @build Agent
   16.34 + * @run main ClassFileInstaller Agent
   16.35 + * @run main Launcher
   16.36 + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent
   16.37 + */
   16.38 +public class Launcher {
   16.39 +    public static void main(String[] args) throws Exception  {
   16.40 +
   16.41 +      PrintWriter pw = new PrintWriter("MANIFEST.MF");
   16.42 +      pw.println("Agent-Class: Agent");
   16.43 +      pw.println("Can-Retransform-Classes: true");
   16.44 +      pw.close();
   16.45 +
   16.46 +      ProcessBuilder pb = new ProcessBuilder();
   16.47 +      pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", System.getProperty("test.classes",".") + "/agent.jar", "Agent.class"});
   16.48 +      pb.start().waitFor();
   16.49 +    }
   16.50 +}
    17.1 --- a/test/runtime/RedefineFinalizer/RedefineFinalizer.java	Fri Jan 26 09:59:10 2018 -0800
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,64 +0,0 @@
    17.4 -/*
    17.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    17.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.7 - *
    17.8 - * This code is free software; you can redistribute it and/or modify it
    17.9 - * under the terms of the GNU General Public License version 2 only, as
   17.10 - * published by the Free Software Foundation.
   17.11 - *
   17.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
   17.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17.14 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   17.15 - * version 2 for more details (a copy is included in the LICENSE file that
   17.16 - * accompanied this code).
   17.17 - *
   17.18 - * You should have received a copy of the GNU General Public License version
   17.19 - * 2 along with this work; if not, write to the Free Software Foundation,
   17.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   17.21 - *
   17.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   17.23 - * or visit www.oracle.com if you need additional information or have any
   17.24 - * questions.
   17.25 - */
   17.26 -
   17.27 -/*
   17.28 - * @test
   17.29 - * @bug 6904403
   17.30 - * @summary Don't assert if we redefine finalize method
   17.31 - * @library /testlibrary
   17.32 - * @build RedefineClassHelper
   17.33 - * @run main RedefineClassHelper
   17.34 - * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
   17.35 - */
   17.36 -
   17.37 -/*
   17.38 - * Regression test for hitting:
   17.39 - *
   17.40 - * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
   17.41 - *
   17.42 - * when redefining finalizer method
   17.43 - */
   17.44 -public class RedefineFinalizer {
   17.45 -
   17.46 -    public static String newB =
   17.47 -                "class RedefineFinalizer$B {" +
   17.48 -                "   protected void finalize() { " +
   17.49 -                "       System.out.println(\"Finalizer called\");" +
   17.50 -                "   }" +
   17.51 -                "}";
   17.52 -
   17.53 -    public static void main(String[] args) throws Exception {
   17.54 -        RedefineClassHelper.redefineClass(B.class, newB);
   17.55 -
   17.56 -        A a = new A();
   17.57 -    }
   17.58 -
   17.59 -    static class A extends B {
   17.60 -    }
   17.61 -
   17.62 -    static class B {
   17.63 -        protected void finalize() {
   17.64 -            // should be empty
   17.65 -        }
   17.66 -    }
   17.67 -}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/test/runtime/RedefineTests/RedefineFinalizer.java	Fri Jan 26 10:50:22 2018 -0800
    18.3 @@ -0,0 +1,64 @@
    18.4 +/*
    18.5 + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
    18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.7 + *
    18.8 + * This code is free software; you can redistribute it and/or modify it
    18.9 + * under the terms of the GNU General Public License version 2 only, as
   18.10 + * published by the Free Software Foundation.
   18.11 + *
   18.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   18.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   18.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   18.15 + * version 2 for more details (a copy is included in the LICENSE file that
   18.16 + * accompanied this code).
   18.17 + *
   18.18 + * You should have received a copy of the GNU General Public License version
   18.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   18.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   18.21 + *
   18.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   18.23 + * or visit www.oracle.com if you need additional information or have any
   18.24 + * questions.
   18.25 + */
   18.26 +
   18.27 +/*
   18.28 + * @test
   18.29 + * @bug 6904403
   18.30 + * @summary Don't assert if we redefine finalize method
   18.31 + * @library /testlibrary
   18.32 + * @build RedefineClassHelper
   18.33 + * @run main RedefineClassHelper
   18.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
   18.35 + */
   18.36 +
   18.37 +/*
   18.38 + * Regression test for hitting:
   18.39 + *
   18.40 + * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
   18.41 + *
   18.42 + * when redefining finalizer method
   18.43 + */
   18.44 +public class RedefineFinalizer {
   18.45 +
   18.46 +    public static String newB =
   18.47 +                "class RedefineFinalizer$B {" +
   18.48 +                "   protected void finalize() { " +
   18.49 +                "       System.out.println(\"Finalizer called\");" +
   18.50 +                "   }" +
   18.51 +                "}";
   18.52 +
   18.53 +    public static void main(String[] args) throws Exception {
   18.54 +        RedefineClassHelper.redefineClass(B.class, newB);
   18.55 +
   18.56 +        A a = new A();
   18.57 +    }
   18.58 +
   18.59 +    static class A extends B {
   18.60 +    }
   18.61 +
   18.62 +    static class B {
   18.63 +        protected void finalize() {
   18.64 +            // should be empty
   18.65 +        }
   18.66 +    }
   18.67 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/runtime/RedefineTests/RedefineRunningMethods.java	Fri Jan 26 10:50:22 2018 -0800
    19.3 @@ -0,0 +1,143 @@
    19.4 +/*
    19.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + *
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.
   19.11 + *
   19.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.15 + * version 2 for more details (a copy is included in the LICENSE file that
   19.16 + * accompanied this code).
   19.17 + *
   19.18 + * You should have received a copy of the GNU General Public License version
   19.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.21 + *
   19.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   19.23 + * or visit www.oracle.com if you need additional information or have any
   19.24 + * questions.
   19.25 + */
   19.26 +
   19.27 +/*
   19.28 + * @test
   19.29 + * @bug 8055008
   19.30 + * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
   19.31 + * @library /testlibrary
   19.32 + * @build RedefineClassHelper
   19.33 + * @run main RedefineClassHelper
   19.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethods
   19.35 + */
   19.36 +public class RedefineRunningMethods {
   19.37 +
   19.38 +    public static String newB =
   19.39 +                "class RedefineRunningMethods$B {" +
   19.40 +                "   static int count1 = 0;" +
   19.41 +                "   static int count2 = 0;" +
   19.42 +                "   public static volatile boolean stop = false;" +
   19.43 +                "  static void localSleep() { " +
   19.44 +                "    try{ " +
   19.45 +                "      Thread.currentThread().sleep(10);" +
   19.46 +                "    } catch(InterruptedException ie) { " +
   19.47 +                "    } " +
   19.48 +                " } " +
   19.49 +                "   public static void infinite() { " +
   19.50 +                "       System.out.println(\"infinite called\");" +
   19.51 +                "   }" +
   19.52 +                "   public static void infinite_emcp() { " +
   19.53 +                "       while (!stop) { count2++; localSleep(); }" +
   19.54 +                "   }" +
   19.55 +                "}";
   19.56 +
   19.57 +    public static String evenNewerB =
   19.58 +                "class RedefineRunningMethods$B {" +
   19.59 +                "   static int count1 = 0;" +
   19.60 +                "   static int count2 = 0;" +
   19.61 +                "   public static volatile boolean stop = false;" +
   19.62 +                "  static void localSleep() { " +
   19.63 +                "    try{ " +
   19.64 +                "      Thread.currentThread().sleep(1);" +
   19.65 +                "    } catch(InterruptedException ie) { " +
   19.66 +                "    } " +
   19.67 +                " } " +
   19.68 +                "   public static void infinite() { }" +
   19.69 +                "   public static void infinite_emcp() { " +
   19.70 +                "       System.out.println(\"infinite_emcp now obsolete called\");" +
   19.71 +                "   }" +
   19.72 +                "}";
   19.73 +
   19.74 +    static class B {
   19.75 +        static int count1 = 0;
   19.76 +        static int count2 = 0;
   19.77 +        public static volatile boolean stop = false;
   19.78 +        static void localSleep() {
   19.79 +          try{
   19.80 +            Thread.currentThread().sleep(10);//sleep for 10 ms
   19.81 +          } catch(InterruptedException ie) {
   19.82 +          }
   19.83 +        }
   19.84 +
   19.85 +        public static void infinite() {
   19.86 +            while (!stop) { count1++; localSleep(); }
   19.87 +        }
   19.88 +        public static void infinite_emcp() {
   19.89 +            while (!stop) { count2++; localSleep(); }
   19.90 +        }
   19.91 +    }
   19.92 +
   19.93 +
   19.94 +    public static void main(String[] args) throws Exception {
   19.95 +
   19.96 +        new Thread() {
   19.97 +            public void run() {
   19.98 +                B.infinite();
   19.99 +            }
  19.100 +        }.start();
  19.101 +
  19.102 +        new Thread() {
  19.103 +            public void run() {
  19.104 +                B.infinite_emcp();
  19.105 +            }
  19.106 +        }.start();
  19.107 +
  19.108 +        RedefineClassHelper.redefineClass(B.class, newB);
  19.109 +
  19.110 +        System.gc();
  19.111 +
  19.112 +        B.infinite();
  19.113 +
  19.114 +        // Start a thread with the second version of infinite_emcp running
  19.115 +        new Thread() {
  19.116 +            public void run() {
  19.117 +                B.infinite_emcp();
  19.118 +            }
  19.119 +        }.start();
  19.120 +
  19.121 +        for (int i = 0; i < 20 ; i++) {
  19.122 +            String s = new String("some garbage");
  19.123 +            System.gc();
  19.124 +        }
  19.125 +
  19.126 +        RedefineClassHelper.redefineClass(B.class, evenNewerB);
  19.127 +        System.gc();
  19.128 +
  19.129 +        for (int i = 0; i < 20 ; i++) {
  19.130 +            B.infinite();
  19.131 +            String s = new String("some garbage");
  19.132 +            System.gc();
  19.133 +        }
  19.134 +
  19.135 +        B.infinite_emcp();
  19.136 +
  19.137 +        // purge should clean everything up.
  19.138 +        B.stop = true;
  19.139 +
  19.140 +        for (int i = 0; i < 20 ; i++) {
  19.141 +            B.infinite();
  19.142 +            String s = new String("some garbage");
  19.143 +            System.gc();
  19.144 +        }
  19.145 +    }
  19.146 +}

mercurial