Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/ui/Inspector.java @ 6972:bd7a7ce2e264
6830717: replay of compilations would help with debugging
Summary: When java process crashed in compiler thread, repeat the compilation process will help finding root cause. This is done with using SA dump application class data and replay data from core dump, then use debug version of jvm to recompile the problematic java method.
Reviewed-by: kvn, twisti, sspitsyn
Contributed-by: yumin.qi@oracle.com
author | minqi |
---|---|
date | Mon, 12 Nov 2012 14:03:53 -0800 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. |
0 | 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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.ui; | |
26 | |
27 import java.awt.*; | |
28 import java.awt.event.*; | |
29 import java.util.*; | |
30 import javax.swing.*; | |
31 import javax.swing.tree.TreePath; | |
32 import sun.jvm.hotspot.debugger.*; | |
33 import sun.jvm.hotspot.oops.*; | |
34 import sun.jvm.hotspot.runtime.*; | |
35 import sun.jvm.hotspot.types.*; | |
36 import sun.jvm.hotspot.ui.tree.*; | |
37 import sun.jvm.hotspot.utilities.*; | |
38 | |
39 /** This class implements tree-browsing functionality of a particular | |
40 SimpleTreeNode, and is only designed to be used in a debugging | |
41 system. It uses a SimpleTreeModel internally. It can inspect both | |
42 oops as well as C++ objects described by the VMStructs database in | |
43 the target VM. */ | |
44 | |
45 public class Inspector extends SAPanel { | |
46 private JTree tree; | |
47 private SimpleTreeModel model; | |
48 | |
49 // UI widgets we need permanent handles to | |
50 private HistoryComboBox addressField; | |
51 private JLabel statusLabel; | |
52 | |
53 private JButton livenessButton; | |
54 private ActionListener livenessButtonListener; | |
55 private ActionListener showLivenessListener; | |
56 private static final String computeLivenessText = "Compute Liveness"; | |
57 private static final String showLivenessText = "Show Liveness"; | |
58 private JLabel liveStatus; | |
59 private LivenessPathList list = null; | |
60 private Oop currentOop = null; | |
61 | |
62 public Inspector() { | |
63 model = new SimpleTreeModel(); | |
64 tree = new JTree(model); | |
65 | |
66 setLayout(new BorderLayout()); | |
67 Box hbox = Box.createHorizontalBox(); | |
68 JButton button = new JButton("Previous Oop"); | |
69 button.addActionListener(new ActionListener() { | |
70 public void actionPerformed(ActionEvent e) { | |
71 String text = addressField.getText(); | |
72 try { | |
73 VM vm = VM.getVM(); | |
74 Address a = vm.getDebugger().parseAddress(text); | |
75 OopHandle handle = a.addOffsetToAsOopHandle(-vm.getAddressSize()); | |
76 addressField.setText(handle.toString()); | |
77 } catch (Exception ex) { | |
78 } | |
79 } | |
80 }); | |
81 hbox.add(button); | |
82 hbox.add(new JLabel("Address / C++ Expression: ")); | |
83 addressField = new HistoryComboBox(); | |
84 hbox.add(addressField); | |
85 statusLabel = new JLabel(); | |
86 hbox.add(statusLabel); | |
87 | |
88 Box hboxDown = Box.createHorizontalBox(); | |
89 hboxDown.add(Box.createGlue()); | |
90 | |
91 livenessButton = new JButton(computeLivenessText); | |
92 livenessButtonListener = new ActionListener() { | |
93 public void actionPerformed(ActionEvent e) { | |
94 if (currentOop != null) { | |
95 fireComputeLiveness(); | |
96 } | |
97 return; | |
98 } | |
99 }; | |
100 showLivenessListener = new ActionListener() { | |
101 public void actionPerformed(ActionEvent e) { | |
102 fireShowLiveness(); | |
103 } | |
104 }; | |
105 livenessButton.addActionListener(livenessButtonListener); | |
106 hboxDown.add(livenessButton); | |
107 hboxDown.add(Box.createGlue()); | |
108 | |
109 liveStatus = new JLabel(); | |
110 hboxDown.add(liveStatus); | |
111 hboxDown.add(Box.createGlue()); | |
112 | |
113 add(hbox, BorderLayout.NORTH); | |
114 add(hboxDown, BorderLayout.SOUTH); | |
115 | |
116 addressField.addActionListener(new ActionListener() { | |
117 public void actionPerformed(ActionEvent e) { | |
118 String text = addressField.getText(); | |
119 try { | |
120 Address a = VM.getVM().getDebugger().parseAddress(text); | |
121 int max_searches = 1000; | |
122 int searches = 0; | |
123 int offset = 0; | |
124 Oop oop = null; | |
125 if (a != null) { | |
126 OopHandle handle = a.addOffsetToAsOopHandle(0); | |
127 while (searches < max_searches) { | |
128 searches++; | |
129 if (RobustOopDeterminator.oopLooksValid(handle)) { | |
130 try { | |
131 oop = VM.getVM().getObjectHeap().newOop(handle); | |
132 addressField.setText(handle.toString()); | |
133 break; | |
134 } catch (UnknownOopException ex) { | |
135 // ok | |
136 } catch (RuntimeException ex) { | |
137 ex.printStackTrace(); | |
138 } | |
139 } | |
140 offset -= 4; | |
141 handle = a.addOffsetToAsOopHandle(offset); | |
142 } | |
143 } | |
144 if (oop != currentOop) { | |
145 currentOop = oop; | |
146 liveStatus.setText(""); | |
147 list = null; | |
148 if (livenessButton.getText().equals(showLivenessText)) { | |
149 livenessButton.setText(computeLivenessText); | |
150 livenessButton.removeActionListener(showLivenessListener); | |
151 livenessButton.addActionListener(livenessButtonListener); | |
152 } | |
153 } | |
154 | |
155 if (oop != null) { | |
156 statusLabel.setText(""); | |
157 setRoot(new OopTreeNodeAdapter(oop, null)); | |
158 return; | |
159 } | |
160 | |
161 // Try to treat this address as a C++ object and deduce its type | |
162 Type t = VM.getVM().getTypeDataBase().guessTypeForAddress(a); | |
163 if (t != null) { | |
164 statusLabel.setText(""); | |
165 setRoot(new CTypeTreeNodeAdapter(a, t, null)); | |
166 return; | |
167 } | |
168 | |
169 statusLabel.setText("<bad oop or unknown C++ object " + text + ">"); | |
170 } | |
171 catch (NumberFormatException ex) { | |
172 currentOop = null; | |
173 liveStatus.setText(""); | |
174 list = null; | |
175 if (livenessButton.getText().equals(showLivenessText)) { | |
176 livenessButton.setText(computeLivenessText); | |
177 livenessButton.removeActionListener(showLivenessListener); | |
178 livenessButton.addActionListener(livenessButtonListener); | |
179 } | |
180 // Try to treat this as a C++ expression | |
181 CPPExpressions.CastExpr cast = CPPExpressions.parseCast(text); | |
182 if (cast != null) { | |
183 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
184 Type t = db.lookupType(cast.getType()); | |
185 if (t == null) { | |
186 statusLabel.setText("<unknown C++ type \"" + cast.getType() + "\">"); | |
187 } else { | |
188 try { | |
189 Address a = VM.getVM().getDebugger().parseAddress(cast.getAddress()); | |
190 statusLabel.setText(""); | |
191 setRoot(new CTypeTreeNodeAdapter(a, t, null)); | |
192 } catch (NumberFormatException ex2) { | |
193 statusLabel.setText("<bad address " + cast.getAddress() + ">"); | |
194 } | |
195 } | |
196 return; | |
197 } | |
198 CPPExpressions.StaticFieldExpr stat = CPPExpressions.parseStaticField(text); | |
199 if (stat != null) { | |
200 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
201 Type t = db.lookupType(stat.getContainingType()); | |
202 if (t == null) { | |
203 statusLabel.setText("<unknown C++ type \"" + stat.getContainingType() + "\">"); | |
204 } else { | |
205 sun.jvm.hotspot.types.Field f = t.getField(stat.getFieldName(), true, false); | |
206 if (f == null) { | |
207 statusLabel.setText("<unknown field \"" + stat.getFieldName() + "\" in type \"" + | |
208 stat.getContainingType() + "\">"); | |
209 } else if (!f.isStatic()) { | |
210 statusLabel.setText("<field \"" + stat.getContainingType() + "::" + | |
211 stat.getFieldName() + "\" was not static>"); | |
212 } else { | |
213 Type fieldType = f.getType(); | |
214 if (fieldType.isPointerType()) { | |
215 fieldType = ((PointerType) fieldType).getTargetType(); | |
216 | |
217 // Try to get a more derived type | |
218 Type typeGuess = db.guessTypeForAddress(f.getAddress()); | |
219 if (typeGuess != null) { | |
220 fieldType = typeGuess; | |
221 } | |
222 | |
223 statusLabel.setText(""); | |
224 setRoot(new CTypeTreeNodeAdapter(f.getAddress(), | |
225 fieldType, | |
226 new NamedFieldIdentifier(text))); | |
227 } else { | |
228 statusLabel.setText(""); | |
229 setRoot(new CTypeTreeNodeAdapter(f.getStaticFieldAddress(), | |
230 f.getType(), | |
231 new NamedFieldIdentifier(text))); | |
232 } | |
233 } | |
234 } | |
235 return; | |
236 } | |
237 | |
238 statusLabel.setText("<parse error>"); | |
239 } | |
240 catch (AddressException ex) { | |
241 ex.printStackTrace(); | |
242 currentOop = null; | |
243 liveStatus.setText(""); | |
244 list = null; | |
245 if (livenessButton.getText().equals(showLivenessText)) { | |
246 livenessButton.setText(computeLivenessText); | |
247 livenessButton.removeActionListener(showLivenessListener); | |
248 livenessButton.addActionListener(livenessButtonListener); | |
249 } | |
250 statusLabel.setText("<bad address>"); | |
251 } | |
252 catch (Exception ex) { | |
253 ex.printStackTrace(); | |
254 currentOop = null; | |
255 liveStatus.setText(""); | |
256 list = null; | |
257 if (livenessButton.getText().equals(showLivenessText)) { | |
258 livenessButton.setText(computeLivenessText); | |
259 livenessButton.removeActionListener(showLivenessListener); | |
260 livenessButton.addActionListener(livenessButtonListener); | |
261 } | |
262 statusLabel.setText("<error constructing oop>"); | |
263 } | |
264 } | |
265 }); | |
266 | |
267 MouseListener ml = new MouseAdapter() { | |
268 public void mousePressed(MouseEvent e) { | |
269 int selRow = tree.getRowForLocation(e.getX(), e.getY()); | |
270 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); | |
271 if(selRow != -1) { | |
272 if (e.getClickCount() == 1 && (e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0) { | |
273 Object node = tree.getLastSelectedPathComponent(); | |
274 if (node != null && node instanceof SimpleTreeNode) { | |
275 showInspector((SimpleTreeNode)node); | |
276 } | |
277 } | |
278 } | |
279 } | |
280 }; | |
281 tree.addMouseListener(ml); | |
282 | |
283 JScrollPane scrollPane = new JScrollPane(tree); | |
284 | |
285 // Let's see what happens if we let the parent deal with resizing the panel | |
286 add(scrollPane, BorderLayout.CENTER); | |
287 } | |
288 | |
289 public Inspector(final SimpleTreeNode root) { | |
290 this(); | |
291 SwingUtilities.invokeLater( new Runnable() { | |
292 public void run() { | |
293 if (root instanceof OopTreeNodeAdapter) { | |
294 final Oop oop = ((OopTreeNodeAdapter)root).getOop(); | |
295 addressField.setText(oop.getHandle().toString()); | |
296 } | |
297 setRoot(root); | |
298 } | |
299 }); | |
300 } | |
301 | |
302 private void setRoot(SimpleTreeNode root) { | |
303 model.setRoot(root); | |
304 | |
305 // tree.invalidate(); | |
306 // tree.validate(); | |
307 // repaint(); | |
308 // FIXME: invalidate? How to get to redraw? Will I have to make | |
309 // tree listeners work? | |
310 } | |
311 | |
312 private void fireComputeLiveness() { | |
313 final Runnable cutoverButtonRunnable = new Runnable() { | |
314 public void run() { | |
315 list = LivenessAnalysis.computeAllLivenessPaths(currentOop); | |
316 if (list == null) { | |
317 liveStatus.setText("Oop is Dead"); | |
318 } else { | |
319 liveStatus.setText("Oop is Alive"); | |
320 livenessButton.removeActionListener(livenessButtonListener); | |
321 livenessButton.addActionListener(showLivenessListener); | |
322 | |
323 livenessButton.setEnabled(true); | |
324 livenessButton.setText(showLivenessText); | |
325 } | |
326 } | |
327 }; | |
328 | |
329 | |
330 if (VM.getVM().getRevPtrs() != null) { | |
331 cutoverButtonRunnable.run(); | |
332 } else { | |
333 final WorkerThread worker = new WorkerThread(); | |
334 worker.invokeLater(new Runnable() { | |
335 public void run() { | |
336 try { | |
337 ReversePtrsAnalysis rev = new ReversePtrsAnalysis(); | |
338 rev.run(); | |
339 cutoverButtonRunnable.run(); | |
340 } finally { | |
341 worker.shutdown(); | |
342 } | |
343 } | |
344 }); | |
345 } | |
346 } | |
347 | |
348 private void fireShowLiveness() { | |
349 if (list == null) { | |
350 return; // dead object | |
351 } | |
352 | |
353 for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { | |
354 SAListener listener = (SAListener) iter.next(); | |
355 listener.showLiveness(currentOop, list); | |
356 } | |
357 } | |
358 } |