Skip to content

Commit 0405564

Browse files
committed
Do the best to handle the OOME when computing children of a node.
1 parent d9f7a46 commit 0405564

File tree

6 files changed

+125
-6
lines changed

6 files changed

+125
-6
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package org.graalvm.visualvm.heapviewer.model;
26+
27+
import org.openide.util.NbBundle;
28+
29+
/**
30+
*
31+
* @author Jiri Sedlacek
32+
*/
33+
@NbBundle.Messages({
34+
"ErrorNode_OOME=<not enough memory>"
35+
})
36+
public class ErrorNode extends TextNode {
37+
38+
public ErrorNode(String text) {
39+
super(text);
40+
}
41+
42+
43+
public static final class OOME extends ErrorNode {
44+
45+
OOME() { super(Bundle.ErrorNode_OOME()); }
46+
47+
}
48+
49+
}

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/model/HeapViewerNode.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,16 @@ private HeapViewerNode[] resolveChildren() {
138138
RootNode root = RootNode.get(this);
139139
if (root == null) return NO_NODES;
140140

141-
children = root.retrieveChildren(this);
142-
143-
if (children == null) {
144-
HeapViewerNode[] ch = computeChildren(root);
145-
setChildren(ch == null ? NO_NODES : ch);
141+
try {
142+
children = root.retrieveChildren(this);
143+
144+
if (children == null) {
145+
HeapViewerNode[] ch = computeChildren(root);
146+
setChildren(ch == null ? NO_NODES : ch);
147+
}
148+
} catch (OutOfMemoryError e) {
149+
handleOOME(e);
150+
setChildren(new HeapViewerNode[] { new ErrorNode.OOME() });
146151
}
147152

148153
return children;
@@ -175,6 +180,9 @@ protected HeapViewerNode[] doInBackground() throws Exception {
175180
ret = lazilyComputeChildren(root.getContext().getFragment().getHeap(), root.getViewID(), root.getViewFilter(), root.getDataTypes(), root.getSortOrders(), progress);
176181
} catch (InterruptedException ex) {
177182
ret = null;
183+
} catch (OutOfMemoryError e) {
184+
handleOOME(e);
185+
ret = new HeapViewerNode[] { new ErrorNode.OOME() };
178186
}
179187
if (Thread.interrupted()) ret = null; // make sure the interrupted flag is handled & reset in all circumstances
180188

@@ -258,6 +266,13 @@ private static HeapViewerNode[] checkForLoops(HeapViewerNode parent, HeapViewerN
258266
}
259267

260268

269+
private void handleOOME(OutOfMemoryError e) {
270+
RootNode root = RootNode.get(this);
271+
if (root != null) root.handleOOME(e);
272+
else System.err.println("Out of memory in " + toString() + ": " + e.getMessage()); // NOI18N
273+
}
274+
275+
261276
// --- Values --------------------------------------------------------------
262277

263278
private static final Object NO_VALUE = new Object();

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/model/RootNode.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ public abstract class RootNode extends HeapViewerNode {
7070
public abstract HeapViewerRenderer resolveRenderer(HeapViewerNode node);
7171

7272

73+
protected void handleOOME(OutOfMemoryError e) {
74+
System.err.println("Out of memory in " + getViewID() + ": " + e.getMessage()); // NOI18N
75+
}
76+
77+
7378
// public RootNode() {
7479
// this(NO_NODES);
7580
// }

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/ui/TreeTableView.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import org.graalvm.visualvm.heapviewer.model.Progress;
7070
import org.graalvm.visualvm.heapviewer.model.RootNode;
7171
import javax.swing.RowSorter;
72+
import org.graalvm.visualvm.heapviewer.utils.HeapUtils;
7273
import org.openide.util.Lookup;
7374
import org.openide.util.NbBundle;
7475

@@ -145,6 +146,7 @@ public TreeTableView(String viewID, HeapContext context, HeapViewerActions actio
145146
protected HeapViewerNode[] retrieveChildren(HeapViewerNode node) { return nodesCache.retrieveChildren(node); }
146147
protected HeapViewerNode[] lazilyComputeChildren(Heap heap, String viewID, HeapViewerNodeFilter viewFilter, List<DataType> dataTypes, List<SortOrder> sortOrders, Progress progress) throws InterruptedException { return TreeTableView.this.computeData(root, heap, viewID, viewFilter, dataTypes, sortOrders, progress); }
147148
public HeapViewerRenderer resolveRenderer(HeapViewerNode node) { return TreeTableView.this.resolveNodeRenderer(node); }
149+
protected void handleOOME(OutOfMemoryError e) { super.handleOOME(e); TreeTableView.this.handleOOME(e); }
148150
};
149151
currentRoot = root;
150152

@@ -420,6 +422,12 @@ public HeapViewerRenderer getNodeRenderer(HeapViewerNode node) {
420422
return nodeRenderer;
421423
}
422424

425+
// --- OOME handling -------------------------------------------------------
426+
427+
protected void handleOOME(OutOfMemoryError e) {
428+
HeapUtils.handleOOME(e);
429+
}
430+
423431
// --- BreadCrumbs prototype -----------------------------------------------
424432

425433
private void setRoot(HeapViewerNode newRoot) {

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/ui/TreeTableViewRenderer.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@
3636
import org.graalvm.visualvm.lib.profiler.api.icons.Icons;
3737
import org.graalvm.visualvm.lib.profiler.heapwalk.ui.icons.HeapWalkerIcons;
3838
import org.graalvm.visualvm.heapviewer.model.DataType;
39+
import org.graalvm.visualvm.heapviewer.model.ErrorNode;
3940
import org.graalvm.visualvm.heapviewer.model.HeapViewerNode;
4041
import org.graalvm.visualvm.heapviewer.model.LoopNode;
4142
import org.graalvm.visualvm.heapviewer.model.ProgressNode;
43+
import org.graalvm.visualvm.lib.profiler.api.icons.GeneralIcons;
4244
import org.openide.util.NbBundle;
4345

4446
/**
@@ -61,6 +63,7 @@ class TreeTableViewRenderer implements ProfilerRenderer {
6163
{
6264
lookup.put(LoopNode.class, new LoopNodeRenderer());
6365
lookup.put(ProgressNode.class, new ProgressNodeRenderer());
66+
lookup.put(ErrorNode.class, new ErrorNodeRenderer());
6467
}
6568

6669

@@ -170,6 +173,22 @@ public String getShortName() {
170173

171174
}
172175

176+
private static class ErrorNodeRenderer extends LabelRenderer implements HeapViewerRenderer {
177+
178+
public ErrorNodeRenderer() {
179+
setIcon(Icons.getIcon(GeneralIcons.ERROR));
180+
}
181+
182+
public void setValue(Object value, int row) {
183+
setText(value == null ? "" : value.toString()); // NOI18N
184+
}
185+
186+
public String getShortName() {
187+
return getText();
188+
}
189+
190+
}
191+
173192
private static class FallbackRenderer extends LabelRenderer implements HeapViewerRenderer {}
174193

175194
}

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@
3232
import java.util.Iterator;
3333
import java.util.List;
3434
import java.util.Map;
35+
import javax.swing.SwingUtilities;
3536
import org.graalvm.visualvm.lib.jfluid.heap.FieldValue;
3637
import org.graalvm.visualvm.lib.jfluid.heap.Heap;
3738
import org.graalvm.visualvm.lib.jfluid.heap.Instance;
3839
import org.graalvm.visualvm.lib.jfluid.heap.JavaClass;
3940
import org.graalvm.visualvm.lib.jfluid.heap.ObjectFieldValue;
41+
import org.graalvm.visualvm.lib.profiler.api.ProfilerDialogs;
4042
import org.graalvm.visualvm.lib.profiler.heapwalk.details.spi.DetailsUtils;
4143
import org.openide.util.NbBundle;
4244

@@ -47,7 +49,9 @@
4749
@NbBundle.Messages({
4850
"HeapUtils_UnknownClass=unknown class",
4951
"HeapUtils_UnknownInstance=unknown instance",
50-
"HeapUtils_Class=class"
52+
"HeapUtils_Class=class",
53+
"HeapUtils_OomeCaption=Out Of Memory",
54+
"HeapUtils_OomeMsg=<html><b>Not enough memory to finish the operation.</b><br/><br/>To avoid this error please increase the -Xmx value<br>in the etc/visualvm.conf file in VisualVM directory.</html>"
5155
})
5256
public final class HeapUtils {
5357

@@ -190,6 +194,25 @@ public static String htmlize(String text) {
190194
}
191195

192196

197+
// --- OOME handling -------------------------------------------------------
198+
199+
private static boolean OOME_NOTIFIED = false;
200+
201+
public static void handleOOME(OutOfMemoryError e) {
202+
SwingUtilities.invokeLater(new Runnable() {
203+
public void run() {
204+
if (!OOME_NOTIFIED) {
205+
OOME_NOTIFIED = true;
206+
ProfilerDialogs.displayError(Bundle.HeapUtils_OomeMsg(), Bundle.HeapUtils_OomeCaption(), null);
207+
// NOTE: might update the Xmx automatically and/or lower MoreObjectsNode.MAX_BUFFER_SIZE
208+
}
209+
}
210+
});
211+
}
212+
213+
214+
// --- Private stuff -------------------------------------------------------
215+
193216
private HeapUtils() {}
194217

195218

0 commit comments

Comments
 (0)