Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4311308

JVMPI_EVENT_MONITOR_DUMP is wrong or has missing info

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P2 P2
    • 1.3.0
    • 1.3.0
    • vm-legacy
    • rc2
    • x86
    • windows_nt
    • Not verified



      Name: krT82822 Date: 02/09/2000


      java version "1.3.0rc1"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc1-T)
      Java HotSpot(TM) Client VM (build 1.3.0rc1-S, mixed mode)

      We have a thread analysis tool that does deadlock detection by regularly
      asking for MONITOR_DUMP events and looking for cycles. With HotSpot RC1,
      the MONITOR_DUMP on a deadlocked Java program does not show the cycle, and
      in the test case below shows no threads even waiting to enter monitors.

      Below are the output from running "java -Xrunjvmpi_tool Deadlock", and the
      source for Deadlock.java and a pared-down JVMPI DLL called jvmpi_tool.

      TEST OUTPUT: note no threads are waiting to enter any of the monitors, and
      none of the monitors are owned:

      Start 0x766214: "Finalizer"
      Start 0x766ed4: "Reference Handler"
      Start 0x762a34: "main"
      Start 0x768074: "Monitor dumper"
      Start 0x76aa84: "Signal Dispatcher"
      Start 0x76eac4: "Thread-0"
      Start 0x76dad4: "One"
      Thread One: lockA
      Start 0x76d4c4: "Two"
      Thread Two: lockB

      Monitor Dump:
      Monitor 0x6b28578: Owner: 0 Entry count: 0
        0 waiting to enter
        0 awaiting notification
      Monitor 0x6b285a8: Owner: 0 Entry count: 0
        0 waiting to enter
        0 awaiting notification
      Monitor 0x2aa4a98: Owner: 0 Entry count: 0
        0 waiting to enter
        0 awaiting notification
      Monitor 0x2a883c0: Owner: 0 Entry count: 0
        0 waiting to enter
        0 awaiting notification
      Monitor 0x2a70328: Owner: 0 Entry count: 0
        0 waiting to enter
        1 awaiting notification
          0x766214
      Monitor 0x2a70238: Owner: 0 Entry count: 0
        0 waiting to enter
        1 awaiting notification
          0x766ed4

      SOURCE FOR Deadlock.java: Always deadlocks:

      import java.lang.*;
      public class Deadlock
      {
              private static String lockA = "lockA";
              private static String lockB = "lockB";
              static Object barrier = new Object();
              static int count = 0;

              public static void main(String[] args) {
                      new Thread (new DeadThread(lockA, lockB), "One").start();
                      new Thread (new DeadThread(lockB, lockA), "Two").start();
              }

              protected static class DeadThread implements Runnable {
                      String first_;
                      String second_;

                      public DeadThread(String first, String second) {
                              first_ = first;
                              second_ = second;
                      }

                      public void run () {
                              String name = Thread.currentThread().getName();

                              synchronized (first_) {
                                      System.out.println("Thread " + name + ": " + fir
      st_);
                                      synchronized (Deadlock.barrier) {
                                              if (Deadlock.count++ > 0) {
                                                      Deadlock.barrier.notify();
                                              } else {
                                                      try {
                                                              Deadlock.barrier.wait();
                                                      } catch (Exception e) {}
                                              }
                                      }
                                      synchronized (second_) {
                                              System.out.println("Impossible: Thread "
       + name + ": " + first_);
                                      }
                              }
                      }
              }
      }

      SOURCE FOR jvmpi_tool: NOTE: Only tested on WinNT, but might happen to work on
      Solaris. I know it's not pretty.

      //
      // Get a monitor dump from JVMPI
      //

      #include <stdio.h>
      #include <jvmpi.h>
      #ifdef _WINDOWS
      # include <windows.h>
      # define SLEEP(s) Sleep(s * 1000);
      #else
      # define SLEEP(s) sleep(s);
      #endif

      #define JVMPI(m) (jvmpi->m)

      static JVMPI_Interface *jvmpi;
      static int delay = 5;
      static volatile int done = 0;
      static int little_endian = 0;

      static long u4(void *);
      static void monitor(void *);
      static void notify(JVMPI_Event *);
      static void dump(char * begin, char * end);

      extern "C" JNIEXPORT jint JNICALL
      JVM_OnLoad(JavaVM *jvm, char *options, void *reserved)
      {
      int res = jvm->GetEnv((void **)&jvmpi, JVMPI_VERSION_1);

      if (res < 0) {
      return JNI_ERR;
      }

      jvmpi->NotifyEvent = notify;

      JVMPI(EnableEvent)(JVMPI_EVENT_JVM_INIT_DONE, NULL);
      JVMPI(EnableEvent)(JVMPI_EVENT_JVM_SHUT_DOWN, NULL);
      JVMPI(EnableEvent)(JVMPI_EVENT_THREAD_START, NULL);

      if (options && *options) {
      int val = atoi(options);
      if (val) {
      delay = val;
      }
      }

      int test = 1;
      if (*(unsigned char *)&test) {
      little_endian = 1;
      }

      return JNI_OK;
      }

      long
      u4(void * buf)
      {
      long result;
      unsigned char * p = (unsigned char *)buf;

      if (little_endian) {
      result = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
      } else {
      result = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
      }

      return result;
      }

      void
      monitor(void * notused)
      {
      do {
      SLEEP(delay);
      if (!done) {
      JVMPI(RequestEvent)(JVMPI_EVENT_MONITOR_DUMP, NULL);
      }
      } while (!done);

      done = 0;
      }

      void
      notify(JVMPI_Event * event)
      {
      jint result;
      char * name;

      switch (event->event_type) {
      case JVMPI_EVENT_JVM_INIT_DONE:
      result = JVMPI(CreateSystemThread)("Monitor dumper",
      JVMPI_NORMAL_PRIORITY, monitor);
      if (result != JNI_OK) {
      fputs("Unable to create Monitor dumper thread\n",
      stderr);
      exit(1);
      }
      break;
      case JVMPI_EVENT_JVM_SHUT_DOWN:
      done = 1;
      while (done) {
      SLEEP(1);
      }
      break;
      case JVMPI_EVENT_THREAD_START:
      name = event->u.thread_start.thread_name;
      printf("Start %#lx: \"%s\"\n",
      (unsigned long)event->u.thread_start.thread_env_id,
      name ? name : "(null)");
      break;
      case JVMPI_REQUESTED_EVENT|JVMPI_EVENT_MONITOR_DUMP:
      dump(event->u.monitor_dump.begin, event->u.monitor_dump.end);
      break;
      }
      }

      #define DUMP_U1(v, ptr) v = (*ptr++)
      #define DUMP_U4(v, ptr) v = u4(ptr); ptr += 4
      #define DUMP_ID(v, ptr) memcpy(&v, ptr, sizeof(v)); ptr += sizeof(v)

      void
      dump(char * begin, char * end)
      {
      fputs("\nMonitor Dump:\n", stdout);

      while (begin < end) {
      char type;
      void * id;
      jint num;
      jint i;

      DUMP_U1(type, begin);
      if (type == JVMPI_MONITOR_JAVA) {
      DUMP_ID(id, begin);
      printf("Monitor %#lx: ", (unsigned long)id);
      } else if (type == JVMPI_MONITOR_RAW) {
      DUMP_ID(id, begin);
      printf("Raw Monitor \"%s\" ", id ? (char *)id :
      "(null)");
      DUMP_ID(id, begin);
      printf("%#lx: ", (unsigned long)id);
      } else {
      printf("Unknown monitor type: %d\n", (int)type);
      return;
      }

      DUMP_ID(id, begin);
      printf("Owner: %#lx ", (unsigned long)id);

      DUMP_U4(num, begin);
      printf("Entry count: %ld\n", num);

      DUMP_U4(num, begin);
      printf(" %ld waiting to enter\n", num);
      for (i = 0; i < num; ++i) {
      DUMP_ID(id, begin);
      printf(" %#lx\n", (unsigned long)id);
      }

      DUMP_U4(num, begin);
      printf(" %ld awaiting notification\n", num);
      for (i = 0; i < num; ++i) {
      DUMP_ID(id, begin);
      printf(" %#lx\n", (unsigned long)id);
      }
      }
      }
      (Review ID: 101035)
      ======================================================================

      Name: elR10090 Date: 05/19/2001


      This bug also affects the testbase_nsk test:
          nsk/regression/b4311308
      ======================================================================

            dcubed Daniel Daugherty
            kryansunw Kevin Ryan (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: