java反序列化
java序列化操作函数
实现Serializable接口
ObjectOutputStream类的writeObject(Object obj)方法,将对象序列化成字符串数据
ObjectInputStream类的readObject(Object obj)方法,将字符串数据反序列化成对象
1 | public class Person implements Serializable { |
更彻底的自定义反序列化
writeReplace:在序列化时,会先调用此方法,再调用writeObject方法。此方法可将任意对象代替目标序列化对象
readResolve:反序列化时替换反序列化出的对象,反序列化出来的对象被立即丢弃。此方法在readeObject后调用。
Externalizable:强制自定义序列化
通过实现Externalizable接口,必须实现writeExternal、readExternal方法。
java反射简介
先看在java中执行系统命令的方法
1 | public class ExecTest { |
该代码会运行并打开windows下的记事本
它正常的步骤是
1 | public class ExecTest { |
Java反射之 getMethod() 与invoke的使用
那么相应的反射的代码如下
ps: Method.invoke
1 | import java.lang.reflect.Method; |
这里第一句Object runtime =Class.forName("java.lang.Runtime")的作用
等价于 Object runtime = Runtime.getRuntime()
目的是获取一个对象实例好被下一个invoke调用
第二句Class.forName("java.lang.Runtime").xxxx的作用就是调用上一步生成的runtime实例的exec方法,并将"notepad.exe"参数传入exec()方法
Method Class.getMethod(String name, Class<?>… parameterTypes)的作用是获得对象所声明的公开方法
该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型。
person.getClass().getMethod(“Speak”, null);
//获得person对象的Speak方法,因为Speak方法没有形参,所以parameterTypes为null
person.getClass().getMethod(“run”, String.class);
//获得person对象的run方法,因为run方法的形参是String类型的,所以parameterTypes为String.class
Transformer接口: 将一个类转换为另一个类,其中的方法是transform
这是apache发布的一个组件包中的方法 下载地址:https://mvnrepository.com/artifact/commons-collections/commons-collections/3.1
有如下几个类使用了Transformer接口,分别是ConstantTransformer,invokerTransformer,ChainedTransformer,TransformedMap。
ConstantTransformer
1 | public class ConstantTransformer implements Transformer, Serializable { |
可以看出transform返回的是iConstant的变量,iConstant的变量必定在ConstantTransformer(Object)方法中被赋值。

InvokerTransformer 获得runtime的Method对象
通过反射创建一个新的对象实例
构造函数:
1 | /** |
其中的transform方法
1 | /** |
iMethodName, iParamTypes通过构造函数传入,transform中通过反射的方法,的到了这个方法(iMethodName)的对象,最后返回Method对象
使用举例,根据上述源码构造一个对象,并且调用transform对象:
1 | InvokerTransformer tran = new InvokerTransformer( |

说一下transform方法中这三行的意思:
cls变量获取到的是传递进来的input的对象值,此处input传递的是Runtime的对象

,下面两行代码要反射Runtime的getRuntime方法,iMethodName表示要得到的方法名称,iParamTypes表示方法中所使用的参数类型的数组。
此处的iMethodName需要Mehtod对象,因此此处是getMethod(构造函数时设置的,getMethod能返回Method对象)

,因此iParamTypes对应的是getMethod对象的参数类型集合,getMethod方法文档如下图所示:
通过查阅官方文档,我们知道了参数应该是String.class和Class[].class
继续往下执行invoke方法,因为是反射getRuntime()方法,参数为空,所以iArgs的值可以为空,回到主程序代码可以发现为null,如下图所示:

执行完毕后:

成功的反射出了Runtime.getRuntime()的方法,然而如果要执行任意代码的化,还需要有exec代码段,全部应该是Runtime.getRuntime().exec(“calc.exe”)
进一步利用获得的getRuntime构造exec执行代码
此时我们已经获得了getRuntime()的Method对象,如果要执行exec(“calc.exe”),我们还需要进行一次invoke反射的过程,因此我们根据上面构造出下面的代码段,如下图:

上图中,构造出tran2的方法,配置invoke的参数都为null,利用tran2.transform(run),反射invoke方法,过程与上文中一样,此处直接看输出了:

此处已经是Runtime类了,继续构造exec(“calc.exe”)代码段,如下图所示:
快速浏览
获取类对象
获取方法
method.invoke(类,参数)
getMethod(方法名, 方法类型) getMethod方法根据方法名称和相关参数,来定位需要查找的Method对象并返回。
invoke(某个对象实例, 传入参数) 作用:调用包装在当前Method对象中的方法。
正常流程: Runtime.getRuntime.exec(“calc.exe”);
反射流程:
-
需要 从Runtime类中搜索匹配
getRuntime方法的名称及参数类型来找到getRuntime方法 并通过getMethod方法获取到getRuntime方法1
2
3
4Class runClass = Runtime.getClass(); // 获取Runtime类 <==> Class.forName("java.lang.Runtime")
Method getRuntime = runClass.getMethod("getRuntime",getRuntime所需要的参数类型); //通过`getMethod`方法获取到`getRuntime`方法
Java反射之 getMethod() 与invoke的使用
https://blog.csdn.net/qq_27446553/article/details/78325204



