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;