Fri, 01 Nov 2013 10:32:36 -0400
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
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