in src/application/org.openjdk.jmc.joverflow/src/main/java/org/openjdk/jmc/joverflow/stats/OverallStatsCalculator.java [73:257]
public HeapStats calculate() throws HprofParsingCancelledException {
int objHeaderSize = snapshot.getObjectHeaderSize();
long arrHeaderSize = snapshot.getArrayHeaderSize(); // Made long to get long result when multiplying by int
StringStatsCollector stringStatsCollector = new StringStatsCollector(snapshot);
PrimitiveArrayDuplicationMap arrayDupMap = new PrimitiveArrayDuplicationMap(snapshot);
Collection<JavaLazyReadObject> allObjects = snapshot.getObjects();
nObjs = 0;
int nInstances = 0, nObjectArrays = 0;
long totalObjectSize = 0, totalInstSize = 0, totalObjArraySize = 0;
int nEntryInstances = 0;
long entryClassSize = 0;
int n0LenObjArrays = 0, n1ObjArrays = 0, n4ObjArrays = 0, n8ObjArrays = 0;
int n0LenValArrays = 0, n1LenValArrays = 0, n4LenValArrays = 0, n8LenValArrays = 0;
int lenZeroObjArraySize = 0, lenOneObjArraySize = 0;
int nBoxedNumbers = 0;
long ovhdBoxedNumbers = 0;
int curChunk = 0;
ObjectToIntMap<String> unmodifiableClassInstanceCount = new ObjectToIntMap<>(15);
ObjectToIntMap<String> synchronizedClassInstanceCount = new ObjectToIntMap<>(15);
for (JavaLazyReadObject obj : allObjects) {
nObjs++;
JavaClass clazz = obj.getClazz();
clazz.incNumInstances();
String clazzName = clazz.getName();
int objSize = obj.getSize();
totalObjectSize += objSize;
if (obj instanceof JavaObject) {
nInstances++;
totalInstSize += objSize;
int primitiveNumSize;
if (clazzName.endsWith("$Entry")) {
nEntryInstances++;
entryClassSize += objSize;
} else if (clazzName.startsWith("java.util.Collections$Unmodifiable")) {
unmodifiableClassInstanceCount.putOneOrIncrement(clazzName);
} else if (clazzName.startsWith("java.util.Collections$Synchronized")) {
synchronizedClassInstanceCount.putOneOrIncrement(clazzName);
} else if (clazz.isString()) {
stringStatsCollector.add((JavaObject) obj);
} else if ((primitiveNumSize = clazz.getBoxedNumberSize()) != 0) {
nBoxedNumbers++;
ovhdBoxedNumbers += objSize - primitiveNumSize + ptrSize;
}
} else if (obj instanceof JavaObjectArray) {
nObjectArrays++;
totalObjArraySize += objSize;
clazz.updateShallowInstanceSize(objSize);
JavaObjectArray objArray = (JavaObjectArray) obj;
int length = objArray.getLength();
if (length == 0) {
n0LenObjArrays++;
if (lenZeroObjArraySize == 0) {
lenZeroObjArraySize = objArray.getSize();
}
} else if (length == 1) {
n1ObjArrays++;
if (lenOneObjArraySize == 0) {
lenOneObjArraySize = objArray.getSize();
}
} else if (length <= 4) {
n4ObjArrays++;
} else if (length <= 8) {
n8ObjArrays++;
}
} else if (obj instanceof JavaValueArray) {
clazz.updateShallowInstanceSize(objSize);
JavaValueArray valArray = (JavaValueArray) obj;
int length = valArray.getLength();
if (length == 0) {
// System.out.println("Zero-length val array: " + obj + " , size = " + objSize);
n0LenValArrays++;
} else if (length == 1) {
n1LenValArrays++;
} else if (length <= 4) {
n4LenValArrays++;
} else if (length <= 8) {
n8LenValArrays++;
}
// Performance optimization: scan as many primitive arrays as possible on
// the first pass, although there is a separate 2nd pass for them. However,
// reading more objects from disk now improves cache locality.
if (!(clazz.isCharArray() || clazz.isByteArray())) {
// This array, because of its type, is guaranteed to not belong to a String
arrayDupMap.add(valArray);
}
}
// System.out.println(obj + " , size = " + objSize);
int newCurChunk = nObjs >> 17; // Check every 128K objects
if (newCurChunk > curChunk) {
curChunk = newCurChunk;
if (cancelled) {
throw new HprofParsingCancelledException();
}
}
}
long ovhdObjectHeaders = nObjs * objHeaderSize;
ObjectToIntMap.Entry<String>[] unmodifiableClasses = unmodifiableClassInstanceCount
.getEntriesSortedByValueThenKey();
ObjectToIntMap.Entry<String>[] synchronizedClasses = synchronizedClassInstanceCount
.getEntriesSortedByValueThenKey();
// Do one more pass, this time to uncover duplicated primitive arrays.
// We could not do it on the previous pass, because there we generally
// unable to distinguish standalone char[] arrays from those that are
// backing Strings.
curChunk = 0;
for (JavaLazyReadObject obj : allObjects) {
nObjs2ndPass++; // This is pure progress tracking
if (!(obj instanceof JavaValueArray)) {
continue;
}
JavaClass clazz = obj.getClazz();
// Ignore if not a char[] or byte[] array - should have been scanned on previous pass
if (!(clazz.isCharArray() || clazz.isByteArray())) {
continue;
}
// Ignore if it's a char[] array for some String
if (obj.isVisitedAsCollectionImpl()) {
continue;
}
JavaValueArray valArray = (JavaValueArray) obj;
arrayDupMap.add(valArray);
int newCurChunk = nObjs2ndPass >> 17; // Check every 128K objects
if (newCurChunk > curChunk) {
curChunk = newCurChunk;
if (cancelled) {
throw new HprofParsingCancelledException();
}
}
}
arrayDupMap.calculateFinalStats();
DupArrayStats dupArrayStats = new DupArrayStats(arrayDupMap.getNumArrays(), arrayDupMap.getNumUniqueArrays(),
arrayDupMap.getNumDifferentDupArrayValues(), arrayDupMap.getDupArrays(),
arrayDupMap.getDupArraysOverhead());
// IMPORTANT: should do this for optimizations in CachedReadBuffer to work!
ReadBuffer readBuf = snapshot.getReadBuffer();
if (readBuf instanceof CachedReadBuffer) {
((CachedReadBuffer) readBuf).incrementPass();
}
ClassloaderStats clStats = new ClassloaderStats(snapshot);
return new HeapStats()
.setGeneralStats(ptrSize, objHeaderSize, snapshot.getObjectAlignment(), snapshot.usingNarrowPointers(),
snapshot.getNumClasses(), nObjs, nInstances, nObjectArrays, totalObjectSize, totalInstSize,
totalObjArraySize)
.setObjOverheadStats(ovhdObjectHeaders, nEntryInstances, entryClassSize).setClassloaderStats(clStats)
.setShortObjArrayStats(new ShortArrayStats(n0LenObjArrays, lenZeroObjArraySize * n0LenObjArrays,
n1ObjArrays, lenOneObjArraySize * n1ObjArrays, n4ObjArrays, arrHeaderSize * n4ObjArrays,
n8ObjArrays, arrHeaderSize * n8ObjArrays))
// TODO: need a better way to calculate overhead for short primitive arrays, at least of size 0 and 1
// Currently it's likely inconsistent with what is reported by detailed analysis
.setShortPrimitiveArrayStats(new ShortArrayStats(n0LenValArrays, arrHeaderSize * n0LenValArrays,
n1LenValArrays, arrHeaderSize * n1LenValArrays, n4LenValArrays, arrHeaderSize * n4LenValArrays,
n8LenValArrays, arrHeaderSize * n8LenValArrays))
.setShortStringStats(stringStatsCollector.getShortStringStats())
.setBoxedNumberStats(nBoxedNumbers, ovhdBoxedNumbers)
.setWrappedCollectionStats(unmodifiableClasses, synchronizedClasses)
.setDupStringStats(stringStatsCollector.getDuplicationStats())
.setCompressibleStringStats(stringStatsCollector.getCompressibleStringStats())
.setNumberEncodingStringStats(stringStatsCollector.getNumberEncodingStringStats())
.setStringLengthHistogram(stringStatsCollector.getLengthHistogram()).setDupArrayStats(dupArrayStats);
}