void register_on_exit_function(void (*func)(void)) { ExitProc *entry = new ExitProc(func); // Classic vm does not throw an exception in case the allocation failed, if (entry != NULL) { entry->set_next(exit_procs); exit_procs = entry; } }
// Note: before_exit() can be executed only once, if more than one threads // are trying to shutdown the VM at the same time, only one thread // can run before_exit() and all other threads must wait. void before_exit(JavaThread * thread) { #define BEFORE_EXIT_NOT_RUN 0 #define BEFORE_EXIT_RUNNING 1 #define BEFORE_EXIT_DONE 2 static jint volatile _before_exit_status = BEFORE_EXIT_NOT_RUN; // Note: don't use a Mutex to guard the entire before_exit(), as // JVMTI post_thread_end_event and post_vm_death_event will run native code. // A CAS or OSMutex would work just fine but then we need to manipulate // thread state for Safepoint. Here we use Monitor wait() and notify_all() // for synchronization. { MutexLocker ml(BeforeExit_lock); switch (_before_exit_status) { case BEFORE_EXIT_NOT_RUN: _before_exit_status = BEFORE_EXIT_RUNNING; break; case BEFORE_EXIT_RUNNING: while (_before_exit_status == BEFORE_EXIT_RUNNING) { BeforeExit_lock->wait(); } assert(_before_exit_status == BEFORE_EXIT_DONE, "invalid state"); return; case BEFORE_EXIT_DONE: return; } } // The only difference between this and Win32's _onexit procs is that // this version is invoked before any threads get killed. ExitProc* current = exit_procs; while (current != NULL) { ExitProc* next = current->next(); current->evaluate(); delete current; current = next; } // Hang forever on exit if we're reporting an error. if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); } // Terminate watcher thread - must before disenrolling any periodic task WatcherThread::stop(); // Print statistics gathered (profiling ...) if (Arguments::has_profile()) { FlatProfiler::disengage(); FlatProfiler::print(10); } // shut down the StatSampler task StatSampler::disengage(); StatSampler::destroy(); #ifndef SERIALGC // stop CMS threads if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::stop(); } #endif // SERIALGC // Print GC/heap related information. if (PrintGCDetails) { Universe::print(); AdaptiveSizePolicyOutput(0); } if (Arguments::has_alloc_profile()) { HandleMark hm; // Do one last collection to enumerate all the objects // allocated since the last one. Universe::heap()->collect(GCCause::_allocation_profiler); AllocationProfiler::disengage(); AllocationProfiler::print(0); } if (PrintBytecodeHistogram) { BytecodeHistogram::print(); } if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_end(thread); } // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution JvmtiExport::post_vm_death(); Threads::shutdown_vm_agents(); // Terminate the signal thread // Note: we don't wait until it actually dies. os::terminate_signal_thread(); print_statistics(); Universe::heap()->print_tracing_info(); VTune::exit(); { MutexLocker ml(BeforeExit_lock); _before_exit_status = BEFORE_EXIT_DONE; BeforeExit_lock->notify_all(); } #undef BEFORE_EXIT_NOT_RUN #undef BEFORE_EXIT_RUNNING #undef BEFORE_EXIT_DONE }
// Note: before_exit() can be executed only once, if more than one threads // are trying to shutdown the VM at the same time, only one thread // can run before_exit() and all other threads must wait. void before_exit(JavaThread * thread) { #define BEFORE_EXIT_NOT_RUN 0 #define BEFORE_EXIT_RUNNING 1 #define BEFORE_EXIT_DONE 2 static jint volatile _before_exit_status = BEFORE_EXIT_NOT_RUN; // Note: don't use a AzLock to guard the entire before_exit(), as // JVMTI post_thread_end_event and post_vm_death_event will run native code. // A CAS or OSMutex would work just fine but then we need to manipulate // thread state for Safepoint. Here we use Monitor wait() and notify_all() // for synchronization. { MutexLocker ml(BeforeExit_lock); switch (_before_exit_status) { case BEFORE_EXIT_NOT_RUN: _before_exit_status = BEFORE_EXIT_RUNNING; break; case BEFORE_EXIT_RUNNING: while (_before_exit_status == BEFORE_EXIT_RUNNING) { BeforeExit_lock.wait(); } assert(_before_exit_status == BEFORE_EXIT_DONE, "invalid state"); return; case BEFORE_EXIT_DONE: return; } } // The only difference between this and Win32's _onexit procs is that // this version is invoked before any threads get killed. ExitProc* current = exit_procs; while (current != NULL) { ExitProc* next = current->next(); current->evaluate(); delete current; current = next; } // Hang forever on exit if we're reporting an error. if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); } // Terminate watcher thread - must before disenrolling any periodic task WatcherThread::stop(); if (UseITR) { InstructionTraceThreads::stopAllThreads(); } if (PrintProfileAtExit) { TickProfiler::print(); } // shut down the StatSampler task StatSampler::disengage(); StatSampler::destroy(); // shut down the TimeMillisUpdateTask if (CacheTimeMillis) { TimeMillisUpdateTask::disengage(); } // Print GC/heap related information. if (PrintGCDetails) { Universe::print(); AdaptiveSizePolicyOutput(0); } if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_end(thread); } // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution JvmtiExport::post_vm_death(); // Terminate the signal thread // Note: we don't wait until it actually dies. os::terminate_signal_thread(); print_statistics(); if (UseSBA && PrintSBAStatistics) { // Not instead PRODUCT... StackBasedAllocation::print_statistics(NULL); } if ( !UseGenPauselessGC ) { Universe::heap()->print_tracing_info(); } { MutexLocker ml(BeforeExit_lock); _before_exit_status = BEFORE_EXIT_DONE; BeforeExit_lock.notify_all(); } #undef BEFORE_EXIT_NOT_RUN #undef BEFORE_EXIT_RUNNING #undef BEFORE_EXIT_DONE }