diff -r 836adbf7a2cd -r 3317bb8137f4 jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java Sun Aug 17 15:54:13 2014 +0100 @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2004, 2013, 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 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, + Resources.format(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)); + + cpuUsage = Math.max(0F, cpuUsage); + + 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; + } + } +}