前言
        反射是Java中一种动态(运行时),通过反射可以在java动态运行时,对于任意一个类,对象可以通过反射获取到他的类,类可以通过反射拿到所有方法(包括私有),动态获取信息,以及动态调用对象的方法的功能称为java语言的反射机制。
反射的具体使用步骤
在调用Java反射机制,主要步骤包括:
- 获取 目标类型的Class对象.
- 通过 Class对象分别获取Constructor类对象、Method类对象 &Field类对象.
- 通过 Constructor类对象、Method类对象 &Field类对象分别获取类的构造函数、方法&属性的具体信息,并进行后续操作.
反射获取类的class对象
要想使用反射,我们首先需要获得代操作的类所对应的Clas对象。
1.常用的获取Class对象有四种方法:
  | 1
 | Class clz = Class.forName("java.lang.String");
 | 
| 1
 | Class clz = String.class;
 | 
| 12
 
 | String str = new String("Hello");Class clz = str.getClass();
 
 | 
| 12
 
 | Class<?> classType = Boolean.TYPE; System.out.println(classType);
 
 | 
反射创建类对象
常用两种方法:
- 通过 Class 对象的 newInstance() 方法,只能使用默认的无参数构造方法。
| 12
 
 | Class clz = pen.class;Pen pen = (pen)clz.newInstance();
 
 | 
- 通过 Constructor 对象的 newInstance() 方法,可以选择特定的构造方法。
| 12
 3
 
 | Class clz = pen.class;Constructor constructor = clz.getConstructor();
 Pen pen = (Pen)constructor.newInstance();
 
 | 
反射获取并调用类的构造函数(Constructor)
1.获取所有公有构造函数
| 12
 3
 
 | Constructor[] conArray = clazz.getConstructors();for(Constructor c : conArray)
 
 
 | 
2.获取所有的构造函数(包括:私有、受保护、默认、公有)
| 12
 3
 4
 
 | conArray = clazz.getDeclaredConstructors();for(Constructor c : conArray)
 
 
 
 | 
3.获取公有、无参的构造函数
| 12
 3
 
 | Constructor con = clazz.getConstructor(null);System.out.println("con = " + con);
 Object obj = con.newInstance();
 
 | 
反射获取并调用类的成员方法(Method)
1.反射有参数方法
| 12
 3
 4
 5
 
 | Class a = Class.forName("org.xiaopan.fanshe.Pen");Pen pen =(Pen) a.newInstance();
 public String[] b(String[] b)
 Method m = a.getMethod("b",String[].class);
 String[] strs = (String[]) m.invoke(pen, new Object[]{new String[]{"str1","str2","str3"}});
 
 | 
2.反射无参数方法
| 12
 3
 4
 5
 
 | Class a = Class.forName("org.xiaopan.fanshe.Pen");Pen pen =(Pen) a.newInstance();
 public void a()
 Method m = a.getMethod("a", null);
 m.invoke(pen,null);
 
 | 
3.反射静态方法
| 12
 3
 4
 
 | Class a = Class.forName("org.fanshe.test.Pen");public static void c()
 Method m = a.getMethod("c");
 m.invoke(null);
 
 | 
反射获取类的成员属性&赋值(Field)
1.反射公共属性
通过Class对象的etFields() 方法获取 Class 类的属性。只能获取公有属性。
| 12
 3
 4
 5
 
 | Class clz = Pen.class;Field[] fields = clz.getFields();
 for (Field field : fields) {
 System.out.println(field.getName());
 }
 
 | 
2.反射私有属性
通过Class 对象的 getDeclaredFields() 方法则可以获取包括私有属性在内的所有属性。
| 12
 3
 4
 5
 
 | Class clz = Pen.class;Field[] fields = clz.getDeclaredFields();
 for (Field field : fields) {
 System.out.println(field.getName());
 }
 
 | 
反射调用Runtime,getRuntime执行本地代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | Class runtimeClass1 = Class.forName("java.lang.Runtime");
 
 
 Constructor constructor = runtimeClass1.getDeclaredConstructor();
 constructor.setAccessible(true);
 
 
 Object runtimeInstance = constructor.newInstance();
 
 
 Method runtimeMethod = runtimeClass1.getMethod("exec", String.class);
 
 
 Process process = (Process) runtimeMethod.invoke(runtimeInstance, cmd);
 
 
 InputStream in = process.getInputStream();
 
 
 System.out.println(IOUtils.toString(in, "UTF-8"));
 
 | 
总结
    Java反射机制是Java动态性中最为重要的体现,利用反射机制我们可以轻松的实现Java类的动态调用。Java的大部分框架都是采用了反射机制来实现的(如:Spring MVC、ORM框架等),Java反射在编写漏洞利用代码、代码审计、绕过RASP方法限制等中起到了至关重要的作用。
参考文章
Java代码审计基础之反射 - FreeBuf网络安全行业门户
(4条消息) Java反射详解_潘建南的博客-CSDN博客
Java 反射由浅入深 | 进阶必备 (juejin.cn)
Java反射机制 · 攻击Java Web应用-[Java Web安全] (javasec.org)