1 /* 2 * Copyright (c) 2004, 2007, 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 import sun.tools.jconsole.resources.Messages; 38 39 import java.util.concurrent.*; 40 41 import static sun.tools.jconsole.Formatter.*; 42 import static sun.tools.jconsole.Utilities.*; 43 44 45 @SuppressWarnings("serial") 46 class ClassTab extends Tab implements ActionListener { 47 PlotterPanel loadedClassesMeter; 48 TimeComboBox timeComboBox; 49 private JCheckBox verboseCheckBox; 50 private HTMLPane details; 51 private ClassOverviewPanel overviewPanel; 52 private boolean plotterListening = false; 53 54 private static final String loadedPlotterKey = "loaded"; 55 private static final String totalLoadedPlotterKey = "totalLoaded"; 56 private static final Color loadedPlotterColor = Plotter.defaultColor; 57 private static final Color totalLoadedPlotterColor = Color.red; 58 59 /* 60 Hierarchy of panels and layouts for this tab: 61 62 ClassTab (BorderLayout) 63 64 North: topPanel (BorderLayout) 65 66 Center: controlPanel (FlowLayout) 67 timeComboBox 68 69 East: topRightPanel (FlowLayout) 70 verboseCheckBox 71 72 Center: plotterPanel (BorderLayout) 73 74 Center: plotter 75 76 South: bottomPanel (BorderLayout) 77 78 Center: details 79 */ 80 81 public static String getTabName() { 82 return Messages.CLASSES; 83 } 84 85 public ClassTab(VMPanel vmPanel) { 86 super(vmPanel, getTabName()); 87 88 setLayout(new BorderLayout(0, 0)); 89 setBorder(new EmptyBorder(4, 4, 3, 4)); 90 91 JPanel topPanel = new JPanel(new BorderLayout()); 92 JPanel plotterPanel = new JPanel(new BorderLayout()); 93 JPanel bottomPanel = new JPanel(new BorderLayout()); 94 95 add(topPanel, BorderLayout.NORTH); 96 add(plotterPanel, BorderLayout.CENTER); 97 add(bottomPanel, BorderLayout.SOUTH); 98 99 JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5)); 100 topPanel.add(controlPanel, BorderLayout.CENTER); 101 102 verboseCheckBox = new JCheckBox(Messages.VERBOSE_OUTPUT); 103 verboseCheckBox.addActionListener(this); 104 verboseCheckBox.setToolTipText(Messages.VERBOSE_OUTPUT_TOOLTIP); 105 JPanel topRightPanel = new JPanel(); 106 topRightPanel.setBorder(new EmptyBorder(0, 65-8, 0, 70)); 107 topRightPanel.add(verboseCheckBox); 108 topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS); 109 110 loadedClassesMeter = new PlotterPanel(Messages.NUMBER_OF_LOADED_CLASSES, 111 Plotter.Unit.NONE, false); 112 loadedClassesMeter.plotter.createSequence(loadedPlotterKey, 113 Messages.LOADED, 114 loadedPlotterColor, 115 true); 116 loadedClassesMeter.plotter.createSequence(totalLoadedPlotterKey, 117 Messages.TOTAL_LOADED, 118 totalLoadedPlotterColor, 119 true); 120 setAccessibleName(loadedClassesMeter.plotter, 121 Messages.CLASS_TAB_LOADED_CLASSES_PLOTTER_ACCESSIBLE_NAME); 122 plotterPanel.add(loadedClassesMeter); 123 124 timeComboBox = new TimeComboBox(loadedClassesMeter.plotter); 125 controlPanel.add(new LabeledComponent(Messages.TIME_RANGE_COLON, 126 Resources.getMnemonicInt(Messages.TIME_RANGE_COLON), 127 timeComboBox)); 128 129 LabeledComponent.layout(plotterPanel); 130 131 bottomPanel.setBorder(new CompoundBorder(new TitledBorder(Messages.DETAILS), 132 new EmptyBorder(10, 10, 10, 10))); 133 134 details = new HTMLPane(); 135 setAccessibleName(details, Messages.DETAILS); 136 JScrollPane scrollPane = new JScrollPane(details); 137 scrollPane.setPreferredSize(new Dimension(0, 150)); 138 bottomPanel.add(scrollPane, BorderLayout.SOUTH); 139 140 } 141 142 public void actionPerformed(ActionEvent ev) { 143 final boolean b = verboseCheckBox.isSelected(); 144 workerAdd(new Runnable() { 145 public void run() { 146 ProxyClient proxyClient = vmPanel.getProxyClient(); 147 try { 148 proxyClient.getClassLoadingMXBean().setVerbose(b); 149 } catch (UndeclaredThrowableException e) { 150 proxyClient.markAsDead(); 151 } catch (IOException ex) { 152 // Ignore 153 } 154 } 155 }); 156 } 157 158 159 public SwingWorker<?, ?> newSwingWorker() { 160 final ProxyClient proxyClient = vmPanel.getProxyClient(); 161 162 if (!plotterListening) { 163 proxyClient.addWeakPropertyChangeListener(loadedClassesMeter.plotter); 164 plotterListening = true; 165 } 166 167 return new SwingWorker<Boolean, Object>() { 168 private long clCount, cuCount, ctCount; 169 private boolean isVerbose; 170 private String detailsStr; 171 private long timeStamp; 172 173 public Boolean doInBackground() { 174 try { 175 ClassLoadingMXBean classLoadingMBean = proxyClient.getClassLoadingMXBean(); 176 177 clCount = classLoadingMBean.getLoadedClassCount(); 178 cuCount = classLoadingMBean.getUnloadedClassCount(); 179 ctCount = classLoadingMBean.getTotalLoadedClassCount(); 180 isVerbose = classLoadingMBean.isVerbose(); 181 detailsStr = formatDetails(); 182 timeStamp = System.currentTimeMillis(); 183 184 return true; 185 } catch (UndeclaredThrowableException e) { 186 proxyClient.markAsDead(); 187 return false; 188 } catch (IOException e) { 189 return false; 190 } 191 } 192 193 protected void done() { 194 try { 195 if (get()) { 196 loadedClassesMeter.plotter.addValues(timeStamp, clCount, ctCount); 197 198 if (overviewPanel != null) { 199 overviewPanel.updateClassInfo(ctCount, clCount); 200 overviewPanel.getPlotter().addValues(timeStamp, clCount); 201 } 202 203 loadedClassesMeter.setValueLabel(clCount + ""); 204 verboseCheckBox.setSelected(isVerbose); 205 details.setText(detailsStr); 206 } 207 } catch (InterruptedException ex) { 208 } catch (ExecutionException ex) { 209 if (JConsole.isDebug()) { 210 ex.printStackTrace(); 211 } 212 } 213 } 214 215 private String formatDetails() { 216 String text = "<table cellspacing=0 cellpadding=0>"; 217 218 long time = System.currentTimeMillis(); 219 String timeStamp = formatDateTime(time); 220 text += newRow(Messages.TIME, timeStamp); 221 text += newRow(Messages.CURRENT_CLASSES_LOADED, justify(clCount, 5)); 222 text += newRow(Messages.TOTAL_CLASSES_LOADED, justify(ctCount, 5)); 223 text += newRow(Messages.TOTAL_CLASSES_UNLOADED, justify(cuCount, 5)); 224 225 return text; 226 } 227 }; 228 } 229 230 231 OverviewPanel[] getOverviewPanels() { 232 if (overviewPanel == null) { 233 overviewPanel = new ClassOverviewPanel(); 234 } 235 return new OverviewPanel[] { overviewPanel }; 236 } 237 238 private static class ClassOverviewPanel extends OverviewPanel { 239 ClassOverviewPanel() { 240 super(Messages.CLASSES, loadedPlotterKey, Messages.LOADED, null); 241 } 242 243 private void updateClassInfo(long total, long loaded) { 244 long unloaded = (total - loaded); 245 getInfoLabel().setText(Resources.format( 246 Messages.CLASS_TAB_INFO_LABEL_FORMAT, loaded, unloaded, total)); 247 } 248 } 249 }