8026946: JvmtiEnv::SetBreakpoint and JvmtiEnv::ClearBreakpoint should use MethodHandle

Fri, 01 Nov 2013 10:32:36 -0400

author
coleenp
date
Fri, 01 Nov 2013 10:32:36 -0400
changeset 6063
910026b800b8
parent 6062
c8fc12209830
child 6065
f8b56489e455

8026946: JvmtiEnv::SetBreakpoint and JvmtiEnv::ClearBreakpoint should use MethodHandle
8026948: JvmtiEnv::SetBreakpoint and JvmtiEnv::ClearBreakpoint might not work with anonymous classes
Summary: Walk methods in breakpoints for marking on stack so they aren't deallocated by redefine classes. Use class_holder rather than class_loader to keep GC from reclaiming class owning the method.
Reviewed-by: sspitsyn, ehelin, sla

src/share/vm/classfile/metadataOnStackMark.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiImpl.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiImpl.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/classfile/metadataOnStackMark.cpp	Thu Oct 31 14:11:02 2013 -0400
     1.2 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp	Fri Nov 01 10:32:36 2013 -0400
     1.3 @@ -27,6 +27,7 @@
     1.4  #include "code/codeCache.hpp"
     1.5  #include "compiler/compileBroker.hpp"
     1.6  #include "oops/metadata.hpp"
     1.7 +#include "prims/jvmtiImpl.hpp"
     1.8  #include "runtime/synchronizer.hpp"
     1.9  #include "runtime/thread.hpp"
    1.10  #include "utilities/growableArray.hpp"
    1.11 @@ -48,6 +49,7 @@
    1.12    Threads::metadata_do(Metadata::mark_on_stack);
    1.13    CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
    1.14    CompileBroker::mark_on_stack();
    1.15 +  JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
    1.16  }
    1.17  
    1.18  MetadataOnStackMark::~MetadataOnStackMark() {
     2.1 --- a/src/share/vm/prims/jvmtiImpl.cpp	Thu Oct 31 14:11:02 2013 -0400
     2.2 +++ b/src/share/vm/prims/jvmtiImpl.cpp	Fri Nov 01 10:32:36 2013 -0400
     2.3 @@ -210,6 +210,14 @@
     2.4    }
     2.5  }
     2.6  
     2.7 +void GrowableCache::metadata_do(void f(Metadata*)) {
     2.8 +  int len = _elements->length();
     2.9 +  for (int i=0; i<len; i++) {
    2.10 +    GrowableElement *e = _elements->at(i);
    2.11 +    e->metadata_do(f);
    2.12 +  }
    2.13 +}
    2.14 +
    2.15  void GrowableCache::gc_epilogue() {
    2.16    int len = _elements->length();
    2.17    for (int i=0; i<len; i++) {
    2.18 @@ -224,20 +232,20 @@
    2.19  JvmtiBreakpoint::JvmtiBreakpoint() {
    2.20    _method = NULL;
    2.21    _bci    = 0;
    2.22 -  _class_loader = NULL;
    2.23 +  _class_holder = NULL;
    2.24  }
    2.25  
    2.26  JvmtiBreakpoint::JvmtiBreakpoint(Method* m_method, jlocation location) {
    2.27    _method        = m_method;
    2.28 -  _class_loader  = _method->method_holder()->class_loader_data()->class_loader();
    2.29 +  _class_holder  = _method->method_holder()->klass_holder();
    2.30  #ifdef CHECK_UNHANDLED_OOPS
    2.31 -  // _class_loader can't be wrapped in a Handle, because JvmtiBreakpoint:s are
    2.32 -  // eventually allocated on the heap.
    2.33 +  // _class_holder can't be wrapped in a Handle, because JvmtiBreakpoints are
    2.34 +  // sometimes allocated on the heap.
    2.35    //
    2.36 -  // The code handling JvmtiBreakpoint:s allocated on the stack can't be
    2.37 -  // interrupted by a GC until _class_loader is reachable by the GC via the
    2.38 +  // The code handling JvmtiBreakpoints allocated on the stack can't be
    2.39 +  // interrupted by a GC until _class_holder is reachable by the GC via the
    2.40    // oops_do method.
    2.41 -  Thread::current()->allow_unhandled_oop(&_class_loader);
    2.42 +  Thread::current()->allow_unhandled_oop(&_class_holder);
    2.43  #endif // CHECK_UNHANDLED_OOPS
    2.44    assert(_method != NULL, "_method != NULL");
    2.45    _bci           = (int) location;
    2.46 @@ -247,7 +255,7 @@
    2.47  void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) {
    2.48    _method   = bp._method;
    2.49    _bci      = bp._bci;
    2.50 -  _class_loader = bp._class_loader;
    2.51 +  _class_holder = bp._class_holder;
    2.52  }
    2.53  
    2.54  bool JvmtiBreakpoint::lessThan(JvmtiBreakpoint& bp) {
    2.55 @@ -365,6 +373,13 @@
    2.56    }
    2.57  }
    2.58  
    2.59 +void VM_ChangeBreakpoints::metadata_do(void f(Metadata*)) {
    2.60 +  // Walk metadata in breakpoints to keep from being deallocated with RedefineClasses
    2.61 +  if (_bp != NULL) {
    2.62 +    _bp->metadata_do(f);
    2.63 +  }
    2.64 +}
    2.65 +
    2.66  //
    2.67  // class JvmtiBreakpoints
    2.68  //
    2.69 @@ -381,6 +396,10 @@
    2.70    _bps.oops_do(f);
    2.71  }
    2.72  
    2.73 +void  JvmtiBreakpoints::metadata_do(void f(Metadata*)) {
    2.74 +  _bps.metadata_do(f);
    2.75 +}
    2.76 +
    2.77  void JvmtiBreakpoints::gc_epilogue() {
    2.78    _bps.gc_epilogue();
    2.79  }
    2.80 @@ -499,6 +518,12 @@
    2.81    }
    2.82  }
    2.83  
    2.84 +void JvmtiCurrentBreakpoints::metadata_do(void f(Metadata*)) {
    2.85 +  if (_jvmti_breakpoints != NULL) {
    2.86 +    _jvmti_breakpoints->metadata_do(f);
    2.87 +  }
    2.88 +}
    2.89 +
    2.90  void JvmtiCurrentBreakpoints::gc_epilogue() {
    2.91    if (_jvmti_breakpoints != NULL) {
    2.92      _jvmti_breakpoints->gc_epilogue();
     3.1 --- a/src/share/vm/prims/jvmtiImpl.hpp	Thu Oct 31 14:11:02 2013 -0400
     3.2 +++ b/src/share/vm/prims/jvmtiImpl.hpp	Fri Nov 01 10:32:36 2013 -0400
     3.3 @@ -69,6 +69,7 @@
     3.4    virtual bool lessThan(GrowableElement *e)=0;
     3.5    virtual GrowableElement *clone()         =0;
     3.6    virtual void oops_do(OopClosure* f)      =0;
     3.7 +  virtual void metadata_do(void f(Metadata*)) =0;
     3.8  };
     3.9  
    3.10  class GrowableCache VALUE_OBJ_CLASS_SPEC {
    3.11 @@ -115,6 +116,8 @@
    3.12    void clear();
    3.13    // apply f to every element and update the cache
    3.14    void oops_do(OopClosure* f);
    3.15 +  // walk metadata to preserve for RedefineClasses
    3.16 +  void metadata_do(void f(Metadata*));
    3.17    // update the cache after a full gc
    3.18    void gc_epilogue();
    3.19  };
    3.20 @@ -148,6 +151,7 @@
    3.21    void remove (int index)               { _cache.remove(index); }
    3.22    void clear()                          { _cache.clear(); }
    3.23    void oops_do(OopClosure* f)           { _cache.oops_do(f); }
    3.24 +  void metadata_do(void f(Metadata*))   { _cache.metadata_do(f); }
    3.25    void gc_epilogue()                    { _cache.gc_epilogue(); }
    3.26  };
    3.27  
    3.28 @@ -169,7 +173,7 @@
    3.29    Method*               _method;
    3.30    int                   _bci;
    3.31    Bytecodes::Code       _orig_bytecode;
    3.32 -  oop                   _class_loader;
    3.33 +  oop                   _class_holder;  // keeps _method memory from being deallocated
    3.34  
    3.35  public:
    3.36    JvmtiBreakpoint();
    3.37 @@ -191,9 +195,15 @@
    3.38    bool lessThan(GrowableElement* e) { Unimplemented(); return false; }
    3.39    bool equals(GrowableElement* e) { return equals((JvmtiBreakpoint&) *e); }
    3.40    void oops_do(OopClosure* f)     {
    3.41 -    // Mark the method loader as live
    3.42 -    f->do_oop(&_class_loader);
    3.43 +    // Mark the method loader as live so the Method* class loader doesn't get
    3.44 +    // unloaded and Method* memory reclaimed.
    3.45 +    f->do_oop(&_class_holder);
    3.46    }
    3.47 +  void metadata_do(void f(Metadata*)) {
    3.48 +    // walk metadata to preserve for RedefineClasses
    3.49 +    f(_method);
    3.50 +  }
    3.51 +
    3.52    GrowableElement *clone()        {
    3.53      JvmtiBreakpoint *bp = new JvmtiBreakpoint();
    3.54      bp->copy(*this);
    3.55 @@ -239,6 +249,7 @@
    3.56  
    3.57    int length();
    3.58    void oops_do(OopClosure* f);
    3.59 +  void metadata_do(void f(Metadata*));
    3.60    void print();
    3.61  
    3.62    int  set(JvmtiBreakpoint& bp);
    3.63 @@ -288,6 +299,7 @@
    3.64    static inline bool is_breakpoint(address bcp);
    3.65  
    3.66    static void oops_do(OopClosure* f);
    3.67 +  static void metadata_do(void f(Metadata*));
    3.68    static void gc_epilogue();
    3.69  };
    3.70  
    3.71 @@ -332,6 +344,7 @@
    3.72    VMOp_Type type() const { return VMOp_ChangeBreakpoints; }
    3.73    void doit();
    3.74    void oops_do(OopClosure* f);
    3.75 +  void metadata_do(void f(Metadata*));
    3.76  };
    3.77  
    3.78  

mercurial