view agent/src/share/classes/sun/jvm/hotspot/ui/ObjectHistogramPanel.java @ 17716:cdb71841f4bc

6498581: ThreadInterruptTest3 produces wrong output on Windows Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set. Reviewed-by: acorn, kvn Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author minqi
date Wed, 26 Feb 2014 15:20:41 -0800
parents c18cbe5936b8
children
line wrap: on
line source

/*
 * Copyright (c) 2000, 2002, 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.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.table.*;

import sun.jvm.hotspot.oops.ObjectHistogram;
import sun.jvm.hotspot.oops.ObjectHistogramElement;
import sun.jvm.hotspot.oops.Klass;

import sun.jvm.hotspot.ui.table.LongCellRenderer;
import sun.jvm.hotspot.ui.table.SortableTableModel;
import sun.jvm.hotspot.ui.table.SortHeaderCellRenderer;
import sun.jvm.hotspot.ui.table.SortHeaderMouseAdapter;
import sun.jvm.hotspot.ui.table.TableModelComparator;

import sun.jvm.hotspot.ui.action.*;

import com.sun.java.swing.ui.StatusBar;
import com.sun.java.swing.ui.CommonToolBar;

import com.sun.java.swing.action.ActionManager;
import com.sun.java.swing.action.DelegateAction;

/**
 * Displays the results of an ObjectHistogram run in a JTable, with a
 * button to display all objects of that type
 */
public class ObjectHistogramPanel extends JPanel implements ActionListener {
    private ObjectHistogramTableModel dataModel;
    private ObjectHistogramToolBar toolbar;
    private StatusBar statusBar;
    private JTable     table;
    private java.util.List listeners;

    public ObjectHistogramPanel(ObjectHistogram histo) {
        dataModel = new ObjectHistogramTableModel(histo);
        statusBar = new StatusBar();

        table = new JTable(dataModel, new ObjectHistogramColummModel());
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent evt) {
                    if (evt.getClickCount() == 2) {
                        fireShowObjectsOfType();
                    }
                }
            });

        JTableHeader header = table.getTableHeader();
        header.setDefaultRenderer(new SortHeaderCellRenderer(header, dataModel));
        header.addMouseListener(new SortHeaderMouseAdapter(table, dataModel));

        setLayout(new BorderLayout());

        toolbar = new ObjectHistogramToolBar(statusBar);
        add(toolbar, BorderLayout.NORTH);
        add(new JScrollPane(table), BorderLayout.CENTER);
        add(statusBar, BorderLayout.SOUTH);

        registerActions();
    }

    private class ObjectHistogramToolBar extends CommonToolBar {

        private JTextField searchTF;

        public ObjectHistogramToolBar(StatusBar status) {
            super(HSDBActionManager.getInstance(), status);
        }

        protected void addComponents() {
            searchTF = new JTextField();
            searchTF.setToolTipText("Find in Class Description");

            // Pressing Enter on the text field will search
            InputMap im = searchTF.getInputMap();
            im.put(KeyStroke.getKeyStroke("ENTER"), "enterPressed");
            ActionMap am = searchTF.getActionMap();
            am.put("enterPressed", manager.getAction(FindAction.VALUE_COMMAND));

            add(searchTF);
            addButton(manager.getAction(FindAction.VALUE_COMMAND));
            addButton(manager.getAction(ShowAction.VALUE_COMMAND));
        }

        public String getFindText() {
            return searchTF.getText();
        }
    }

    private class ObjectHistogramColummModel extends DefaultTableColumnModel {
        private final String LABEL_SIZE = "Size";
        private final String LABEL_COUNT = "Count";
        private final String LABEL_DESC = "Class Description";


        public ObjectHistogramColummModel() {
            // Should actually get the line metrics for
            int PREF_WIDTH = 80;
            int MAX_WIDTH = 100;
            int HUGE_WIDTH = 140;

            LongCellRenderer lcRender = new LongCellRenderer();

            TableColumn column;

            // Size
            column = new TableColumn(0, PREF_WIDTH);
            column.setHeaderValue(LABEL_SIZE);
            column.setMaxWidth(MAX_WIDTH);
            column.setResizable(false);
            column.setCellRenderer(lcRender);
            addColumn(column);

            // Count
            column = new TableColumn(1, PREF_WIDTH);
            column.setHeaderValue(LABEL_COUNT);
            column.setMaxWidth(MAX_WIDTH);
            column.setResizable(false);
            column.setCellRenderer(lcRender);
            addColumn(column);

            // Description
            column = new TableColumn(2, HUGE_WIDTH);
            column.setHeaderValue(LABEL_DESC);
            addColumn(column);
        }
    }


    /**
     * A table model which encapsulates the ObjectHistogram
     */
    private class ObjectHistogramTableModel extends SortableTableModel {
        private String[] columnNames = { "Size", "Count", "Class Description" };
        private Class[] columnClasses = { Long.class, Long.class, String.class };

        public ObjectHistogramTableModel(ObjectHistogram histo) {
            // Set the rows
            elements = histo.getElements();
            setComparator(new ObjectHistogramComparator(this));

        }

        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return elements.size();
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Class getColumnClass(int col) {
            return columnClasses[col];
        }

        public Object getValueAt(int row, int col) {
            return getValueForColumn(getElement(row), col);
        }

        public Object getValueForColumn(Object obj, int col) {
            ObjectHistogramElement el = (ObjectHistogramElement)obj;
            switch (col) {
            case 0:
                return new Long(el.getSize());
            case 1:
                return new Long(el.getCount());
            case 2:
                return el.getDescription();
            default:
                throw new RuntimeException("Index (" + col + ") out of bounds");
            }
        }

        public ObjectHistogramElement getElement(int index) {
            return (ObjectHistogramElement) elements.get(index);
        }

        private class ObjectHistogramComparator extends TableModelComparator {

            public ObjectHistogramComparator(ObjectHistogramTableModel model) {
                super(model);
            }

            /**
             * Returns the value for the comparing object for the
             * column.
             *
             * @param obj Object that was passed for Comparator
             * @param column the column to retrieve
             */
            public Object getValueForColumn(Object obj, int column) {
                ObjectHistogramTableModel omodel = (ObjectHistogramTableModel)model;
                return omodel.getValueForColumn(obj, column);
            }
        }

    }


    //
    // ActionListener implementation and actions support
    //

    public void actionPerformed(ActionEvent evt) {
        String command = evt.getActionCommand();

        if (command.equals(ShowAction.VALUE_COMMAND)) {
            fireShowObjectsOfType();
        } else if (command.equals(FindAction.VALUE_COMMAND)) {
            findObject();
        }

    }

    protected void registerActions() {
        registerAction(FindAction.VALUE_COMMAND);
        registerAction(ShowAction.VALUE_COMMAND);
    }

    private void registerAction(String actionName) {
        ActionManager manager = ActionManager.getInstance();
        DelegateAction action = manager.getDelegateAction(actionName);
        action.addActionListener(this);
    }

    public interface Listener {
        public void showObjectsOfType(Klass type);
    }

    public void addPanelListener(Listener listener) {
        if (listeners == null) {
            listeners = new ArrayList();
        }
        listeners.add(listener);
    }

    public void removePanelListener(Listener listener) {
        if (listeners != null) {
            listeners.remove(listener);
        }
    }

    //--------------------------------------------------------------------------------
    // Internals only below this point
    //

    /**
     * Find and select the row that contains the text in the find field starting
     * from the current selected row.
     *
     * Uses a linear search from the current row. Could be optimized withing the
     * model and internal representation.
     */
    private void findObject() {
        String findText = toolbar.getFindText();

        if (findText == null || findText.equals("")) {
            return;
        }

        TableModel model = table.getModel();

        int row = table.getSelectedRow();
        if (row == model.getRowCount()) {
            row = 0;
        } else {
            // Start at the row after the selected row.
            row++;
        }

        String value;
        for (int i = row; i < model.getRowCount(); i++) {
            value = (String)model.getValueAt(i, 2);
            if (value != null && value.startsWith(findText)) {
                table.setRowSelectionInterval(i, i);
                Rectangle cellBounds = table.getCellRect(i, 0, true);
                table.scrollRectToVisible(cellBounds);
                return;
            }
        }

        // Wrap the table to search in the top rows.
        for (int i = 0; i < row; i++) {
            value = (String)model.getValueAt(i, 2);
            if (value != null && value.startsWith(findText)) {
                table.setRowSelectionInterval(i, i);
                Rectangle cellBounds = table.getCellRect(i, 0, true);
                table.scrollRectToVisible(cellBounds);
                return;
            }
        }
    }

    private void fireShowObjectsOfType() {
        int i = table.getSelectedRow();
        if (i < 0) {
            return;
        }

        ObjectHistogramElement el = dataModel.getElement(i);

        for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
            Listener listener = (Listener) iter.next();
            listener.showObjectsOfType(el.getKlass());
        }
    }

    public static void main(String[] args) {

    }
}