OpenJDK9 Hotspot: Object wait/notify method

Keywords: Java jvm

Preface

Object wait/notify method is a thread synchronization method based on Object Monitor provided by early JVM. This paper first introduces the related data structures (classes), then starts with the internal implementation of wait/notify method, and briefly analyses the principle and implementation of Object Monitor.

Park

PlatformParker

ObjectMonitor

ObjectSynchronizer

wait

Many methods in Object class are native methods, wait is no exception.

public final void wait() throws InterruptedException {
    wait(0);
}

public final native void wait(long timeout) throws InterruptedException;

The corresponding native function of wait method is JVM_MonitorWait

JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
  JVMWrapper("JVM_MonitorWait");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  JavaThreadInObjectWaitState jtiows(thread, ms != 0);
  if (JvmtiExport::should_post_monitor_wait()) {
    JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);

    // The current thread already owns the monitor and it has not yet
    // been added to the wait queue so the current thread cannot be
    // made the successor. This means that the JVMTI_EVENT_MONITOR_WAIT
    // event handler cannot accidentally consume an unpark() meant for
    // the ParkEvent associated with this ObjectMonitor.
  }
  ObjectSynchronizer::wait(obj, ms, CHECK);
JVM_END

It first calls the JNIHandles::resolve_non_null function to convert the handle of job type into oop (refer to the previous series of articles on oop and Handle concepts), then calls the static method wait of the ObjectSynchronizer class, where the first class, ObjectSynchronizer, related to Object Monitor, appears, first marks it, and then looks down.

int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
  if (UseBiasedLocking) {
    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
  }
  if (millis < 0) {
    TEVENT(wait - throw IAX);
    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
        "timeout value is negative");
  }
  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
                                                       obj(),
                                                       inflate_cause_wait);

  DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
  monitor->wait(millis, true, THREAD);

  // This dummy call is in place to get around dtrace bug 6254741.  Once
  // that's fixed we can uncomment the following line, remove the call
  // and change this function back into a "void" func.
  // DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD);
  return dtrace_waited_probe(monitor, obj, THREAD);
}

Here comes the second class ObjectMonitor (protagonist), which calls the wait method of monitor after obtaining the ObjectMonitor of the object through the ObjectSynchronizer::inflate method.

summary

Posted by legend986 on Tue, 12 Feb 2019 04:39:18 -0800