OSC 请你来轰趴啦!1028 苏州源创会,一起寻宝 AI 时代
如何获取一个Java类的对象实例呢?这个类即不一定是单例,也不一定提供静态方法,也不一定由Spring管理,甚至还不能修改其源码的情况下,我们该怎么获取这个类的所有对象实例呢?这里介绍一种基于JVMTI的实现方法。
使用说明
首先引用maven依赖
io.github.liubsyy
FindInstancesOfClass
1.0.1
然后直接调用函数 InstancesOfClass.getInstances(Class> targetClass) 即可获取一个类的所有对象实例
public class InstancesOfClass {
/**
* native方法 : 返回所有的实例对象
* @param targetClass 需要查询实例的Class
* @return
*/
public static native Object[] getInstances(Class> targetClass);
}
实现原理
Java里面是没有根据类获取实例的接口的,需要用到JVMTI的接口 IterateOverInstancesOfClass和GetObjectsWithTags
首先写一个包含native方法的类
public class InstancesOfClass {
/**
* native方法 : 返回所有的实例对象
* @param targetClass 需要查询实例的Class
* @return
*/
public static native Object[] getInstances(Class> targetClass);
}
再用javah生成.h文件,然后用C++写实现部分
#include
#include
#include "com_liubs_findinstances_jvmti_InstancesOfClass.h"
static jvmtiIterationControl JNICALL objectInstanceCallback(jlong class_tag, jlong size, jlong* tag_ptr, void* user_data) {
*tag_ptr = 1;
return JVMTI_ITERATION_CONTINUE;
}
JNIEXPORT jobjectArray JNICALL Java_com_liubs_findinstances_jvmti_InstancesOfClass_getInstances(JNIEnv* env, jclass clazz, jclass targetClazz) {
JavaVM* vm;
env->GetJavaVM(&vm);
jvmtiEnv* jvmti;
vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0);
jvmtiCapabilities capabilities = {0};
capabilities.can_tag_objects = 1;
jvmti->AddCapabilities(&capabilities);
jvmti->IterateOverInstancesOfClass(targetClazz, JVMTI_HEAP_OBJECT_EITHER,
objectInstanceCallback, NULL);
jlong tag = 1;
jint count;
jobject* instances;
jvmti->GetObjectsWithTags(1, &tag, &count, &instances, NULL);
printf("Found %d objects with tagn", count);
// 转换jobject* 为 jobjectArray 并返回
jobjectArray result = env->NewObjectArray(count, targetClazz, NULL);
for (int i = 0; i SetObjectArrayElement(result, i, instances[i]);
}
jvmti->Deallocate((unsigned char*)instances);
return result;
}
然后用gcc/g++编译cpp源码,生成linux/mac/windows下对应的动态链接库文件 .so, .dylib和.dll,通过System.load()加载对应本地链接库,最后调用InstancesOfClass.getInstances(Class> targetClass) 方法即可。
具体源码详见 https://github.com/Liubsyy/FindInstancesOfClass,里面包含了测试用例