Describe the bug
Making two memory profiling snapshots and comparing them with each other leads to a partial GUI crash when I try to expand a class entry that is present in one but not the other.
Stack trace:
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10588
at org.graalvm.visualvm.lib.jfluid.results.memory.MemoryResultsSnapshot.createPresentationCCT(MemoryResultsSnapshot.java:213)
at org.graalvm.visualvm.lib.jfluid.results.memory.LivenessMemoryResultsSnapshot.createPresentationCCT(LivenessMemoryResultsSnapshot.java:329)
at org.graalvm.visualvm.lib.jfluid.results.memory.LivenessMemoryResultsDiff.createPresentationCCT(LivenessMemoryResultsDiff.java:162)
at org.graalvm.visualvm.lib.jfluid.results.memory.LivenessMemoryResultsDiff.createPresentationCCT(LivenessMemoryResultsDiff.java:44)
at org.graalvm.visualvm.lib.jfluid.results.memory.MemoryCCTManager.<init>(MemoryCCTManager.java:46)
at org.graalvm.visualvm.lib.ui.memory.LivenessTreeTableView$1Node.getChildren(LivenessTreeTableView.java:254)
at org.graalvm.visualvm.lib.ui.memory.LivenessTreeTableView$1Node.getChildCount(LivenessTreeTableView.java:266)
at java.desktop/javax.swing.tree.DefaultTreeModel.getChildCount(DefaultTreeModel.java:201)
at org.graalvm.visualvm.lib.ui.swing.ProfilerTreeTable$FilteredTreeModel.getChildCount(ProfilerTreeTable.java:926)
at java.desktop/javax.swing.tree.FixedHeightLayoutCache$VisibleFHTreeStateNodeEnumeration.updateNextIndex(FixedHeightLayoutCache.java:1599)
[ ... a lot more GUI stack frames ... ]
Potential Fix
The reason is that MemoryResultsSnapshot.createPresentationCCT gets -1 and cannot handle it.
The issue seems to be that LivenessMemoryResultsDiff.createPresentationCCT does not take care of this:
|
protected PresoObjLivenessCCTNode createPresentationCCT(RuntimeMemoryCCTNode rootNode, int classId, |
|
boolean dontShowZeroLiveObjAllocPaths) { |
|
PresoObjLivenessCCTNode node1 = snapshot1.createPresentationCCT(rootNode, classId1(classId), dontShowZeroLiveObjAllocPaths); |
|
PresoObjLivenessCCTNode node2 = snapshot2.createPresentationCCT(rootNode, classId2(classId), dontShowZeroLiveObjAllocPaths); |
|
return new DiffObjLivenessCCTNode(node1, node2); |
|
} |
I imagine the solution would look very similar to JdbcResultsDiff.createPresentationCCT:
|
public PresoObjAllocCCTNode createPresentationCCT(int selectId, boolean dontShowZeroLiveObjAllocPaths) { |
|
int selectId1 = selectId1(selectId); |
|
int selectId2 = selectId2(selectId); |
|
PresoObjAllocCCTNode node1 = null; |
|
PresoObjAllocCCTNode node2 = null; |
|
|
|
if (selectId1 != -1) { |
|
node1 = snapshot1.createPresentationCCT(selectId1, dontShowZeroLiveObjAllocPaths); |
|
} |
|
if (selectId2 != -1) { |
|
node2 = snapshot2.createPresentationCCT(selectId2, dontShowZeroLiveObjAllocPaths); |
|
} |
|
return new DiffObjAllocCCTNode(node1, node2); |
|
} |
A similar issue could be somewhere else in the code as well, e.g.:
|
protected PresoObjAllocCCTNode createPresentationCCT(RuntimeMemoryCCTNode rootNode, int classId, |
|
boolean dontShowZeroLiveObjAllocPaths) { |
|
PresoObjAllocCCTNode node1 = snapshot1.createPresentationCCT(rootNode, selectId1(classId), dontShowZeroLiveObjAllocPaths); |
|
PresoObjAllocCCTNode node2 = snapshot2.createPresentationCCT(rootNode, selectId2(classId), dontShowZeroLiveObjAllocPaths); |
|
return new DiffObjAllocCCTNode(node1, node2); |
|
} |
I have not tested this one, but there seems to be an array access based on the class index further down the line as well.
There might be even more similar problems, I haven't checked the whole codebase.
Alternative Fix
MemoryResultsSnapshot.createPresentationCCT and alike return null if the class is -1.
Describe the bug
Making two memory profiling snapshots and comparing them with each other leads to a partial GUI crash when I try to expand a class entry that is present in one but not the other.
Stack trace:
Potential Fix
The reason is that
MemoryResultsSnapshot.createPresentationCCTgets-1and cannot handle it.The issue seems to be that
LivenessMemoryResultsDiff.createPresentationCCTdoes not take care of this:visualvm/visualvm/libs.profiler/lib.profiler/src/org/graalvm/visualvm/lib/jfluid/results/memory/LivenessMemoryResultsDiff.java
Lines 180 to 185 in a3f9289
I imagine the solution would look very similar to
JdbcResultsDiff.createPresentationCCT:visualvm/visualvm/libs.profiler/lib.profiler/src/org/graalvm/visualvm/lib/jfluid/results/jdbc/JdbcResultsDiff.java
Lines 83 to 96 in a3f9289
A similar issue could be somewhere else in the code as well, e.g.:
visualvm/visualvm/libs.profiler/lib.profiler/src/org/graalvm/visualvm/lib/jfluid/results/jdbc/JdbcResultsDiff.java
Lines 110 to 115 in a3f9289
I have not tested this one, but there seems to be an array access based on the class index further down the line as well.
There might be even more similar problems, I haven't checked the whole codebase.
Alternative Fix
MemoryResultsSnapshot.createPresentationCCTand alike returnnullif the class is-1.