前言
不得不开始系统化的学习一下java了,之前搞过java的简单开发,也零散的学了一些java的漏洞,但终究不够系统。综合网上的资料,进行一个系统的学习还是很有必要的。
java反射机制
反射允许java在运行期间借助ReflectionAPI取得任何类的内部消息,并能直接操作任意对象的内部属性和方法。
正常方式:
反射:
java中获取类的方法:
- 直接通过一个class的静态变量class获取:
Class cls = String.class;
- 通过该实例变量提供的getClass()方法获取
String s = "eval"; Class cls = s.getClass();
- 知道一个class的完整类名,可以通过静态方法Class.forName()获取
Class cls = Class.forName("java.lang.String");
java.lang.Runtime
因为有一个exec方法可以执行本地命令,我们常使用反射去获取exec方法来执行命令
正常使用:
// 输出命令执行结果
System.out.println(IOUtils.toString(Runtime.getRuntime().exec("whoami").getInputStream(), "UTF-8"));
使用反射:
// 获取Runtime类对象
Class runtimeClass1 = Class.forName("java.lang.Runtime");
// 获取构造方法
Constructor constructor = runtimeClass1.getDeclaredConstructor();
constructor.setAccessible(true);
// 创建Runtime类示例,等价于 Runtime rt = new Runtime();
Object runtimeInstance = constructor.newInstance();
// 获取Runtime的exec(String cmd)方法
Method runtimeMethod = runtimeClass1.getMethod("exec", String.class);
// 调用exec方法,等价于 rt.exec(cmd);
Process process = (Process) runtimeMethod.invoke(runtimeInstance, cmd);
// 获取命令执行结果
InputStream in = process.getInputStream();
// 输出命令执行结果
System.out.println(IOUtils.toString(in, "UTF-8"));
简化一下:
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),"calc");
反射调用类方法
Class对象提供了一个个获取某个类的所有的成员方法的方法,也可以通过方法名和方法参数类型来获取指定成员方法。
Method getMethod(name, Class...)
:获取某个public的Method(包括父类)Method getDeclaredMethod(name, Class...)
:获取当前类的某个Method(不包括父类)Method[] getMethods()
:获取所有public的Method(包括父类)Method[] getDeclaredMethods()
:获取当前类的所有Method(不包括父类)
获取到java.lang.reflect.Method
对象以后我们可以通过Method的invoke方法来调用类方法。
method.invoke(方法实例对象, 方法参数值,多个参数值用","隔开);
如果调用static方法,那第一个参数传null,因为在 java 中调用静态方法是不需要有类实例的,可以直接类名.方法名(参数)的方式调用
// 获取Integer.parseInt(String)方法,参数为String:
Method m = Integer.class.getMethod("parseInt", String.class);
// 调用该静态方法并获取结果:
Integer n = (Integer) m.invoke(null, "23333");
System.out.println(n);
第二个参数,若该方法无参,可以不传
例子:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String name = "Kitsch";
Method substring = String.class.getMethod("substring", int.class);
System.out.println(substring.invoke(name,4));
}
}
反射调用成员变量
Field fields = clazz.getDeclaredFields();
: 获取当前类所有成员变量Field field = clazz.getDeclaredField("变量名");
: 获取当前类的制定成员变量Object obj = field.get(类实例对象);
: 获取成员变量值field.set(类实例对象, 修改后的值);
: 修改成员变量值field.setAccessible(true)
: 反射时访问私有变量
如果我们要修改修饰词为final
的成员变量
// 反射获取Field类的modifiers
Field modifiers = field.getClass().getDeclaredField("modifiers");
// 设置modifiers修改权限
modifiers.setAccessible(true);
// 修改成员变量的Field对象的modifiers值
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
// 修改成员变量值
field.set(类实例对象, 修改后的值);
Comments | NOTHING