1/*
2 * Copyright (c) 2002, 2008, 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.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25package sun.jvm.hotspot.ui;
26
27import java.util.*;
28import java.io.*;
29import java.awt.*;
30import java.awt.event.*;
31import javax.swing.*;
32import javax.swing.text.*;
33
34import sun.jvm.hotspot.debugger.*;
35import sun.jvm.hotspot.oops.*;
36import sun.jvm.hotspot.runtime.*;
37import sun.jvm.hotspot.utilities.*;
38
39/** Finds a given (Address) value in the heap. Only intended for use
40    in a debugging system. */
41
42public class FindInHeapPanel extends JPanel {
43  private RawHeapVisitor   iterator;
44  private long             addressSize;
45  private long             usedSize;
46  private long             iterated;
47  private Address          value;
48  private ProgressBarPanel progressBar;
49  private HistoryComboBox  addressField;
50  private JButton          findButton;
51  private JTextArea        textArea;
52  private ArrayList        updates;
53  private double           lastFrac;
54
55  static final double minUpdateFraction = 0.05;
56
57  public FindInHeapPanel() {
58    super();
59
60    setLayout(new BorderLayout());
61
62    JPanel topPanel = new JPanel();
63    topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
64
65    JPanel panel = new JPanel();
66    panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
67    panel.add(new JLabel("Address to search for:"));
68
69    addressField = new HistoryComboBox();
70    panel.add(addressField);
71
72    addressSize = VM.getVM().getAddressSize();
73
74    iterator = new RawHeapVisitor() {
75        boolean error = false;
76
77        public void prologue(long used) {
78          usedSize = used;
79          iterated = 0;
80          lastFrac = 0;
81          error = false;
82          updates = new ArrayList();
83        }
84
85        public void visitAddress(Address addr) {
86          if (error) return;
87
88          Address val = addr.getAddressAt(0);
89          if (AddressOps.equal(val, value)) {
90            error = reportResult(addr);
91          }
92          iterated += addressSize;
93          updateProgressBar();
94        }
95        public void visitCompOopAddress(Address addr) {
96          if (error) return;
97
98          Address val = addr.getCompOopAddressAt(0);
99          if (AddressOps.equal(val, value)) {
100            error = reportResult(addr);
101          }
102          iterated += addressSize;
103          updateProgressBar();
104
105        }
106        public void epilogue() {
107          iterated = 0;
108          updateProgressBar();
109          findButton.setEnabled(true);
110        }
111      };
112
113    findButton = new JButton("Find");
114    ActionListener listener = new ActionListener() {
115        public void actionPerformed(ActionEvent e) {
116          clearResultWindow();
117          // Parse text
118          try {
119            Address val = VM.getVM().getDebugger().parseAddress(addressField.getText());
120            value = val;
121
122            findButton.setEnabled(false);
123
124            java.lang.Thread t = new java.lang.Thread(new Runnable() {
125                public void run() {
126                  try {
127                    VM.getVM().getObjectHeap().iterateRaw(iterator);
128                  } finally {
129                    SwingUtilities.invokeLater(new Runnable() {
130                        public void run() {
131                          findButton.setEnabled(true);
132                        }
133                      });
134                  }
135                }
136              });
137            t.start();
138          } catch (Exception ex) {
139            textArea.setText("Error parsing address");
140          }
141        }
142      };
143    panel.add(findButton);
144    findButton.addActionListener(listener);
145    addressField.addActionListener(listener);
146    topPanel.add(panel);
147
148    progressBar = new ProgressBarPanel(ProgressBarPanel.HORIZONTAL, "Search progress:");
149    topPanel.add(progressBar);
150
151    add(topPanel, BorderLayout.NORTH);
152
153    textArea = new JTextArea();
154    JScrollPane scroller = new JScrollPane(textArea);
155    add(scroller, BorderLayout.CENTER);
156  }
157
158  private boolean pendingUpdate = false;
159
160  private boolean reportResult(final Address addr) {
161    synchronized (this) {
162      try {
163        updates.add("found at " + addr + "\n");
164        if (!pendingUpdate) {
165          pendingUpdate = true;
166          SwingUtilities.invokeLater(new Runnable() {
167              public void run() {
168                updateResultWindow();
169              }
170            });
171        }
172      } catch (Throwable t) {
173        t.printStackTrace();
174        return true;
175      }
176    }
177
178    return false;
179  }
180
181  private void clearResultWindow() {
182    SwingUtilities.invokeLater(new Runnable() {
183        public void run() {
184
185          Document d = textArea.getDocument();
186          try {
187            d.remove(0, d.getLength());
188          } catch (BadLocationException e) {
189          }
190        }
191      });
192  }
193
194  private synchronized void updateResultWindow() {
195    if (updates.size() > 0) {
196      Iterator i = updates.iterator();
197      while (i.hasNext()) {
198        textArea.append((String)i.next());
199      }
200      updates = new ArrayList();;
201    }
202    pendingUpdate = false;
203  }
204
205  private void invokeInDispatchThread(Runnable runnable) {
206    if (EventQueue.isDispatchThread()) {
207      runnable.run();
208    } else {
209      SwingUtilities.invokeLater(runnable);
210    }
211  }
212
213  private void updateProgressBar() {
214    final double frac = (double) iterated / (double) usedSize;
215    if (frac == 0.0 || (frac - lastFrac > minUpdateFraction)) {
216      lastFrac = frac;
217      if (iterated > usedSize) {
218        System.out.println("iterated " + iterated + " usedSize " + usedSize);
219      }
220      SwingUtilities.invokeLater(new Runnable() {
221          public void run() {
222            progressBar.setValue(frac);
223          }
224        });
225    }
226  }
227}
228