获取类中类

AspectJWeaver 反序列化中,需要获取SimpleCache中的私有类StorableCachingMap

目前我已知的方法有两种,第一种是比较方便的获取方法

直接SimpleCache$StorableCachingMap表示类中类

1
2
3
4
5
Class clazz = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Constructor constructor = clazz.getDeclaredConstructor(String.class ,int.class);
constructor.setAccessible(true);
// 因为其为private,所以得给其强转为他的父类;
HashMap simpleCache = (HashMap) constructor.newInstance("/tmp" ,60000);

第二种是通过父类中的变量获取到类,相对麻烦一点

1
2
3
4
5
6
7
Class clazz2 = SimpleCache.class;
Constructor constructor1 = clazz2.getDeclaredConstructor(String.class ,boolean.class);
constructor1.setAccessible(true);
SimpleCache simpleCache1 = (SimpleCache) constructor1.newInstance("/tmp" ,true);
Field field = clazz2.getDeclaredField("cacheMap");
field.setAccessible(true);
Map map = (Map) field.get(simpleCache1);

关键点就是,需要将变量对应的类转化为对应的,也就是需要将其转为Map类型

image-20241121173126136

不使用构造方法创建对象

核心是使用ReflectionFactory 链接

Java8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package Seri.ReflectDemo;

import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectionFactoryDemo {
public static void main(String[] args)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取ReflectionFactory对象,它本身是单例的
ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
//获取Object类的构造器
Constructor<Object> constructor = Object.class.getDeclaredConstructor();
//根据Object构造器创建一个User类的构造器
Constructor<?> constructorForSerialization = reflectionFactory
.newConstructorForSerialization(User.class, constructor);
constructorForSerialization.setAccessible(true);
//实例化对象
System.out.println(constructorForSerialization.newInstance());
}

public static class User {
private String name = "lisi";
public User() {
System.out.println("User created");
}
@Override
public String toString() {
return "user=" + name;
}
}
}
Java11
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestReflectionFactory {
public static void main(String[] args) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
Constructor<?> constructor = newConstructorForSerialization(User.class, getJavaLangObjectConstructor());
System.out.println(constructor.newInstance());
}

public static class User {
private String name = "lisi";
public User() {
System.out.println("User created");
}
@Override
public String toString() {
return "user=" + name;
}
}

public static <T> Constructor<T> newConstructorForSerialization(Class<T> type, Constructor<?> constructor) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Class<?> reflectionFactoryClass = getReflectionFactoryClass();
Object reflectionFactory = createReflectionFactory(reflectionFactoryClass);
Method newConstructorForSerializationMethod = getNewConstructorForSerializationMethod(reflectionFactoryClass);
return (Constructor) newConstructorForSerializationMethod.invoke(reflectionFactory, type, constructor);
}
private static Class<?> getReflectionFactoryClass() throws ClassNotFoundException {
return Class.forName("sun.reflect.ReflectionFactory");
}
private static Object createReflectionFactory(Class<?> reflectionFactoryClass) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = reflectionFactoryClass.getDeclaredMethod("getReflectionFactory");
return method.invoke((Object) null);
}
private static Method getNewConstructorForSerializationMethod(Class<?> reflectionFactoryClass) throws NoSuchMethodException {
return reflectionFactoryClass.getDeclaredMethod("newConstructorForSerialization", Class.class, Constructor.class);
}
private static Constructor<Object> getJavaLangObjectConstructor() throws NoSuchMethodException {
return Object.class.getConstructor((Class[]) null);
}
}

反射修改父类中的属性

Hibernate1 这条链中,

PojoComponentTuplizerAbstractComponentTuplizer的子类,但是PojoComponentTuplizer中调用了很多父类的属性,所以需要修改父类中的变量

由于反射是直接修改内存中的属性,所以可以直接修改AbstractComponentTuplizer中的属性

像这样(伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.lang.reflect.Field;

class AbstractComponentTuplizer {
private String value = "Parent Value"; // 私有属性

public String getValue() {
return value; // 获取属性值
}
}

class PojoComponentTuplizer extends AbstractComponentTuplizer {
// 子类无需特别实现,直接使用父类的属性
}

public class Main {
public static void main(String[] args) throws Exception {
// 创建子类实例
PojoComponentTuplizer tuplizer = new PojoComponentTuplizer();

System.out.println("Before modification: " + tuplizer.getValue());

// 获取父类的Class对象
Class<?> parentClass = AbstractComponentTuplizer.class;

// 获取父类的私有属性
Field valueField = parentClass.getDeclaredField("value");

// 设置为可访问
valueField.setAccessible(true);

// 修改父类属性的值
valueField.set(tuplizer, "Modified Value");

System.out.println("After modification: " + tuplizer.getValue());
}
}

反射修改HashSet中唯一值

只能修改容量为一的HashSet对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 容量为1
HashSet hashSet = new HashSet(1);
hashSet.add("xxx");

Field setMap = hashSet.getClass().getDeclaredField("map");
setMap.setAccessible(true);
HashMap hashMap = (HashMap) setMap.get(hashSet);
Field setTable = hashMap.getClass().getDeclaredField("table");
setTable.setAccessible(true);
Object[] table = (Object[]) setTable.get(hashMap);
Object Node = table[1];
Field setKey = Node.getClass().getDeclaredField("key");
setKey.setAccessible(true);

// 设置值
setKey.set(Node, tiedMapEntry);