src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java
changeset 47216 71c04702a3d5
parent 25859 3317bb8137f4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java	Tue Sep 12 19:03:39 2017 +0200
@@ -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 =   "<tr><td colspan=4><font size =-1><hr>";
+    private static final String newTable =     "<tr><td colspan=4 align=left><table cellpadding=1>";
+    private static final String newLeftTable = "<tr><td colspan=2 align=left><table cellpadding=1>";
+    private static final String newRightTable =  "<td colspan=2 align=left><table cellpadding=1>";
+    private static final String endTable = "</table>";
+
+    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<Result, Object>() {
+            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("<table cellpadding=1>");
+
+        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("<tr><td colspan=4>");
+            append("<center><b>" + Messages.SUMMARY_TAB_TAB_NAME + "</b></center>");
+            String dateTime =
+                headerDateTimeFormat.format(System.currentTimeMillis());
+            append("<center>" + dateTime + "</center>");
+
+            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<GarbageCollectorMXBean> 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<String> 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("</table>");
+
+        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,
+                                  "<b></b>" + 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;
+        }
+    }
+}