From 25a20843b63f98c22782b2c735f54e93c3686525 Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Fri, 23 May 2025 10:35:28 +0800 Subject: [PATCH 1/6] Add mallocTrim command to vmTool --- arthas-vmtool/src/main/java/arthas/VmTool.java | 6 ++++++ .../src/main/java/arthas/VmToolMXBean.java | 5 +++++ .../src/main/native/src/jni-library.cpp | 17 ++++++++++++++++- .../core/command/monitor200/VmToolCommand.java | 7 ++++++- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index 19d2c6c0bf5..ff471c5113c 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -116,4 +116,10 @@ public Class[] getAllLoadedClasses() { return getAllLoadedClasses0(Class.class); } + @Override + public boolean mallocTrim() { + return mallocTrim0(); + } + + private static synchronized native boolean mallocTrim0(); } diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index 076a8f6977a..bdfb0f4077d 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -57,4 +57,9 @@ public interface VmToolMXBean { * 获取所有已加载的类 */ public Class[] getAllLoadedClasses(); + + /** + * glibc 释放空闲内存 + */ + public boolean mallocTrim(); } diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index dd11e2ef810..ebbfe05ebb3 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -4,6 +4,9 @@ #include #include "arthas_VmTool.h" // under target/native/javah/ +#ifdef __GLIBC__ +#include +#endif static jvmtiEnv *jvmti; static jlong tagCounter = 0; @@ -204,4 +207,16 @@ JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 } jvmti->Deallocate(reinterpret_cast(classes)); return array; -} \ No newline at end of file +} + + +extern "C" +JNIEXPORT jboolean JNICALL Java_arthas_VmTool_mallocTrim + (JNIEnv *env, jclass thisClass) { +#ifdef __GLIBC__ + if (!::malloc_trim(0)) { + return JNI_FALSE; + } +#endif + return JNI_TRUE; +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 548f66acfe6..a5a67ace093 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -157,7 +157,7 @@ public void setThreadId(int threadId) { } public enum VmToolAction { - getInstances, forceGc, interruptThread + getInstances, forceGc, interruptThread, mallocTrim } @Override @@ -238,6 +238,11 @@ public void process(final CommandProcess process) { process.write("\n"); process.end(); + return; + } else if (VmToolAction.mallocTrim.equals(action)) { + boolean result = vmToolInstance().mallocTrim(); + process.write("\n"); + process.end(result ? 0 : -1, "mallocTrim result: " + result); return; } From c2b8b10b07ee10037824d3f6536918179f9bf4f3 Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Fri, 23 May 2025 10:40:13 +0800 Subject: [PATCH 2/6] remove empty line --- arthas-vmtool/src/main/native/src/jni-library.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index ebbfe05ebb3..abc1421a7d8 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -209,7 +209,6 @@ JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 return array; } - extern "C" JNIEXPORT jboolean JNICALL Java_arthas_VmTool_mallocTrim (JNIEnv *env, jclass thisClass) { From f65f5e5041f12df415e36ca3e407979e5bde8514 Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Fri, 23 May 2025 11:21:36 +0800 Subject: [PATCH 3/6] add EXAMPLE --- arthas-vmtool/src/main/native/src/jni-library.cpp | 2 +- .../taobao/arthas/core/command/monitor200/VmToolCommand.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index abc1421a7d8..3e9fdb2717b 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -210,7 +210,7 @@ JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 } extern "C" -JNIEXPORT jboolean JNICALL Java_arthas_VmTool_mallocTrim +JNIEXPORT jboolean JNICALL Java_arthas_VmTool_mallocTrim0 (JNIEnv *env, jclass thisClass) { #ifdef __GLIBC__ if (!::malloc_trim(0)) { diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index a5a67ace093..024409f84c5 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -56,6 +56,7 @@ + " vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext\n" + " vmtool --action forceGc\n" + " vmtool --action interruptThread -t 1\n" + + " vmtool --action mallocTrim\n" + Constants.WIKI + Constants.WIKI_HOME + "vmtool") //@formatter:on public class VmToolCommand extends AnnotatedCommand { From 0da277913dab7aa2069ebfd5c180cbb1867a8949 Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Wed, 4 Jun 2025 08:59:06 +0800 Subject: [PATCH 4/6] Change return type to int --- arthas-vmtool/src/main/java/arthas/VmTool.java | 4 ++-- arthas-vmtool/src/main/java/arthas/VmToolMXBean.java | 2 +- arthas-vmtool/src/main/native/src/jni-library.cpp | 8 +++----- .../arthas/core/command/monitor200/VmToolCommand.java | 5 +++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index ff471c5113c..97e00d481e1 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -117,9 +117,9 @@ public Class[] getAllLoadedClasses() { } @Override - public boolean mallocTrim() { + public int mallocTrim() { return mallocTrim0(); } - private static synchronized native boolean mallocTrim0(); + private static synchronized native int mallocTrim0(); } diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index bdfb0f4077d..d178645e2c7 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -61,5 +61,5 @@ public interface VmToolMXBean { /** * glibc 释放空闲内存 */ - public boolean mallocTrim(); + public int mallocTrim(); } diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 3e9fdb2717b..c363f878776 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -210,12 +210,10 @@ JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 } extern "C" -JNIEXPORT jboolean JNICALL Java_arthas_VmTool_mallocTrim0 +JNIEXPORT jint JNICALL Java_arthas_VmTool_mallocTrim0 (JNIEnv *env, jclass thisClass) { #ifdef __GLIBC__ - if (!::malloc_trim(0)) { - return JNI_FALSE; - } + return ::malloc_trim(0); #endif - return JNI_TRUE; + return -1; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 024409f84c5..1e0d235ad3e 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -241,9 +241,10 @@ public void process(final CommandProcess process) { return; } else if (VmToolAction.mallocTrim.equals(action)) { - boolean result = vmToolInstance().mallocTrim(); + int result = vmToolInstance().mallocTrim(); process.write("\n"); - process.end(result ? 0 : -1, "mallocTrim result: " + result); + process.end(result == 1 ? 0 : -1, "mallocTrim result: " + + (result == 1 ? "true" : (result == 0 ? "false" : "not supported"))); return; } From acd574a845f15cdc91c814f57bb9de6f60264824 Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Fri, 6 Jun 2025 16:27:10 +0800 Subject: [PATCH 5/6] add mallocStats and some test --- arthas-vmtool/src/main/java/arthas/VmTool.java | 6 ++++++ arthas-vmtool/src/main/java/arthas/VmToolMXBean.java | 5 +++++ arthas-vmtool/src/main/native/src/jni-library.cpp | 11 +++++++++++ arthas-vmtool/src/test/java/arthas/VmToolTest.java | 12 ++++++++++++ .../core/command/monitor200/VmToolCommand.java | 9 ++++++++- 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index 97e00d481e1..96ca5380ee1 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -122,4 +122,10 @@ public int mallocTrim() { } private static synchronized native int mallocTrim0(); + + @Override + public boolean mallocStats() { + return mallocStats0(); + } + private static synchronized native boolean mallocStats0(); } diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index d178645e2c7..cbaf4aea5ac 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -62,4 +62,9 @@ public interface VmToolMXBean { * glibc 释放空闲内存 */ public int mallocTrim(); + + /** + * glibc 输出内存状态到应用的 stderr + */ + public boolean mallocStats(); } diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index c363f878776..69650e5e3f5 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -217,3 +217,14 @@ JNIEXPORT jint JNICALL Java_arthas_VmTool_mallocTrim0 #endif return -1; } + +extern "C" +JNIEXPORT jboolean JNICALL Java_arthas_VmTool_mallocStats0 + (JNIEnv *env, jclass thisClass) { +#ifdef __GLIBC__ + ::malloc_stats(); + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index b48e7607622..8e7126c5d0d 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -210,4 +210,16 @@ public void test_interrupt_thread() throws InterruptedException { TimeUnit.SECONDS.sleep(5); Assert.assertEquals(("interrupted " + interruptMe.getId() + " thread success."), re[0].getMessage()); } + + @Test + public void testMallocTrim() { + VmTool vmtool = initVmTool(); + vmtool.mallocTrim(); + } + + @Test + public void testMallocStats() { + VmTool vmtool = initVmTool(); + vmtool.mallocStats(); + } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 1e0d235ad3e..758b93323c1 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -57,6 +57,7 @@ + " vmtool --action forceGc\n" + " vmtool --action interruptThread -t 1\n" + " vmtool --action mallocTrim\n" + + " vmtool --action mallocStats\n" + Constants.WIKI + Constants.WIKI_HOME + "vmtool") //@formatter:on public class VmToolCommand extends AnnotatedCommand { @@ -158,7 +159,7 @@ public void setThreadId(int threadId) { } public enum VmToolAction { - getInstances, forceGc, interruptThread, mallocTrim + getInstances, forceGc, interruptThread, mallocTrim, mallocStats } @Override @@ -246,6 +247,12 @@ public void process(final CommandProcess process) { process.end(result == 1 ? 0 : -1, "mallocTrim result: " + (result == 1 ? "true" : (result == 0 ? "false" : "not supported"))); return; + } else if (VmToolAction.mallocStats.equals(action)) { + boolean result = vmToolInstance().mallocStats(); + process.write("\n"); + process.end(result ? 0 : -1, "mallocStats result: " + + (result ? "true" : "not supported")); + return; } process.end(); From c183b1dc0590fc6c653fb4c1e1948dc85b86cf47 Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Fri, 6 Jun 2025 16:41:30 +0800 Subject: [PATCH 6/6] add mallocTrim/mallocStats command doc --- site/docs/doc/vmtool.md | 29 +++++++++++++++++++++++++++++ site/docs/en/doc/vmtool.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/site/docs/doc/vmtool.md b/site/docs/doc/vmtool.md index a173b65691d..0620f0d1355 100644 --- a/site/docs/doc/vmtool.md +++ b/site/docs/doc/vmtool.md @@ -97,3 +97,32 @@ thread id 通过`-t`参数指定,可以使用 `thread`命令获取。 ```bash vmtool --action interruptThread -t 1 ``` + +## glibc 释放空闲内存 + +Linux man page: [malloc_trim](https://man7.org/linux/man-pages/man3/malloc_trim.3.html) + +```bash +vmtool --action mallocTrim +``` + +## glibc 内存状态 + +内存状态将会输出到应用的 stderr。Linux man page: [malloc_stats](https://man7.org/linux/man-pages/man3/malloc_stats.3.html) + +```bash +vmtool --action mallocStats +``` + +输出到 stderr 的内容如下: + +``` +Arena 0: +system bytes = 135168 +in use bytes = 74352 +Total (incl. mmap): +system bytes = 135168 +in use bytes = 74352 +max mmap regions = 0 +max mmap bytes = 0 +``` diff --git a/site/docs/en/doc/vmtool.md b/site/docs/en/doc/vmtool.md index 6bd2f9a8151..e90652f0511 100644 --- a/site/docs/en/doc/vmtool.md +++ b/site/docs/en/doc/vmtool.md @@ -97,3 +97,32 @@ The thread id is specified by the `-t` parameter. It can be obtained using the ` ```bash vmtool --action interruptThread -t 1 ``` + +## glibc Release Free Memory + +Linux man page: [malloc_trim](https://man7.org/linux/man-pages/man3/malloc_trim.3.html) + +```bash +vmtool --action mallocTrim +``` + +## glibc Memory Status + +The memory status will be output to the application's stderr. Linux man page: [malloc_stats](https://man7.org/linux/man-pages/man3/malloc_stats.3.html) + +```bash +vmtool --action mallocStats +``` + +The output to stderr is as follows: + +``` +Arena 0: +system bytes = 135168 +in use bytes = 74352 +Total (incl. mmap): +system bytes = 135168 +in use bytes = 74352 +max mmap regions = 0 +max mmap bytes = 0 +```