in src/application/org.openjdk.jmc.joverflow/src/main/java/org/openjdk/jmc/joverflow/stats/BreadthFirstHeapScanner.java [95:219]
protected void scanObjectsFromRootObj(JavaHeapObject obj) {
while (obj != null) {
if (obj.setVisitedIfNot()) {
currentProcessedObjNo++;
if (cancelled) {
throw new HprofParsingCancelledException.Runtime();
}
JavaClass clazz = obj.getClazz();
if (clazz.isString()) {
objHandler.handleString((JavaObject) obj);
} else {
if (obj instanceof JavaObject) {
JavaObject javaObj = (JavaObject) obj;
JavaThing[] fields = javaObj.getFields();
CollectionInstanceDescriptor colDesc = objHandler.handleInstance(javaObj, fields);
if (fields.length > 0 && obj.getClazz().hasReferenceFields()) {
// Nullify various fields like those for auxiliary linked list in LinkedHashMap,
// so that scanObjectFields does not have problems with long lists, etc.
int[] bannedFieldIndices = clazz.getBannedFieldIndices();
if (bannedFieldIndices != null) {
for (int bannedFieldIdx : bannedFieldIndices) {
fields[bannedFieldIdx] = null;
}
}
if (colDesc != null) {
// obj is a collection. Add its elements ("payload") to the nextFrontier,
// and handle its internal implementation objects immediately.
if (colDesc.getClassDescriptor().isMap()) {
colDesc.iterateMap(new CollectionInstanceDescriptor.MapIteratorCallback() {
@Override
public boolean scanMapEntry(JavaHeapObject key, JavaHeapObject value) {
pushCollectionElement(key);
pushCollectionElement(value);
return true;
}
@Override
public boolean scanImplementationObject(JavaHeapObject implObj) {
if (implObj.setVisitedIfNot()) {
currentProcessedObjNo++;
if (implObj instanceof JavaObject) {
JavaObject implJavaObj = (JavaObject) implObj;
objHandler.handleInstance(implJavaObj, implJavaObj.getFields());
} else {
// We set elements param to null to avoid overhead. They won't be
// used by handler anyway, because array should be marked as
// visitedAsCollectionImpl() by this time.
objHandler.handleObjectArray((JavaObjectArray) implObj, null);
}
return true;
} else {
// Probably corrupted data - we shouldn't see a visited object
return false;
}
}
});
} else {
colDesc.iterateList(new CollectionInstanceDescriptor.ListIteratorCallback() {
@Override
public boolean scanListElement(JavaHeapObject element) {
pushCollectionElement(element);
return true;
}
@Override
public boolean scanImplementationObject(JavaHeapObject implObj) {
if (implObj.setVisitedIfNot()) {
currentProcessedObjNo++;
if (implObj instanceof JavaObject) {
JavaObject implJavaObj = (JavaObject) implObj;
objHandler.handleInstance(implJavaObj, implJavaObj.getFields());
} else {
objHandler.handleObjectArray((JavaObjectArray) implObj, null);
}
return true;
} else {
// Probably corrupted data - we shouldn't see a visited object
return false;
}
}
});
}
finishCollectionPush(obj);
if (colDesc.hasExtraObjFields()) {
colDesc.filterExtraObjFields(fields);
pushFields(obj, fields, ParentType.INSTANCE);
}
} else {
// An ordinary, non-collection object
pushFields(obj, fields, ParentType.INSTANCE);
}
}
} else if (obj instanceof JavaClass) {
JavaThing[] staticFields = ((JavaClass) obj).getStaticValues();
if (staticFields.length > 0) {
pushFields(obj, staticFields, ParentType.CLAZZ);
}
} else if (obj instanceof JavaObjectArray) {
JavaObjectArray objArray = (JavaObjectArray) obj;
JavaHeapObject[] elements = objArray.getElements();
objHandler.handleObjectArray(objArray, elements);
if (elements.length > 0) {
pushArrayElements(obj, elements);
}
} else {
objHandler.handleValueArray((JavaValueArray) obj);
}
}
}
// Determine the next object to scan
obj = getNextObjFromFrontier();
}
curFrontier = null;
}