skytree
skytree

Reputation: 1100

How does WatcherThread invoke JVM monitoring routines?

"VM Periodic Task Thread"

Aka the "WatcherThread". This is a VM thread that performs periodic tasks, e.g., updating performance counters.

see link

Periodic task scheduling of threads, it was founded by WatcherThread, is a singleton object.

The thread in JVM more frequently used, For example, the running status of the memory monitoring, JVM monitoring regularly. And we often need to perform some jstat this command for the GC case.

As follows: jstat -gcutil 234832507 making this command tells the JVM in the console to print PID: GC 23483, An interval of 250 msec print a, A total of over 7 prints.

see link

This is what I find in the JVM source code.

I think when the "VM Periodic Task Thread"(WatcherThread) starts, it should perform "run" function. The only thing I notice is that it spins in the while loop, but how does WatcherThread invoke JVM monitoring routines, like jstat? Where is the sub-routine of jstat in this while loop? I am curious how WatcherThread updates performance counters and things like that.

void WatcherThread::run() {
  assert(this == watcher_thread(), "just checking");

  this->record_stack_base_and_size();
  this->set_native_thread_name(this->name());
  this->set_active_handles(JNIHandleBlock::allocate_block());

  while (true) {
    assert(watcher_thread() == Thread::current(), "thread consistency check");
    assert(watcher_thread() == this, "thread consistency check");

    // Calculate how long it'll be until the next PeriodicTask work
    // should be done, and sleep that amount of time.
    int time_waited = sleep();  // return 50

    if (is_error_reported()) {
      // A fatal error has happened, the error handler(VMError::report_and_die)
      // should abort JVM after creating an error log file. However in some
      // rare cases, the error handler itself might deadlock. Here we try to
      // kill JVM if the fatal error handler fails to abort in 2 minutes.
      //
      // This code is in WatcherThread because WatcherThread wakes up
      // periodically so the fatal error handler doesn't need to do anything;
      // also because the WatcherThread is less likely to crash than other
      // threads.

      for (;;) {
        if (!ShowMessageBoxOnError
            && (OnError == NULL || OnError[0] == '\0')
            && Arguments::abort_hook() == NULL) {
          os::sleep(this, (jlong)ErrorLogTimeout * 1000, false); // in seconds
          fdStream err(defaultStream::output_fd());
          err.print_raw_cr("# [ timer expired, abort... ]");
          // skip atexit/vm_exit/vm_abort hooks
          os::die();
        }

        // Wake up 5 seconds later, the fatal handler may reset OnError or
        // ShowMessageBoxOnError when it is ready to abort.
        os::sleep(this, 5 * 1000, false);
      }
    }

    if (_should_terminate) {
      // check for termination before posting the next tick
      break;
    }

    PeriodicTask::real_time_tick(time_waited);
  }

  // Signal that it is terminated
  {
    MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag);
    _watcher_thread = NULL;
    Terminator_lock->notify();
  }
}

Upvotes: 0

Views: 474

Answers (1)

apangin
apangin

Reputation: 98580

Obviously JVM does not call jstat or other external utilities.

You are probably looking for StatSampler::collect_sample:

/*
 * the collect_sample() method is the method invoked by the
 * WatcherThread via the PeriodicTask::task() method. This method
 * is responsible for collecting data samples from sampled
 * PerfData instances every PerfDataSamplingInterval milliseconds.
 * It is also responsible for logging the requested set of
 * PerfData instances every _sample_count milliseconds. While
 * logging data, it will output a column header after every _print_header
 * rows of data have been logged.
 */
void StatSampler::collect_sample() {

WatcherThread executes registered instances of PeriodicTask class, and StatSamplerTask is one of such tasks.

Upvotes: 1

Related Questions