/* * Copyright (c) 2004, 2007, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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.tools.jconsole; import java.awt.*; import java.awt.event.*; import java.io.*; import java.lang.management.*; import java.lang.reflect.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import javax.swing.text.*; import java.util.*; import java.util.List; import java.util.concurrent.*; import sun.awt.*; import static sun.tools.jconsole.Formatter.*; import static sun.tools.jconsole.Resources.*; import static sun.tools.jconsole.Utilities.*; @SuppressWarnings("serial") class ClassTab extends Tab implements ActionListener { PlotterPanel loadedClassesMeter; TimeComboBox timeComboBox; private JCheckBox verboseCheckBox; private HTMLPane details; private ClassOverviewPanel overviewPanel; private boolean plotterListening = false; private static final String loadedPlotterKey = "loaded"; private static final String totalLoadedPlotterKey = "totalLoaded"; private static final String loadedPlotterName = Resources.getText("Loaded"); private static final String totalLoadedPlotterName = Resources.getText("Total Loaded"); private static final Color loadedPlotterColor = Plotter.defaultColor; private static final Color totalLoadedPlotterColor = Color.red; private static final String infoLabelFormat = "ClassTab.infoLabelFormat"; /* Hierarchy of panels and layouts for this tab: ClassTab (BorderLayout) North: topPanel (BorderLayout) Center: controlPanel (FlowLayout) timeComboBox East: topRightPanel (FlowLayout) verboseCheckBox Center: plotterPanel (BorderLayout) Center: plotter South: bottomPanel (BorderLayout) Center: details */ public static String getTabName() { return Resources.getText("Classes"); } public ClassTab(VMPanel vmPanel) { super(vmPanel, getTabName()); setLayout(new BorderLayout(0, 0)); setBorder(new EmptyBorder(4, 4, 3, 4)); JPanel topPanel = new JPanel(new BorderLayout()); JPanel plotterPanel = new JPanel(new BorderLayout()); JPanel bottomPanel = new JPanel(new BorderLayout()); add(topPanel, BorderLayout.NORTH); add(plotterPanel, BorderLayout.CENTER); add(bottomPanel, BorderLayout.SOUTH); JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5)); topPanel.add(controlPanel, BorderLayout.CENTER); verboseCheckBox = new JCheckBox(Resources.getText("Verbose Output")); verboseCheckBox.addActionListener(this); verboseCheckBox.setToolTipText(getText("Verbose Output.toolTip")); JPanel topRightPanel = new JPanel(); topRightPanel.setBorder(new EmptyBorder(0, 65-8, 0, 70)); topRightPanel.add(verboseCheckBox); topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS); loadedClassesMeter = new PlotterPanel(Resources.getText("Number of Loaded Classes"), Plotter.Unit.NONE, false); loadedClassesMeter.plotter.createSequence(loadedPlotterKey, loadedPlotterName, loadedPlotterColor, true); loadedClassesMeter.plotter.createSequence(totalLoadedPlotterKey, totalLoadedPlotterName, totalLoadedPlotterColor, true); setAccessibleName(loadedClassesMeter.plotter, getText("ClassTab.loadedClassesPlotter.accessibleName")); plotterPanel.add(loadedClassesMeter); timeComboBox = new TimeComboBox(loadedClassesMeter.plotter); controlPanel.add(new LabeledComponent(Resources.getText("Time Range:"), getMnemonicInt("Time Range:"), timeComboBox)); LabeledComponent.layout(plotterPanel); bottomPanel.setBorder(new CompoundBorder(new TitledBorder(Resources.getText("Details")), new EmptyBorder(10, 10, 10, 10))); details = new HTMLPane(); setAccessibleName(details, getText("Details")); JScrollPane scrollPane = new JScrollPane(details); scrollPane.setPreferredSize(new Dimension(0, 150)); bottomPanel.add(scrollPane, BorderLayout.SOUTH); } public void actionPerformed(ActionEvent ev) { final boolean b = verboseCheckBox.isSelected(); workerAdd(new Runnable() { public void run() { ProxyClient proxyClient = vmPanel.getProxyClient(); try { proxyClient.getClassLoadingMXBean().setVerbose(b); } catch (UndeclaredThrowableException e) { proxyClient.markAsDead(); } catch (IOException ex) { // Ignore } } }); } public SwingWorker<?, ?> newSwingWorker() { final ProxyClient proxyClient = vmPanel.getProxyClient(); if (!plotterListening) { proxyClient.addWeakPropertyChangeListener(loadedClassesMeter.plotter); plotterListening = true; } return new SwingWorker<Boolean, Object>() { private long clCount, cuCount, ctCount; private boolean isVerbose; private String detailsStr; private long timeStamp; public Boolean doInBackground() { try { ClassLoadingMXBean classLoadingMBean = proxyClient.getClassLoadingMXBean(); clCount = classLoadingMBean.getLoadedClassCount(); cuCount = classLoadingMBean.getUnloadedClassCount(); ctCount = classLoadingMBean.getTotalLoadedClassCount(); isVerbose = classLoadingMBean.isVerbose(); detailsStr = formatDetails(); timeStamp = System.currentTimeMillis(); return true; } catch (UndeclaredThrowableException e) { proxyClient.markAsDead(); return false; } catch (IOException e) { return false; } } protected void done() { try { if (get()) { loadedClassesMeter.plotter.addValues(timeStamp, clCount, ctCount); if (overviewPanel != null) { overviewPanel.updateClassInfo(ctCount, clCount); overviewPanel.getPlotter().addValues(timeStamp, clCount); } loadedClassesMeter.setValueLabel(clCount + ""); verboseCheckBox.setSelected(isVerbose); details.setText(detailsStr); } } catch (InterruptedException ex) { } catch (ExecutionException ex) { if (JConsole.isDebug()) { ex.printStackTrace(); } } } private String formatDetails() { String text = "<table cellspacing=0 cellpadding=0>"; long time = System.currentTimeMillis(); String timeStamp = formatDateTime(time); text += newRow(Resources.getText("Time"), timeStamp); text += newRow(Resources.getText("Current classes loaded"), justify(clCount, 5)); text += newRow(Resources.getText("Total classes loaded"), justify(ctCount, 5)); text += newRow(Resources.getText("Total classes unloaded"), justify(cuCount, 5)); return text; } }; } OverviewPanel[] getOverviewPanels() { if (overviewPanel == null) { overviewPanel = new ClassOverviewPanel(); } return new OverviewPanel[] { overviewPanel }; } private static class ClassOverviewPanel extends OverviewPanel { ClassOverviewPanel() { super(getText("Classes"), loadedPlotterKey, loadedPlotterName, null); } private void updateClassInfo(long total, long loaded) { long unloaded = (total - loaded); getInfoLabel().setText(getText(infoLabelFormat, loaded, unloaded, total)); } } }