|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
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); |
|
|
|
{ |
|
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); |
|
|
|
{ |
|
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); |
|
|
|
{ |
|
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); |
|
|
|
{ |
|
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 |
|
|
|
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); |
|
|
|
{ |
|
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) { |
|
|
|
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 |
|
|
|
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; |
|
} |
|
} |
|
} |