1 /* 2 * Copyright (c) 2004, 2012, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.tools.jconsole; 27 28 import java.awt.*; 29 import java.awt.event.*; 30 import java.io.*; 31 import java.lang.management.*; 32 import java.lang.reflect.*; 33 34 import javax.swing.*; 35 import javax.swing.border.*; 36 37 38 import java.util.concurrent.*; 39 40 import static sun.tools.jconsole.Formatter.*; 41 import static sun.tools.jconsole.Utilities.*; 42 43 44 @SuppressWarnings("serial") 45 class ClassTab extends Tab implements ActionListener { 46 PlotterPanel loadedClassesMeter; 47 TimeComboBox timeComboBox; 48 private JCheckBox verboseCheckBox; 49 private HTMLPane details; 50 private ClassOverviewPanel overviewPanel; 51 private boolean plotterListening = false; 52 53 private static final String loadedPlotterKey = "loaded"; 54 private static final String totalLoadedPlotterKey = "totalLoaded"; 55 private static final Color loadedPlotterColor = Plotter.defaultColor; 56 private static final Color totalLoadedPlotterColor = Color.red; 57 58 /* 59 Hierarchy of panels and layouts for this tab: 60 61 ClassTab (BorderLayout) 62 63 North: topPanel (BorderLayout) 64 65 Center: controlPanel (FlowLayout) 66 timeComboBox 67 68 East: topRightPanel (FlowLayout) 69 verboseCheckBox 70 71 Center: plotterPanel (BorderLayout) 72 73 Center: plotter 74 75 South: bottomPanel (BorderLayout) 76 77 Center: details 78 */ 79 getTabName()80 public static String getTabName() { 81 return Messages.CLASSES; 82 } 83 ClassTab(VMPanel vmPanel)84 public ClassTab(VMPanel vmPanel) { 85 super(vmPanel, getTabName()); 86 87 setLayout(new BorderLayout(0, 0)); 88 setBorder(new EmptyBorder(4, 4, 3, 4)); 89 90 JPanel topPanel = new JPanel(new BorderLayout()); 91 JPanel plotterPanel = new JPanel(new BorderLayout()); 92 JPanel bottomPanel = new JPanel(new BorderLayout()); 93 94 add(topPanel, BorderLayout.NORTH); 95 add(plotterPanel, BorderLayout.CENTER); 96 add(bottomPanel, BorderLayout.SOUTH); 97 98 JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5)); 99 topPanel.add(controlPanel, BorderLayout.CENTER); 100 101 verboseCheckBox = new JCheckBox(Messages.VERBOSE_OUTPUT); 102 verboseCheckBox.addActionListener(this); 103 verboseCheckBox.setToolTipText(Messages.VERBOSE_OUTPUT_TOOLTIP); 104 JPanel topRightPanel = new JPanel(); 105 topRightPanel.setBorder(new EmptyBorder(0, 65-8, 0, 70)); 106 topRightPanel.add(verboseCheckBox); 107 topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS); 108 109 loadedClassesMeter = new PlotterPanel(Messages.NUMBER_OF_LOADED_CLASSES, 110 Plotter.Unit.NONE, false); 111 loadedClassesMeter.plotter.createSequence(loadedPlotterKey, 112 Messages.LOADED, 113 loadedPlotterColor, 114 true); 115 loadedClassesMeter.plotter.createSequence(totalLoadedPlotterKey, 116 Messages.TOTAL_LOADED, 117 totalLoadedPlotterColor, 118 true); 119 setAccessibleName(loadedClassesMeter.plotter, 120 Messages.CLASS_TAB_LOADED_CLASSES_PLOTTER_ACCESSIBLE_NAME); 121 plotterPanel.add(loadedClassesMeter); 122 123 timeComboBox = new TimeComboBox(loadedClassesMeter.plotter); 124 controlPanel.add(new LabeledComponent(Messages.TIME_RANGE_COLON, 125 Resources.getMnemonicInt(Messages.TIME_RANGE_COLON), 126 timeComboBox)); 127 128 LabeledComponent.layout(plotterPanel); 129 130 bottomPanel.setBorder(new CompoundBorder(new TitledBorder(Messages.DETAILS), 131 new EmptyBorder(10, 10, 10, 10))); 132 133 details = new HTMLPane(); 134 setAccessibleName(details, Messages.DETAILS); 135 JScrollPane scrollPane = new JScrollPane(details); 136 scrollPane.setPreferredSize(new Dimension(0, 150)); 137 bottomPanel.add(scrollPane, BorderLayout.SOUTH); 138 139 } 140 actionPerformed(ActionEvent ev)141 public void actionPerformed(ActionEvent ev) { 142 final boolean b = verboseCheckBox.isSelected(); 143 workerAdd(new Runnable() { 144 public void run() { 145 ProxyClient proxyClient = vmPanel.getProxyClient(); 146 try { 147 proxyClient.getClassLoadingMXBean().setVerbose(b); 148 } catch (UndeclaredThrowableException e) { 149 proxyClient.markAsDead(); 150 } catch (IOException ex) { 151 // Ignore 152 } 153 } 154 }); 155 } 156 157 newSwingWorker()158 public SwingWorker<?, ?> newSwingWorker() { 159 final ProxyClient proxyClient = vmPanel.getProxyClient(); 160 161 if (!plotterListening) { 162 proxyClient.addWeakPropertyChangeListener(loadedClassesMeter.plotter); 163 plotterListening = true; 164 } 165 166 return new SwingWorker<Boolean, Object>() { 167 private long clCount, cuCount, ctCount; 168 private boolean isVerbose; 169 private String detailsStr; 170 private long timeStamp; 171 172 public Boolean doInBackground() { 173 try { 174 ClassLoadingMXBean classLoadingMBean = proxyClient.getClassLoadingMXBean(); 175 176 clCount = classLoadingMBean.getLoadedClassCount(); 177 cuCount = classLoadingMBean.getUnloadedClassCount(); 178 ctCount = classLoadingMBean.getTotalLoadedClassCount(); 179 isVerbose = classLoadingMBean.isVerbose(); 180 detailsStr = formatDetails(); 181 timeStamp = System.currentTimeMillis(); 182 183 return true; 184 } catch (UndeclaredThrowableException e) { 185 proxyClient.markAsDead(); 186 return false; 187 } catch (IOException e) { 188 return false; 189 } 190 } 191 192 protected void done() { 193 try { 194 if (get()) { 195 loadedClassesMeter.plotter.addValues(timeStamp, clCount, ctCount); 196 197 if (overviewPanel != null) { 198 overviewPanel.updateClassInfo(ctCount, clCount); 199 overviewPanel.getPlotter().addValues(timeStamp, clCount); 200 } 201 202 loadedClassesMeter.setValueLabel(clCount + ""); 203 verboseCheckBox.setSelected(isVerbose); 204 details.setText(detailsStr); 205 } 206 } catch (InterruptedException ex) { 207 } catch (ExecutionException ex) { 208 if (JConsole.isDebug()) { 209 ex.printStackTrace(); 210 } 211 } 212 } 213 214 private String formatDetails() { 215 String text = "<table cellspacing=0 cellpadding=0>"; 216 217 long time = System.currentTimeMillis(); 218 String timeStamp = formatDateTime(time); 219 text += newRow(Messages.TIME, timeStamp); 220 text += newRow(Messages.CURRENT_CLASSES_LOADED, justify(clCount, 5)); 221 text += newRow(Messages.TOTAL_CLASSES_LOADED, justify(ctCount, 5)); 222 text += newRow(Messages.TOTAL_CLASSES_UNLOADED, justify(cuCount, 5)); 223 224 return text; 225 } 226 }; 227 } 228 229 getOverviewPanels()230 OverviewPanel[] getOverviewPanels() { 231 if (overviewPanel == null) { 232 overviewPanel = new ClassOverviewPanel(); 233 } 234 return new OverviewPanel[] { overviewPanel }; 235 } 236 237 private static class ClassOverviewPanel extends OverviewPanel { ClassOverviewPanel()238 ClassOverviewPanel() { 239 super(Messages.CLASSES, loadedPlotterKey, Messages.LOADED, null); 240 } 241 updateClassInfo(long total, long loaded)242 private void updateClassInfo(long total, long loaded) { 243 long unloaded = (total - loaded); 244 getInfoLabel().setText(Resources.format(Messages.CLASS_TAB_INFO_LABEL_FORMAT, 245 loaded, unloaded, total)); 246 } 247 } 248 } 249