基础的Java语法
- 类与对象
类是一个模板:抽象,对象是一个具体的实例 - 方法
定义、调用! - 对应的引用
引用类型: 基本类型(8)
对象是通过引用来操作的:栈—>堆 - 属性:字段Field 成员变量
默认初始化:
数字: 0 0.0
char : u0000
boolean: false
引用: null
修饰符 属性类型 属性名 = 属性值! - 对象的创建和使用
- 必须使用new 关键字创造对象,构造器 Person kuangshen = new Person();
- 对象的属性 kuangshen.name
- 对象的方法 kuangshen.sleep()
6.类:
静态的属性 属性
动态的行为 方法
封装、继承、多态

super

重写

多态

Java 反序列化
反射
大白话说Java反射:入门、使用、原理 - 陈树义 - 博客园
知道类名,用正射:
1 | Apple apple = new Apple(); |
Java 中一切皆对象,类是Class对象,方法是Method对象,构造方法是Constructor对象,字段是Field对象。
不知道类名,只能把类名先存变量里面,再一句一句跟代码说要对这个类干什么,这是反射:
1 | Class clz = Class.forName("com.zhenai.api.Apple"); |
对于名字叫 xxx 的类,获取 xxx 类的Class对象(请注意这里不等于 xxx 对象),就是根据 xxx 这个名字,把 xxx 的档案调出来。
1 | Constructor appleConstructor = clz.getConstructor(); |
对于这个对象,获取 xxx 的构造方法/construct/无参函数的对象也调出来,也就是Constructor对象。就是根据 xxx 的档案,把 xxx 的 DNA 也调出来。
1 | Object appleObj = appleConstructor.newInstance(); |
用Constructor对象新建一个实例。
根据 xxx 的 DNA,新建一个 xxx。
如果要调用方法:
1 | Method setPriceMethod = clz.getMethod("setPrice", int.class); |
用Class对象获取Method对象,这个Method对象是一个名字叫setPrice,参数类型是int的方法 。
在 xxx 的档案里找一个叫setPrice的技能档案,把这个技能教给 xxx。
1 | setPriceMethod.invoke(appleObj, 14); |
用Method对象调用 invoke 方法,传入对象名字和参数。。
让 xxx 以指定的方式使用技能。
CC1链——全网最菜的分析思路 - FreeBuf网络安全行业门户
反序列化和 readObject
序列化是把对象变成字节流,反序列化是把字节流还原成对象。
定义类 Student.java
1 | import java.io.Serializable; |
implements Serializable必须写上这个接口这个类才可以被序列化。
主程序 Main.java:
1 | import java.io.*; |
这段代码演示了序列化和反序列化的过程。
反序列化不仅可以把字节流还原成对象,如果类里面有readObject这个方法,那么反序列化的时候会调用这个方法。如果该方法中有恶意代码,也会执行。所以自定义了 readObject()方法的类就是我们寻找的入口点。
如果现在有一个程序Demo.java
1 | import java.io.*; |
可以看到开发者自己写了一个readObject,那么我们这里可以写一个调用反序列化的主程序:
1 | public class Main { |
输出:
1 | readObject 被调用了! |
readObject 是起点,能执行命令的类是终点,从起点到终点,前一个触发了后一个,所以是一条链。
通过反射来执行 Runtime 命令:
1 | Class clazz = Runtime.class; |
获取类,获取方法,获取实例,执行命令
CommonsCollections1 链
InvokerTransformer 类
使用InvokerTransformer 对象调用 transform()方法,会以反射的方式 执行任意方法。
1 | InvokerTransformer invokerTransformer = new InvokerTransformer( |
这里看不出反射是因为反射被封装在transform()方法内部。