< prev index next >
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -26,18 +26,23 @@
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.*;
+import sun.jvm.hotspot.debugger.*;
public abstract class JavaVFrame extends VFrame {
+
+ private static final String ADDRESS_FORMAT = VM.getVM().isLP64() ? "0x%016x"
+ : "0x%08x";
+
/** JVM state */
public abstract Method getMethod();
public abstract int getBCI();
public abstract StackValueCollection getLocals();
public abstract StackValueCollection getExpressions();
- public abstract List getMonitors(); // List<MonitorInfo>
+ public abstract List<MonitorInfo> getMonitors();
/** Test operation */
public boolean isJavaFrame() { return true; }
/** Package-internal constructor */
@@ -47,13 +52,129 @@
/** Get monitor (if any) that this JavaVFrame is trying to enter */
// FIXME: not yet implemented
// public Address getPendingMonitor(int frameCount);
+ public void printLockedObjectClassName(PrintStream tty,
+ OopHandle hobj, String lockState) {
+ if (hobj.asLongValue() != 0L) {
+ tty.format("\t- %s <" + ADDRESS_FORMAT + "> ",
+ lockState, hobj.asLongValue());
+
+ Klass klass = Oop.getKlassForOopHandle(hobj);
+ String klassName = klass.getName().asString();
+ tty.print("(a ");
+ if (klassName.equals("java/lang/Class")) {
+ Oop obj = VM.getVM().getObjectHeap().newOop(hobj);
+ klassName = java_lang_Class.asExternalName(obj);
+ tty.print("java.lang.Class for ");
+ }
+ tty.println(klassName.replace('/', '.') + ")");
+ }
+ }
+
/** Printing used during stack dumps */
- // FIXME: not yet implemented
- // void print_lock_info(int frame_count);
+ public void printLockInfo(PrintStream tty, int frameCount) {
+ // 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 (frameCount == 0) {
+ if (getMethod().getName().asString().equals("wait") &&
+ getMethod().getMethodHolder().getName().asString().equals("java/lang/Object")) {
+ String waitState = "waiting on"; // assume we are waiting
+ // If earlier in the output we reported java.lang.Thread.State ==
+ // "WAITING (on object monitor)" and now we report "waiting on", then
+ // we are still waiting for notification or timeout. Otherwise if
+ // we earlier reported java.lang.Thread.State == "BLOCKED (on object
+ // monitor)", then we are actually waiting to re-lock the monitor.
+ // At this level we can't distinguish the two cases to report
+ // "waited on" rather than "waiting on" for the second case.
+ StackValueCollection locs = getLocals();
+ if (!locs.isEmpty()) {
+ StackValue sv = locs.get(0);
+ if (sv.getType() == BasicType.getTObject()) {
+ OopHandle o = sv.getObject();
+ printLockedObjectClassName(tty, o, waitState);
+ }
+ } else {
+ tty.println("\t- " + waitState + " <no object reference available>");
+ }
+ } else if (thread.getCurrentParkBlocker() != null) {
+ Oop obj = thread.getCurrentParkBlocker();
+ Klass k = obj.getKlass();
+ tty.format("\t- parking to wait for <" + ADDRESS_FORMAT + "> (a %s)",
+ obj.getHandle().asLongValue(), k.getName().asString());
+ tty.println();
+ }
+ }
+
+ // Print out all monitors that we have locked, or are trying to lock,
+ // including re-locking after being notified or timing out in a wait().
+ List<MonitorInfo> mons = getMonitors();
+ if (!mons.isEmpty()) {
+ boolean foundFirstMonitor = false;
+ for (int index = mons.size() - 1; index >= 0; index--) {
+ MonitorInfo monitor = mons.get(index);
+ if (monitor.eliminated() && isCompiledFrame()) { // Eliminated in compiled code
+ if (monitor.ownerIsScalarReplaced()) {
+ Klass k = Oop.getKlassForOopHandle(monitor.ownerKlass());
+ tty.println("\t- eliminated <owner is scalar replaced> (a " + k.getName().asString() + ")");
+ } else if (monitor.owner() != null) {
+ printLockedObjectClassName(tty, monitor.owner(), "eliminated");
+ }
+ continue;
+ }
+ if (monitor.owner() != null) {
+ // the monitor is associated with an object, i.e., it is locked
+
+ Mark mark = null;
+ String lockState = "locked";
+ if (!foundFirstMonitor && frameCount == 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 = new Mark(monitor.owner());
+ if (mark.hasMonitor() &&
+ ( // we have marked ourself as pending on this monitor
+ mark.monitor().equals(thread.getCurrentPendingMonitor()) ||
+ // we are not the owner of this monitor
+ !mark.monitor().isEntered(thread)
+ )) {
+ lockState = "waiting to lock";
+ } else {
+ // We own the monitor which is not as interesting so
+ // disable the extra printing below.
+ mark = null;
+ }
+ } else if (frameCount != 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 = new Mark(monitor.owner());
+ if (mark.hasMonitor() &&
+ ( // we have marked ourself as pending on this monitor
+ mark.monitor().equals(thread.getCurrentPendingMonitor()) ||
+ // we are not the owner of this monitor
+ !mark.monitor().isEntered(thread)
+ )) {
+ lockState = "waiting to re-lock in wait()";
+ } else {
+ // We own the monitor which is not as interesting so
+ // disable the extra printing below.
+ mark = null;
+ }
+ }
+ printLockedObjectClassName(tty, monitor.owner(), lockState);
+ foundFirstMonitor = true;
+ }
+ }
+ }
+ }
/** Printing operations */
//
// FIXME: implement visitor pattern for traversing vframe contents?
@@ -71,26 +192,10 @@
tty.println();
tty.println("\tbci:\t" + getBCI());
printStackValuesOn(tty, "locals", getLocals());
printStackValuesOn(tty, "expressions", getExpressions());
-
- // List<MonitorInfo>
- // FIXME: not yet implemented
- // List list = getMonitors();
- // if (list.isEmpty()) {
- // return;
- // }
- // for (int index = 0; index < list.size(); index++) {
- // MonitorInfo monitor = (MonitorInfo) list.get(index);
- // tty.print("\t obj\t");
- // monitor.getOwner().printValueOn(tty);
- // tty.println();
- // tty.print("\t ");
- // monitor.lock().printOn(tty);
- // tty.println();
- // }
}
public void printActivation(int index) {
printActivationOn(System.out, index);
}
< prev index next >