forked from fanruan/design
hades
4 years ago
6 changed files with 300 additions and 54 deletions
@ -0,0 +1,174 @@ |
|||||||
|
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]); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.fr.base; |
||||||
|
|
||||||
|
import com.fr.form.main.Form; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import java.util.Set; |
||||||
|
import junit.framework.TestCase; |
||||||
|
import org.junit.Assert; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/28 |
||||||
|
*/ |
||||||
|
public class ClassHelperTest extends TestCase { |
||||||
|
|
||||||
|
|
||||||
|
public void testGetPluginClassLoaders() { |
||||||
|
WorkBook workBook = new WorkBook(); |
||||||
|
Set<ClassLoader> set = ClassHelper.getPluginClassLoaders(workBook); |
||||||
|
Assert.assertEquals(0, set.size()); |
||||||
|
Form form = new Form(); |
||||||
|
Set<ClassLoader> set1 = ClassHelper.getPluginClassLoaders(form); |
||||||
|
Assert.assertEquals(0, set1.size()); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue