All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wgzhao.addax.common.statistics.VMInfo Maven / Gradle / Ivy

There is a newer version: 4.1.4
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.wgzhao.addax.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
{
    static final long MB = 1024L * 1024L;
    static final long GB = 1024 * 1024 * 1024L;
    private static final Logger LOG = LoggerFactory.getLogger(VMInfo.class);
    private static VMInfo vmInfo;
    // 数据的MxBean
    private final OperatingSystemMXBean osMXBean;
    private final RuntimeMXBean runtimeMXBean;
    private final List garbageCollectorMXBeanList;
    private final List 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 processMemoryStatus = 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();

        jvmInfo = runtimeMXBean.getVmVendor() + " " + runtimeMXBean.getSpecVersion() + " " + runtimeMXBean.getVmVersion();
        osInfo = 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();
                processMemoryStatus.memoryStatusMap.put(pool.getName(), memoryStatus);
            }
        }
    }

    /**
     * static method, get vm information and returns
     * @return null or vmInfo. null is something error, job no care it.
     */
    public static synchronized VMInfo getVmInfo()
    {
        if (vmInfo == null) {
            vmInfo = new VMInfo();
        }
        return vmInfo;
    }

    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;
    }

    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 + "\n"
                + processMemoryStatus + "\n";
    }

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

    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 = processMemoryStatus.memoryStatusMap.get(pool.getName());
                    if (memoryStatus == null) {
                        memoryStatus = new MemoryStatus();
                        memoryStatus.name = pool.getName();
                        processMemoryStatus.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() + processMemoryStatus.getDeltaString() + processGCStatus.getDeltaString());
            }
        }
        catch (Exception e) {
            LOG.warn("no need care, the fail is ignored : vmInfo getDelta failed {}", e.getMessage(), e);
        }
    }

    private static 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 static class ProcessGCStatus
    {
        final Map gcStatusMap = new HashMap<>();

        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 static class ProcessMemoryStatus
    {
        final Map memoryStatusMap = new HashMap<>();

        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", ms.percent) + "%",
                        String.format("%,.2f", (float) ms.maxUsedSize / MB) + "MB",
                        String.format("%,.2f", ms.maxPercent) + "%"));
            }
            return sb.toString();
        }
    }

    private static 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 static 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;
        }
    }

    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()
        {

            return "\n\t [delta cpu info] => \n" +
                    "\t\t" +
                    String.format("%-30s | %-30s | %-30s | %-30s %n", "curDeltaCpu", "averageCpu", "maxDeltaCpu", "minDeltaCpu") +
                    "\t\t" +
                    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));
        }

        public String getTotalString()
        {

            return "\n\t [total cpu info] => \n" +
                    "\t\t" +
                    String.format("%-30s | %-30s | %-30s %n", "averageCpu", "maxDeltaCpu", "minDeltaCpu") +
                    "\t\t" +
                    String.format("%-30s | %-30s | %-30s %n",
                            String.format("%,.2f%%", processCpuStatus.averageCpu),
                            String.format("%,.2f%%", processCpuStatus.maxDeltaCpu),
                            String.format("%,.2f%%%n", processCpuStatus.minDeltaCpu));
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy