Java 代码之 JVM 操作和监控

1. jvm操作

1. 返回获取正在运行的jvm列表

1
2
3
com.sun.tools.attach.VirtualMachine.list()

// [sun.tools.attach.WindowsAttachProvider@404b9385: 2384 com.taobao.arthas.core.Arthas, sun.tools.attach.WindowsAttachProvider@404b9385: 13796 org.springframework.ide.vscode.boot.app.BootLanguagServerBootApp --languageserver.hover-timeout=225, sun.tools.attach.WindowsAttachProvider@404b9385: 6628 ]

2. 使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 已知所需的jvm的PID
String requiredPid = "1111";
VirtualMachineDescriptor virtualMachineDescriptor = null;
for (VirtualMachineDescriptor descriptor : VirtualMachine.list()) {
String pid = descriptor.id();
if (pid.equals(requiredPid)) {
virtualMachineDescriptor = descriptor;
break;
}
}

VirtualMachine virtualMachine = null;
// 获取所需 jvm
try {
if (null == virtualMachineDescriptor) { // 使用 attach(String pid) 这种方式
virtualMachine = VirtualMachine.attach("" + configure.getJavaPid());
} else {
virtualMachine = VirtualMachine.attach(virtualMachineDescriptor);
}
// 获取系统参数
Properties targetSystemProperties = virtualMachine.getSystemProperties();
} finally {
if (null != virtualMachine) {
virtualMachine.detach();
}
}

2. jvm 监控

1. wiki

查看 jvm 启动的参数和各类内存的使用状况,可以使用 java.lang.management.* 自带包,也可以使用 jvisualvm.exe 自带监控工具。

类名 作用
ClassLoadingMXBean 用于 Java 虚拟机的类加载系统的管理接口
CompilationMXBean 用于 Java 虚拟机的编译系统的管理接口
GarbageCollectorMXBean 用于 Java 虚拟机的垃圾回收的管理接口
MemoryManagerMXBean 内存管理器的管理接口
MemoryMXBean Java 虚拟机的内存系统的管理接口
MemoryPoolMXBean 内存池的管理接口
OperatingSystemMXBean 用于操作系统的管理接口,Java 虚拟机在此操作系统上运行
RuntimeMXBean Java 虚拟机的运行时系统的管理接口
ThreadMXBean Java 虚拟机线程系统的管理接口

2. 示例

定义获取的信息 bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.lang.management.MemoryUsage;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class SystemInfoBean {
/********** 操作系统 **********/
// 操作系统的名称
private String operateName;
// 操作系统的进程数
private int processListCount;
// 操作系统的架构
private String archName;
// 操作系统的版本号码
private String versionName;
// 设备平均负载
private double systemLoadAverage;

/********** 虚拟机运行时信息 **********/
// 虚拟机的名称
private String vmName;
// 虚拟机的版本
private String vmVersion;
// 系统的供应商的名称
private String vmVendor;
// JVM启动时间
private Date startTime;
// 输入参数
private List<String> arguments;
// 系统参数
private Map<String, String> systemProperties;
// 虚拟机启动根目录
private String bootClassPath;

/********** 虚拟机内存信息 **********/
// 堆内存信息
private MemoryUsage heapMemoryUsage;
// 非堆内存信息
private MemoryUsage nonHeapMemoryUsage;

/********** 虚拟机类加载信息 **********/
// 当前加载类的数量
private int loadClazzCount;
// 已经加载类的数量
private long hasloadClazzCount;
// 尚未加载类的数量
private long hasUnloadClazzCount;

/*********** 虚拟机编译信息 ***********/
// 编译器名称
private String compilersName;
// 总编译时间
private long totalCompilationTime;

/*********** 虚拟机线程信息 ***********/
private int threadCount;
private long[] allThreadIds;
private long currentThreadUserTime;

// get/set function...
}

获取信息的工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryManagerMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class SystemInfoUtils {

private SystemInfoBean infoBean = null;

private static class SingletonClassInstance {
private static final SystemInfoUtils instance = new SystemInfoUtils();
}

public static SystemInfoUtils getInstance() {
return SingletonClassInstance.instance;
}

public void init() {
infoBean = new SystemInfoBean();
getSystemInfo();
getJvmInfo();
MemoryInfo();
getClassLoading();
getCompilation();
getThread();
showGarbageCollector();
showMemoryManager();
showMemoryPool();
}

/**
* 操作系统信息
*/
public void getSystemInfo() {
OperatingSystemMXBean operateSystemMBean = ManagementFactory.getOperatingSystemMXBean();

// 操作系统名,如 Windows 10
String operateName = operateSystemMBean.getName();
// 操作系统架构名,等于 System.getProperty("os.arch"); ,但后者可能未赋值
String archName = operateSystemMBean.getArch();
// 系统版本号,等于 System.getProperty("os.version"); ,但后者可能未赋值
String versionName = operateSystemMBean.getVersion();
// 操作系统内核数
int processListCount = operateSystemMBean.getAvailableProcessors();
// 设备平均负载
double systemLoadAverage = operateSystemMBean.getSystemLoadAverage();

infoBean.setOperateName(operateName);
infoBean.setArchName(archName);
infoBean.setVersionName(versionName);
infoBean.setProcessListCount(processListCount);
infoBean.setSystemLoadAverage(systemLoadAverage);
}

/**
* 虚拟机的运行时信息
*/
public void getJvmInfo() {
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();

// 虚拟机名称
String vmName = runtimeMXBean.getVmName();
// 虚拟机版本
String vmVersion = runtimeMXBean.getVmVersion();
// 虚拟机实现供应商,可能会为空
String vmVendor = runtimeMXBean.getVmVendor();
// 虚拟机启动时间
long startTime = runtimeMXBean.getStartTime();
// 虚拟机输入参数
List<String> inputArguments = runtimeMXBean.getInputArguments();
// 虚拟机系统参数,基本可以获得所有参数
Map<String, String> systemProperties = runtimeMXBean.getSystemProperties();
// 虚拟机启动根目录
String bootClassPath = runtimeMXBean.getBootClassPath();

infoBean.setVmName(vmName);
infoBean.setVmVersion(System.getProperty("java.version") + " (" + vmVersion + ")");
infoBean.setVmVendor(vmVendor);
infoBean.setStartTime(new Date(startTime));
infoBean.setArguments(inputArguments);
infoBean.setSystemProperties(systemProperties);
infoBean.setBootClassPath(bootClassPath);
}

/**
* 虚拟机内存信息
*/
public void MemoryInfo() {
MemoryMXBean memoryUsage = ManagementFactory.getMemoryMXBean();

// 堆内存信息
MemoryUsage heapMemoryUsage = memoryUsage.getHeapMemoryUsage();
// 非堆内存信息
MemoryUsage nonHeapMemoryUsage = memoryUsage.getNonHeapMemoryUsage();

infoBean.setHeapMemoryUsage(heapMemoryUsage);
infoBean.setNonHeapMemoryUsage(nonHeapMemoryUsage);

}

/**
* 虚拟机的类加载信息
*/
public void getClassLoading() {
ClassLoadingMXBean classLoadMXBean = ManagementFactory.getClassLoadingMXBean();

// 当前加载类总数
int loadClazzCount = classLoadMXBean.getLoadedClassCount();
// 已加载类总数
long hasloadClazzCount = classLoadMXBean.getTotalLoadedClassCount();
// 未加载类总数
long hasUnloadClazzCount = classLoadMXBean.getUnloadedClassCount();

infoBean.setLoadClazzCount(loadClazzCount);
infoBean.setHasloadClazzCount(hasloadClazzCount);
infoBean.setHasUnloadClazzCount(hasUnloadClazzCount);
}

/**
* 虚拟机编译信息
*/
public void getCompilation() {
CompilationMXBean com = ManagementFactory.getCompilationMXBean();

// 编译器名称
String compilersName = com.getName();
// 编译时间
long totalCompilationTime = com.getTotalCompilationTime();

infoBean.setCompilersName(compilersName);
infoBean.setTotalCompilationTime(totalCompilationTime);
}

/**
* 虚拟机线程信息
*/
public void getThread() {
ThreadMXBean thread = ManagementFactory.getThreadMXBean();

int threadCount = thread.getThreadCount();
long[] allThreadIds = thread.getAllThreadIds();
long currentThreadUserTime = thread.getCurrentThreadUserTime();

infoBean.setThreadCount(threadCount);
infoBean.setAllThreadIds(allThreadIds);
infoBean.setCurrentThreadUserTime(currentThreadUserTime);

}

/**
* 虚拟机垃圾回收器
*
*/
public static void showGarbageCollector() {
List<GarbageCollectorMXBean> gc = ManagementFactory.getGarbageCollectorMXBeans();

for (GarbageCollectorMXBean GarbageCollectorMXBean : gc) {
System.out.println("name:" + GarbageCollectorMXBean.getName());
System.out.println("CollectionCount:" + GarbageCollectorMXBean.getCollectionCount());
System.out.println("CollectionTime" + GarbageCollectorMXBean.getCollectionTime());
}
}

/**
* 虚拟机内存管理器
*/
public static void showMemoryManager() {
List<MemoryManagerMXBean> mm = ManagementFactory.getMemoryManagerMXBeans();

for (MemoryManagerMXBean eachmm : mm) {
System.out.println("name:" + eachmm.getName());
System.out.println("MemoryPoolNames:" + eachmm.getMemoryPoolNames().toString());
}
}

/**
* 虚拟机中的内存池
*/
public static void showMemoryPool() {
List<MemoryPoolMXBean> mps = ManagementFactory.getMemoryPoolMXBeans();

for (MemoryPoolMXBean mp : mps) {
System.out.println("name:" + mp.getName());
System.out.println("CollectionUsage:" + mp.getCollectionUsage());
System.out.println("type:" + mp.getType());
}
}
}

3. datax 中获取 jvm 信息类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
package com.alibaba.datax.common.statistics;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Created by liqiang on 15/11/12.
*/
public class VMInfo {
private static final Logger LOG = LoggerFactory.getLogger(VMInfo.class);
static final long MB = 1024 * 1024;
static final long GB = 1024 * 1024 * 1024;
public static Object lock = new Object();
private static VMInfo vmInfo;

/**
* @return null or vmInfo. null is something error, job no care it.
*/
public static VMInfo getVmInfo() {
if (vmInfo == null) {
synchronized (lock) {
if (vmInfo == null) {
try {
vmInfo = new VMInfo();
} catch (Exception e) {
LOG.warn("no need care, the fail is ignored : vmInfo init failed " + e.getMessage(), e);
}
}
}

}
return vmInfo;
}

// 数据的MxBean
private final OperatingSystemMXBean osMXBean;
private final RuntimeMXBean runtimeMXBean;
private final List<GarbageCollectorMXBean> garbageCollectorMXBeanList;
private final List<MemoryPoolMXBean> memoryPoolMXBeanList;
/**
* 静态信息
*/
private final String osInfo;
private final String jvmInfo;

/**
* cpu个数
*/
private final int totalProcessorCount;

/**
* 机器的各个状态,用于中间打印和统计上报
*/
private final PhyOSStatus startPhyOSStatus;
private final ProcessCpuStatus processCpuStatus = new ProcessCpuStatus();
private final ProcessGCStatus processGCStatus = new ProcessGCStatus();
private final ProcessMemoryStatus processMomoryStatus = new ProcessMemoryStatus();
//ms
private long lastUpTime = 0;
//nano
private long lastProcessCpuTime = 0;


private VMInfo() {
//初始化静态信息
osMXBean = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
runtimeMXBean = java.lang.management.ManagementFactory.getRuntimeMXBean();
garbageCollectorMXBeanList = java.lang.management.ManagementFactory.getGarbageCollectorMXBeans();
memoryPoolMXBeanList = java.lang.management.ManagementFactory.getMemoryPoolMXBeans();

osInfo = runtimeMXBean.getVmVendor() + " " + runtimeMXBean.getSpecVersion() + " " + runtimeMXBean.getVmVersion();
jvmInfo = osMXBean.getName() + " " + osMXBean.getArch() + " " + osMXBean.getVersion();
totalProcessorCount = osMXBean.getAvailableProcessors();

//构建startPhyOSStatus
startPhyOSStatus = new PhyOSStatus();
LOG.info("VMInfo# operatingSystem class => " + osMXBean.getClass().getName());
if (VMInfo.isSunOsMBean(osMXBean)) {
{
startPhyOSStatus.totalPhysicalMemory = VMInfo.getLongFromOperatingSystem(osMXBean, "getTotalPhysicalMemorySize");
startPhyOSStatus.freePhysicalMemory = VMInfo.getLongFromOperatingSystem(osMXBean, "getFreePhysicalMemorySize");
startPhyOSStatus.maxFileDescriptorCount = VMInfo.getLongFromOperatingSystem(osMXBean, "getMaxFileDescriptorCount");
startPhyOSStatus.currentOpenFileDescriptorCount = VMInfo.getLongFromOperatingSystem(osMXBean, "getOpenFileDescriptorCount");
}
}

//初始化processGCStatus;
for (GarbageCollectorMXBean garbage : garbageCollectorMXBeanList) {
GCStatus gcStatus = new GCStatus();
gcStatus.name = garbage.getName();
processGCStatus.gcStatusMap.put(garbage.getName(), gcStatus);
}

//初始化processMemoryStatus
if (memoryPoolMXBeanList != null && !memoryPoolMXBeanList.isEmpty()) {
for (MemoryPoolMXBean pool : memoryPoolMXBeanList) {
MemoryStatus memoryStatus = new MemoryStatus();
memoryStatus.name = pool.getName();
memoryStatus.initSize = pool.getUsage().getInit();
memoryStatus.maxSize = pool.getUsage().getMax();
processMomoryStatus.memoryStatusMap.put(pool.getName(), memoryStatus);
}
}
}

public String toString() {
return "the machine info => \n\n"
+ "\tosInfo:\t" + osInfo + "\n"
+ "\tjvmInfo:\t" + jvmInfo + "\n"
+ "\tcpu num:\t" + totalProcessorCount + "\n\n"
+ startPhyOSStatus.toString() + "\n"
+ processGCStatus.toString() + "\n"
+ processMomoryStatus.toString() + "\n";
}

public String totalString() {
return (processCpuStatus.getTotalString() + processGCStatus.getTotalString());
}

public void getDelta() {
getDelta(true);
}

public synchronized void getDelta(boolean print) {

try {
if (VMInfo.isSunOsMBean(osMXBean)) {
long curUptime = runtimeMXBean.getUptime();
long curProcessTime = getLongFromOperatingSystem(osMXBean, "getProcessCpuTime");
//百分比, uptime是ms,processTime是nano
if ((curUptime > lastUpTime) && (curProcessTime >= lastProcessCpuTime)) {
float curDeltaCpu = (float) (curProcessTime - lastProcessCpuTime) / ((curUptime - lastUpTime) * totalProcessorCount * 10000);
processCpuStatus.setMaxMinCpu(curDeltaCpu);
processCpuStatus.averageCpu = (float) curProcessTime / (curUptime * totalProcessorCount * 10000);

lastUpTime = curUptime;
lastProcessCpuTime = curProcessTime;
}
}

for (GarbageCollectorMXBean garbage : garbageCollectorMXBeanList) {

GCStatus gcStatus = processGCStatus.gcStatusMap.get(garbage.getName());
if (gcStatus == null) {
gcStatus = new GCStatus();
gcStatus.name = garbage.getName();
processGCStatus.gcStatusMap.put(garbage.getName(), gcStatus);
}

long curTotalGcCount = garbage.getCollectionCount();
gcStatus.setCurTotalGcCount(curTotalGcCount);

long curtotalGcTime = garbage.getCollectionTime();
gcStatus.setCurTotalGcTime(curtotalGcTime);
}

if (memoryPoolMXBeanList != null && !memoryPoolMXBeanList.isEmpty()) {
for (MemoryPoolMXBean pool : memoryPoolMXBeanList) {

MemoryStatus memoryStatus = processMomoryStatus.memoryStatusMap.get(pool.getName());
if (memoryStatus == null) {
memoryStatus = new MemoryStatus();
memoryStatus.name = pool.getName();
processMomoryStatus.memoryStatusMap.put(pool.getName(), memoryStatus);
}
memoryStatus.commitedSize = pool.getUsage().getCommitted();
memoryStatus.setMaxMinUsedSize(pool.getUsage().getUsed());
long maxMemory = memoryStatus.commitedSize > 0 ? memoryStatus.commitedSize : memoryStatus.maxSize;
memoryStatus.setMaxMinPercent(maxMemory > 0 ? (float) 100 * memoryStatus.usedSize / maxMemory : -1);
}
}

if (print) {
LOG.info(processCpuStatus.getDeltaString() + processMomoryStatus.getDeltaString() + processGCStatus.getDeltaString());
}

} catch (Exception e) {
LOG.warn("no need care, the fail is ignored : vmInfo getDelta failed " + e.getMessage(), e);
}
}

public static boolean isSunOsMBean(OperatingSystemMXBean operatingSystem) {
final String className = operatingSystem.getClass().getName();

return "com.sun.management.UnixOperatingSystem".equals(className);
}

public static long getLongFromOperatingSystem(OperatingSystemMXBean operatingSystem, String methodName) {
try {
final Method method = operatingSystem.getClass().getMethod(methodName, (Class<?>[]) null);
method.setAccessible(true);
return (Long) method.invoke(operatingSystem, (Object[]) null);
} catch (final Exception e) {
LOG.info(String.format("OperatingSystemMXBean %s failed, Exception = %s ", methodName, e.getMessage()));
}

return -1;
}

private class PhyOSStatus {
long totalPhysicalMemory = -1;
long freePhysicalMemory = -1;
long maxFileDescriptorCount = -1;
long currentOpenFileDescriptorCount = -1;

public String toString() {
return String.format("\ttotalPhysicalMemory:\t%,.2fG\n"
+ "\tfreePhysicalMemory:\t%,.2fG\n"
+ "\tmaxFileDescriptorCount:\t%s\n"
+ "\tcurrentOpenFileDescriptorCount:\t%s\n",
(float) totalPhysicalMemory / GB, (float) freePhysicalMemory / GB, maxFileDescriptorCount, currentOpenFileDescriptorCount);
}
}

private class ProcessCpuStatus {
// 百分比的值 比如30.0 表示30.0%
float maxDeltaCpu = -1;
float minDeltaCpu = -1;
float curDeltaCpu = -1;
float averageCpu = -1;

public void setMaxMinCpu(float curCpu) {
this.curDeltaCpu = curCpu;
if (maxDeltaCpu < curCpu) {
maxDeltaCpu = curCpu;
}

if (minDeltaCpu == -1 || minDeltaCpu > curCpu) {
minDeltaCpu = curCpu;
}
}

public String getDeltaString() {
StringBuilder sb = new StringBuilder();
sb.append("\n\t [delta cpu info] => \n");
sb.append("\t\t");
sb.append(String.format("%-30s | %-30s | %-30s | %-30s \n", "curDeltaCpu", "averageCpu", "maxDeltaCpu", "minDeltaCpu"));
sb.append("\t\t");
sb.append(String.format("%-30s | %-30s | %-30s | %-30s \n",
String.format("%,.2f%%", processCpuStatus.curDeltaCpu),
String.format("%,.2f%%", processCpuStatus.averageCpu),
String.format("%,.2f%%", processCpuStatus.maxDeltaCpu),
String.format("%,.2f%%\n", processCpuStatus.minDeltaCpu)));

return sb.toString();
}

public String getTotalString() {
StringBuilder sb = new StringBuilder();
sb.append("\n\t [total cpu info] => \n");
sb.append("\t\t");
sb.append(String.format("%-30s | %-30s | %-30s \n", "averageCpu", "maxDeltaCpu", "minDeltaCpu"));
sb.append("\t\t");
sb.append(String.format("%-30s | %-30s | %-30s \n",
String.format("%,.2f%%", processCpuStatus.averageCpu),
String.format("%,.2f%%", processCpuStatus.maxDeltaCpu),
String.format("%,.2f%%\n", processCpuStatus.minDeltaCpu)));

return sb.toString();
}

}

private class ProcessGCStatus {
final Map<String, GCStatus> gcStatusMap = new HashMap<String, GCStatus>();

public String toString() {
return "\tGC Names\t" + gcStatusMap.keySet() + "\n";
}

public String getDeltaString() {
StringBuilder sb = new StringBuilder();
sb.append("\n\t [delta gc info] => \n");
sb.append("\t\t ");
sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n", "NAME", "curDeltaGCCount", "totalGCCount", "maxDeltaGCCount", "minDeltaGCCount", "curDeltaGCTime", "totalGCTime", "maxDeltaGCTime", "minDeltaGCTime"));
for (GCStatus gc : gcStatusMap.values()) {
sb.append("\t\t ");
sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n",
gc.name, gc.curDeltaGCCount, gc.totalGCCount, gc.maxDeltaGCCount, gc.minDeltaGCCount,
String.format("%,.3fs",(float)gc.curDeltaGCTime/1000),
String.format("%,.3fs",(float)gc.totalGCTime/1000),
String.format("%,.3fs",(float)gc.maxDeltaGCTime/1000),
String.format("%,.3fs",(float)gc.minDeltaGCTime/1000)));

}
return sb.toString();
}

public String getTotalString() {
StringBuilder sb = new StringBuilder();
sb.append("\n\t [total gc info] => \n");
sb.append("\t\t ");
sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n", "NAME", "totalGCCount", "maxDeltaGCCount", "minDeltaGCCount", "totalGCTime", "maxDeltaGCTime", "minDeltaGCTime"));
for (GCStatus gc : gcStatusMap.values()) {
sb.append("\t\t ");
sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n",
gc.name, gc.totalGCCount, gc.maxDeltaGCCount, gc.minDeltaGCCount,
String.format("%,.3fs",(float)gc.totalGCTime/1000),
String.format("%,.3fs",(float)gc.maxDeltaGCTime/1000),
String.format("%,.3fs",(float)gc.minDeltaGCTime/1000)));

}
return sb.toString();
}
}

private class ProcessMemoryStatus {
final Map<String, MemoryStatus> memoryStatusMap = new HashMap<String, MemoryStatus>();

public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\t");
sb.append(String.format("%-30s | %-30s | %-30s \n", "MEMORY_NAME", "allocation_size", "init_size"));
for (MemoryStatus ms : memoryStatusMap.values()) {
sb.append("\t");
sb.append(String.format("%-30s | %-30s | %-30s \n",
ms.name, String.format("%,.2fMB", (float) ms.maxSize / MB), String.format("%,.2fMB", (float) ms.initSize / MB)));
}
return sb.toString();
}

public String getDeltaString() {
StringBuilder sb = new StringBuilder();
sb.append("\n\t [delta memory info] => \n");
sb.append("\t\t ");
sb.append(String.format("%-30s | %-30s | %-30s | %-30s | %-30s \n", "NAME", "used_size", "used_percent", "max_used_size", "max_percent"));
for (MemoryStatus ms : memoryStatusMap.values()) {
sb.append("\t\t ");
sb.append(String.format("%-30s | %-30s | %-30s | %-30s | %-30s \n",
ms.name, String.format("%,.2f", (float) ms.usedSize / MB) + "MB",
String.format("%,.2f", (float) ms.percent) + "%",
String.format("%,.2f", (float) ms.maxUsedSize / MB) + "MB",
String.format("%,.2f", (float) ms.maxpercent) + "%"));

}
return sb.toString();
}
}

private class GCStatus {
String name;
long maxDeltaGCCount = -1;
long minDeltaGCCount = -1;
long curDeltaGCCount;
long totalGCCount = 0;
long maxDeltaGCTime = -1;
long minDeltaGCTime = -1;
long curDeltaGCTime;
long totalGCTime = 0;

public void setCurTotalGcCount(long curTotalGcCount) {
this.curDeltaGCCount = curTotalGcCount - totalGCCount;
this.totalGCCount = curTotalGcCount;

if (maxDeltaGCCount < curDeltaGCCount) {
maxDeltaGCCount = curDeltaGCCount;
}

if (minDeltaGCCount == -1 || minDeltaGCCount > curDeltaGCCount) {
minDeltaGCCount = curDeltaGCCount;
}
}

public void setCurTotalGcTime(long curTotalGcTime) {
this.curDeltaGCTime = curTotalGcTime - totalGCTime;
this.totalGCTime = curTotalGcTime;

if (maxDeltaGCTime < curDeltaGCTime) {
maxDeltaGCTime = curDeltaGCTime;
}

if (minDeltaGCTime == -1 || minDeltaGCTime > curDeltaGCTime) {
minDeltaGCTime = curDeltaGCTime;
}
}
}

private class MemoryStatus {
String name;
long initSize;
long maxSize;
long commitedSize;
long usedSize;
float percent;
long maxUsedSize = -1;
float maxpercent = 0;

void setMaxMinUsedSize(long curUsedSize) {
if (maxUsedSize < curUsedSize) {
maxUsedSize = curUsedSize;
}
this.usedSize = curUsedSize;
}

void setMaxMinPercent(float curPercent) {
if (maxpercent < curPercent) {
maxpercent = curPercent;
}
this.percent = curPercent;
}
}

}

4. 访问 MXBean 的方法的三种方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public static void visitMBean() {

// 第一种直接调用同一 Java 虚拟机内的 MXBean 中的方法。
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
String vendor1 = mxbean.getVmVendor();
System.out.println("vendor1:" + vendor1);

// 第二种通过一个连接到正在运行的虚拟机的平台 MBeanServer 的 MBeanServerConnection。
MBeanServerConnection mbs = null;
// Connect to a running JVM (or itself) and get MBeanServerConnection
// that has the JVM MXBeans registered in it

try {
// Assuming the RuntimeMXBean has been registered in mbs
ObjectName oname = new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
String vendor2 = (String)mbs.getAttribute(oname, "VmVendor");
System.out.println("vendor2:" + vendor2);
} catch (Exception e) {
e.printStackTrace();
}

// 第三种使用 MXBean 代理
MBeanServerConnection mbs3 = null;
RuntimeMXBean proxy;
try {
proxy = ManagementFactory.newPlatformMXBeanProxy(mbs3, ManagementFactory.RUNTIME_MXBEAN_NAME,
RuntimeMXBean.class);
String vendor = proxy.getVmVendor();
} catch (IOException e) {
e.printStackTrace();
}
}