/*
 * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.ui;

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;

Finds a given (Address) value in the heap. Only intended for use in a debugging system.
/** Finds a given (Address) value in the heap. Only intended for use in a debugging system. */
public class FindInHeapPanel extends JPanel { private RawHeapVisitor iterator; private long addressSize; private long usedSize; private long iterated; private Address value; private ProgressBarPanel progressBar; private HistoryComboBox addressField; private JButton findButton; private JTextArea textArea; private ArrayList updates; private double lastFrac; static final double minUpdateFraction = 0.05; public FindInHeapPanel() { super(); setLayout(new BorderLayout()); JPanel topPanel = new JPanel(); topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS)); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); panel.add(new JLabel("Address to search for:")); addressField = new HistoryComboBox(); panel.add(addressField); addressSize = VM.getVM().getAddressSize(); iterator = new RawHeapVisitor() { boolean error = false; public void prologue(long used) { usedSize = used; iterated = 0; lastFrac = 0; error = false; updates = new ArrayList(); } public void visitAddress(Address addr) { if (error) return; Address val = addr.getAddressAt(0); if (AddressOps.equal(val, value)) { error = reportResult(addr); } iterated += addressSize; updateProgressBar(); } public void visitCompOopAddress(Address addr) { if (error) return; Address val = addr.getCompOopAddressAt(0); if (AddressOps.equal(val, value)) { error = reportResult(addr); } iterated += addressSize; updateProgressBar(); } public void epilogue() { iterated = 0; updateProgressBar(); findButton.setEnabled(true); } }; findButton = new JButton("Find"); ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent e) { clearResultWindow(); // Parse text try { Address val = VM.getVM().getDebugger().parseAddress(addressField.getText()); value = val; findButton.setEnabled(false); java.lang.Thread t = new java.lang.Thread(new Runnable() { public void run() { try { VM.getVM().getObjectHeap().iterateRaw(iterator); } finally { SwingUtilities.invokeLater(new Runnable() { public void run() { findButton.setEnabled(true); } }); } } }); t.start(); } catch (Exception ex) { textArea.setText("Error parsing address"); } } }; panel.add(findButton); findButton.addActionListener(listener); addressField.addActionListener(listener); topPanel.add(panel); progressBar = new ProgressBarPanel(ProgressBarPanel.HORIZONTAL, "Search progress:"); topPanel.add(progressBar); add(topPanel, BorderLayout.NORTH); textArea = new JTextArea(); JScrollPane scroller = new JScrollPane(textArea); add(scroller, BorderLayout.CENTER); } private boolean pendingUpdate = false; private boolean reportResult(final Address addr) { synchronized (this) { try { updates.add("found at " + addr + "\n"); if (!pendingUpdate) { pendingUpdate = true; SwingUtilities.invokeLater(new Runnable() { public void run() { updateResultWindow(); } }); } } catch (Throwable t) { t.printStackTrace(); return true; } } return false; } private void clearResultWindow() { SwingUtilities.invokeLater(new Runnable() { public void run() { Document d = textArea.getDocument(); try { d.remove(0, d.getLength()); } catch (BadLocationException e) { } } }); } private synchronized void updateResultWindow() { if (updates.size() > 0) { Iterator i = updates.iterator(); while (i.hasNext()) { textArea.append((String)i.next()); } updates = new ArrayList();; } pendingUpdate = false; } private void invokeInDispatchThread(Runnable runnable) { if (EventQueue.isDispatchThread()) { runnable.run(); } else { SwingUtilities.invokeLater(runnable); } } private void updateProgressBar() { final double frac = (double) iterated / (double) usedSize; if (frac == 0.0 || (frac - lastFrac > minUpdateFraction)) { lastFrac = frac; if (iterated > usedSize) { System.out.println("iterated " + iterated + " usedSize " + usedSize); } SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(frac); } }); } } }