diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java index a4018044b..540112b21 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java @@ -3,6 +3,7 @@ package com.taobao.arthas.core.command.monitor200; 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.util.StringUtils; import com.taobao.arthas.core.util.affect.RowAffect; import com.taobao.middleware.cli.annotations.Description; import com.taobao.middleware.cli.annotations.Name; @@ -12,15 +13,7 @@ import com.taobao.text.ui.Element; import com.taobao.text.ui.TableElement; import com.taobao.text.util.RenderUtil; -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.OperatingSystemMXBean; -import java.lang.management.RuntimeMXBean; -import java.lang.management.ThreadMXBean; +import java.lang.management.*; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; @@ -180,24 +173,27 @@ public class JvmCommand extends AnnotatedCommand { } private Element drawMemoryTable(TableElement table) { + MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage(); table.row("HEAP-MEMORY-USAGE\n[committed/init/max/used]", - memoryMXBean.getHeapMemoryUsage().getCommitted() - + "/" + memoryMXBean.getHeapMemoryUsage().getInit() - + "/" + memoryMXBean.getHeapMemoryUsage().getMax() - + "/" + memoryMXBean.getHeapMemoryUsage().getUsed() + formatMemoryByte(heapMemoryUsage.getCommitted()) + + "/" + formatMemoryByte(heapMemoryUsage.getInit()) + + "/" + formatMemoryByte(heapMemoryUsage.getMax()) + + "/" + formatMemoryByte(heapMemoryUsage.getUsed()) ); - + MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage(); table.row("NO-HEAP-MEMORY-USAGE\n[committed/init/max/used]", - memoryMXBean.getNonHeapMemoryUsage().getCommitted() - + "/" + memoryMXBean.getNonHeapMemoryUsage().getInit() - + "/" + memoryMXBean.getNonHeapMemoryUsage().getMax() - + "/" + memoryMXBean.getNonHeapMemoryUsage().getUsed() + formatMemoryByte(nonHeapMemoryUsage.getCommitted()) + + "/" + formatMemoryByte(nonHeapMemoryUsage.getInit()) + + "/" + formatMemoryByte(nonHeapMemoryUsage.getMax()) + + "/" + formatMemoryByte(nonHeapMemoryUsage.getUsed()) ); table.row("PENDING-FINALIZE-COUNT", "" + memoryMXBean.getObjectPendingFinalizationCount()); return table; } - + private String formatMemoryByte(long bytes){ + return String.format("%s(%s)",bytes, StringUtils.humanReadableByteCount(bytes)); + } private Element drawOperatingSystemMXBeanTable(TableElement table) { table.row("OS", operatingSystemMXBean.getName()).row("ARCH", operatingSystemMXBean.getArch()) @@ -210,9 +206,17 @@ public class JvmCommand extends AnnotatedCommand { private Element drawThreadTable(TableElement table) { table.row("COUNT", "" + threadMXBean.getThreadCount()) .row("DAEMON-COUNT", "" + threadMXBean.getDaemonThreadCount()) - .row("LIVE-COUNT", "" + threadMXBean.getPeakThreadCount()) - .row("STARTED-COUNT", "" + threadMXBean.getTotalStartedThreadCount()); + .row("PEAK-COUNT", "" + threadMXBean.getPeakThreadCount()) + .row("STARTED-COUNT", "" + threadMXBean.getTotalStartedThreadCount()) + .row("DEADLOCK-COUNT","" + getDeadlockedThreadsCount(threadMXBean)); return table; } - + private int getDeadlockedThreadsCount(ThreadMXBean threads) { + final long[] ids = threads.findDeadlockedThreads(); + if (ids == null) { + return 0; + } else { + return ids.length; + } + } } diff --git a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java index 0e9688d0c..79a96f0c9 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java @@ -20,6 +20,8 @@ public abstract class StringUtils { private static final String TOP_PATH = ".."; private static final String CURRENT_PATH = "."; private static final char EXTENSION_SEPARATOR = '.'; + public static final int UNIT = 1024; + public static final String STRING_UNITS = "KMGTPE"; /** @@ -872,4 +874,16 @@ public abstract class StringUtils { if (clazz == null || clazz.getClassLoader() == null) return "null"; return Integer.toHexString(clazz.getClassLoader().hashCode()); } + + /** + * format byte size to human readable format + * @param bytes byets + * @return human readable format + */ + public static String humanReadableByteCount(long bytes) { + if (bytes < UNIT) return bytes + " B"; + int exp = (int) (Math.log(bytes) / Math.log(UNIT)); + String pre = STRING_UNITS.charAt(exp-1) + "i"; + return String.format("%.2f %sB", bytes / Math.pow(UNIT, exp), pre); + } } diff --git a/core/src/test/java/com/taobao/arthas/core/util/StringUtilsTest.java b/core/src/test/java/com/taobao/arthas/core/util/StringUtilsTest.java new file mode 100644 index 000000000..fafaf237e --- /dev/null +++ b/core/src/test/java/com/taobao/arthas/core/util/StringUtilsTest.java @@ -0,0 +1,21 @@ +package com.taobao.arthas.core.util; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author bohrqiu 2018-09-21 01:01 + */ +public class StringUtilsTest { + + @Test + public void testHumanReadableByteCount() { + Assert.assertEquals(StringUtils.humanReadableByteCount(1023L), "1023 B"); + Assert.assertEquals(StringUtils.humanReadableByteCount(1024L), "1.00 KiB"); + Assert.assertEquals(StringUtils.humanReadableByteCount(1024L * 1024L), "1.00 MiB"); + Assert.assertEquals(StringUtils.humanReadableByteCount(1024L * 1024L - 100), "1023.90 KiB"); + Assert.assertEquals(StringUtils.humanReadableByteCount(1024L * 1024 * 1024L), "1.00 GiB"); + Assert.assertEquals(StringUtils.humanReadableByteCount(1024L * 1024 * 1024 * 1024L), "1.00 TiB"); + Assert.assertEquals(StringUtils.humanReadableByteCount(1024L * 1024 * 1024 * 1024 * 1024), "1.00 PiB"); + } +} \ No newline at end of file diff --git a/site/src/site/sphinx/jvm.md b/site/src/site/sphinx/jvm.md index 4c626f041..14989e5c3 100644 --- a/site/src/site/sphinx/jvm.md +++ b/site/src/site/sphinx/jvm.md @@ -70,9 +70,9 @@ $ jvm PS Old Gen - MEMORY HEAP-MEMORY-USAGE 186646528/134217728/1908932608/31245568 + MEMORY HEAP-MEMORY-USAGE 1073741824(1.00 GiB)/1073741824(1.00 GiB)/5242880000(4.88 GiB)/278637584(265.73 MiB) [committed/init/max/used] - NO-HEAP-MEMORY-USAGE 35520512/2555904/-1/34584616 + NO-HEAP-MEMORY-USAGE 172597248(164.60 MiB)/2555904(2.44 MiB)/1862270976(1.73 GiB)/166521144(158.81 MiB) [committed/init/max/used] PENDING-FINALIZE-COUNT 0 @@ -84,8 +84,10 @@ $ jvm THREAD COUNT 16 DAEMON-COUNT 10 - LIVE-COUNT 18 + PEAK-COUNT 18 STARTED-COUNT 19 + DEADLOCK-COUNT 0 + Affect cost in 2 ms. ```