/* * 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.io.*; import java.lang.management.*; import java.lang.reflect.*; import java.text.*; import java.util.*; import java.util.concurrent.*; import javax.swing.*; import sun.tools.jconsole.resources.Messages; import static sun.tools.jconsole.Formatter.*; import static sun.tools.jconsole.Utilities.*; @SuppressWarnings("serial") class SummaryTab extends Tab { private static final String cpuUsageKey = "cpu"; private static final String newDivider = "
"; private static final String newTable = ""; private static final String newLeftTable = "
"; private static final String newRightTable = "
"; private static final String endTable = "
"; private static final int CPU_DECIMALS = 1; private CPUOverviewPanel overviewPanel; private DateFormat headerDateTimeFormat; private String pathSeparator = null; HTMLPane info; private static class Result { long upTime = -1L; long processCpuTime = -1L; long timeStamp; int nCPUs; String summary; } public static String getTabName() { return Messages.SUMMARY_TAB_TAB_NAME; } public SummaryTab(VMPanel vmPanel) { super(vmPanel, getTabName()); setLayout(new BorderLayout()); info = new HTMLPane(); setAccessibleName(info, getTabName()); add(new JScrollPane(info)); headerDateTimeFormat = Formatter.getDateTimeFormat(Messages.SUMMARY_TAB_HEADER_DATE_TIME_FORMAT); } public SwingWorker newSwingWorker() { return new SwingWorker() { public Result doInBackground() { return formatSummary(); } protected void done() { try { Result result = get(); if (result != null) { info.setText(result.summary); if (overviewPanel != null && result.upTime > 0L && result.processCpuTime >= 0L) { overviewPanel.updateCPUInfo(result); } } } catch (InterruptedException ex) { } catch (ExecutionException ex) { if (JConsole.isDebug()) { ex.printStackTrace(); } } } }; } StringBuilder buf; synchronized Result formatSummary() { Result result = new Result(); ProxyClient proxyClient = vmPanel.getProxyClient(); if (proxyClient.isDead()) { return null; } buf = new StringBuilder(); append(""); try { RuntimeMXBean rmBean = proxyClient.getRuntimeMXBean(); CompilationMXBean cmpMBean = proxyClient.getCompilationMXBean(); ThreadMXBean tmBean = proxyClient.getThreadMXBean(); MemoryMXBean memoryBean = proxyClient.getMemoryMXBean(); ClassLoadingMXBean clMBean = proxyClient.getClassLoadingMXBean(); OperatingSystemMXBean osMBean = proxyClient.getOperatingSystemMXBean(); com.sun.management.OperatingSystemMXBean sunOSMBean = proxyClient.getSunOperatingSystemMXBean(); append("
"); append("
" + Messages.SUMMARY_TAB_TAB_NAME + "
"); String dateTime = headerDateTimeFormat.format(System.currentTimeMillis()); append("
" + dateTime + "
"); append(newDivider); { // VM info append(newLeftTable); append(Messages.CONNECTION_NAME, vmPanel.getDisplayName()); append(Messages.VIRTUAL_MACHINE, Resources.format(Messages.SUMMARY_TAB_VM_VERSION, rmBean.getVmName(), rmBean.getVmVersion())); append(Messages.VENDOR, rmBean.getVmVendor()); append(Messages.NAME, rmBean.getName()); append(endTable); append(newRightTable); result.upTime = rmBean.getUptime(); append(Messages.UPTIME, formatTime(result.upTime)); if (sunOSMBean != null) { result.processCpuTime = sunOSMBean.getProcessCpuTime(); append(Messages.PROCESS_CPU_TIME, formatNanoTime(result.processCpuTime)); } if (cmpMBean != null) { append(Messages.JIT_COMPILER, cmpMBean.getName()); append(Messages.TOTAL_COMPILE_TIME, cmpMBean.isCompilationTimeMonitoringSupported() ? formatTime(cmpMBean.getTotalCompilationTime()) : Messages.UNAVAILABLE); } else { append(Messages.JIT_COMPILER, Messages.UNAVAILABLE); } append(endTable); } append(newDivider); { // Threads and Classes append(newLeftTable); int tlCount = tmBean.getThreadCount(); int tdCount = tmBean.getDaemonThreadCount(); int tpCount = tmBean.getPeakThreadCount(); long ttCount = tmBean.getTotalStartedThreadCount(); String[] strings1 = formatLongs(tlCount, tpCount, tdCount, ttCount); append(Messages.LIVE_THREADS, strings1[0]); append(Messages.PEAK, strings1[1]); append(Messages.DAEMON_THREADS, strings1[2]); append(Messages.TOTAL_THREADS_STARTED, strings1[3]); append(endTable); append(newRightTable); long clCount = clMBean.getLoadedClassCount(); long cuCount = clMBean.getUnloadedClassCount(); long ctCount = clMBean.getTotalLoadedClassCount(); String[] strings2 = formatLongs(clCount, cuCount, ctCount); append(Messages.CURRENT_CLASSES_LOADED, strings2[0]); append(Messages.TOTAL_CLASSES_LOADED, strings2[2]); append(Messages.TOTAL_CLASSES_UNLOADED, strings2[1]); append(null, ""); append(endTable); } append(newDivider); { // Memory MemoryUsage u = memoryBean.getHeapMemoryUsage(); append(newLeftTable); String[] strings1 = formatKByteStrings(u.getUsed(), u.getMax()); append(Messages.CURRENT_HEAP_SIZE, strings1[0]); append(Messages.MAXIMUM_HEAP_SIZE, strings1[1]); append(endTable); append(newRightTable); String[] strings2 = formatKByteStrings(u.getCommitted()); append(Messages.COMMITTED_MEMORY, strings2[0]); append(Messages.SUMMARY_TAB_PENDING_FINALIZATION_LABEL, Messages.SUMMARY_TAB_PENDING_FINALIZATION_VALUE, memoryBean.getObjectPendingFinalizationCount()); append(endTable); append(newTable); Collection garbageCollectors = proxyClient.getGarbageCollectorMXBeans(); for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) { String gcName = garbageCollectorMBean.getName(); long gcCount = garbageCollectorMBean.getCollectionCount(); long gcTime = garbageCollectorMBean.getCollectionTime(); append(Messages.GARBAGE_COLLECTOR, Resources.format(Messages.GC_INFO, gcName, gcCount, (gcTime >= 0) ? formatTime(gcTime) : Messages.UNAVAILABLE), 4); } append(endTable); } append(newDivider); { // Operating System info append(newLeftTable); String osName = osMBean.getName(); String osVersion = osMBean.getVersion(); String osArch = osMBean.getArch(); result.nCPUs = osMBean.getAvailableProcessors(); append(Messages.OPERATING_SYSTEM, osName + " " + osVersion); append(Messages.ARCHITECTURE, osArch); append(Messages.NUMBER_OF_PROCESSORS, result.nCPUs+""); if (pathSeparator == null) { // Must use separator of remote OS, not File.pathSeparator // from this local VM. In the future, consider using // RuntimeMXBean to get the remote system property. pathSeparator = osName.startsWith("Windows ") ? ";" : ":"; } if (sunOSMBean != null) { String[] kbStrings1 = formatKByteStrings(sunOSMBean.getCommittedVirtualMemorySize()); String[] kbStrings2 = formatKByteStrings(sunOSMBean.getTotalPhysicalMemorySize(), sunOSMBean.getFreePhysicalMemorySize(), sunOSMBean.getTotalSwapSpaceSize(), sunOSMBean.getFreeSwapSpaceSize()); append(Messages.COMMITTED_VIRTUAL_MEMORY, kbStrings1[0]); append(endTable); append(newRightTable); append(Messages.TOTAL_PHYSICAL_MEMORY, kbStrings2[0]); append(Messages.FREE_PHYSICAL_MEMORY, kbStrings2[1]); append(Messages.TOTAL_SWAP_SPACE, kbStrings2[2]); append(Messages.FREE_SWAP_SPACE, kbStrings2[3]); } append(endTable); } append(newDivider); { // VM arguments and paths append(newTable); String args = ""; java.util.List inputArguments = rmBean.getInputArguments(); for (String arg : inputArguments) { args += arg + " "; } append(Messages.VM_ARGUMENTS, args, 4); append(Messages.CLASS_PATH, rmBean.getClassPath(), 4); append(Messages.LIBRARY_PATH, rmBean.getLibraryPath(), 4); append(Messages.BOOT_CLASS_PATH, rmBean.isBootClassPathSupported() ? rmBean.getBootClassPath() : Messages.UNAVAILABLE, 4); append(endTable); } } catch (IOException e) { if (JConsole.isDebug()) { e.printStackTrace(); } proxyClient.markAsDead(); return null; } catch (UndeclaredThrowableException e) { if (JConsole.isDebug()) { e.printStackTrace(); } proxyClient.markAsDead(); return null; } append("
"); result.timeStamp = System.currentTimeMillis(); result.summary = buf.toString(); return result; } private synchronized void append(String str) { buf.append(str); } void append(String label, String value) { append(newRow(label, value)); } private void append(String label, String value, int columnPerRow) { if (columnPerRow == 4 && pathSeparator != null) { value = value.replace(pathSeparator, "" + pathSeparator); } append(newRow(label, value, columnPerRow)); } OverviewPanel[] getOverviewPanels() { if (overviewPanel == null) { overviewPanel = new CPUOverviewPanel(); } return new OverviewPanel[] { overviewPanel }; } private static class CPUOverviewPanel extends OverviewPanel { private long prevUpTime, prevProcessCpuTime; CPUOverviewPanel() { super(Messages.CPU_USAGE, cpuUsageKey, Messages.CPU_USAGE, Plotter.Unit.PERCENT); getPlotter().setDecimals(CPU_DECIMALS); } public void updateCPUInfo(Result result) { if (prevUpTime > 0L && result.upTime > prevUpTime) { // elapsedCpu is in ns and elapsedTime is in ms. long elapsedCpu = result.processCpuTime - prevProcessCpuTime; long elapsedTime = result.upTime - prevUpTime; // cpuUsage could go higher than 100% because elapsedTime // and elapsedCpu are not fetched simultaneously. Limit to // 99% to avoid Plotter showing a scale from 0% to 200%. float cpuUsage = Math.min(99F, elapsedCpu / (elapsedTime * 10000F * result.nCPUs)); getPlotter().addValues(result.timeStamp, Math.round(cpuUsage * Math.pow(10.0, CPU_DECIMALS))); getInfoLabel().setText(Resources.format(Messages.CPU_USAGE_FORMAT, String.format("%."+CPU_DECIMALS+"f", cpuUsage))); } this.prevUpTime = result.upTime; this.prevProcessCpuTime = result.processCpuTime; } } }