You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
5.1 KiB
175 lines
5.1 KiB
4 years ago
|
package com.fr.base;
|
||
|
|
||
|
import com.fr.general.ComparatorUtils;
|
||
|
import com.fr.log.FineLoggerFactory;
|
||
|
import java.lang.reflect.Array;
|
||
|
import java.lang.reflect.Field;
|
||
|
import java.lang.reflect.Modifier;
|
||
|
import java.util.HashMap;
|
||
|
import java.util.HashSet;
|
||
|
import java.util.Map;
|
||
|
import java.util.Set;
|
||
|
import org.jetbrains.annotations.Nullable;
|
||
|
|
||
|
/**
|
||
|
* @author hades
|
||
|
* @version 10.0
|
||
|
* Created by hades on 2020/12/28
|
||
|
*/
|
||
|
public class ClassHelper {
|
||
|
|
||
|
private static final Set<String> primClasses = new HashSet<>();
|
||
|
|
||
|
private static final Set<ClassLoader> classLoaders = new HashSet<>();
|
||
|
|
||
|
private static final Map<String, Field[]> map = new HashMap<>();
|
||
|
|
||
|
private static final Set<Object> data = new HashSet<>();
|
||
|
|
||
|
private static final String PLUGIN_CLASS_CLASSLOADER= "com.fr.plugin.engine.core.PluginClassLoader";
|
||
|
|
||
|
static {
|
||
|
primClasses.add("boolean");
|
||
|
primClasses.add("byte");
|
||
|
primClasses.add("char");
|
||
|
primClasses.add("short");
|
||
|
primClasses.add("int");
|
||
|
primClasses.add("long");
|
||
|
primClasses.add("float");
|
||
|
primClasses.add("double");
|
||
|
primClasses.add("void");
|
||
|
primClasses.add("java.lang.Boolean");
|
||
|
primClasses.add("java.lang.Byte");
|
||
|
primClasses.add("java.lang.Character");
|
||
|
primClasses.add("java.lang.Short");
|
||
|
primClasses.add("java.lang.Integer");
|
||
|
primClasses.add("java.lang.Long");
|
||
|
primClasses.add("java.lang.FLOAT");
|
||
|
primClasses.add("java.lang.DOUBLE");
|
||
|
primClasses.add("java.lang.Void");
|
||
|
primClasses.add("java.lang.String");
|
||
|
primClasses.add("java.awt.image.BufferedImage");
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 获取当前对象字段中由插件加载出类的classloader
|
||
|
*
|
||
|
* @param o
|
||
|
* @return
|
||
|
*/
|
||
|
@Nullable
|
||
|
public static Set<ClassLoader> getPluginClassLoaders(Object o) {
|
||
|
try {
|
||
|
collectClassloader(o);
|
||
|
Set<ClassLoader> result = new HashSet<>(classLoaders);
|
||
|
data.clear();
|
||
|
classLoaders.clear();
|
||
|
map.clear();
|
||
|
return result;
|
||
|
} catch (Throwable e) {
|
||
|
FineLoggerFactory.getLogger().warn(e.getMessage(), e);
|
||
|
data.clear();
|
||
|
classLoaders.clear();
|
||
|
map.clear();
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void collectClassloader(Object o) {
|
||
|
if (o == null) {
|
||
|
return;
|
||
|
}
|
||
|
Field[] fields;
|
||
|
Class<?> aclass = o.getClass();
|
||
|
|
||
|
String className = aclass.getName();
|
||
|
|
||
|
if (map.containsKey(className)) {
|
||
|
fields = map.get(className);
|
||
|
} else {
|
||
|
fields = fields(aclass, o);
|
||
|
map.put(className, fields);
|
||
|
}
|
||
|
|
||
|
if (aclass.isArray()) {
|
||
|
for (int i = 0, len = Array.getLength(o); i < len; i++) {
|
||
|
Object arrayOb = Array.get(o, i);
|
||
|
if (arrayOb != null) {
|
||
|
Class<?> arrayObClass = arrayOb.getClass();
|
||
|
String name = arrayObClass.getName();
|
||
|
if (primClasses.contains(name)) {
|
||
|
return;
|
||
|
}
|
||
|
data.add(arrayOb);
|
||
|
ClassLoader loader = arrayObClass.getClassLoader();
|
||
|
if (loader != null && ComparatorUtils.equals(loader.getClass().getName(), PLUGIN_CLASS_CLASSLOADER)) {
|
||
|
classLoaders.add(loader);
|
||
|
}
|
||
|
} else {
|
||
|
continue;
|
||
|
}
|
||
|
collectClassloader(arrayOb);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fields.length == 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (Field field : fields) {
|
||
|
if (!field.isAccessible()) {
|
||
|
field.setAccessible(true);
|
||
|
}
|
||
|
Object ob = null;
|
||
|
try {
|
||
|
ob = field.get(o);
|
||
|
|
||
|
if (ob == null) {
|
||
|
continue;
|
||
|
}
|
||
|
Class<?> clazz = ob.getClass();
|
||
|
String name = clazz.getName();
|
||
|
|
||
|
if (primClasses.contains(name)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!data.contains(ob)) {
|
||
|
data.add(ob);
|
||
|
ClassLoader loader = clazz.getClassLoader();
|
||
|
if (loader != null && ComparatorUtils.equals(loader.getClass().getName(), PLUGIN_CLASS_CLASSLOADER)) {
|
||
|
classLoaders.add(loader);
|
||
|
}
|
||
|
collectClassloader(ob);
|
||
|
}
|
||
|
|
||
|
} catch (Throwable e) {
|
||
|
FineLoggerFactory.getLogger().warn(e.getMessage(), e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
private static Field[] fields(Class<?> clazz, Object o) {
|
||
|
|
||
|
Class<?> t = clazz;
|
||
|
Set<Field> result = new HashSet<>();
|
||
|
|
||
|
do {
|
||
|
for (Field field : t.getDeclaredFields()) {
|
||
|
if (clazz != o ^ Modifier.isStatic(field.getModifiers())) {
|
||
|
result.add(field);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
t = t.getSuperclass();
|
||
|
}
|
||
|
while (t != null);
|
||
|
|
||
|
return result.toArray(new Field[0]);
|
||
|
}
|
||
|
|
||
|
}
|