java management_Java ManagementFactory解析

本文介绍了如何使用Java的ManagementFactory获取JVM的运行时信息,如线程状态、内存使用情况和GC统计。通过示例代码展示了ThreadMXBean、MemoryMXBean和GarbageCollectorMXBean的使用,帮助开发者监控和优化JVM性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者: 一字马胡

转载标志 【2017-11-14】

更新日志

日期

更新内容

备注

2017-11-14

新建文章

初版

导入

ManagementFactory是一个为我们提供各种获取JVM信息的工厂类,使用ManagementFactory可以获取大量的运行时JVM信息,比如JVM堆的使用情况,以及GC情况,线程信息等,通过这些数据项我们可以了解正在运行的JVM的情况,以便我们可以做出相应的调整。本文将基于ManagementFactory,介绍如何通过ManagementFactory获取一些运行时的JVM信息,下面首先展示了ManagementFactory的类图,可以看出它提供了大量的工厂方法,使得我们可以通过调用这些方法来获取运行时的相关Bean,通过这些Bean就可以获取到我们想要的数据:

5d854245051d

使用ManagementFactory

上文中展示的ManagementFactory类图直观的说明了ManagementFactory提供的一些方法,可以看出我们可以获取的内容很多,下面将挑选几个具有代表性的MXBean来作为使用示例。

线程:ThreadMXBean

首先,可以通过下面的方式来获取一个ThreadMXBean:

ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();

下面的图片展示了ThreadMXBean支持的查询方法:

5d854245051d

下面的代码展示了ThreadMXBean的使用方法,通过ThreadMXBean提供的方法,我们可以获取详细的运行时JVM内的线程信息:

private static Map collectThreadInfo() {

final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();

Map map = new LinkedHashMap();

map.put("jvm.thread.count", threadBean.getThreadCount());

map.put("jvm.thread.daemon.count", threadBean.getDaemonThreadCount());

map.put("jvm.thread.totalstarted.count", threadBean.getTotalStartedThreadCount());

ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadBean.getAllThreadIds());

int newThreadCount = 0;

int runnableThreadCount = 0;

int blockedThreadCount = 0;

int waitThreadCount = 0;

int timeWaitThreadCount = 0;

int terminatedThreadCount = 0;

if (threadInfos != null) {

for (ThreadInfo threadInfo : threadInfos) {

if (threadInfo != null) {

switch (threadInfo.getThreadState()) {

case NEW:

newThreadCount++;

break;

case RUNNABLE:

runnableThreadCount++;

break;

case BLOCKED:

blockedThreadCount++;

break;

case WAITING:

waitThreadCount++;

break;

case TIMED_WAITING:

timeWaitThreadCount++;

break;

case TERMINATED:

terminatedThreadCount++;

break;

default:

break;

}

} else {

/*

* If a thread of a given ID is not alive or does not exist,

* the corresponding element in the returned array will,

* contain null,because is mut exist ,so the thread is terminated

*/

terminatedThreadCount++;

}

}

}

map.put("jvm.thread.new.count", newThreadCount);

map.put("jvm.thread.runnable.count", runnableThreadCount);

map.put("jvm.thread.blocked.count", blockedThreadCount);

map.put("jvm.thread.waiting.count", waitThreadCount);

map.put("jvm.thread.time_waiting.count", timeWaitThreadCount);

map.put("jvm.thread.terminated.count", terminatedThreadCount);

long[] ids = threadBean.findDeadlockedThreads();

map.put("jvm.thread.deadlock.count", ids == null ? 0 : ids.length);

return map;

}

使用上面的代码可以获取当前JVM内的线程数量,并且可以计算出每种状态下的线程数量,更多数据可以参考上面展示的ThreadMXBean提供查询接口图。

内存相关MxBean

关于JVM内存相关的数据就比较丰富了,你可以参考文章浅谈JVM中的垃圾回收来初步了解JVM的内存模型,之后你应该也可以根据该文章了解到HotSpot JVM的实现中的内存模型,阅读完该文章之后,就应该知道年轻代、老年代、永久代等相关概念,下面的类是获取这些内存信息的根据类,其中包含了详细的JVM运行时内存信息,甚至包括了堆外内存信息。

class MemoryInformation {

// usedMemory 是heap使用内存 (eden+survivor+old)

private final long m_usedMemory;

// maxMemory 是heap最大内存

private final long m_maxMemory;

// usedOldGen "Old Gen"使用内存

private final long m_usedOldGen;

// maxOldGen "Old Gen"最大内存

private final long m_maxOldGen;

// usedPermGen "Perm Gen"使用内存

private final long m_usedPermGen;

// maxPermGen "Perm Gen"最大内存

private final long m_maxPermGen;

// usedEdenSpace "Eden Space"使用内存

private final long m_usedEdenSpace;

// maxEdenSpace "Eden Space"最大内存

private final long m_maxEdenSpace;

// usedSurvivorSpace "Survivor Space"使用内存

private final long m_usedSurvivorSpace;

// maxSurvivorSpace "Survivor Space"最大内存

private final long m_maxSurvivorSpace;

private final long m_usedNonHeapMemory;

private final long m_maxNonHeapMemory;

private MBeanServer m_mbeanServer = ManagementFactory.getPlatformMBeanServer();

private static final String DIRECT_BUFFER_MBEAN = "java.nio:type=BufferPool,name=direct";

private static final String MAPPED_BUFFER_MBEAN = "java.nio:type=BufferPool,name=mapped";

public MemoryInformation() {

m_usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

m_maxMemory = Runtime.getRuntime().maxMemory();

final MemoryPoolMXBean permGenMemoryPool = getPermGenMemoryPool();

if (permGenMemoryPool != null) {

final MemoryUsage usage = permGenMemoryPool.getUsage();

m_usedPermGen = usage.getUsed();

m_maxPermGen = usage.getMax();

} else {

m_usedPermGen = 0;

m_maxPermGen = 0;

}

final MemoryPoolMXBean oldGenMemoryPool = getOldGenMemoryPool();

if (oldGenMemoryPool != null) {

final MemoryUsage usage = oldGenMemoryPool.getUsage();

m_usedOldGen = usage.getUsed();

m_maxOldGen = usage.getMax();

} else {

m_usedOldGen = 0;

m_maxOldGen = 0;

}

final MemoryPoolMXBean edenSpaceMemoryPool = getEdenSpacePool();

if (edenSpaceMemoryPool != null) {

final MemoryUsage usage = edenSpaceMemoryPool.getUsage();

m_usedEdenSpace = usage.getUsed();

m_maxEdenSpace = usage.getMax();

} else {

m_usedEdenSpace = 0;

m_maxEdenSpace = 0;

}

final MemoryPoolMXBean survivorSpacePool = getSurvivorSpaceMemoryPool();

if (survivorSpacePool != null) {

final MemoryUsage usage = survivorSpacePool.getUsage();

m_usedSurvivorSpace = usage.getUsed();

m_maxSurvivorSpace = usage.getMax();

} else {

m_usedSurvivorSpace = 0;

m_maxSurvivorSpace = 0;

}

final MemoryUsage nonHeapMemoryUsage = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();

m_usedNonHeapMemory = nonHeapMemoryUsage.getUsed();

m_maxNonHeapMemory = nonHeapMemoryUsage.getMax();

}

public long getMaxEdenSpace() {

return m_maxEdenSpace;

}

public long getMaxMemory() {

return m_maxMemory;

}

public long getMaxNonHeapMemory() {

return m_maxNonHeapMemory;

}

public long getMaxOldGen() {

return m_maxOldGen;

}

public long getMaxPermGen() {

return m_maxPermGen;

}

public long getMaxSurvivorSpace() {

return m_maxSurvivorSpace;

}

private MemoryPoolMXBean getEdenSpacePool() {

for (final MemoryPoolMXBean memoryPool : ManagementFactory.getMemoryPoolMXBeans()) {

if (memoryPool.getName().endsWith("Eden Space")) {

return memoryPool;

}

}

return null;

}

private MemoryPoolMXBean getOldGenMemoryPool() {

for (final MemoryPoolMXBean memoryPool : ManagementFactory.getMemoryPoolMXBeans()) {

if (memoryPool.getName().endsWith("Old Gen")) {

return memoryPool;

}

}

return null;

}

private MemoryPoolMXBean getPermGenMemoryPool() {

for (final MemoryPoolMXBean memoryPool : ManagementFactory.getMemoryPoolMXBeans()) {

if (memoryPool.getName().endsWith("Perm Gen")) {

return memoryPool;

}

}

return null;

}

private MemoryPoolMXBean getSurvivorSpaceMemoryPool() {

for (final MemoryPoolMXBean memoryPool : ManagementFactory.getMemoryPoolMXBeans()) {

if (memoryPool.getName().endsWith("Survivor Space")) {

return memoryPool;

}

}

return null;

}

public long getUsedDirectBufferSize() {

long directBufferSize = 0;

try {

ObjectName directPool = new ObjectName(DIRECT_BUFFER_MBEAN);

directBufferSize = (Long) m_mbeanServer.getAttribute(directPool, "MemoryUsed");

} catch (Exception e) {

e.printStackTrace();

}

return directBufferSize;

}

public long getUsedEdenSpace() {

return m_usedEdenSpace;

}

public double getUsedEdenSpacePercentage() {

if (m_usedEdenSpace > 0 && m_maxEdenSpace > 0) {

return 100d * m_usedEdenSpace / m_maxEdenSpace;

}

return 0d;

}

public long getUsedMappedSize() {

long mappedBufferSize = 0;

try {

ObjectName directPool = new ObjectName(MAPPED_BUFFER_MBEAN);

mappedBufferSize = (Long) m_mbeanServer.getAttribute(directPool, "MemoryUsed");

} catch (Exception e) {

e.printStackTrace();

}

return mappedBufferSize;

}

public long getUsedMemory() {

return m_usedMemory;

}

public double getUsedMemoryPercentage() {

return 100d * m_usedMemory / m_maxMemory;

}

public long getUsedNonHeapMemory() {

return m_usedNonHeapMemory;

}

public double getUsedNonHeapPercentage() {

if (m_usedNonHeapMemory > 0 && m_maxNonHeapMemory > 0) {

return 100d * m_usedNonHeapMemory / m_maxNonHeapMemory;

}

return 0d;

}

public long getUsedOldGen() {

return m_usedOldGen;

}

public double getUsedOldGenPercentage() {

if (m_usedOldGen > 0 && m_maxOldGen > 0) {

return 100d * m_usedOldGen / m_maxOldGen;

}

return 0d;

}

public long getUsedPermGen() {

return m_usedPermGen;

}

public double getUsedPermGenPercentage() {

if (m_usedPermGen > 0 && m_maxPermGen > 0) {

return 100d * m_usedPermGen / m_maxPermGen;

}

return 0d;

}

public long getUsedSurvivorSpace() {

return m_usedSurvivorSpace;

}

public double getUsedSurvivorSpacePercentage() {

if (m_usedSurvivorSpace > 0 && m_maxSurvivorSpace > 0) {

return 100d * m_usedSurvivorSpace / m_maxSurvivorSpace;

}

return 0d;

}

@Override

public String toString() {

return getClass().getSimpleName() +

"[usedMemory=" + getUsedMemory() +

", maxMemory=" + getMaxMemory() + ']';

}

}

虽然代码较多,但是都是可以直接运行的,参考价值非常大,如果在工作或者其他地方需要获取这些信息,可以直接参考就可以了。

GC:GarbageCollectorMXBean

同样,你应该首先阅读文章浅谈JVM中的垃圾回收来了解关于GC的一些基础内容,并且知道有哪些GC,以及设置参数,关于JVM的参数设置这部分内容,将会新建一个【JVM参数解析系列】,下面的代码可以获取关于JVM运行时GC相关的数据信息,在统计GC相关信息的时候使用了GarbageCollectorMXBean:

class GarbageCollectorInfo {

private long m_lastGcCount = 0;

private long m_lastGcTime = 0;

private long m_lastFullgcTime = 0;

private long m_lastFullgcCount = 0;

private long m_lastYounggcTime = 0;

private long m_lastYounggcCount = 0;

public long getM_lastGcCount() {

return this.m_lastGcCount;

}

public long getM_lastGcTime() {

return this.m_lastGcTime;

}

public long getM_lastFullgcTime() {

return this.m_lastFullgcTime;

}

public long getM_lastFullgcCount() {

return this.m_lastFullgcCount;

}

public long getM_lastYounggcTime() {

return this.m_lastYounggcTime;

}

public long getM_lastYounggcCount() {

return this.m_lastYounggcCount;

}

private Set younggcAlgorithm = new LinkedHashSet() {

{

add("Copy");

add("ParNew");

add("PS Scavenge");

add("G1 Young Generation");

}

};

private Set oldgcAlgorithm = new LinkedHashSet() {

{

add("MarkSweepCompact");

add("PS MarkSweep");

add("ConcurrentMarkSweep");

add("G1 Old Generation");

}

};

private Map collectGC() {

long gcCount = 0;

long gcTime = 0;

long oldGCount = 0;

long oldGcTime = 0;

long youngGcCount = 0;

long youngGcTime = 0;

Map map = new LinkedHashMap<>();

for (final GarbageCollectorMXBean garbageCollector :

ManagementFactory.getGarbageCollectorMXBeans()) {

gcTime += garbageCollector.getCollectionTime();

gcCount += garbageCollector.getCollectionCount();

String gcAlgorithm = garbageCollector.getName();

if (younggcAlgorithm.contains(gcAlgorithm)) {

youngGcTime += garbageCollector.getCollectionTime();

youngGcCount += garbageCollector.getCollectionCount();

} else if (oldgcAlgorithm.contains(gcAlgorithm)) {

oldGcTime += garbageCollector.getCollectionTime();

oldGCount += garbageCollector.getCollectionCount();

}

}

//

// GC实时统计信息

//

map.put("jvm.gc.count", gcCount - m_lastGcCount);

map.put("jvm.gc.time", gcTime - m_lastGcTime);

final long fullGcCount = oldGCount - m_lastFullgcCount;

map.put("jvm.fullgc.count", fullGcCount);

map.put("jvm.fullgc.time", oldGcTime - m_lastFullgcTime);

map.put("jvm.younggc.count", youngGcCount - m_lastYounggcCount);

map.put("jvm.younggc.time", youngGcTime - m_lastYounggcTime);

if (youngGcCount > m_lastYounggcCount) {

map.put("jvm.younggc.meantime",

(youngGcTime - m_lastYounggcTime) / (youngGcCount - m_lastYounggcCount));

} else {

map.put("jvm.younggc.meantime", 0);

}

//

// GC增量统计信息

//

m_lastGcCount = gcCount;

m_lastGcTime = gcTime;

m_lastYounggcCount = youngGcCount;

m_lastYounggcTime = youngGcTime;

m_lastFullgcCount = oldGCount;

m_lastFullgcTime = oldGcTime;

return map;

}

}

类加载器:ClassLoadingMXBean

使用ClassLoadingMXBean可以获取当前JVM的类加载信息,下面的代码展示了ClassLoadingMXBean的使用方法:

private static Map collectClassLoadingInfo() {

ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();

Map map = new LinkedHashMap();

map.put("jvm.classloading.loaded.count", classLoadingMXBean.getLoadedClassCount());

map.put("jvm.classloading.totalloaded.count", classLoadingMXBean.getTotalLoadedClassCount());

map.put("jvm.classloading.unloaded.count", classLoadingMXBean.getUnloadedClassCount());

return map;

}

结语

本文包含了大量的代码,但是这些代码都是可执行的代码,执行这些代码可以快速直观的获取到JVM运行时的一些关键数据,根据这些数据我们就可以初步了解正在运行的JVM的一些信息,有时候就可以根据这些信息来优化我们的项目,比如是否有太多的线程在空闲状态,或者是否内存占用量很大,或者是否频繁发生Full GC(以此来调整我们的JVM启动参数)。这些数据对于维护和优化项目代码都是非常有价值的,本文试图分析与总结java的ManagementFactory的用法,从文章开篇的图片可以看出ManagementFactory提供了非常丰富的获取JVM运行时数据接口,而本文仅仅挑选了其中比较有代表性的MXBean,关于其他的MXBean的相关用法可以直接参考jdk源码,本文没有涉及到的那些MXBean将在未来合适的时候补充进来,或者在其他的文章中进行分析总结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值