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