use of com.ibm.dtfj.java.JavaObject in project openj9 by eclipse.
the class PHDJavaRuntime method prepThreads.
/**
* Remember objects associated with threads.
* Performance optimization - we can then find these objects on a scan through the heap
* and remember them, saving a fruitless search of the heap if they only exist in a javacore.
*/
private void prepThreads() {
if (metaJavaRuntime != null) {
final PHDJavaClassLoader boot = loaders.get(null);
for (Iterator it = metaJavaRuntime.getThreads(); it.hasNext(); ) {
Object next = it.next();
if (next instanceof CorruptData)
continue;
JavaThread thr = (JavaThread) next;
try {
JavaObject jo = thr.getObject();
saveExtraObject(boot, jo);
} catch (CorruptDataException e) {
}
}
}
}
use of com.ibm.dtfj.java.JavaObject in project openj9 by eclipse.
the class DeadlockCommand method doCommand.
public void doCommand() {
SortedMap monitorNodes = new TreeMap();
JavaRuntime jr = ctx.getRuntime();
Iterator itMonitor = jr.getMonitors();
int nodeListNum = 0;
out.print("\n deadlocks for runtime \n");
// JVM dumps on Linux don't have all the image threads, so we now use JavaThreads
while (itMonitor.hasNext()) {
JavaMonitor monitor = (JavaMonitor) itMonitor.next();
MonitorNode node = new MonitorNode(monitor);
JavaThread owner = null;
Long id = null;
try {
owner = monitor.getOwner();
} catch (CorruptDataException e) {
out.println("exception encountered while getting monitor owner: " + Exceptions.getCorruptDataExceptionString());
return;
}
if (null == owner) {
// the monitor's owner or the next monitor in a potential deadlock chain.
continue;
} else {
JavaObject threadObject;
try {
threadObject = owner.getObject();
} catch (CorruptDataException e) {
out.println("exception encountered while getting owner's JavaObject: " + Exceptions.getCorruptDataExceptionString());
return;
}
id = new Long(threadObject.getID().getAddress());
}
// Note: defect 133638, we used to give up here with an error if there was already
// a monitor node in the table with the same key (thread). This is very common (a
// thread owning multiple monitors). Longer term the intention is to replace this
// algorithm with the one used in javacore, but for now we carry on to see if we can
// still find a deadlock, with some node(s) discarded.
monitorNodes.put(id, node);
}
// Step 1.b
// Add the JUC locks, technically to find all of them you need to walk the whole
// heap. But the active ones can be found by walking the thread list and looking
// at the blocking objects. (Any others aren't blocking any threads anyway so aren't
// interesting.
Iterator itThread = jr.getThreads();
while (itThread.hasNext()) {
try {
Object o = itThread.next();
if (!(o instanceof JavaThread)) {
continue;
}
JavaThread jt = (JavaThread) o;
JavaThread owner = null;
Long id = null;
if ((jt.getState() & JavaThread.STATE_PARKED) != 0) {
JavaObject lock = jt.getBlockingObject();
MonitorNode node = new JUCMonitorNode(lock, jr);
try {
owner = Utils.getParkBlockerOwner(lock, jr);
if (owner == null) {
continue;
}
} catch (MemoryAccessException e) {
out.println("exception encountered while getting monitor owner: " + Exceptions.getCorruptDataExceptionString());
return;
}
JavaObject threadObject;
try {
threadObject = owner.getObject();
} catch (CorruptDataException e) {
out.println("exception encountered while getting owner's JavaObject: " + Exceptions.getCorruptDataExceptionString());
return;
}
id = new Long(threadObject.getID().getAddress());
monitorNodes.put(id, node);
}
} catch (CorruptDataException cde) {
out.println("\nwarning, corrupt data encountered during scan for java.util.concurrent locks...");
} catch (DataUnavailable du) {
out.println("\nwarning, data unavailable encountered during scan for java.util.concurrent locks...");
}
}
Iterator values = monitorNodes.values().iterator();
// enter waiter, set that waiter's MonitorNode's waitingOn to m1.
while (values.hasNext()) {
MonitorNode currNode = (MonitorNode) values.next();
Iterator itWaiters = currNode.getEnterWaiters();
while (itWaiters.hasNext()) {
Object o = itWaiters.next();
if (!(o instanceof JavaThread)) {
continue;
}
JavaThread waiter = (JavaThread) o;
JavaObject threadObject;
Long id = null;
try {
threadObject = waiter.getObject();
} catch (CorruptDataException e) {
out.println("exception encountered while getting waiter's ImageThread: " + Exceptions.getCorruptDataExceptionString());
return;
}
id = new Long(threadObject.getID().getAddress());
MonitorNode waiterNode = (MonitorNode) monitorNodes.get(id);
if (null != waiterNode) {
waiterNode.waitingOn = currNode;
}
}
}
values = monitorNodes.values().iterator();
int visit = 1;
Vector lists = new Vector();
while (values.hasNext()) {
MonitorNode startNode = (MonitorNode) values.next();
MonitorNode currNode = startNode;
MonitorNode endNode;
if (0 != startNode.visit) {
continue;
}
while (true) {
currNode.visit = visit;
if (null == currNode.waitingOn) {
currNode.deadlock = MonitorNode.NO_DEADLOCK;
break;
}
if (isDeadlocked(currNode.waitingOn)) {
// we've encountered a deadlocked node in the chain;
// set branch deadlock for all nodes between startNode
// and currNode
endNode = currNode.waitingOn;
currNode = startNode;
NodeList branchList = null;
while (currNode != endNode) {
if (null == branchList) {
branchList = new NodeList(currNode, nodeListNum++);
}
currNode.deadlock = MonitorNode.BRANCH_DEADLOCK;
currNode = currNode.waitingOn;
branchList.add(currNode);
if (currNode != endNode)
currNode.inList = branchList;
}
if (endNode.inList.isLoop()) {
lists.insertElementAt(branchList, lists.indexOf(endNode.inList));
} else {
NodeList oldList = endNode.inList;
// FIXME: the below line will cause problems with at least
// one case that was not considered when attachOrSplit was
// coded: if a NodeList n1 has already been split and another
// NodeList n2 tries to attach to the end of n1, then n1 will
// allow n2 to attach to n1, while what n1 should really do is
// just return n2 and not allow n2 to attach to itself
NodeList split = endNode.inList.attachOrSplit(branchList, nodeListNum++);
if (null != split) {
lists.insertElementAt(split, lists.indexOf(oldList));
lists.insertElementAt(branchList, lists.indexOf(oldList));
}
}
break;
}
if (currNode.waitingOn.visit == visit) {
// we've encountered a node in the same visit as the current
// visit, ie. we've found a loop; first flag the whole loop
// with a loop deadlock flag, then flag the rest of the nodes
// in the chain with a branch deadlock
endNode = currNode.waitingOn;
currNode = endNode;
NodeList loopList = new NodeList(currNode, nodeListNum++);
lists.insertElementAt(loopList, 0);
do {
currNode.deadlock = MonitorNode.LOOP_DEADLOCK;
currNode = currNode.waitingOn;
loopList.add(currNode);
currNode.inList = loopList;
} while (currNode != endNode);
currNode = startNode;
NodeList branchList = null;
while (currNode != endNode) {
if (null == branchList) {
branchList = new NodeList(currNode, nodeListNum++);
lists.insertElementAt(branchList, 0);
}
currNode.deadlock = MonitorNode.BRANCH_DEADLOCK;
currNode = currNode.waitingOn;
branchList.add(currNode);
if (currNode != endNode)
currNode.inList = branchList;
}
break;
}
currNode = currNode.waitingOn;
}
visit++;
}
if (lists.isEmpty()) {
out.print("\n");
out.print("\t no deadlocks detected");
out.print("\n");
return;
}
boolean lastListWasLoop = true;
Iterator itList = lists.iterator();
// Step 5. print the lists
while (itList.hasNext()) {
NodeList list = (NodeList) itList.next();
if (list.isLoop()) {
out.print("\n deadlock loop:\n");
lastListWasLoop = true;
} else if (lastListWasLoop) {
// && !list.isLoop()
out.print("\n\n deadlock branch(es):\n");
lastListWasLoop = false;
}
out.print("\t " + list.toString());
out.print("\n");
}
out.print("\n");
}
use of com.ibm.dtfj.java.JavaObject in project openj9 by eclipse.
the class HeapdumpCommand method getClassReferences.
/* Reference code reimplemented (rather than using the DTFJ getReferences() API)
* because we are trying to match the behaviour of the runtime heapdump rather than
* the GC spec. The set of references we're trying to create is different.
*/
/**
* Gets the references for the supplied class
*
* @param thisJavaClass Class being examined
*/
private ReferenceIterator getClassReferences(JavaClass thisJavaClass) {
List references = new LinkedList();
try {
// Class object instance references
addReferences(thisJavaClass.getObject(), references);
// Statics
addStaticReferences(thisJavaClass, references);
addProtectionDomainReference(thisJavaClass, references);
// Constant pool class references
Iterator constantPoolIt = thisJavaClass.getConstantPoolReferences();
while (constantPoolIt.hasNext()) {
Object cpObject = constantPoolIt.next();
if (cpObject instanceof JavaClass) {
// Found a class reference, add it to the list
JavaClass cpJavaClass = (JavaClass) cpObject;
references.add(new Long(cpJavaClass.getObject().getID().getAddress()));
}
}
// Superclass references
JavaClass superClass = thisJavaClass.getSuperclass();
while (null != superClass) {
references.add(new Long(superClass.getObject().getID().getAddress()));
superClass = superClass.getSuperclass();
}
// Classloader
JavaClassLoader loader = thisJavaClass.getClassLoader();
if (loader != null) {
JavaObject loaderObject = loader.getObject();
if (loaderObject != null) {
references.add(new Long(loaderObject.getID().getAddress()));
} else {
reportError("Null loader object returned for class: " + thisJavaClass.getName() + "(" + thisJavaClass.getID() + ")", null);
_numberOfErrors++;
}
} else {
reportError("Null classloader returned for class: " + thisJavaClass.getName() + "(" + thisJavaClass.getID() + ")", null);
_numberOfErrors++;
}
} catch (DTFJException ex) {
reportError(null, ex);
_numberOfErrors++;
}
return new LongListReferenceIterator(references);
}
use of com.ibm.dtfj.java.JavaObject in project openj9 by eclipse.
the class HeapdumpCommand method dumpClasses.
/**
* Walks the runtime classes and passes them through the formatter interface
*/
private void dumpClasses(HeapDumpFormatter formatter, JavaRuntime runtime) throws IOException {
Iterator classLoaderIt = runtime.getJavaClassLoaders();
int numberOfClasses = 0;
ITERATING_LOADERS: while (classLoaderIt.hasNext()) {
Object potential = classLoaderIt.next();
if (potential instanceof CorruptData) {
_numberOfErrors++;
reportError("CorruptData found in classloader list at address: " + ((CorruptData) potential).getAddress(), null);
continue ITERATING_LOADERS;
}
JavaClassLoader thisClassLoader = (JavaClassLoader) potential;
Iterator classesIt = thisClassLoader.getDefinedClasses();
ITERATING_CLASSES: while (classesIt.hasNext()) {
potential = classesIt.next();
numberOfClasses++;
try {
if (potential instanceof CorruptData) {
_numberOfErrors++;
reportError("CorruptData found in class list for classloader " + Long.toHexString(thisClassLoader.getObject().getID().getAddress()) + " at address: " + ((CorruptData) potential).getAddress(), null);
continue ITERATING_CLASSES;
}
JavaClass thisJavaClass = (JavaClass) potential;
JavaClass superClass = thisJavaClass.getSuperclass();
JavaObject classObject = thisJavaClass.getObject();
long instanceSize;
if (thisJavaClass.isArray()) {
instanceSize = 0;
} else {
instanceSize = thisJavaClass.getInstanceSize();
}
int hashcode = 0;
if (_is32BitHash) {
// JVMs from 2.6 on, optional 32-bit hashcodes, if object was hashed
try {
hashcode = classObject != null ? (int) classObject.getPersistentHashcode() : 0;
} catch (DataUnavailable ex) {
// no persistent hashcode for this object, pass hashcode=0 to the heapdump formatter
}
} else {
// JVMs prior to 2.6, all objects should have a 16-bit hashcode
hashcode = classObject != null ? (int) classObject.getHashcode() : 0;
}
formatter.addClass(classObject.getID().getAddress(), thisJavaClass.getName(), superClass != null ? superClass.getID().getAddress() : 0, classObject != null ? (int) classObject.getSize() : 0, instanceSize, hashcode, getClassReferences(thisJavaClass));
} catch (DTFJException ex) {
// Handle CorruptDataException and DataUnavailableException the same way
_numberOfErrors++;
reportError(null, ex);
continue ITERATING_CLASSES;
}
}
}
_numberOfClasses = numberOfClasses;
if ((pdSkipCount > 0) && _verbose) {
out.println("Warning : The protection domain information was not available for " + pdSkipCount + " classes");
}
}
use of com.ibm.dtfj.java.JavaObject in project openj9 by eclipse.
the class HeapdumpCommand method addReferences.
/**
* Extracts the instance references from an object
* @param object Object being walked
* @param references List<Long> to add references to
* @param thisClass Class of object
*/
private void addReferences(JavaObject object, List<Long> references) throws CorruptDataException, MemoryAccessException {
Iterator it = object.getReferences();
Object ref = null;
// discard the first reference which is always to the class
if (it.hasNext()) {
// test hasNext() to be on the safe side.
ref = it.next();
}
while (it.hasNext()) {
ref = it.next();
if (ref instanceof CorruptData) {
// can sometimes get a nasty surprise in the list - e.g. a J9DDRCorruptData
_numberOfErrors++;
reportError("Corrupt data found at address " + ((CorruptData) ref).getAddress() + " getting references from object at address: " + Long.toHexString(object.getID().getAddress()) + " of class " + object.getJavaClass().getName() + "(" + object.getJavaClass().getID() + ")", null);
continue;
}
if (!(ref instanceof JavaReference)) {
_numberOfErrors++;
reportError("Object of unexpected type " + ref.getClass() + " found within references from object at address: " + object.getID().getAddress() + " of class " + object.getJavaClass().getName() + "(" + object.getJavaClass().getID() + ")", null);
continue;
} else {
Object target;
try {
target = ((JavaReference) ref).getTarget();
} catch (DataUnavailable e) {
_numberOfErrors++;
reportError("DataUnavailable thrown from call to getTarget() on reference: " + ref, null);
continue;
}
// the following ugliness is necessary as JavaObject and JavaClass both support getID() but do not inherit from a common parent
if (target instanceof JavaObject) {
references.add(new Long(((JavaObject) target).getID().getAddress()));
} else if (target instanceof JavaClass) {
references.add(new Long(((JavaClass) target).getID().getAddress()));
} else {
_numberOfErrors++;
reportError("Object of unexpected type " + target.getClass() + " returned from call to getTarget() on reference " + ref, null);
}
}
}
}
Aggregations