refactor Vmtool, support singleton, support VMtoolMXBean. #1781

This commit is contained in:
hengyunabc
2021-04-27 17:09:52 +08:00
parent 4f91d181e2
commit 15f7844b4f
5 changed files with 100 additions and 22 deletions
@@ -0,0 +1,48 @@
package arthas;
import java.util.ArrayList;
/**
* VMtool interface for JMX server. How to register VMtool MBean:
*
* <pre>
* {@code
* ManagementFactory.getPlatformMBeanServer().registerMBean(
* VMtool.getInstance(),
* new ObjectName("arthas:type=VMtool")
* );
* }
* </pre>
* @author hengyunabc 2021-04-26
*/
public interface VMtoolMXBean {
/**
* 检测jni-lib是否正常,如果正常,应该输出OK
*/
public String check();
/**
* 获取某个class在jvm中当前所有存活实例
*/
public <T> ArrayList<T> getInstances(Class<T> klass);
/**
* 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte
*/
public long sumInstanceSize(Class<?> klass);
/**
* 获取某个实例的占用内存,单位:Byte
*/
public long getInstanceSize(Object instance);
/**
* 统计某个class在jvm中当前所有存活实例的总个数
*/
public long countInstances(Class<?> klass);
/**
* 获取所有已加载的类
*/
public ArrayList<Class<?>> getAllLoadedClasses();
}
+38 -8
View File
@@ -7,7 +7,7 @@ import java.util.ArrayList;
* @author hengyunabc 2021-04-26
* @since 3.5.1
*/
public class Vmtool {
public class Vmtool implements VMtoolMXBean {
/**
* 不要修改jni-lib的名称
@@ -41,39 +41,69 @@ public class Vmtool {
/**
* 检测jni-lib是否正常,如果正常,应该输出OK
*/
public static native String check();
private static native String check0();
/**
* 获取某个class在jvm中当前所有存活实例
*/
public static native <T> ArrayList<T> getInstances(Class<T> klass);
private static native <T> ArrayList<T> getInstances0(Class<T> klass);
/**
* 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte
*/
public static native long sumInstanceSize(Class<?> klass);
private static native long sumInstanceSize0(Class<?> klass);
/**
* 获取某个实例的占用内存,单位:Byte
*/
public static native long getInstanceSize(Object instance);
private static native long getInstanceSize0(Object instance);
/**
* 统计某个class在jvm中当前所有存活实例的总个数
*/
public static native long countInstances(Class<?> klass);
private static native long countInstances0(Class<?> klass);
/**
* 获取所有已加载的类
*/
public static native ArrayList<Class<?>> getAllLoadedClasses();
private static native ArrayList<Class<?>> getAllLoadedClasses0();
/**
* 包括小类型(如int)
*/
@SuppressWarnings("all")
public static ArrayList<Class> getAllClasses() {
return getInstances(Class.class);
return getInstances0(Class.class);
}
@Override
public String check() {
return check0();
}
@Override
public <T> ArrayList<T> getInstances(Class<T> klass) {
return getInstances0(klass);
}
@Override
public long sumInstanceSize(Class<?> klass) {
return sumInstanceSize0(klass);
}
@Override
public long getInstanceSize(Object instance) {
return getInstanceSize0(instance);
}
@Override
public long countInstances(Class<?> klass) {
return countInstances0(klass);
}
@Override
public ArrayList<Class<?>> getAllLoadedClasses() {
return getAllLoadedClasses0();
}
}
@@ -12,7 +12,7 @@ extern "C" {
* Method: check
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_arthas_Vmtool_check
JNIEXPORT jstring JNICALL Java_arthas_Vmtool_check0
(JNIEnv *, jclass);
/*
@@ -6,7 +6,7 @@
extern "C"
JNIEXPORT jstring JNICALL
Java_arthas_Vmtool_check(JNIEnv *env, jclass thisClass) {
Java_arthas_Vmtool_check0(JNIEnv *env, jclass thisClass) {
return env->NewStringUTF("OK");
}
@@ -47,7 +47,7 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data)
extern "C"
JNIEXPORT jobject JNICALL
Java_arthas_Vmtool_getInstances(JNIEnv *env, jclass thisClass, jclass klass) {
Java_arthas_Vmtool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) {
jvmtiEnv *jvmti = getJvmtiEnv(env);
@@ -88,7 +88,7 @@ Java_arthas_Vmtool_getInstances(JNIEnv *env, jclass thisClass, jclass klass) {
extern "C"
JNIEXPORT jlong JNICALL
Java_arthas_Vmtool_sumInstanceSize(JNIEnv *env, jclass thisClass, jclass klass) {
Java_arthas_Vmtool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) {
jvmtiEnv *jvmti = getJvmtiEnv(env);
@@ -126,7 +126,7 @@ Java_arthas_Vmtool_sumInstanceSize(JNIEnv *env, jclass thisClass, jclass klass)
}
extern "C"
JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize
JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize0
(JNIEnv *env, jclass thisClass, jobject instance) {
jvmtiEnv *jvmti = getJvmtiEnv(env);
@@ -142,7 +142,7 @@ JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize
extern "C"
JNIEXPORT jlong JNICALL
Java_arthas_Vmtool_countInstances(JNIEnv *env, jclass thisClass, jclass klass) {
Java_arthas_Vmtool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) {
jvmtiEnv *jvmti = getJvmtiEnv(env);
@@ -172,7 +172,7 @@ Java_arthas_Vmtool_countInstances(JNIEnv *env, jclass thisClass, jclass klass) {
}
extern "C"
JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses
JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses0
(JNIEnv *env, jclass thisClass) {
jvmtiEnv *jvmti = getJvmtiEnv(env);
@@ -28,27 +28,27 @@ public class VmtoolTest {
System.err.println(path);
String libPath = new File(path, System.mapLibraryName(Vmtool.JNI_LIBRARY_NAME)).getAbsolutePath();
Vmtool.getInstance(libPath);
Vmtool vmtool = Vmtool.getInstance(libPath);
//调用native方法,获取已加载的类,不包括小类型(如int)
ArrayList<Class<?>> allLoadedClasses = Vmtool.getAllLoadedClasses();
ArrayList<Class<?>> allLoadedClasses = vmtool.getAllLoadedClasses();
System.out.println("allLoadedClasses->" + allLoadedClasses.size());
//通过下面的例子,可以看到getInstances(Class<T> klass)拿到的是当前存活的所有对象
WeakReference<VmtoolTest> weakReference1 = new WeakReference<VmtoolTest>(new VmtoolTest());
WeakReference<VmtoolTest> weakReference2 = new WeakReference<VmtoolTest>(new VmtoolTest());
System.out.println(weakReference1.get() + " " + weakReference2.get());
ArrayList<Vmtool> beforeInstances = Vmtool.getInstances(Vmtool.class);
ArrayList<Vmtool> beforeInstances = vmtool.getInstances(Vmtool.class);
System.out.println("before instances->" + beforeInstances);
System.out.println("size->" + Vmtool.getInstanceSize(weakReference1.get()));
System.out.println("count->" + Vmtool.countInstances(Vmtool.class));
System.out.println("sum size->" + Vmtool.sumInstanceSize(Vmtool.class));
System.out.println("size->" + vmtool.getInstanceSize(weakReference1.get()));
System.out.println("count->" + vmtool.countInstances(Vmtool.class));
System.out.println("sum size->" + vmtool.sumInstanceSize(Vmtool.class));
beforeInstances = null;
System.gc();
Thread.sleep(100);
System.out.println(weakReference1.get() + " " + weakReference2.get());
ArrayList<Vmtool> afterInstances = Vmtool.getInstances(Vmtool.class);
ArrayList<Vmtool> afterInstances = vmtool.getInstances(Vmtool.class);
System.out.println("after instances->" + afterInstances);
} catch (Exception e) {
e.printStackTrace();