src/share/vm/runtime/vframe.cpp

Print this page

        

*** 158,188 **** } void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ResourceMark rm; ! // If this is the first frame, and java.lang.Object.wait(...) then print out the receiver. if (frame_count == 0) { if (method()->name() == vmSymbols::wait_name() && method()->method_holder()->name() == vmSymbols::java_lang_Object()) { StackValueCollection* locs = locals(); if (!locs->is_empty()) { StackValue* sv = locs->at(0); if (sv->type() == T_OBJECT) { Handle o = locs->at(0)->get_obj(); ! print_locked_object_class_name(st, o, "waiting on"); } } } else if (thread()->current_park_blocker() != NULL) { oop obj = thread()->current_park_blocker(); Klass* k = obj->klass(); st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name()); } } ! // Print out all monitors that we have locked or are trying to lock GrowableArray<MonitorInfo*>* mons = monitors(); if (!mons->is_empty()) { bool found_first_monitor = false; for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); --- 158,201 ---- } void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ResourceMark rm; ! // If this is the first frame and it is java.lang.Object.wait(...) ! // then print out the receiver. Locals are not always available, ! // e.g., compiled native frames have no scope so there are no locals. if (frame_count == 0) { if (method()->name() == vmSymbols::wait_name() && method()->method_holder()->name() == vmSymbols::java_lang_Object()) { + const char *wait_state = "waiting on"; // assume we are waiting + // It would be nice to distinguish between "waiting on" and + // "waited on". Currently, "waiting on" here with a + // java.lang.Thread.State == "WAITING (on object monitor)" + // earlier in the output means that the monitor has not yet been + // notified and java.lang.Thread.State == "BLOCKED (on object + // monitor)" earlier in the output means that the monitor has + // been notified and the thread is blocked on reentry. StackValueCollection* locs = locals(); if (!locs->is_empty()) { StackValue* sv = locs->at(0); if (sv->type() == T_OBJECT) { Handle o = locs->at(0)->get_obj(); ! print_locked_object_class_name(st, o, wait_state); } + } else { + st->print_cr("\t- %s <no locals available>", wait_state); } } else if (thread()->current_park_blocker() != NULL) { oop obj = thread()->current_park_blocker(); Klass* k = obj->klass(); st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name()); } } ! // Print out all monitors that we have locked, are trying to lock ! // or are trying to relock after a wait(). GrowableArray<MonitorInfo*>* mons = monitors(); if (!mons->is_empty()) { bool found_first_monitor = false; for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index);
*** 200,233 **** continue; } if (monitor->owner() != NULL) { // the monitor is associated with an object, i.e., it is locked - // First, assume we have the monitor locked. If we haven't found an - // owned monitor before and this is the first frame, then we need to - // see if we have completed the lock or we are blocked trying to - // acquire it - we can only be blocked if the monitor is inflated - markOop mark = NULL; const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { mark = monitor->owner()->mark(); if (mark->has_monitor() && ( // we have marked ourself as pending on this monitor mark->monitor() == thread()->current_pending_monitor() || // we are not the owner of this monitor !mark->monitor()->is_entered(thread()) )) { lock_state = "waiting to lock"; } else { ! mark = NULL; // Disable printing below } } print_locked_object_class_name(st, monitor->owner(), lock_state); ! if (Verbose && mark != NULL) { ! // match with format above, replacing "-" with " ". ! st->print("\t lockbits="); mark->print_on(st); st->cr(); } found_first_monitor = true; --- 213,266 ---- continue; } if (monitor->owner() != NULL) { // the monitor is associated with an object, i.e., it is locked markOop mark = NULL; const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { + // If this is the first frame and we haven't found an owned + // monitor before, then we need to see if we have completed + // the lock or if we are blocked trying to acquire it. Only + // an inflated monitor that is first on the monitor list in + // the first frame can block us on a monitor enter. mark = monitor->owner()->mark(); if (mark->has_monitor() && ( // we have marked ourself as pending on this monitor mark->monitor() == thread()->current_pending_monitor() || // we are not the owner of this monitor !mark->monitor()->is_entered(thread()) )) { lock_state = "waiting to lock"; } else { ! // We own the monitor which is not as interesting so ! // disable the extra printing below. ! mark = NULL; } + } else if (frame_count != 0) { + // This is not the first frame so we either own this monitor + // or we owned the monitor before and called wait(). Because + // wait() could have been called on any monitor in a lower + // numbered frame on the stack, we have to check all the + // monitors on the list for this frame. + mark = monitor->owner()->mark(); + if (mark->has_monitor() && + ( // we have marked ourself as pending on this monitor + mark->monitor() == thread()->current_pending_monitor() || + // we are not the owner of this monitor + !mark->monitor()->is_entered(thread()) + )) { + lock_state = "waiting to relock"; + } else { + // We own the monitor which is not as interesting so + // disable the extra printing below. + mark = NULL; } + } print_locked_object_class_name(st, monitor->owner(), lock_state); ! if (VerboseStackTrace && mark != NULL) { ! st->print("\t- lockbits="); mark->print_on(st); st->cr(); } found_first_monitor = true;