diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index ae08763d7..d530a06d5 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -41,6 +41,8 @@ public class VmTool implements VmToolMXBean { */ private static native String check0(); + private static native void forceGc0(); + /** * 获取某个class在jvm中当前所有存活实例 */ @@ -78,6 +80,11 @@ public class VmTool implements VmToolMXBean { return check0(); } + @Override + public void forceGc() { + forceGc0(); + } + @Override public T[] getInstances(Class klass) { return getInstances0(klass); diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index 51af311ae..92df09be1 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -19,6 +19,11 @@ public interface VmToolMXBean { */ public String check(); + /** + * https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#ForceGarbageCollection + */ + public void forceGc(); + /** * 获取某个class在jvm中当前所有存活实例 */ diff --git a/arthas-vmtool/src/main/native/include/arthas_VmTool.h b/arthas-vmtool/src/main/native/include/arthas_VmTool.h index 3f11b40a6..4f7b087f8 100644 --- a/arthas-vmtool/src/main/native/include/arthas_VmTool.h +++ b/arthas-vmtool/src/main/native/include/arthas_VmTool.h @@ -15,6 +15,14 @@ extern "C" { JNIEXPORT jstring JNICALL Java_arthas_VmTool_check0 (JNIEnv *, jclass); +/* + * Class: arthas_VmTool + * Method: forceGc0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_arthas_VmTool_forceGc0 + (JNIEnv *, jclass); + /* * Class: arthas_VmTool * Method: getInstances0 diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 95fab8f62..0351dfead 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -19,12 +19,6 @@ JNIEXPORT jclass JNICALL getClass(JNIEnv *env) { return cachedClass; } -extern "C" -JNIEXPORT jstring JNICALL -Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { - return env->NewStringUTF("OK"); -} - extern "C" jvmtiEnv *getJvmtiEnv(JNIEnv *env) { @@ -36,6 +30,19 @@ jvmtiEnv *getJvmtiEnv(JNIEnv *env) { return jvmti; } +extern "C" +JNIEXPORT void JNICALL +Java_arthas_VmTool_forceGc0(JNIEnv *env, jclass thisClass) { + jvmtiEnv *jvmti = getJvmtiEnv(env); + jvmti->ForceGarbageCollection(); +} + +extern "C" +JNIEXPORT jstring JNICALL +Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { + return env->NewStringUTF("OK"); +} + extern "C" jobject createJavaInstance(JNIEnv *env, jclass javaClass) { //找到java类的构造方法 diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index 03d3e11a4..16a7bac47 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -43,7 +43,7 @@ public class VmToolTest { System.out.println("sum size->" + vmtool.sumInstanceSize(VmTool.class)); beforeInstances = null; - System.gc(); + vmtool.forceGc(); Thread.sleep(100); System.out.println(weakReference1.get() + " " + weakReference2.get()); VmTool[] afterInstances = vmtool.getInstances(VmTool.class); @@ -80,7 +80,7 @@ public class VmToolTest { totalTime.addAndGet(cost); System.out.println(i + " instance size:" + (instances == null ? 0 : instances.length) + ", cost " + cost + "ms avgCost " + totalTime.doubleValue() / i + "ms"); instances = null; - System.gc(); + vmtool.forceGc(); } } 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 bd17d6e16..05ab8cd12 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 @@ -46,7 +46,8 @@ import arthas.VmTool; @Summary("jvm tool") @Description(Constants.EXAMPLE + " vmtool --action getInstances --className demo.MathGame\n" - + " vmtool --action getInstances --className demo.MathGame --express 'instances.size()'\n" + + " vmtool --action getInstances --className demo.MathGame --express 'instances.length'\n" + + " vmtool --action forceGc\n" + Constants.WIKI + Constants.WIKI_HOME + "vmtool") //@formatter:on public class VmToolCommand extends AnnotatedCommand { @@ -123,7 +124,7 @@ public class VmToolCommand extends AnnotatedCommand { } public enum VmToolAction { - getInstances, load + getInstances, forceGc, load } @Override @@ -178,8 +179,14 @@ public class VmToolCommand extends AnnotatedCommand { } process.write(new ObjectView(value, this.expand).draw()); + process.write("\n"); process.end(); } + } else if (VmToolAction.forceGc.equals(action)) { + vmToolInstance().forceGc(); + process.write("\n"); + process.end(); + return; } process.end(); diff --git a/lib/libArthasJniLibrary-x64.dylib b/lib/libArthasJniLibrary-x64.dylib index 8ab0de586..5547993f5 100644 Binary files a/lib/libArthasJniLibrary-x64.dylib and b/lib/libArthasJniLibrary-x64.dylib differ diff --git a/spy/src/main/java/arthas/VmTool.java b/spy/src/main/java/arthas/VmTool.java index ae08763d7..d530a06d5 100644 --- a/spy/src/main/java/arthas/VmTool.java +++ b/spy/src/main/java/arthas/VmTool.java @@ -41,6 +41,8 @@ public class VmTool implements VmToolMXBean { */ private static native String check0(); + private static native void forceGc0(); + /** * 获取某个class在jvm中当前所有存活实例 */ @@ -78,6 +80,11 @@ public class VmTool implements VmToolMXBean { return check0(); } + @Override + public void forceGc() { + forceGc0(); + } + @Override public T[] getInstances(Class klass) { return getInstances0(klass); diff --git a/spy/src/main/java/arthas/VmToolMXBean.java b/spy/src/main/java/arthas/VmToolMXBean.java index 51af311ae..92df09be1 100644 --- a/spy/src/main/java/arthas/VmToolMXBean.java +++ b/spy/src/main/java/arthas/VmToolMXBean.java @@ -19,6 +19,11 @@ public interface VmToolMXBean { */ public String check(); + /** + * https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#ForceGarbageCollection + */ + public void forceGc(); + /** * 获取某个class在jvm中当前所有存活实例 */