--- old/src/share/vm/runtime/thread.cpp 2016-03-31 12:09:39.772953779 +0200 +++ new/src/share/vm/runtime/thread.cpp 2016-03-31 12:09:39.708953782 +0200 @@ -3301,6 +3301,7 @@ : JavaThread(&sweeper_thread_entry) { _scanned_nmethod = NULL; } + void CodeCacheSweeperThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) { JavaThread::oops_do(f, cld_f, cf); if (_scanned_nmethod != NULL && cf != NULL) { @@ -3311,6 +3312,16 @@ } } +void CodeCacheSweeperThread::nmethods_do(CodeBlobClosure* cf) { + Thread::nmethods_do(cf); + if (_scanned_nmethod != NULL && cf != NULL) { + // Safepoints can occur when the sweeper is scanning an nmethod so + // process it here to make sure it isn't unloaded in the middle of + // a scan. + cf->do_code_blob(_scanned_nmethod); + } +} + // ======= Threads ======== @@ -4348,7 +4359,12 @@ void Threads::nmethods_do(CodeBlobClosure* cf) { ALL_JAVA_THREADS(p) { - p->nmethods_do(cf); + // This is used by the code cache sweeper to mark nmethods that are active + // on the stack of a Java thread. Ignore the sweeper thread itself to avoid + // marking CodeCacheSweeperThread::_scanned_nmethod as active. + if(!p->is_Code_cache_sweeper_thread()) { + p->nmethods_do(cf); + } } VMThread::vm_thread()->nmethods_do(cf); } --- old/src/share/vm/runtime/thread.hpp 2016-03-31 12:09:40.072953765 +0200 +++ new/src/share/vm/runtime/thread.hpp 2016-03-31 12:09:40.004953768 +0200 @@ -1997,10 +1997,10 @@ bool is_hidden_from_external_view() const { return true; } bool is_Code_cache_sweeper_thread() const { return true; } - // GC support - // Apply "f->do_oop" to all root oops in "this". - // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames + + // Prevent GC from unloading _scanned_nmethod void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf); + void nmethods_do(CodeBlobClosure* cf); }; // A thread used for Compilation.