1
2
3
4
5
6
7
8
9
10
11
12
13
14 package net.sf.madmap;
15
16 import java.io.*;
17 import java.util.*;
18 import java.awt.*;
19 import java.awt.event.*;
20 import javax.swing.*;
21 import javax.swing.event.*;
22 import javax.swing.filechooser.*;
23
24 public class MainWindow extends JPanel implements ActionListener, ItemListener {
25 static private final String newline = "\n";
26 public JTextArea log;
27 JTabbedPane tabbedPane;
28 JFileChooser fc;
29 JFileChooser saveChooser;
30 JProgressBar pb;
31 JLabel pbl;
32 JProgressBar mpb;
33 JLabel mpbl;
34 JMenuItem newWindowItem;
35 JMenuItem openItem;
36 JMenuItem saveItem;
37 JMenuItem quitItem;
38 JMenuItem classSizeItem;
39 JMenuItem memberNamesItem;
40 JMenuItem verboseItem;
41 JMenuItem helpItem;
42 JFrame frame;
43 Madmap document = null;
44
45 ILogger _logger = (ILogger)(MadmapMain.appContext()).getBean("logger");
46 IResources _resources = (IResources)(MadmapMain.appContext()).getBean("resources");
47
48 public static File getCWD(){
49 return new File(System.getProperty("user.dir"));
50 }
51
52 public JMenuBar createMenuBar() {
53 JMenuBar menuBar;
54 JMenu menu;
55
56 menuBar = new JMenuBar();
57
58 menu = new JMenu(_resources.getString("fileMenu"));
59 menuBar.add(menu);
60
61 newWindowItem = new JMenuItem(_resources.getString("newItem"));
62 newWindowItem.getAccessibleContext().setAccessibleDescription(_resources.getString("newDescription"));
63 menu.add(newWindowItem);
64 newWindowItem.addActionListener(this);
65
66 openItem = new JMenuItem(_resources.getString("openItem"));
67 openItem.getAccessibleContext().setAccessibleDescription(_resources.getString("openDescription"));
68 menu.add(openItem);
69 openItem.addActionListener(this);
70
71 saveItem = new JMenuItem(_resources.getString("saveItem"));
72 saveItem.getAccessibleContext().setAccessibleDescription(_resources.getString("saveDescription"));
73 menu.add(saveItem);
74 saveItem.addActionListener(this);
75
76 quitItem = new JMenuItem(_resources.getString("quitItem"));
77 quitItem.getAccessibleContext().setAccessibleDescription(_resources.getString("quitDescription"));
78 menu.add(quitItem);
79 quitItem.addActionListener(this);
80
81 menu = new JMenu(_resources.getString("helpMenu"));
82 menuBar.add(menu);
83
84
85
86
87
88
89 memberNamesItem = new JCheckBoxMenuItem(_resources.getString("memberNamesItem"));
90
91 menu.add(memberNamesItem);
92 memberNamesItem.addItemListener(this);
93 memberNamesItem.setSelected(MadmapMain.getSaveMemberNames());
94
95 verboseItem = new JCheckBoxMenuItem(_resources.getString("verboseItem"));
96
97 menu.add(verboseItem);
98
99 verboseItem.addItemListener(this);
100 verboseItem.setSelected(MadmapMain.verbose());
101
102 helpItem = new JMenuItem(_resources.getString("helpItem"));
103 helpItem.getAccessibleContext().setAccessibleDescription(_resources.getString("helpDescription"));
104 menu.add(helpItem);
105 helpItem.addActionListener(this);
106
107 return menuBar;
108 }
109
110
111 public MainWindow(JFrame theFrame) {
112 super(new BorderLayout());
113 frame = theFrame;
114
115
116
117 log = new JTextArea();
118 log.setMargin(new Insets(5,5,5,5));
119 log.setEditable(false);
120
121
122 pb = new JProgressBar(0,100);
123 pb.setStringPainted(true);
124 pbl = new JLabel( "Ready. " );
125
126
127 mpb = new JProgressBar(0,100);
128 mpb.setStringPainted(true);
129 mpbl = new JLabel( "Heap used: " );
130
131 mpb.setMinimum(0);
132 mpb.setMaximum(100);
133 mpb.setValue(0);
134
135 fc = new JFileChooser(getCWD());
136 saveChooser = new JFileChooser(getCWD());
137
138 JPanel buttonPanel = new JPanel();
139 buttonPanel.add(pbl);
140 buttonPanel.add(pb);
141 buttonPanel.add(mpbl);
142 buttonPanel.add(mpb);
143
144 tabbedPane = new JTabbedPane();
145
146 JComponent panel1 = makeLogPanel();
147 panel1.setPreferredSize(new Dimension(600, 200));
148 tabbedPane.addTab("Report", null, panel1,
149 "Progress and diagnostic messages. You can save the report by the Save Button");
150
151 add(buttonPanel, BorderLayout.PAGE_END);
152 add(tabbedPane, BorderLayout.CENTER);
153 }
154
155 protected JComponent makeTextPanel(String text) {
156 JPanel panel = new JPanel(false);
157 JLabel filler = new JLabel(text);
158 filler.setHorizontalAlignment(JLabel.CENTER);
159 panel.setLayout(new GridLayout(1, 1));
160 panel.add(filler);
161 return panel;
162 }
163
164 protected JComponent makeLogPanel() {
165 JPanel panel = new JPanel(false);
166 JScrollPane logScrollPane = new JScrollPane(log);
167 panel.setLayout(new GridLayout(1, 1));
168 panel.add(logScrollPane);
169 return panel;
170 }
171
172 public void addLiveHeapTab( java.util.List<HprofClassElement> liveHeap, long liveSize ) {
173 JPanel panel2 = new JPanel(false);
174 JTable table = new JTable(new LiveHeapTableModel(liveHeap, liveSize));
175 JScrollPane scrollpane = new JScrollPane(table);
176 panel2.setLayout(new GridLayout(1, 1));
177 panel2.add(scrollpane);
178 tabbedPane.addTab("Live Heap", null, panel2,
179 "Display live heap table with size and count");
180 }
181
182 public void addRetainedByClassTab( Madmap m, ArrayList liveHeap, long liveSize, String title ) {
183 JPanel panel = new JPanel(false);
184 JTable table = new JTable(new CumulativeRetainedHeapTableModel(m, liveHeap, liveSize));
185 JScrollPane scrollpane = new JScrollPane(table);
186 panel.setLayout(new GridLayout(1, 1));
187 panel.add(scrollpane);
188 tabbedPane.addTab(new String("Ret by Class: " + title), null, panel,
189 "Display classes retaining the most cumulative size when roots sorted by " + title);
190 }
191
192 public void addRetainedHeapTab( Madmap m, ArrayList liveHeap, long liveSize, String title ) {
193 JPanel panel2 = new JPanel(false);
194 JTextArea retLog = new JTextArea();
195 JTable table = new JTable(new RetainedHeapTableModel(m, liveHeap, liveSize, retLog));
196
197 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
198 table.getSelectionModel().addListSelectionListener(new RowListener(table));
199
200 JScrollPane scrollpane = new JScrollPane(table);
201 panel2.setLayout(new GridLayout(2, 0));
202 panel2.add(scrollpane, BorderLayout.PAGE_START);
203
204 retLog.setMargin(new Insets(5,5,5,5));
205 retLog.setEditable(false);
206 JScrollPane retScrollPane = new JScrollPane(retLog);
207 panel2.add(retScrollPane, BorderLayout.PAGE_END);
208
209 retLog.setText("Click on a row to see the allocation site.");
210 tabbedPane.addTab(new String( "Ret: " + title ), null, panel2,
211 "Display objects retaining the most size when roots sorted by " + title);
212 }
213
214 private void outputSelection(JTable table) {
215 int selectedRow[] = table.getSelectedRows();
216
217 assert selectedRow.length == 1 : "Should set selection model to single";
218
219 JTextArea retLog = ((RetainedHeapTableModel)table.getModel()).getLog();
220 java.util.List stk = ((RetainedHeapTableModel)table.getModel()).getStack( selectedRow[0] );
221
222 retLog.setText( "" );
223 retLog.setText( "Allocation site:\n" );
224 if ( stk != null ) {
225 for (int i = 0; i < stk.size(); i++ ) {
226 String output = new String( " " + ((String) stk.get(i)) + "\n" );
227 retLog.append(output);
228 }
229 } else {
230 String output = new String( " <no stack trace available>" + "\n" );
231 retLog.append(output);
232 }
233
234 retLog.append("\n");
235
236 String summary = ((RetainedHeapTableModel)table.getModel()).childrenSummary( selectedRow[0] );
237 if ( summary != null ) {
238 retLog.append(summary);
239 } else {
240 String output = new String( " <no member data available>" + "\n" );
241 retLog.append(output);
242 }
243
244 retLog.updateUI();
245 updateMemoryProgressBar();
246 }
247
248 private class RowListener implements ListSelectionListener {
249 JTable _parent;
250 public RowListener( JTable t ) {
251 _parent = t;
252 }
253 public void valueChanged(ListSelectionEvent event) {
254 if (event.getValueIsAdjusting()) {
255 return;
256 }
257 outputSelection(_parent);
258 }
259 }
260
261
262 public void addFinalizerHeapTab( java.util.List<HprofClassElement> finalizableHeap ) {
263 JPanel panel2 = new JPanel(false);
264 JTable table = new JTable(new FinalizerTableModel(finalizableHeap));
265 JScrollPane scrollpane = new JScrollPane(table);
266 panel2.setLayout(new GridLayout(1, 1));
267 panel2.add(scrollpane);
268 tabbedPane.addTab("Finalizable Objects", null, panel2,
269 "Display finalizable objects table with size and count");
270 }
271
272 public void addThreadsTab( TreeSet threads ) {
273 JPanel panel2 = new JPanel(false);
274 JTable table = new JTable(new ThreadTableModel(threads));
275 JScrollPane scrollpane = new JScrollPane(table);
276 panel2.setLayout(new GridLayout(1, 1));
277 panel2.add(scrollpane);
278 tabbedPane.addTab("Threads", null, panel2,
279 "Display threads appearing in the profile. Not all the threads may be live at the time the heap dump was written.");
280 }
281
282 public void itemStateChanged(ItemEvent e) {
283 if (e.getSource() == verboseItem) {
284 boolean curr = verboseItem.isSelected();
285
286 MadmapMain.setVerbose(curr);
287
288 } else if (e.getSource() == memberNamesItem) {
289 boolean curr = memberNamesItem.isSelected();
290 MadmapMain.setSaveMemberNames(curr);
291 }
292 }
293
294 public void actionPerformed(ActionEvent e) {
295 if (e.getSource() == openItem) {
296 if (document == null) {
297 int returnVal = fc.showOpenDialog(MainWindow.this);
298 if (returnVal == JFileChooser.APPROVE_OPTION) {
299 File file = fc.getSelectedFile();
300 log.append("Opening: " + file.getName() + "." + newline);
301 frame.setTitle( "Madmap: " + file.getName() );
302 (new Thread( document = new Madmap(file, this))).start();
303 }
304 log.setCaretPosition(log.getDocument().getLength());
305 } else {
306
307
308 int returnVal = fc.showOpenDialog(MainWindow.this);
309 if (returnVal == JFileChooser.APPROVE_OPTION) {
310 File file = fc.getSelectedFile();
311 JFrame frame = new JFrame("Madmap");
312 frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
313 newContentPane = new MainWindow(frame);
314 newContentPane.setOpaque(true);
315 frame.setContentPane(newContentPane);
316 frame.setJMenuBar(newContentPane.createMenuBar());
317 frame.pack();
318 frame.setVisible(true);
319 frame.setTitle( "Madmap: " + file.getName() );
320 (new Thread( document = new Madmap(file, newContentPane))).start();
321 }
322 }
323 } else if (e.getSource() == newWindowItem) {
324 init();
325 } else if (e.getSource() == saveItem) {
326 int returnVal = saveChooser.showSaveDialog(MainWindow.this);
327 if (returnVal == JFileChooser.APPROVE_OPTION) {
328 File file = saveChooser.getSelectedFile();
329 log.append("Saving: " + file.getName() + "." + newline);
330 _logger.saveConsoleLog( this, file );
331 } else {
332 log.append("Save command cancelled by user." + newline);
333 }
334 log.setCaretPosition(log.getDocument().getLength());
335 } else if (e.getSource() == helpItem) {
336
337 log.append( _resources.getString("helpText") );
338 log.append( _resources.getString("usageStrs") );
339 } else if (e.getSource() == saveItem) {
340 } else if (e.getSource() == quitItem) {
341 System.err.println("goodbye!");
342 System.exit(0);
343 }
344 }
345
346 static MainWindow newContentPane = null;
347
348 public static MainWindow getToolUI() { return newContentPane; }
349
350
351 private static void createAndShowGUI() {
352 JFrame frame = new JFrame("Madmap");
353 frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
354
355 newContentPane = new MainWindow(frame);
356 newContentPane.setOpaque(true);
357 frame.setContentPane(newContentPane);
358
359 frame.setJMenuBar(newContentPane.createMenuBar());
360
361
362 frame.pack();
363 frame.setVisible(true);
364 }
365
366 public static void init() {
367 javax.swing.SwingUtilities.invokeLater(new Runnable() {
368 public void run() {
369 createAndShowGUI();
370 MadmapMain.guiNotify();
371 }
372 });
373 }
374
375 public JProgressBar getProgressBar() {
376 return pb;
377 }
378
379 public JLabel getLabelForProgressBar() {
380 return pbl;
381 }
382
383 public void updateMemoryProgressBar() {
384 long total = Runtime.getRuntime().totalMemory();
385 long free = Runtime.getRuntime().freeMemory();
386 int usedPct = (int)( (double)(total - free)/((double)total) * (double)100.0 );
387 mpb.setValue(usedPct);
388 }
389 }
390