1. 程式人生 > >Java類MemoryUsage查看虛擬機的使用情況

Java類MemoryUsage查看虛擬機的使用情況

core handlers 更改 target taobao import sco nec iter

原文地址:https://www.cnblogs.com/xubiao/p/5465473.html

Java類MemoryUsage,通過MemoryUsage可以查看Java 虛擬機的內存池的內存使用情況。

MemoryUsage類有四個值(均以字節為單位):

Init:java虛擬機在啟動的時候向操作系統請求的初始內存容量,java虛擬機在運行的過程中可能向操作系統請求更多的內存或將內存釋放給操作系統,所以init的值是不確定的。

Used:當前已經使用的內存量。

Committed:表示保證java虛擬機能使用的內存量,已提交的內存量可以隨時間而變化(增加或減少)。Java 虛擬機可能會將內存釋放給系統,committed 可以小於 init。committed 將始終大於或等於 used。

Max:表示可以用於內存管理的最大內存量(以字節為單位)。可以不定義其值。如果定義了該值,最大內存量可能隨時間而更改。已使用的內存量和已提 交的內存量將始終小於或等於 max(如果定義了 max)。如果內存分配試圖增加滿足以下條件的已使用內存將會失敗:used > committed,即使 used <= max 仍然為 true(例如,當系統的虛擬內存不足時)。

直接看demo吧!

在實際開發中,一般可以用這個監控線程占用內存使用情況。

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;

public class MemoryUseTest { public String getMemoryUseInfo(){ MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); long getCommitted = mu.getCommitted(); long getInit = mu.getInit(); long getUsed = mu.getUsed();
long max = mu.getMax(); return ">>getCommitted(MB)=>" + getCommitted / 1000 / 1000 + "\n" +">>getInit(MB)=" + getInit / 1000 / 1000 + "\n" +">>getUsed(MB)=" + getUsed / 1000 / 1000 + "\n" +">>max(MB)=" + max / 1000 / 1000 + "\n"; } public static void main(String[] args){ System.out.println(new MemoryUseTest().getMemoryUseInfo()); } }

https://blog.csdn.net/dataiyangu/article/details/83539727

JVM中MemoryUsage中init,committed,used,max的含義

package java.lang.management;

import javax.management.openmbean.CompositeData;
import sun.management.MemoryUsageCompositeData;

/**
 * A <tt>MemoryUsage</tt> object represents a snapshot of memory usage.
 * Instances of the <tt>MemoryUsage</tt> class are usually constructed
 * by methods that are used to obtain memory usage
 * information about individual memory pool of the Java virtual machine or
 * the heap or non-heap memory of the Java virtual machine as a whole.
 *
 * <p> A <tt>MemoryUsage</tt> object contains four values:
 * <table summary="Describes the MemoryUsage object content">
 * <tr>
 * <td valign=top> <tt>init</tt> </td>
 * <td valign=top> represents the initial amount of memory (in bytes) that
 *      the Java virtual machine requests from the operating system
 *      for memory management during startup.  The Java virtual machine
 *      may request additional memory from the operating system and
 *      may also release memory to the system over time.
 *      The value of <tt>init</tt> may be undefined.
 * </td>
 * </tr>
 * <tr>
 * <td valign=top> <tt>used</tt> </td>
 * <td valign=top> represents the amount of memory currently used (in bytes).
 * </td>
 * </tr>
 * <tr>
 * <td valign=top> <tt>committed</tt> </td>
 * <td valign=top> represents the amount of memory (in bytes) that is
 *      guaranteed to be available for use by the Java virtual machine.
 *      The amount of committed memory may change over time (increase
 *      or decrease).  The Java virtual machine may release memory to
 *      the system and <tt>committed</tt> could be less than <tt>init</tt>.
 *      <tt>committed</tt> will always be greater than
 *      or equal to <tt>used</tt>.
 * </td>
 * </tr>
 * <tr>
 * <td valign=top> <tt>max</tt> </td>
 * <td valign=top> represents the maximum amount of memory (in bytes)
 *      that can be used for memory management. Its value may be undefined.
 *      The maximum amount of memory may change over time if defined.
 *      The amount of used and committed memory will always be less than
 *      or equal to <tt>max</tt> if <tt>max</tt> is defined.
 *      A memory allocation may fail if it attempts to increase the
 *      used memory such that <tt>used &gt; committed</tt> even
 *      if <tt>used &lt;= max</tt> would still be true (for example,
 *      when the system is low on virtual memory).
 * </td>
 * </tr>
 * </table>
 *
 * Below is a picture showing an example of a memory pool:
 *
 * <pre>
 *        +----------------------------------------------+
 *        +////////////////           |                  +
 *        +////////////////           |                  +
 *        +----------------------------------------------+
 *
 *        |--------|
 *           init
 *        |---------------|
 *               used
 *        |---------------------------|
 *                  committed
 *        |----------------------------------------------|
 *                            max
 * </pre>
 *
 * <h3>MXBean Mapping</h3>
 * <tt>MemoryUsage</tt> is mapped to a {@link CompositeData CompositeData}
 * with attributes as specified in the {@link #from from} method.
 *
 * @author   Mandy Chung
 * @since   1.5
 */
public class MemoryUsage {
    private final long init;
    private final long used;
    private final long committed;
    private final long max;

    /**
     * Constructs a <tt>MemoryUsage</tt> object.
     *
     * @param init      the initial amount of memory in bytes that
     *                  the Java virtual machine allocates;
     *                  or <tt>-1</tt> if undefined.
     * @param used      the amount of used memory in bytes.
     * @param committed the amount of committed memory in bytes.
     * @param max       the maximum amount of memory in bytes that
     *                  can be used; or <tt>-1</tt> if undefined.
     *
     * @throws IllegalArgumentException if
     * <ul>
     * <li> the value of <tt>init</tt> or <tt>max</tt> is negative
     *      but not <tt>-1</tt>; or</li>
     * <li> the value of <tt>used</tt> or <tt>committed</tt> is negative;
     *      or</li>
     * <li> <tt>used</tt> is greater than the value of <tt>committed</tt>;
     *      or</li>
     * <li> <tt>committed</tt> is greater than the value of <tt>max</tt>
     *      <tt>max</tt> if defined.</li>
     * </ul>
     */
    public MemoryUsage(long init,
                       long used,
                       long committed,
                       long max) {
        if (init < -1) {
            throw new IllegalArgumentException( "init parameter = " +
                init + " is negative but not -1.");
        }
        if (max < -1) {
            throw new IllegalArgumentException( "max parameter = " +
                max + " is negative but not -1.");
        }
        if (used < 0) {
            throw new IllegalArgumentException( "used parameter = " +
                used + " is negative.");
        }
        if (committed < 0) {
            throw new IllegalArgumentException( "committed parameter = " +
                committed + " is negative.");
        }
        if (used > committed) {
            throw new IllegalArgumentException( "used = " + used +
                " should be <= committed = " + committed);
        }
        if (max >= 0 && committed > max) {
            throw new IllegalArgumentException( "committed = " + committed +
                " should be < max = " + max);
        }

        this.init = init;
        this.used = used;
        this.committed = committed;
        this.max = max;
    }

    /**
     * Constructs a <tt>MemoryUsage</tt> object from a
     * {@link CompositeData CompositeData}.
     */
    private MemoryUsage(CompositeData cd) {
        // validate the input composite data
        MemoryUsageCompositeData.validateCompositeData(cd);

        this.init = MemoryUsageCompositeData.getInit(cd);
        this.used = MemoryUsageCompositeData.getUsed(cd);
        this.committed = MemoryUsageCompositeData.getCommitted(cd);
        this.max = MemoryUsageCompositeData.getMax(cd);
    }

    /**
     * Returns the amount of memory in bytes that the Java virtual machine
     * initially requests from the operating system for memory management.
     * This method returns <tt>-1</tt> if the initial memory size is undefined.
     *
     * @return the initial size of memory in bytes;
     * <tt>-1</tt> if undefined.
     */
    public long getInit() {
        return init;
    }

    /**
     * Returns the amount of used memory in bytes.
     *
     * @return the amount of used memory in bytes.
     *
     */
    public long getUsed() {
        return used;
    };

    /**
     * Returns the amount of memory in bytes that is committed for
     * the Java virtual machine to use.  This amount of memory is
     * guaranteed for the Java virtual machine to use.
     *
     * @return the amount of committed memory in bytes.
     *
     */
    public long getCommitted() {
        return committed;
    };

    /**
     * Returns the maximum amount of memory in bytes that can be
     * used for memory management.  This method returns <tt>-1</tt>
     * if the maximum memory size is undefined.
     *
     * <p> This amount of memory is not guaranteed to be available
     * for memory management if it is greater than the amount of
     * committed memory.  The Java virtual machine may fail to allocate
     * memory even if the amount of used memory does not exceed this
     * maximum size.
     *
     * @return the maximum amount of memory in bytes;
     * <tt>-1</tt> if undefined.
     */
    public long getMax() {
        return max;
    };

    /**
     * Returns a descriptive representation of this memory usage.
     */
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("init = " + init + "(" + (init >> 10) + "K) ");
        buf.append("used = " + used + "(" + (used >> 10) + "K) ");
        buf.append("committed = " + committed + "(" +
                   (committed >> 10) + "K) " );
        buf.append("max = " + max + "(" + (max >> 10) + "K)");
        return buf.toString();
    }

    /**
     * Returns a <tt>MemoryUsage</tt> object represented by the
     * given <tt>CompositeData</tt>. The given <tt>CompositeData</tt>
     * must contain the following attributes:
     *
     * <blockquote>
     * <table border summary="The attributes and the types the given CompositeData contains">
     * <tr>
     *   <th align=left>Attribute Name</th>
     *   <th align=left>Type</th>
     * </tr>
     * <tr>
     *   <td>init</td>
     *   <td><tt>java.lang.Long</tt></td>
     * </tr>
     * <tr>
     *   <td>used</td>
     *   <td><tt>java.lang.Long</tt></td>
     * </tr>
     * <tr>
     *   <td>committed</td>
     *   <td><tt>java.lang.Long</tt></td>
     * </tr>
     * <tr>
     *   <td>max</td>
     *   <td><tt>java.lang.Long</tt></td>
     * </tr>
     * </table>
     * </blockquote>
     *
     * @param cd <tt>CompositeData</tt> representing a <tt>MemoryUsage</tt>
     *
     * @throws IllegalArgumentException if <tt>cd</tt> does not
     *   represent a <tt>MemoryUsage</tt> with the attributes described
     *   above.
     *
     * @return a <tt>MemoryUsage</tt> object represented by <tt>cd</tt>
     *         if <tt>cd</tt> is not <tt>null</tt>;
     *         <tt>null</tt> otherwise.
     */
    public static MemoryUsage from(CompositeData cd) {
        if (cd == null) {
            return null;
        }

        if (cd instanceof MemoryUsageCompositeData) {
            return ((MemoryUsageCompositeData) cd).getMemoryUsage();
        } else {
            return new MemoryUsage(cd);
        }

    }
}

jdk 1.8.0_191

技術分享圖片

package com.taobao.arthas.core.command.monitor200;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.taobao.arthas.core.command.Constants;
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.shell.handlers.Handler;
import com.taobao.arthas.core.shell.handlers.shell.QExitHandler;
import com.taobao.arthas.core.shell.session.Session;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.arthas.core.util.NetUtils;
import com.taobao.arthas.core.util.NetUtils.Response;
import com.taobao.arthas.core.util.ThreadUtil;
import com.taobao.arthas.core.util.metrics.SumRateCounter;
import com.taobao.middleware.cli.annotations.Description;
import com.taobao.middleware.cli.annotations.Name;
import com.taobao.middleware.cli.annotations.Option;
import com.taobao.middleware.cli.annotations.Summary;
import com.taobao.middleware.logger.Logger;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.Style;
import com.taobao.text.renderers.ThreadRenderer;
import com.taobao.text.ui.RowElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;

import java.lang.management.BufferPoolMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author hengyunabc 2015年11月19日 上午11:57:21
 */
@Name("dashboard")
@Summary("Overview of target jvm‘s thread, memory, gc, vm, tomcat info.")
@Description(Constants.EXAMPLE +
        "  dashboard\n" +
        "  dashboard -n 10\n" +
        "  dashboard -i 2000\n" +
        Constants.WIKI + Constants.WIKI_HOME + "dashboard")
public class DashboardCommand extends AnnotatedCommand {

    private static final Logger logger = LogUtil.getArthasLogger();

    private SumRateCounter tomcatRequestCounter = new SumRateCounter();
    private SumRateCounter tomcatErrorCounter = new SumRateCounter();
    private SumRateCounter tomcatReceivedBytesCounter = new SumRateCounter();
    private SumRateCounter tomcatSentBytesCounter = new SumRateCounter();

    private int numOfExecutions = Integer.MAX_VALUE;

    private boolean batchMode;

    private long interval = 5000;

    private volatile long count = 0;
    private volatile Timer timer;

    @Option(shortName = "n", longName = "number-of-execution")
    @Description("The number of times this command will be executed.")
    public void setNumOfExecutions(int numOfExecutions) {
        this.numOfExecutions = numOfExecutions;
    }

    @Option(shortName = "b", longName = "batch")
    @Description("Execute this command in batch mode.")
    public void setBatchMode(boolean batchMode) {
        this.batchMode = batchMode;
    }

    @Option(shortName = "i", longName = "interval")
    @Description("The interval (in ms) between two executions, default is 5000 ms.")
    public void setInterval(long interval) {
        this.interval = interval;
    }


    @Override
    public void process(final CommandProcess process) {

        Session session = process.session();
        timer = new Timer("Timer-for-arthas-dashboard-" + session.getSessionId(), true);

        // ctrl-C support
        process.interruptHandler(new DashboardInterruptHandler(process, timer));

        /*
         * 通過handle回調,在suspend和end時停止timer,resume時重啟timer
         */
        Handler<Void> stopHandler = new Handler<Void>() {
            @Override
            public void handle(Void event) {
                stop();
            }
        };

        Handler<Void> restartHandler = new Handler<Void>() {
            @Override
            public void handle(Void event) {
                restart(process);
            }
        };
        process.suspendHandler(stopHandler);
        process.resumeHandler(restartHandler);
        process.endHandler(stopHandler);

        // q exit support
        process.stdinHandler(new QExitHandler(process));

        // start the timer
        timer.scheduleAtFixedRate(new DashboardTimerTask(process), 0, getInterval());
    }

    public synchronized void stop() {
        if (timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
        }
    }

    public synchronized void restart(CommandProcess process) {
        if (timer == null) {
            Session session = process.session();
            timer = new Timer("Timer-for-arthas-dashboard-" + session.getSessionId(), true);
            timer.scheduleAtFixedRate(new DashboardTimerTask(process), 0, getInterval());
        }
    }

    public int getNumOfExecutions() {
        return numOfExecutions;
    }

    public boolean isBatchMode() {
        return batchMode;
    }

    public long getInterval() {
        return interval;
    }

    private static String beautifyName(String name) {
        return name.replace(‘ ‘, ‘_‘).toLowerCase();
    }

    private static void addBufferPoolMemoryInfo(TableElement table) {
        try {
            @SuppressWarnings("rawtypes")
            Class bufferPoolMXBeanClass = Class.forName("java.lang.management.BufferPoolMXBean");
            @SuppressWarnings("unchecked")
            List<BufferPoolMXBean> bufferPoolMXBeans = ManagementFactory.getPlatformMXBeans(bufferPoolMXBeanClass);
            for (BufferPoolMXBean mbean : bufferPoolMXBeans) {
                long used = mbean.getMemoryUsed();
                long total = mbean.getTotalCapacity();
                new MemoryEntry(mbean.getName(), used, total, Long.MIN_VALUE).addTableRow(table);
            }
        } catch (ClassNotFoundException e) {
            // ignore
        }
    }

    private static void addRuntimeInfo(TableElement table) {
        table.row("os.name", System.getProperty("os.name"));
        table.row("os.version", System.getProperty("os.version"));
        table.row("java.version", System.getProperty("java.version"));
        table.row("java.home", System.getProperty("java.home"));
        table.row("systemload.average",
                String.format("%.2f", ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage()));
        table.row("processors", "" + Runtime.getRuntime().availableProcessors());
        table.row("uptime", "" + ManagementFactory.getRuntimeMXBean().getUptime() / 1000 + "s");
    }

    private static void addMemoryInfo(TableElement table) {
        MemoryUsage heapMemoryUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
        MemoryUsage nonHeapMemoryUsage = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();

        List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();

        new MemoryEntry("heap", heapMemoryUsage).addTableRow(table, Decoration.bold.bold());
        for (MemoryPoolMXBean poolMXBean : memoryPoolMXBeans) {
            if (MemoryType.HEAP.equals(poolMXBean.getType())) {
                MemoryUsage usage = poolMXBean.getUsage();
                String poolName = beautifyName(poolMXBean.getName());
                new MemoryEntry(poolName, usage).addTableRow(table);
            }
        }

        new MemoryEntry("nonheap", nonHeapMemoryUsage).addTableRow(table, Decoration.bold.bold());
        for (MemoryPoolMXBean poolMXBean : memoryPoolMXBeans) {
            if (MemoryType.NON_HEAP.equals(poolMXBean.getType())) {
                MemoryUsage usage = poolMXBean.getUsage();
                String poolName = beautifyName(poolMXBean.getName());
                new MemoryEntry(poolName, usage).addTableRow(table);
            }
        }

        addBufferPoolMemoryInfo(table);
    }

    private static void addGcInfo(TableElement table) {
        List<GarbageCollectorMXBean> garbageCollectorMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
        for (GarbageCollectorMXBean garbageCollectorMXBean : garbageCollectorMxBeans) {
            String name = garbageCollectorMXBean.getName();
            table.add(new RowElement().style(Decoration.bold.bold()).add("gc." + beautifyName(name) + ".count",
                    "" + garbageCollectorMXBean.getCollectionCount()));
            table.row("gc." + beautifyName(name) + ".time(ms)", "" + garbageCollectorMXBean.getCollectionTime());
        }
    }

    private static String formatBytes(long size) {
        int unit = 1;
        String unitStr = "B";
        if (size / 1024 > 0) {
            unit = 1024;
            unitStr = "K";
        } else if (size / 1024 / 1024 > 0) {
            unit = 1024 * 1024;
            unitStr = "M";
        }

        return String.format("%d%s", size / unit, unitStr);
    }

    private void addTomcatInfo(TableElement table) {

        String threadPoolPath = "http://localhost:8006/connector/threadpool";
        String connectorStatPath = "http://localhost:8006/connector/stats";
        Response connectorStatResponse = NetUtils.request(connectorStatPath);
        if (connectorStatResponse.isSuccess()) {
            List<JSONObject> connectorStats = JSON.parseArray(connectorStatResponse.getContent(), JSONObject.class);
            for (JSONObject stat : connectorStats) {
                String name = stat.getString("name").replace("\"", "");
                long bytesReceived = stat.getLongValue("bytesReceived");
                long bytesSent = stat.getLongValue("bytesSent");
                long processingTime = stat.getLongValue("processingTime");
                long requestCount = stat.getLongValue("requestCount");
                long errorCount = stat.getLongValue("errorCount");

                tomcatRequestCounter.update(requestCount);
                tomcatErrorCounter.update(errorCount);
                tomcatReceivedBytesCounter.update(bytesReceived);
                tomcatSentBytesCounter.update(bytesSent);

                table.add(new RowElement().style(Decoration.bold.bold()).add("connector", name));
                table.row("QPS", String.format("%.2f", tomcatRequestCounter.rate()));
                table.row("RT(ms)", String.format("%.2f", processingTime / (double) requestCount));
                table.row("error/s", String.format("%.2f", tomcatErrorCounter.rate()));
                table.row("received/s", formatBytes((long) tomcatReceivedBytesCounter.rate()));
                table.row("sent/s", formatBytes((long) tomcatSentBytesCounter.rate()));
            }
        }

        Response threadPoolResponse = NetUtils.request(threadPoolPath);
        if (threadPoolResponse.isSuccess()) {
            List<JSONObject> threadPoolInfos = JSON.parseArray(threadPoolResponse.getContent(), JSONObject.class);
            for (JSONObject info : threadPoolInfos) {
                String name = info.getString("name").replace("\"", "");
                long busy = info.getLongValue("threadBusy");
                long total = info.getLongValue("threadCount");
                table.add(new RowElement().style(Decoration.bold.bold()).add("threadpool", name));
                table.row("busy", "" + busy);
                table.row("total", "" + total);
            }
        }
    }

    static String drawThreadInfo(int width, int height) {
        Map<String, Thread> threads = ThreadUtil.getThreads();
        return RenderUtil.render(threads.values().iterator(), new ThreadRenderer(), width, height);
    }

    static String drawMemoryInfoAndGcInfo(int width, int height) {
        TableElement table = new TableElement(1, 1);

        TableElement memoryInfoTable = new TableElement(3, 1, 1, 1, 1).rightCellPadding(1);
        memoryInfoTable.add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("Memory",
                "used", "total", "max", "usage"));

        addMemoryInfo(memoryInfoTable);

        TableElement gcInfoTable = new TableElement(1, 1).rightCellPadding(1);
        gcInfoTable.add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("GC", ""));
        addGcInfo(gcInfoTable);

        table.row(memoryInfoTable, gcInfoTable);
        return RenderUtil.render(table, width, height);
    }

    String drawRuntineInfoAndTomcatInfo(int width, int height) {
        TableElement table = new TableElement(1, 1);

        TableElement runtimeInfoTable = new TableElement(1, 1).rightCellPadding(1);
        runtimeInfoTable
                .add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("Runtime", ""));

        addRuntimeInfo(runtimeInfoTable);

        TableElement tomcatInfoTable = new TableElement(1, 1).rightCellPadding(1);

        try {
            // 如果請求tomcat信息失敗,則不顯示tomcat信息
            if (NetUtils.request("http://localhost:8006").isSuccess()) {
                tomcatInfoTable
                        .add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("Tomcat", ""));
                addTomcatInfo(tomcatInfoTable);
            }
        } catch (Throwable t) {
            logger.error(null, "get Tomcat Info error!", t);
        }

        table.row(runtimeInfoTable, tomcatInfoTable);
        return RenderUtil.render(table, width, height);
    }

    static class MemoryEntry {
        String name;
        long used;
        long total;
        long max;

        int unit;
        String unitStr;

        public MemoryEntry(String name, long used, long total, long max) {
            this.name = name;
            this.used = used;
            this.total = total;
            this.max = max;

            unitStr = "K";
            unit = 1024;
            if (used / 1024 / 1024 > 0) {
                unitStr = "M";
                unit = 1024 * 1024;
            }
        }

        public MemoryEntry(String name, MemoryUsage usage) {
            this(name, usage.getUsed(), usage.getCommitted(), usage.getMax());
        }

        private String format(long value) {
            String valueStr = "-";
            if (value == -1) {
                return "-1";
            }
            if (value != Long.MIN_VALUE) {
                valueStr = value / unit + unitStr;
            }
            return valueStr;
        }

        public void addTableRow(TableElement table) {
            double usage = used / (double) (max == -1 || max == Long.MIN_VALUE ? total : max) * 100;

            table.row(name, format(used), format(total), format(max), String.format("%.2f%%", usage));
        }

        public void addTableRow(TableElement table, Style.Composite style) {
            double usage = used / (double) (max == -1 || max == Long.MIN_VALUE ? total : max) * 100;

            table.add(new RowElement().style(style).add(name, format(used), format(total), format(max),
                    String.format("%.2f%%", usage)));
        }
    }

    private class DashboardTimerTask extends TimerTask {
        private CommandProcess process;

        public DashboardTimerTask(CommandProcess process) {
            this.process = process;
        }

        @Override
        public void run() {
            if (count >= getNumOfExecutions()) {
                // stop the timer
                timer.cancel();
                timer.purge();
                process.write("Process ends after " + getNumOfExecutions() + " time(s).\n");
                process.end();
                return;
            }

            int width = process.width();
            int height = process.height();

            // 上半部分放thread top。下半部分再切分為田字格,其中上面兩格放memory, gc的信息。下面兩格放tomcat,
            // runtime的信息
            int totalHeight = height - 1;
            int threadTopHeight = totalHeight / 2;
            int lowerHalf = totalHeight - threadTopHeight;

            int runtimeInfoHeight = lowerHalf / 2;
            int heapInfoHeight = lowerHalf - runtimeInfoHeight;

            String threadInfo = drawThreadInfo(width, threadTopHeight);
            String memoryAndGc = drawMemoryInfoAndGcInfo(width, runtimeInfoHeight);
            String runTimeAndTomcat = drawRuntineInfoAndTomcatInfo(width, heapInfoHeight);

            process.write(threadInfo + memoryAndGc + runTimeAndTomcat);

            count++;
            process.times().incrementAndGet();
        }
    }
}

com.taobao.arthas.core.command.monitor200.DashboardCommand

Java類MemoryUsage查看虛擬機的使用情況