第34天:安全开发-JavaEE应用&反射机制&攻击链&类对象&成员变量方法&构造方法

Snipaste_2025-06-15_22-18-27

Snipaste_2025-06-15_22-19-09

1. 类加载与 Class 对象

当 Java 程序运行时,每个类都会被 JVM 加载到内存中,并生成一个对应的Class对象(类似于类的 “元数据模板”)。这个Class对象包含了该类的所有信息:字段、方法、构造器等。
类比:就像建筑图纸(Class对象)包含了建筑物(类)的所有设计细节,程序可以通过图纸了解建筑物的结构。

2. 获取 Class 对象的三种方式

程序可以通过以下方式获取Class对象:

  • 类名.classClass<?> clazz = Person.class;
  • 对象.getClass ()Class<?> clazz = personInstance.getClass();
  • 全类名反射Class<?> clazz = Class.forName("com.example.Person");

类比:就像通过建筑物的名字、实际建筑或地址来获取对应的图纸。

3. 通过 Class 对象访问类成员

一旦获得Class对象,就可以获取类的各种成员(字段、方法、构造器)的 “反射对象”:

  • 获取字段Field field = clazz.getField("name");
  • 获取方法Method method = clazz.getMethod("sayHello", String.class);
  • 获取构造器Constructor<?> constructor = clazz.getConstructor(String.class, int.class);

类比:从图纸中找到房间(字段)、电梯(方法)或入口(构造器)的位置。

4. 动态创建对象与调用方法

反射允许在运行时动态创建对象、调用方法或修改字段值:

  • 创建对象Person person = (Person) constructor.newInstance("Alice", 30);
  • 调用方法method.invoke(person, "World");
  • 修改字段field.set(person, "Bob");

类比:根据图纸现场建造建筑物(创建对象),操作电梯(调用方法),或更改房间用途(修改字段)。

5. 反射的应用场景

  • 框架开发:Spring、Hibernate 等框架通过反射实现依赖注入、ORM 映射。
  • JSON 序列化 / 反序列化:Gson、Jackson 通过反射解析对象字段。
  • 插件系统:动态加载外部类或模块。
  • 调试工具:查看对象的内部状态。

6.反射的优缺点

  • 优点:灵活、可扩展,适合框架和工具开发。
  • 缺点:性能开销大(比直接调用慢),破坏封装性(可访问私有成员),可能导致安全风险。

什么是反射,为什么要用到反射

1
参考:https://xz.aliyun.com/t/9117

演示

Java-反射-Class对象类获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1、根据类名:
类名.class
Class userClass = User.class;

2、根据对象:
对象.getClass()
User user = new User();
Class aClass = user.getClass();

3、根据全限定类名:
Class.forName("全路径类名")
Class aClass1 = Class.forName("com.example.reflectdemo.User");

4、通过类加载器获得Class对象:
ClassLoader.getSystemClassLoader().loadClass("全路径类名");
ClassLoader clsload=ClassLoader.getSystemClassLoader();
Class aClass2 = clsload.loadClass("com.example.reflectdemo.User");

新建项目,新建一个User的类

Snipaste_2025-06-15_22-44-52

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example.reflectdemo;

public class User {
//成员变量
public String name="xiaodi";
public int age = 31;
private String gender="man";
protected String job="sec";

//构造方法
public User(){
//System.out.println("无参数");
}

public User(String name){
System.out.println("我的名字"+name);
}

private User(String name,int age){
System.out.println(name);
System.out.println(age);
}

//成员方法
public void userinfo(String name,int age,String gender,String job){
this.job=job;
this.age=age;
this.name = name;
this.gender=gender;
}

protected void users(String name,String gender){
this.name = name;
this.gender=gender;
System.out.println("users成员方法:"+name);
System.out.println("users成员方法:"+gender);
}
}

GetClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.reflectdemo;

public class GetClass {
public static void main(String[] args) throws ClassNotFoundException {
//1、根据全限定类名:Class.forName("全路径类名")
Class aClass = Class.forName("com.example.reflectdemo.User");
System.out.println(aClass);

//2、根据类名:类名.class
Class userClass = User.class;
System.out.println(userClass);

//3、根据对象:对象.getClass()
User user= new User();
Class aClass1 = user.getClass();
System.out.println(aClass1);

//4、通过类加载器获得Class对象://ClassLoader.getSystemClassLoader().loadClass("全路径类名");
ClassLoader clsload=ClassLoader.getSystemClassLoader();
Class aClass2 = clsload.loadClass("com.example.reflectdemo.User");
System.out.println(aClass2);
}
}

Snipaste_2025-06-16_00-19-49

Java-反射-Field成员变量类获取

Snipaste_2025-06-15_22-18-58

Snipaste_2025-06-15_22-19-04

GetFiled

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.example.reflectdemo;

import java.lang.reflect.Field;

public class GetFiled {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class aClass = Class.forName("com.example.reflectdemo.User");

//获取公共的成员变量
Field[] fields = aClass.getFields();
for(Field fd:fields){ //将Fields的值依次给到fd
System.out.println(fd);
}

//获取所有的成员变量
// Field[] fields = aClass.getDeclaredFields();
// for(Field fd:fields){
// System.out.println(fd);
// }


// //获取单个的公共成员变量
// Field name = aClass.getField("name");
// System.out.println(name);
//
// //获取单个的成员变量
// Field gender = aClass.getDeclaredField("gender");
// System.out.println(gender);

//获取公共的成员变量age的值
User u = new User();
Field field=aClass.getField("name");

//取值
Object a=field.get(u);
System.out.println(a);

//赋值
// field.set(u,32);
// Object aa=field.get(u);
// System.out.println(aa);



}
}

获取公共成员变量

Snipaste_2025-06-16_00-45-29

获取所有成员变量

Snipaste_2025-06-16_00-46-30

获取单个的公共成员变量 && 获取单个成员变量

Snipaste_2025-06-16_00-47-46

赋值修改

Snipaste_2025-06-16_00-49-36

Java-反射-Method 成员方法类获取

Snipaste_2025-06-15_22-19-14

GetMethod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.example.reflectdemo;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class GetMethod {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class aClass = Class.forName("com.example.reflectdemo.User");
// //获取包括继承的公共成员方法
Method[] methods = aClass.getMethods();
for(Method me:methods){
System.out.println(me);
}

//获取不包括继承的所有成员方法
// Method[] methods = aClass.getDeclaredMethods();
// for(Method me:methods){
// System.out.println(me);
// }

//获取单个的成员方法
// Method users = aClass.getDeclaredMethod("users", String.class,String.class);
// System.out.println(users);


//对成员方法进行执行
// User u = new User();
// Method users = aClass.getDeclaredMethod("users", String.class,String.class);
// users.invoke(u,"xiaodigay","gay1");


}
}

获取包括继承的公共成员方法

Snipaste_2025-06-16_00-51-58

获取不包括继承的所有成员方法

Snipaste_2025-06-16_00-53-06

获取单个的成员方法

Snipaste_2025-06-16_00-54-05

对成员方法进行执行

Snipaste_2025-06-16_00-54-52

Java-反射-不安全命令执行&反序列化链

GetRunExec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.reflectdemo;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class GetRunExec {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//原生调用 JDK自带的rt.jar
// Runtime.getRuntime().exec("calc");


//如果是第三方的jar包呢
Class aClass = Class.forName("java.lang.Runtime");
//获取所有公共包括继承的成员方法
// Method[] methods = aClass.getMethods();
// for(Method me:methods){
// System.out.println(me);
// }
//获取exec成员方法
Method exec = aClass.getMethod("exec", String.class);
//获取getRuntime成员方法
Method getRuntimeMethod = aClass.getMethod("getRuntime");

Object runtime = getRuntimeMethod.invoke(aClass);
//利用 Java 的反射机制来动态调用getRuntime方法
exec.invoke(runtime, "calc.exe");
//执行

}
}

原生调用

这里有点像,调用java自带的执行系统命令的函数。

Snipaste_2025-06-16_00-56-23

第三方调用

Snipaste_2025-06-16_01-05-31

目录结构:

Snipaste_2025-06-16_01-07-33

java中各种类型的访问修饰符

公共方法(Public Method)

类比:公共方法就像是一个人的 “公开技能”,任何人都可以使用或调用。
特点

  • 可以被类外部的代码访问(如其他类、对象)。
  • 用于暴露类的功能,是类与外部交互的接口。

私有方法(Private Method)

类比:私有方法就像是一个人的 “内部思考过程”,只能在自己的大脑(类内部)使用。
特点

  • 只能在定义它的类内部被调用。
  • 用于封装类的内部实现细节,不对外公开。

保护方法(Protected Method)

类比:保护方法就像是一个家族的 “祖传手艺”,只有家族成员(子类)可以继承和使用。
特点

  • 可以被同一个包内的类访问,也可以被不同包的子类访问。
  • 用于在继承体系中共享功能,但限制外部访问。
访问修饰符 类内部 同一个包 不同包子类 其他类
public
protected
private

一句话总结

  • :定义事物的 “模板”。
  • 公共方法:对外提供的 “公开服务”。
  • 私有方法:内部使用的 “工具函数”。
  • 保护方法:家族内部共享的 “祖传秘方”。