JobPlus知识库 IT 软件开发 文章
Java ManagementFactory解析

导入

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

使用ManagementFactory

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

线程:ThreadMXBean的

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

ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();

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

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

   private static Map<String, Number> collectThreadInfo() {        final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();        Map<String, Number> map = new LinkedHashMap<String, Number>();        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运行时内存信息,甚至包括了堆外内存信息。

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

来了解关于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<String> younggcAlgorithm = new LinkedHashSet<String>() {        {            add("Copy");            add("ParNew");            add("PS Scavenge");            add("G1 Young Generation");        }    };    private Set<String> oldgcAlgorithm = new LinkedHashSet<String>() {        {            add("MarkSweepCompact");            add("PS MarkSweep");            add("ConcurrentMarkSweep");            add("G1 Old Generation");        }    };    private Map<String, Number> collectGC() {        long gcCount = 0;        long gcTime = 0;        long oldGCount = 0;        long oldGcTime = 0;        long youngGcCount = 0;        long youngGcTime = 0;        Map<String, Number> 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<String, Number> collectClassLoadingInfo() {        ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();        Map<String, Number> map = new LinkedHashMap<String, Number>();        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;    }

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏支持
357人赞 举报
分享到
用户评价(0)

暂无评价,你也可以发布评价哦:)

扫码APP

扫描使用APP

扫码使用

扫描使用小程序