Skip to content

Commit 2e1e87c

Browse files
committed
Try to explicitly handle OOME in merged fields/references/GC roots.
1 parent 0c9fad7 commit 2e1e87c

File tree

4 files changed

+72
-64
lines changed

4 files changed

+72
-64
lines changed

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/java/impl/JavaFieldsPlugin.java

Lines changed: 59 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.graalvm.visualvm.heapviewer.java.InstancesWrapper;
5252
import org.graalvm.visualvm.heapviewer.java.JavaHeapFragment;
5353
import org.graalvm.visualvm.heapviewer.model.DataType;
54+
import org.graalvm.visualvm.heapviewer.model.ErrorNode;
5455
import org.graalvm.visualvm.heapviewer.model.HeapViewerNode;
5556
import org.graalvm.visualvm.heapviewer.model.HeapViewerNodeFilter;
5657
import org.graalvm.visualvm.heapviewer.model.Progress;
@@ -63,6 +64,7 @@
6364
import org.graalvm.visualvm.heapviewer.ui.TreeTableViewColumn;
6465
import org.graalvm.visualvm.heapviewer.ui.UIThresholds;
6566
import org.graalvm.visualvm.heapviewer.utils.ExcludingIterator;
67+
import org.graalvm.visualvm.heapviewer.utils.HeapUtils;
6668
import org.graalvm.visualvm.heapviewer.utils.InterruptibleIterator;
6769
import org.graalvm.visualvm.heapviewer.utils.NodesComputer;
6870
import org.graalvm.visualvm.heapviewer.utils.ProgressIterator;
@@ -98,7 +100,6 @@
98100
"JavaFieldsPlugin_MenuStaticFields=Static Fields",
99101
"JavaFieldsPlugin_MenuFieldsHisto=Fields Histogram",
100102
"JavaFieldsPlugin_ValuesCountHint=({0} values)",
101-
"JavaFieldsPlugin_OOMEWarning=<too many instances - increase heap size!>",
102103
"JavaFieldsPlugin_FieldHistogramNodesContainer=<values {0}-{1}>"
103104
})
104105
class JavaFieldsPlugin extends HeapViewPlugin {
@@ -355,62 +356,60 @@ private String getName() {
355356
abstract InterruptibleIterator<Instance> instancesIterator();
356357

357358
protected HeapViewerNode[] lazilyComputeChildren(Heap heap, String viewID, HeapViewerNodeFilter viewFilter, List<DataType> dataTypes, List<SortOrder> sortOrders, Progress progress) throws InterruptedException {
358-
String fieldTypeName = fieldType.getName();
359-
360-
if ("object".equals(fieldTypeName)) { // NOI18N
361-
final InstanceCounter values = new InstanceCounter(instancesCount());
362-
363-
progress.setupKnownSteps(instancesCount());
364-
365-
Iterator<Instance> instances = instancesIterator();
366-
try {
367-
while (instances.hasNext()) {
368-
Instance instance = instances.next();
369-
progress.step();
370-
FieldValue value = getValueOfField(instance, fieldName);
371-
if (value instanceof ObjectFieldValue)
372-
values.count(((ObjectFieldValue)value).getInstance());
373-
}
374-
if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
375-
} finally {
376-
progress.finish();
377-
}
378-
379-
valuesCount = values.size();
380-
381-
NodesComputer<InstanceCounter.Record> computer = new NodesComputer<InstanceCounter.Record>(valuesCount, UIThresholds.MAX_MERGED_OBJECTS) {
382-
protected boolean sorts(DataType dataType) {
383-
return true;
384-
}
385-
protected HeapViewerNode createNode(InstanceCounter.Record object) {
386-
return new InstanceFieldValueNode(object.getInstance(heap), object.getCount()) {
387-
@Override
388-
String fieldName() { return fieldName; }
389-
@Override
390-
InterruptibleIterator<Instance> instancesIterator() { return FieldHistogramNode.this.instancesIterator(); }
391-
};
392-
}
393-
protected ProgressIterator<InstanceCounter.Record> objectsIterator(int index, Progress progress) {
394-
Iterator<InstanceCounter.Record> iterator = values.iterator();
395-
return new ProgressIterator(iterator, index, true, progress);
396-
}
397-
protected String getMoreNodesString(String moreNodesCount) {
398-
return Bundle.JavaFieldsPlugin_FieldHistogramMoreNodes(moreNodesCount);
399-
}
400-
protected String getSamplesContainerString(String objectsCount) {
401-
return Bundle.JavaFieldsPlugin_FieldHistogramSamplesContainer(objectsCount);
402-
}
403-
protected String getNodesContainerString(String firstNodeIdx, String lastNodeIdx) {
404-
return Bundle.JavaFieldsPlugin_FieldHistogramNodesContainer(firstNodeIdx, lastNodeIdx);
405-
}
406-
};
407-
408-
return computer.computeNodes(FieldHistogramNode.this, heap, viewID, null, dataTypes, sortOrders, progress);
409-
} else {
359+
try {
410360
int instancesCount = instancesCount();
411-
412-
try {
413-
361+
String fieldTypeName = fieldType.getName();
362+
363+
if ("object".equals(fieldTypeName)) { // NOI18N
364+
final InstanceCounter values = new InstanceCounter(instancesCount);
365+
366+
progress.setupKnownSteps(instancesCount);
367+
368+
Iterator<Instance> instances = instancesIterator();
369+
try {
370+
while (instances.hasNext()) {
371+
Instance instance = instances.next();
372+
progress.step();
373+
FieldValue value = getValueOfField(instance, fieldName);
374+
if (value instanceof ObjectFieldValue)
375+
values.count(((ObjectFieldValue)value).getInstance());
376+
}
377+
if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
378+
} finally {
379+
progress.finish();
380+
}
381+
382+
valuesCount = values.size();
383+
384+
NodesComputer<InstanceCounter.Record> computer = new NodesComputer<InstanceCounter.Record>(valuesCount, UIThresholds.MAX_MERGED_OBJECTS) {
385+
protected boolean sorts(DataType dataType) {
386+
return true;
387+
}
388+
protected HeapViewerNode createNode(InstanceCounter.Record object) {
389+
return new InstanceFieldValueNode(object.getInstance(heap), object.getCount()) {
390+
@Override
391+
String fieldName() { return fieldName; }
392+
@Override
393+
InterruptibleIterator<Instance> instancesIterator() { return FieldHistogramNode.this.instancesIterator(); }
394+
};
395+
}
396+
protected ProgressIterator<InstanceCounter.Record> objectsIterator(int index, Progress progress) {
397+
Iterator<InstanceCounter.Record> iterator = values.iterator();
398+
return new ProgressIterator(iterator, index, true, progress);
399+
}
400+
protected String getMoreNodesString(String moreNodesCount) {
401+
return Bundle.JavaFieldsPlugin_FieldHistogramMoreNodes(moreNodesCount);
402+
}
403+
protected String getSamplesContainerString(String objectsCount) {
404+
return Bundle.JavaFieldsPlugin_FieldHistogramSamplesContainer(objectsCount);
405+
}
406+
protected String getNodesContainerString(String firstNodeIdx, String lastNodeIdx) {
407+
return Bundle.JavaFieldsPlugin_FieldHistogramNodesContainer(firstNodeIdx, lastNodeIdx);
408+
}
409+
};
410+
411+
return computer.computeNodes(FieldHistogramNode.this, heap, viewID, null, dataTypes, sortOrders, progress);
412+
} else {
414413
final PrimitiveCounter counter = PrimitiveCounter.create(fieldTypeName, instancesCount);
415414

416415
progress.setupKnownSteps(instancesCount);
@@ -458,12 +457,11 @@ protected String getNodesContainerString(String firstNodeIdx, String lastNodeIdx
458457
};
459458

460459
return computer.computeNodes(FieldHistogramNode.this, heap, viewID, null, dataTypes, sortOrders, progress);
461-
462-
} catch (OutOfMemoryError e) {
463-
464-
return new HeapViewerNode[] { new TextNode(Bundle.JavaFieldsPlugin_OOMEWarning()) };
465-
466460
}
461+
} catch (OutOfMemoryError e) {
462+
System.err.println("Out of memory in JavaFieldsPlugin: " + e.getMessage()); // NOI18N
463+
HeapUtils.handleOOME(e);
464+
return new HeapViewerNode[] { new ErrorNode.OOME() };
467465
}
468466

469467
}

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/java/impl/JavaReferencesPlugin.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.graalvm.visualvm.heapviewer.java.InstancesWrapper;
5252
import org.graalvm.visualvm.heapviewer.java.JavaHeapFragment;
5353
import org.graalvm.visualvm.heapviewer.model.DataType;
54+
import org.graalvm.visualvm.heapviewer.model.ErrorNode;
5455
import org.graalvm.visualvm.heapviewer.model.HeapViewerNode;
5556
import org.graalvm.visualvm.heapviewer.model.HeapViewerNodeFilter;
5657
import org.graalvm.visualvm.heapviewer.model.Progress;
@@ -64,6 +65,7 @@
6465
import org.graalvm.visualvm.heapviewer.ui.UIThresholds;
6566
import org.graalvm.visualvm.heapviewer.utils.ExcludingIterator;
6667
import org.graalvm.visualvm.heapviewer.utils.HeapOperations;
68+
import org.graalvm.visualvm.heapviewer.utils.HeapUtils;
6769
import org.graalvm.visualvm.heapviewer.utils.InterruptibleIterator;
6870
import org.graalvm.visualvm.heapviewer.utils.NodesComputer;
6971
import org.graalvm.visualvm.heapviewer.utils.ProgressIterator;
@@ -92,8 +94,7 @@
9294
"JavaReferencesPlugin_ISamplesContainer=<sample {0} instances>",
9395
"JavaReferencesPlugin_INodesContainer=<instances {0}-{1}>",
9496
"JavaReferencesPlugin_MenuShowMergedReferences=Show Merged References",
95-
"JavaReferencesPlugin_MenuShowLogicalReferences=Show Logical References",
96-
"JavaReferencesPlugin_OOMEWarning=<too many references - increase heap size!>"
97+
"JavaReferencesPlugin_MenuShowLogicalReferences=Show Logical References"
9798
})
9899
class JavaReferencesPlugin extends HeapViewPlugin {
99100

@@ -243,7 +244,9 @@ private HeapViewerNode[] computeInstancesReferences(final InstancesWrapper insta
243244
}
244245
if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
245246
} catch (OutOfMemoryError e) {
246-
return new HeapViewerNode[] { new TextNode(Bundle.JavaReferencesPlugin_OOMEWarning()) };
247+
System.err.println("Out of memory in JavaReferencesPlugin: " + e.getMessage()); // NOI18N
248+
HeapUtils.handleOOME(e);
249+
return new HeapViewerNode[] { new ErrorNode.OOME() };
247250
} finally {
248251
progress.finish();
249252
}

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/java/impl/PathToGCRootPlugin.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@
6565
import javax.swing.JPopupMenu;
6666
import javax.swing.SwingUtilities;
6767
import org.graalvm.visualvm.heapviewer.java.InstancesWrapper;
68+
import org.graalvm.visualvm.heapviewer.model.ErrorNode;
6869
import org.graalvm.visualvm.heapviewer.utils.HeapOperations;
70+
import org.graalvm.visualvm.heapviewer.utils.HeapUtils;
6971
import org.graalvm.visualvm.lib.ui.swing.renderer.LabelRenderer;
7072
import org.openide.util.NbBundle;
7173
import org.openide.util.NbPreferences;
@@ -311,6 +313,10 @@ private static Collection<HeapViewerNode> computeInstancesRoots(Iterator<Instanc
311313
progress.step();
312314
}
313315
if (current.isInterrupted()) throw new InterruptedException();
316+
} catch (OutOfMemoryError e) {
317+
System.err.println("Out of memory in PathToGCRootPlugin: " + e.getMessage()); // NOI18N
318+
HeapUtils.handleOOME(e);
319+
return Collections.singleton(new ErrorNode.OOME());
314320
} finally {
315321
progress.finish();
316322
}

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/utils/HeapUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ public void run() {
205205
OOME_NOTIFIED = true;
206206
ProfilerDialogs.displayError(Bundle.HeapUtils_OomeMsg(), Bundle.HeapUtils_OomeCaption(), null);
207207
// NOTE: might update the Xmx automatically and/or lower MoreObjectsNode.MAX_BUFFER_SIZE
208+
// (won't work for OOMEs from merged references etc.)
208209
}
209210
}
210211
});

0 commit comments

Comments
 (0)