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