/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
void VM_DeoptimizeAll::doit() {
JavaThreadIteratorWithHandle jtiwh; // deoptimize all java threads in the system if (DeoptimizeALot) { for (; JavaThread *thread = jtiwh.next(); ) { if (thread->has_last_Java_frame()) {
thread->deoptimize();
}
}
} elseif (DeoptimizeRandom) {
// Deoptimize some selected threads and frames int tnum = os::random() & 0x3; int fnum = os::random() & 0x3; int tcount = 0; for (; JavaThread *thread = jtiwh.next(); ) { if (thread->has_last_Java_frame()) { if (tcount++ == tnum) {
tcount = 0; int fcount = 0; // Deoptimize some selected frames. for(StackFrameStream fst(thread, false/* update */, true /* process_frames */); !fst.is_done(); fst.next()) { if (fst.current()->can_be_deoptimized()) { if (fcount++ == fnum) {
fcount = 0;
Deoptimization::deoptimize(thread, *fst.current());
}
}
}
}
}
}
}
}
bool VM_PrintThreads::doit_prologue() { // Get Heap_lock if concurrent locks will be dumped if (_print_concurrent_locks) {
Heap_lock->lock();
} returntrue;
}
VM_FindDeadlocks::~VM_FindDeadlocks() { if (_deadlocks != NULL) {
DeadlockCycle* cycle = _deadlocks; while (cycle != NULL) {
DeadlockCycle* d = cycle;
cycle = cycle->next(); delete d;
}
}
}
void VM_FindDeadlocks::doit() { // Update the hazard ptr in the originating thread to the current // list of threads. This VM operation needs the current list of // threads for proper deadlock detection and those are the // JavaThreads we need to be protected when we return info to the // originating thread.
_setter.set();
_deadlocks = ThreadService::find_deadlocks_at_safepoint(_setter.list(), _concurrent_locks); if (_out != NULL) { int num_deadlocks = 0; for (DeadlockCycle* cycle = _deadlocks; cycle != NULL; cycle = cycle->next()) {
num_deadlocks++;
cycle->print_on_with(_setter.list(), _out);
}
// Set the hazard ptr in the originating thread to protect the // current list of threads. This VM operation needs the current list // of threads for a proper dump and those are the JavaThreads we need // to be protected when we return info to the originating thread.
_result->set_t_list();
ConcurrentLocksDump concurrent_locks(true); if (_with_locked_synchronizers) {
concurrent_locks.dump_at_safepoint();
}
ObjectMonitorsHashtable table;
ObjectMonitorsHashtable* tablep = nullptr; if (_with_locked_monitors) { // The caller wants locked monitor information and that's expensive to gather // when there are a lot of inflated monitors. So we deflate idle monitors and // gather information about owned monitors at the same time.
tablep = &table; while (ObjectSynchronizer::deflate_idle_monitors(tablep) > 0) {
; /* empty */
}
}
if (_num_threads == 0) { // Snapshot all live threads
for (uint i = 0; i < _result->t_list()->length(); i++) {
JavaThread* jt = _result->t_list()->thread_at(i); if (jt->is_exiting() ||
jt->is_hidden_from_external_view()) { // skip terminating threads and hidden threads continue;
}
ThreadConcurrentLocks* tcl = NULL; if (_with_locked_synchronizers) {
tcl = concurrent_locks.thread_concurrent_locks(jt);
}
snapshot_thread(jt, tcl, tablep);
}
} else { // Snapshot threads in the given _threads array // A dummy snapshot is created if a thread doesn't exist
for (int i = 0; i < _num_threads; i++) {
instanceHandle th = _threads->at(i); if (th() == NULL) { // skip if the thread doesn't exist // Add a dummy snapshot
_result->add_thread_snapshot(); continue;
}
// Dump thread stack only if the thread is alive and not exiting // and not VM internal thread.
JavaThread* jt = java_lang_Thread::thread(th()); if (jt != NULL && !_result->t_list()->includes(jt)) { // _threads[i] doesn't refer to a valid JavaThread; this check // is primarily for JVM_DumpThreads() which doesn't have a good // way to validate the _threads array.
jt = NULL;
} if (jt == NULL || /* thread not alive */
jt->is_exiting() ||
jt->is_hidden_from_external_view()) { // add a NULL snapshot if skipped
_result->add_thread_snapshot(); continue;
}
ThreadConcurrentLocks* tcl = NULL; if (_with_locked_synchronizers) {
tcl = concurrent_locks.thread_concurrent_locks(jt);
}
snapshot_thread(jt, tcl, tablep);
}
}
}
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint already");
int num_active = 0;
_shutdown_thread = thr_cur;
_vm_exited = true; // global flag for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { if (thr != thr_cur && thr->thread_state() == _thread_in_native) {
++num_active;
thr->set_terminated(JavaThread::_vm_exited); // per-thread flag
}
}
return num_active;
}
int VM_Exit::wait_for_threads_in_native_to_block() { // VM exits at safepoint. This function must be called at the final safepoint // to wait for threads in _thread_in_native state to be quiescent.
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint already");
// Compiler threads need longer wait because they can access VM data directly // while in native. If they are active and some structures being used are // deleted by the shutdown sequence, they will crash. On the other hand, user // threads must go through native=>Java/VM transitions first to access VM // data, and they will be stopped during state transition. In theory, we // don't have to wait for user threads to be quiescent, but it's always // better to terminate VM when current thread is the only active thread, so // wait for user threads too. Numbers are in 10 milliseconds. int max_wait_user_thread = 30; // at least 300 milliseconds int max_wait_compiler_thread = 1000; // at least 10 seconds
int max_wait = max_wait_compiler_thread;
int attempts = 0;
JavaThreadIteratorWithHandle jtiwh; while (true) { int num_active = 0; int num_active_compiler_thread = 0;
jtiwh.rewind(); for (; JavaThread *thr = jtiwh.next(); ) { if (thr!=thr_cur && thr->thread_state() == _thread_in_native) {
num_active++; if (thr->is_Compiler_thread()) { #if INCLUDE_JVMCI
CompilerThread* ct = (CompilerThread*) thr; if (ct->compiler() == NULL || !ct->compiler()->is_jvmci()) {
num_active_compiler_thread++;
} else { // A JVMCI compiler thread never accesses VM data structures // while in _thread_in_native state so there's no need to wait // for it and potentially add a 300 millisecond delay to VM // shutdown.
num_active--;
} #else
num_active_compiler_thread++; #endif
}
}
}
if (VerifyBeforeExit) {
HandleMark hm(VMThread::vm_thread()); // Among other things, this ensures that Eden top is correct.
Universe::heap()->prepare_for_verify(); // Silent verification so as not to pollute normal output, // unless we really asked for it.
Universe::verify();
}
CompileBroker::set_should_block();
// Wait for a short period for threads in native to block. Any thread // still executing native code after the wait will be stopped at // native==>Java/VM barriers. // Among 16276 JCK tests, 94% of them come here without any threads still // running in native; the other 6% are quiescent within 250ms (Ultra 80).
wait_for_threads_in_native_to_block();
set_vm_exited();
// The ObjectMonitor subsystem uses perf counters so do this before // we call exit_globals() so we don't run afoul of perfMemory_exit().
ObjectSynchronizer::do_final_audit_and_print_stats();
// We'd like to call IdealGraphPrinter::clean_up() to finalize the // XML logging, but we can't safely do that here. The logic to make // XML termination logging safe is tied to the termination of the // VMThread, and it doesn't terminate on this exit path. See 8222534.
// cleanup globals resources before exiting. exit_globals() currently // cleans up outputStream resources and PerfMemory resources.
exit_globals();
LogConfiguration::finalize();
// Check for exit hook
exit_hook_t exit_hook = Arguments::exit_hook(); if (exit_hook != NULL) { // exit hook should exit.
exit_hook(_exit_code); // ... but if it didn't, we must do it here
vm_direct_exit(_exit_code);
} else {
vm_direct_exit(_exit_code);
}
}
void VM_Exit::wait_if_vm_exited() { if (_vm_exited &&
Thread::current_or_null() != _shutdown_thread) { // _vm_exited is set at safepoint, and the Threads_lock is never released // so we will block here until the process dies.
Threads_lock->lock();
ShouldNotReachHere();
}
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.12Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.