001: /*
002: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.jconsole;
027:
028: import java.awt.*;
029: import java.io.*;
030: import java.lang.management.*;
031: import java.lang.reflect.*;
032: import java.net.URL;
033: import java.text.*;
034: import java.util.*;
035: import java.util.concurrent.*;
036:
037: import javax.swing.*;
038: import javax.swing.event.*;
039: import javax.swing.text.*;
040:
041: import static sun.tools.jconsole.Formatter.*;
042: import static sun.tools.jconsole.Resources.*;
043: import static sun.tools.jconsole.Utilities.*;
044:
045: @SuppressWarnings("serial")
046: class SummaryTab extends Tab {
047: private static final String cpuUsageKey = "cpu";
048: private static final String cpuUsageName = getText("CPU Usage");
049: private static final String cpuUsageFormat = "CPUUsageFormat";
050:
051: private static final String newDivider = "<tr><td colspan=4><font size =-1><hr>";
052: private static final String newTable = "<tr><td colspan=4 align=left><table cellpadding=1>";
053: private static final String newLeftTable = "<tr><td colspan=2 align=left><table cellpadding=1>";
054: private static final String newRightTable = "<td colspan=2 align=left><table cellpadding=1>";
055: private static final String endTable = "</table>";
056:
057: private static final int CPU_DECIMALS = 1;
058:
059: private CPUOverviewPanel overviewPanel;
060: private DateFormat headerDateTimeFormat;
061: private String pathSeparator = null;
062: HTMLPane info;
063:
064: private static class Result {
065: long upTime = -1L;
066: long processCpuTime = -1L;
067: long timeStamp;
068: int nCPUs;
069: String summary;
070: }
071:
072: public static String getTabName() {
073: return Resources.getText("SummaryTab.tabName");
074: }
075:
076: public SummaryTab(VMPanel vmPanel) {
077: super (vmPanel, getTabName());
078:
079: setLayout(new BorderLayout());
080:
081: info = new HTMLPane();
082: setAccessibleName(info, getTabName());
083: add(new JScrollPane(info));
084:
085: headerDateTimeFormat = getDateTimeFormat("SummaryTab.headerDateTimeFormat");
086: }
087:
088: public SwingWorker<?, ?> newSwingWorker() {
089: return new SwingWorker<Result, Object>() {
090: public Result doInBackground() {
091: return formatSummary();
092: }
093:
094: protected void done() {
095: try {
096: Result result = get();
097: if (result != null) {
098: info.setText(result.summary);
099: if (overviewPanel != null && result.upTime > 0L
100: && result.processCpuTime >= 0L) {
101:
102: overviewPanel.updateCPUInfo(result);
103: }
104: }
105: } catch (InterruptedException ex) {
106: } catch (ExecutionException ex) {
107: if (JConsole.isDebug()) {
108: ex.printStackTrace();
109: }
110: }
111: }
112: };
113: }
114:
115: StringBuilder buf;
116:
117: synchronized Result formatSummary() {
118: Result result = new Result();
119: ProxyClient proxyClient = vmPanel.getProxyClient();
120: if (proxyClient.isDead()) {
121: return null;
122: }
123:
124: buf = new StringBuilder();
125: append("<table cellpadding=1>");
126:
127: try {
128: RuntimeMXBean rmBean = proxyClient.getRuntimeMXBean();
129: CompilationMXBean cmpMBean = proxyClient
130: .getCompilationMXBean();
131: ThreadMXBean tmBean = proxyClient.getThreadMXBean();
132: MemoryMXBean memoryBean = proxyClient.getMemoryMXBean();
133: ClassLoadingMXBean clMBean = proxyClient
134: .getClassLoadingMXBean();
135: OperatingSystemMXBean osMBean = proxyClient
136: .getOperatingSystemMXBean();
137: com.sun.management.OperatingSystemMXBean sunOSMBean = proxyClient
138: .getSunOperatingSystemMXBean();
139:
140: append("<tr><td colspan=4>");
141: append("<center><b>" + getText("SummaryTab.tabName")
142: + "</b></center>");
143: String dateTime = headerDateTimeFormat.format(System
144: .currentTimeMillis());
145: append("<center>" + dateTime + "</center>");
146:
147: append(newDivider);
148:
149: { // VM info
150: append(newLeftTable);
151: append("Connection name", vmPanel.getDisplayName());
152: append("Virtual Machine", getText(
153: "SummaryTab.vmVersion", rmBean.getVmName(),
154: rmBean.getVmVersion()));
155: append("Vendor", rmBean.getVmVendor());
156: append("Name", rmBean.getName());
157: append(endTable);
158:
159: append(newRightTable);
160: result.upTime = rmBean.getUptime();
161: append("Uptime", formatTime(result.upTime));
162: if (sunOSMBean != null) {
163: result.processCpuTime = sunOSMBean
164: .getProcessCpuTime();
165: append("Process CPU time",
166: formatNanoTime(result.processCpuTime));
167: }
168:
169: if (cmpMBean != null) {
170: append("JIT compiler", cmpMBean.getName());
171: append(
172: "Total compile time",
173: cmpMBean
174: .isCompilationTimeMonitoringSupported() ? formatTime(cmpMBean
175: .getTotalCompilationTime())
176: : getText("Unavailable"));
177: } else {
178: append("JIT compiler", getText("Unavailable"));
179: }
180: append(endTable);
181: }
182:
183: append(newDivider);
184:
185: { // Threads and Classes
186: append(newLeftTable);
187: int tlCount = tmBean.getThreadCount();
188: int tdCount = tmBean.getDaemonThreadCount();
189: int tpCount = tmBean.getPeakThreadCount();
190: long ttCount = tmBean.getTotalStartedThreadCount();
191: String[] strings1 = formatLongs(tlCount, tpCount,
192: tdCount, ttCount);
193: append("Live Threads", strings1[0]);
194: append("Peak", strings1[1]);
195: append("Daemon threads", strings1[2]);
196: append("Total threads started", strings1[3]);
197: append(endTable);
198:
199: append(newRightTable);
200: long clCount = clMBean.getLoadedClassCount();
201: long cuCount = clMBean.getUnloadedClassCount();
202: long ctCount = clMBean.getTotalLoadedClassCount();
203: String[] strings2 = formatLongs(clCount, cuCount,
204: ctCount);
205: append("Current classes loaded", strings2[0]);
206: append("Total classes loaded", strings2[2]);
207: append("Total classes unloaded", strings2[1]);
208: append(null, "");
209: append(endTable);
210: }
211:
212: append(newDivider);
213:
214: { // Memory
215: MemoryUsage u = memoryBean.getHeapMemoryUsage();
216:
217: append(newLeftTable);
218: String[] strings1 = formatKByteStrings(u.getUsed(), u
219: .getMax());
220: append("Current heap size", strings1[0]);
221: append("Maximum heap size", strings1[1]);
222: append(endTable);
223:
224: append(newRightTable);
225: String[] strings2 = formatKByteStrings(u.getCommitted());
226: append("Committed memory", strings2[0]);
227: append("SummaryTab.pendingFinalization.label", getText(
228: "SummaryTab.pendingFinalization.value",
229: memoryBean.getObjectPendingFinalizationCount()));
230: append(endTable);
231:
232: append(newTable);
233: Collection<GarbageCollectorMXBean> garbageCollectors = proxyClient
234: .getGarbageCollectorMXBeans();
235: for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
236: String gcName = garbageCollectorMBean.getName();
237: long gcCount = garbageCollectorMBean
238: .getCollectionCount();
239: long gcTime = garbageCollectorMBean
240: .getCollectionTime();
241:
242: append("Garbage collector", getText("GcInfo",
243: gcName, gcCount,
244: (gcTime >= 0) ? formatTime(gcTime)
245: : getText("Unavailable")), 4);
246: }
247: append(endTable);
248: }
249:
250: append(newDivider);
251:
252: { // Operating System info
253: append(newLeftTable);
254: String osName = osMBean.getName();
255: String osVersion = osMBean.getVersion();
256: String osArch = osMBean.getArch();
257: result.nCPUs = osMBean.getAvailableProcessors();
258: append("Operating System", osName + " " + osVersion);
259: append("Architecture", osArch);
260: append("Number of processors", result.nCPUs + "");
261:
262: if (pathSeparator == null) {
263: // Must use separator of remote OS, not File.pathSeparator
264: // from this local VM. In the future, consider using
265: // RuntimeMXBean to get the remote system property.
266: pathSeparator = osName.startsWith("Windows ") ? ";"
267: : ":";
268: }
269:
270: if (sunOSMBean != null) {
271: String[] kbStrings1 = formatKByteStrings(sunOSMBean
272: .getCommittedVirtualMemorySize());
273:
274: String[] kbStrings2 = formatKByteStrings(sunOSMBean
275: .getTotalPhysicalMemorySize(), sunOSMBean
276: .getFreePhysicalMemorySize(), sunOSMBean
277: .getTotalSwapSpaceSize(), sunOSMBean
278: .getFreeSwapSpaceSize());
279:
280: append("Committed virtual memory", kbStrings1[0]);
281: append(endTable);
282:
283: append(newRightTable);
284: append("Total physical memory", kbStrings2[0]);
285: append("Free physical memory", kbStrings2[1]);
286: append("Total swap space", kbStrings2[2]);
287: append("Free swap space", kbStrings2[3]);
288: }
289:
290: append(endTable);
291: }
292:
293: append(newDivider);
294:
295: { // VM arguments and paths
296: append(newTable);
297: String args = "";
298: java.util.List<String> inputArguments = rmBean
299: .getInputArguments();
300: for (String arg : inputArguments) {
301: args += arg + " ";
302: }
303: append("VM arguments", args, 4);
304: append("Class path", rmBean.getClassPath(), 4);
305: append("Library path", rmBean.getLibraryPath(), 4);
306: append("Boot class path", rmBean
307: .isBootClassPathSupported() ? rmBean
308: .getBootClassPath() : getText("Unavailable"), 4);
309: append(endTable);
310: }
311: } catch (IOException e) {
312: if (JConsole.isDebug()) {
313: e.printStackTrace();
314: }
315: proxyClient.markAsDead();
316: return null;
317: } catch (UndeclaredThrowableException e) {
318: if (JConsole.isDebug()) {
319: e.printStackTrace();
320: }
321: proxyClient.markAsDead();
322: return null;
323: }
324:
325: append("</table>");
326:
327: result.timeStamp = System.currentTimeMillis();
328: result.summary = buf.toString();
329:
330: return result;
331: }
332:
333: private synchronized void append(String str) {
334: buf.append(str);
335: }
336:
337: void append(String label, String value) {
338: append(newRow((label != null) ? getText(label) : label, value));
339: }
340:
341: private void append(String label, String value, int columnPerRow) {
342: if (columnPerRow == 4 && pathSeparator != null) {
343: value = value.replace(pathSeparator, "<b></b>"
344: + pathSeparator);
345: }
346: append(newRow(getText(label), value, columnPerRow));
347: }
348:
349: void append(String label1, String value1, String label2,
350: String value2) {
351: append(newRow(getText(label1), value1, getText(label2), value2));
352: }
353:
354: OverviewPanel[] getOverviewPanels() {
355: if (overviewPanel == null) {
356: overviewPanel = new CPUOverviewPanel();
357: }
358: return new OverviewPanel[] { overviewPanel };
359: }
360:
361: private static class CPUOverviewPanel extends OverviewPanel {
362: private long prevUpTime, prevProcessCpuTime;
363:
364: CPUOverviewPanel() {
365: super (getText("CPU Usage"), cpuUsageKey, cpuUsageName,
366: Plotter.Unit.PERCENT);
367: getPlotter().setDecimals(CPU_DECIMALS);
368: }
369:
370: public void updateCPUInfo(Result result) {
371: if (prevUpTime > 0L && result.upTime > prevUpTime) {
372: // elapsedCpu is in ns and elapsedTime is in ms.
373: long elapsedCpu = result.processCpuTime
374: - prevProcessCpuTime;
375: long elapsedTime = result.upTime - prevUpTime;
376: // cpuUsage could go higher than 100% because elapsedTime
377: // and elapsedCpu are not fetched simultaneously. Limit to
378: // 99% to avoid Plotter showing a scale from 0% to 200%.
379: float cpuUsage = Math.min(99F, elapsedCpu
380: / (elapsedTime * 10000F * result.nCPUs));
381:
382: getPlotter().addValues(
383: result.timeStamp,
384: Math.round(cpuUsage
385: * Math.pow(10.0, CPU_DECIMALS)));
386: getInfoLabel().setText(
387: getText(cpuUsageFormat, String.format("%."
388: + CPU_DECIMALS + "f", cpuUsage)));
389: }
390: this.prevUpTime = result.upTime;
391: this.prevProcessCpuTime = result.processCpuTime;
392: }
393: }
394:
395: }
|