blob: 9c1740af714fa2ae62750bb349d2fce50b01a864 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.tools.jconsole;
27
28import java.awt.*;
29import java.io.*;
30import java.lang.management.*;
31import java.lang.reflect.*;
32import java.net.URL;
33import java.text.*;
34import java.util.*;
35import java.util.concurrent.*;
36
37import javax.swing.*;
38import javax.swing.event.*;
39import javax.swing.text.*;
40
41import static sun.tools.jconsole.Formatter.*;
42import static sun.tools.jconsole.Resources.*;
43import static sun.tools.jconsole.Utilities.*;
44
45@SuppressWarnings("serial")
46class SummaryTab extends Tab {
47 private static final String cpuUsageKey = "cpu";
48 private static final String cpuUsageName = getText("CPU Usage");
49 private static final String cpuUsageFormat = "CPUUsageFormat";
50
51 private static final String newDivider = "<tr><td colspan=4><font size =-1><hr>";
52 private static final String newTable = "<tr><td colspan=4 align=left><table cellpadding=1>";
53 private static final String newLeftTable = "<tr><td colspan=2 align=left><table cellpadding=1>";
54 private static final String newRightTable = "<td colspan=2 align=left><table cellpadding=1>";
55 private static final String endTable = "</table>";
56
57 private static final int CPU_DECIMALS = 1;
58
59 private CPUOverviewPanel overviewPanel;
60 private DateFormat headerDateTimeFormat;
61 private String pathSeparator = null;
62 HTMLPane info;
63
64 private static class Result {
65 long upTime = -1L;
66 long processCpuTime = -1L;
67 long timeStamp;
68 int nCPUs;
69 String summary;
70 }
71
72 public static String getTabName() {
73 return Resources.getText("SummaryTab.tabName");
74 }
75
76 public SummaryTab(VMPanel vmPanel) {
77 super(vmPanel, getTabName());
78
79 setLayout(new BorderLayout());
80
81 info = new HTMLPane();
82 setAccessibleName(info, getTabName());
83 add(new JScrollPane(info));
84
85 headerDateTimeFormat =
86 getDateTimeFormat("SummaryTab.headerDateTimeFormat");
87 }
88
89 public SwingWorker<?, ?> newSwingWorker() {
90 return new SwingWorker<Result, Object>() {
91 public Result doInBackground() {
92 return formatSummary();
93 }
94
95
96 protected void done() {
97 try {
98 Result result = get();
99 if (result != null) {
100 info.setText(result.summary);
101 if (overviewPanel != null &&
102 result.upTime > 0L &&
103 result.processCpuTime >= 0L) {
104
105 overviewPanel.updateCPUInfo(result);
106 }
107 }
108 } catch (InterruptedException ex) {
109 } catch (ExecutionException ex) {
110 if (JConsole.isDebug()) {
111 ex.printStackTrace();
112 }
113 }
114 }
115 };
116 }
117
118 StringBuilder buf;
119
120 synchronized Result formatSummary() {
121 Result result = new Result();
122 ProxyClient proxyClient = vmPanel.getProxyClient();
123 if (proxyClient.isDead()) {
124 return null;
125 }
126
127 buf = new StringBuilder();
128 append("<table cellpadding=1>");
129
130 try {
131 RuntimeMXBean rmBean = proxyClient.getRuntimeMXBean();
132 CompilationMXBean cmpMBean = proxyClient.getCompilationMXBean();
133 ThreadMXBean tmBean = proxyClient.getThreadMXBean();
134 MemoryMXBean memoryBean = proxyClient.getMemoryMXBean();
135 ClassLoadingMXBean clMBean = proxyClient.getClassLoadingMXBean();
136 OperatingSystemMXBean osMBean = proxyClient.getOperatingSystemMXBean();
137 com.sun.management.OperatingSystemMXBean sunOSMBean =
138 proxyClient.getSunOperatingSystemMXBean();
139
140 append("<tr><td colspan=4>");
141 append("<center><b>" + getText("SummaryTab.tabName") + "</b></center>");
142 String dateTime =
143 headerDateTimeFormat.format(System.currentTimeMillis());
144 append("<center>" + dateTime + "</center>");
145
146 append(newDivider);
147
148 { // VM info
149 append(newLeftTable);
150 append("Connection name", vmPanel.getDisplayName());
151 append("Virtual Machine",
152 getText("SummaryTab.vmVersion",
153 rmBean.getVmName(), rmBean.getVmVersion()));
154 append("Vendor", rmBean.getVmVendor());
155 append("Name", rmBean.getName());
156 append(endTable);
157
158 append(newRightTable);
159 result.upTime = rmBean.getUptime();
160 append("Uptime", formatTime(result.upTime));
161 if (sunOSMBean != null) {
162 result.processCpuTime = sunOSMBean.getProcessCpuTime();
163 append("Process CPU time", formatNanoTime(result.processCpuTime));
164 }
165
166 if (cmpMBean != null) {
167 append("JIT compiler", cmpMBean.getName());
168 append("Total compile time",
169 cmpMBean.isCompilationTimeMonitoringSupported()
170 ? formatTime(cmpMBean.getTotalCompilationTime())
171 : getText("Unavailable"));
172 } else {
173 append("JIT compiler", getText("Unavailable"));
174 }
175 append(endTable);
176 }
177
178 append(newDivider);
179
180 { // Threads and Classes
181 append(newLeftTable);
182 int tlCount = tmBean.getThreadCount();
183 int tdCount = tmBean.getDaemonThreadCount();
184 int tpCount = tmBean.getPeakThreadCount();
185 long ttCount = tmBean.getTotalStartedThreadCount();
186 String[] strings1 = formatLongs(tlCount, tpCount,
187 tdCount, ttCount);
188 append("Live Threads", strings1[0]);
189 append("Peak", strings1[1]);
190 append("Daemon threads", strings1[2]);
191 append("Total threads started", strings1[3]);
192 append(endTable);
193
194 append(newRightTable);
195 long clCount = clMBean.getLoadedClassCount();
196 long cuCount = clMBean.getUnloadedClassCount();
197 long ctCount = clMBean.getTotalLoadedClassCount();
198 String[] strings2 = formatLongs(clCount, cuCount, ctCount);
199 append("Current classes loaded", strings2[0]);
200 append("Total classes loaded", strings2[2]);
201 append("Total classes unloaded", strings2[1]);
202 append(null, "");
203 append(endTable);
204 }
205
206 append(newDivider);
207
208 { // Memory
209 MemoryUsage u = memoryBean.getHeapMemoryUsage();
210
211 append(newLeftTable);
212 String[] strings1 = formatKByteStrings(u.getUsed(), u.getMax());
213 append("Current heap size", strings1[0]);
214 append("Maximum heap size", strings1[1]);
215 append(endTable);
216
217 append(newRightTable);
218 String[] strings2 = formatKByteStrings(u.getCommitted());
219 append("Committed memory", strings2[0]);
220 append("SummaryTab.pendingFinalization.label",
221 getText("SummaryTab.pendingFinalization.value",
222 memoryBean.getObjectPendingFinalizationCount()));
223 append(endTable);
224
225 append(newTable);
226 Collection<GarbageCollectorMXBean> garbageCollectors =
227 proxyClient.getGarbageCollectorMXBeans();
228 for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
229 String gcName = garbageCollectorMBean.getName();
230 long gcCount = garbageCollectorMBean.getCollectionCount();
231 long gcTime = garbageCollectorMBean.getCollectionTime();
232
233 append("Garbage collector",
234 getText("GcInfo", gcName, gcCount,
235 (gcTime >= 0) ? formatTime(gcTime)
236 : getText("Unavailable")),
237 4);
238 }
239 append(endTable);
240 }
241
242 append(newDivider);
243
244 { // Operating System info
245 append(newLeftTable);
246 String osName = osMBean.getName();
247 String osVersion = osMBean.getVersion();
248 String osArch = osMBean.getArch();
249 result.nCPUs = osMBean.getAvailableProcessors();
250 append("Operating System", osName + " " + osVersion);
251 append("Architecture", osArch);
252 append("Number of processors", result.nCPUs+"");
253
254 if (pathSeparator == null) {
255 // Must use separator of remote OS, not File.pathSeparator
256 // from this local VM. In the future, consider using
257 // RuntimeMXBean to get the remote system property.
258 pathSeparator = osName.startsWith("Windows ") ? ";" : ":";
259 }
260
261 if (sunOSMBean != null) {
262 String[] kbStrings1 =
263 formatKByteStrings(sunOSMBean.getCommittedVirtualMemorySize());
264
265 String[] kbStrings2 =
266 formatKByteStrings(sunOSMBean.getTotalPhysicalMemorySize(),
267 sunOSMBean.getFreePhysicalMemorySize(),
268 sunOSMBean.getTotalSwapSpaceSize(),
269 sunOSMBean.getFreeSwapSpaceSize());
270
271 append("Committed virtual memory", kbStrings1[0]);
272 append(endTable);
273
274 append(newRightTable);
275 append("Total physical memory", kbStrings2[0]);
276 append("Free physical memory", kbStrings2[1]);
277 append("Total swap space", kbStrings2[2]);
278 append("Free swap space", kbStrings2[3]);
279 }
280
281 append(endTable);
282 }
283
284 append(newDivider);
285
286 { // VM arguments and paths
287 append(newTable);
288 String args = "";
289 java.util.List<String> inputArguments = rmBean.getInputArguments();
290 for (String arg : inputArguments) {
291 args += arg + " ";
292 }
293 append("VM arguments", args, 4);
294 append("Class path", rmBean.getClassPath(), 4);
295 append("Library path", rmBean.getLibraryPath(), 4);
296 append("Boot class path",
297 rmBean.isBootClassPathSupported()
298 ? rmBean.getBootClassPath()
299 : getText("Unavailable"),
300 4);
301 append(endTable);
302 }
303 } catch (IOException e) {
304 if (JConsole.isDebug()) {
305 e.printStackTrace();
306 }
307 proxyClient.markAsDead();
308 return null;
309 } catch (UndeclaredThrowableException e) {
310 if (JConsole.isDebug()) {
311 e.printStackTrace();
312 }
313 proxyClient.markAsDead();
314 return null;
315 }
316
317 append("</table>");
318
319 result.timeStamp = System.currentTimeMillis();
320 result.summary = buf.toString();
321
322 return result;
323 }
324
325 private synchronized void append(String str) {
326 buf.append(str);
327 }
328
329 void append(String label, String value) {
330 append(newRow((label != null) ? getText(label) : label, value));
331 }
332
333 private void append(String label, String value, int columnPerRow) {
334 if (columnPerRow == 4 && pathSeparator != null) {
335 value = value.replace(pathSeparator,
336 "<b></b>" + pathSeparator);
337 }
338 append(newRow(getText(label), value, columnPerRow));
339 }
340
341 void append(String label1, String value1,
342 String label2, String value2) {
343 append(newRow(getText(label1), value1,
344 getText(label2), value2));
345 }
346
347 OverviewPanel[] getOverviewPanels() {
348 if (overviewPanel == null) {
349 overviewPanel = new CPUOverviewPanel();
350 }
351 return new OverviewPanel[] { overviewPanel };
352 }
353
354 private static class CPUOverviewPanel extends OverviewPanel {
355 private long prevUpTime, prevProcessCpuTime;
356
357 CPUOverviewPanel() {
358 super(getText("CPU Usage"), cpuUsageKey, cpuUsageName, Plotter.Unit.PERCENT);
359 getPlotter().setDecimals(CPU_DECIMALS);
360 }
361
362 public void updateCPUInfo(Result result) {
363 if (prevUpTime > 0L && result.upTime > prevUpTime) {
364 // elapsedCpu is in ns and elapsedTime is in ms.
365 long elapsedCpu = result.processCpuTime - prevProcessCpuTime;
366 long elapsedTime = result.upTime - prevUpTime;
367 // cpuUsage could go higher than 100% because elapsedTime
368 // and elapsedCpu are not fetched simultaneously. Limit to
369 // 99% to avoid Plotter showing a scale from 0% to 200%.
370 float cpuUsage =
371 Math.min(99F,
372 elapsedCpu / (elapsedTime * 10000F * result.nCPUs));
373
374 getPlotter().addValues(result.timeStamp,
375 Math.round(cpuUsage * Math.pow(10.0, CPU_DECIMALS)));
376 getInfoLabel().setText(getText(cpuUsageFormat,
377 String.format("%."+CPU_DECIMALS+"f", cpuUsage)));
378 }
379 this.prevUpTime = result.upTime;
380 this.prevProcessCpuTime = result.processCpuTime;
381 }
382 }
383
384
385
386}