[java安全]反射

news2025/1/11 20:30:10

文章目录

    • [java安全]反射
      • 定义
      • 反射的运用
        • 1、反射获取类对象
          • 1.1、Class.forName()
          • 1.2、Object.class
          • 1.3、obj.getClass()
        • 2、反射获取成员方法
          • 2.1、getMethods()
          • 2.2、getDeclaredMethods()
          • 2.3、getMethod()
          • 2.4、getDeclaredMethod()
        • 3、反射获取构造方法
        • 4、反射创建对象
          • 4.1、通过Constructor创建对象
            • 方法介绍
          • 4.2、通过Class类对象创建对象
        • 5、反射调用成员方法
          • 通过Runtime对象的exec方法去调用计算器
        • 6、反射获取成员变量并使用
          • 6.1、获取成员变量的值
          • 6.2、设置成员变量的值
      • 总结

[java安全]反射

定义

在讲反射之前,我们需要知道什么是反射

运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意属性和方法;
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

简单的说:反射是指在运行时动态地获取一个类的信息,包括其成员变量、方法和构造函数等,以及在运行时对它们进行操作的能力。

使用反射,你可以在编译时期并不知道某个类的具体类型,而在运行时期动态地创建该类的对象、调用该类的方法,或访问和修改该类的属性。这种能力使得Java具有了很高的灵活性和扩展性。

反射就像是一个工具箱,它提供了一系列方法来检查和操作类的信息,包括:

  • 获取一个类的相关信息,如名称、修饰符、继承关系等;
  • 获取一个类的所有成员变量,并可以通过反射的方式修改它们的值;
  • 获取一个类的所有方法,并可以通过反射的方式调用它们;
  • 获取一个类的所有构造函数,并可以通过反射的方式创建它们的实例。
  • (包括私有属性)

反射的运用

1、反射获取类对象

获取类对象主要有以下三种形式:

  • Class.forName()
  • Object.class
  • obj.getClass()

在我们获取了类对象后,我们就可以去使用类对象去获取类中的方法、成员变量、构造方法…了

1.1、Class.forName()

Class.forName(parameter)方法是Class类中的一个静态方法,直接通过Class调用,其中的参数传入一个类的全限定名(包名+类名)

例如:

public class Reflect1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> runtime = Class.forName("java.lang.Runtime");
        System.out.println(runtime);
    }
}

输出:
class java.lang.Runtime

成功创建了一个Runtime的class类

1.2、Object.class

通过类的class属性直接获取类对象:

public class Reflect1 {
    public static void main(String[] args) {
        Class<Runtime> runtime = Runtime.class;
        System.out.println(runtime);
    }
}

输出:
class java.lang.Runtime

此处Runtime类处于 java.lang包下,所以不需要导包

1.3、obj.getClass()
public class Reflect1 {
    public static void main(String[] args)  {
        Runtime runtime = Runtime.getRuntime();
        Class<? extends Runtime> run = (Class<? extends Runtime>) runtime.getClass();
    }
}

首先我们先创建runtime对象,然后调用对象的 getClass() 方法获取类对象

2、反射获取成员方法

  • getMethods()
  • getDeclaredMethods()
  • getMethod(String functionName, Class<?>… parameterTypes)
  • getDeclaredMethod(String functionName, Class<?>… parameterTypes)
2.1、getMethods()

通过class类对象的getMethods()方法可以返回所有public公共成员方法(包括继承的)数组

例如:

import java.lang.reflect.Method;
public class Reflect1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> run = Class.forName("java.lang.Runtime");
        Method[] methods = run.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

image-20230528163233262

其中也包含了非Runtime类的成员方法

2.2、getDeclaredMethods()

通过class类对象的getDeclaredMethods()方法可以返回所有权限的成员方法(包括私有的、不包括继承的)数组

import java.lang.reflect.Method;
public class Reflect1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> run = Class.forName("java.lang.Runtime");
        Method[] methods = run.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

image-20230528163626019

如图,所有方法都是Runtime类的,无继承方法,并且可以获得除public权限外的方法

2.3、getMethod()

返回单个public公共成员方法对象(包括继承)

getMethod(String functionName, Class<?>... parameterTypes)

参数1:代表想要获取的函数名称

参数2~x:代表对应函数声明类型的字节码对象

public class Reflect1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> run = Class.forName("java.lang.Runtime");
        Method method = run.getMethod("equals", Object.class); 
		// 此处equals(Object name)的参数为string类型,所以需要传递Object.class字节码对象
    }
}
2.4、getDeclaredMethod()

返回单个任意权限成员方法对象(包括私有,不包括继承)

getDeclaredMethod(String functionName, Class<?>... parameterTypes)

参数1:代表想要获取的函数名称

参数2~x:代表对应函数声明类型的字节码对象

public class Reflect1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> run = Class.forName("java.lang.Runtime");
        Method method = run.getDeclaredMethod("exec", String.class);

    }
}

3、反射获取构造方法

  • getConstructors()
  • getDeclaredConstructors()
  • getConstructor()
  • getDeclaredConstructor()
方法名说明
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor getConstructor(Class<?>… parameterTypes)返回单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造方法对象

后两个函数的参数都是构造方法的函数声明中形参的字节码文件,与上面类似

4、反射创建对象

4.1、通过Constructor创建对象
方法介绍
  • newInstance() 根据指定的构造方法创建对象
  • setAccessible() 设置为true,表示取消访问检查

我们这里使用getDeclaredConstructor()先获取Runtime类的构造方法,然后使用Constructor对象的newInstance(Object...initargs)方法(括号中传入构造方法所需的值)创建对象

public class Reflect1 {
    public static void main(String[] args) throws Exception {
        Class<?> run = Class.forName("java.lang.Runtime");
        Constructor<?> constructor = run.getDeclaredConstructor();
        Object runtime = constructor.newInstance();
        System.out.println(runtime);
    }
}

但是这里报错了:

image-20230528170640904

我们进Runtime类看一下构造方法的权限:

image-20230528170721782

我们发现Runtime类的构造方法是private修饰的,私有的

在反射中被private修饰的不能直接使用,需要使用setAccessible(true)取消访问检查,暴力反射

因此,我们在创建对象之前,先使用setAccessible(true)取消访问检查,然后创建对象

public class Reflect1 {
    public static void main(String[] args) throws Exception {
        Class<?> run = Class.forName("java.lang.Runtime");
        Constructor<?> constructor = run.getDeclaredConstructor();
        constructor.setAccessible(true);
        Object runtime = constructor.newInstance();
        System.out.println(runtime);
    }
}

image-20230528172256663

成功创建对象

4.2、通过Class类对象创建对象

在Class类对象中可以直接调用newInstance() 方法调用无参构造方法创建一个空参对象

但是这里不能调用setAccessible()方法访问private修饰的构造方法

因此,如果我们使用这种方法创建Runtime对象就会失败:

image-20230528173022759

但是我们可以使用Class类对象的newInstance()方法创建构造方法不为private的对象

public class Reflect1 {
    public static void main(String[] args) throws Exception {
        Class<?> run = Class.forName("java.lang.String");
        Object runtime = run.newInstance();
    }
}

5、反射调用成员方法

  • 方法介绍

    方法名说明
    Object invoke(Object obj, Object… args)运行方法

    参数一: 用obj对象调用该方法

    参数二: 调用方法的传递的参数(如果没有就不写)

    返回值: 方法的返回值(如果没有就不写)

在我们获取到Method对象后,我们就可以使用Method对象的 invoke()方法去调用函数了

通过Runtime对象的exec方法去调用计算器

首先我们创建Runtime的Class类,然后获取构造方法创建Runtime对象、获取exec方法,最后调用exec方法

public class Reflect1 {
    public static void main(String[] args) throws Exception {
        Class<?> run = Class.forName("java.lang.Runtime");
        Constructor<?> constructor = run.getDeclaredConstructor();
        //注意需要取消访问检查,因为Runtime的构造方法是私有的
        constructor.setAccessible(true); 
        Object runtime = constructor.newInstance();
        Method exec = run.getMethod("exec", String.class);
        exec.invoke(runtime,"C:\\Windows\\System32\\calc.exe");
    }
}

成功弹出计算器,getshell

image-20230528174206005

6、反射获取成员变量并使用

方法分类

方法名说明
Field[] getFields()返回所有public公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象

用法和上面类似,参数名就是变量的名字。getField()getFields() 都可以获取继承的属性

6.1、获取成员变量的值
  • get()
class Student extends Teacher {
    public String name = "stu";
}

public class Reflect1 {
    public static void main(String[] args) throws Exception {
        Class<?> stu = Class.forName("com.leekos.Student");
        Object newInstance = stu.newInstance();
        Field name = stu.getDeclaredField("name");
        System.out.println(name.get(newInstance));
    }
}

输出:
stu
6.2、设置成员变量的值
  • set()
public class Reflect1 {
    public static void main(String[] args) throws Exception {
        Class<?> stu = Class.forName("com.leekos.Student");
        Object newInstance = stu.newInstance();
        Field name = stu.getDeclaredField("name");
        name.set(newInstance,"666");
        System.out.println(name.get(newInstance));
    }
}

输出:
666

总结

反射常用的方法

  • 获取类的⽅法: Class.forName()
  • 实例化类对象的⽅法: newInstance()
  • 获取函数的⽅法: getMethod()
  • 执⾏函数的⽅法: invoke()
  • 限制突破方法:setAccessible()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/580091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

复习之Linux系统中的用户管理

1.用户及用户组的意义 在Linux中&#xff0c;用户&#xff08;User&#xff09;和用户组&#xff08;Group&#xff09;是管理系统权限和资源访问的重要概念。 &#xff08;1&#xff09;用户 用户是指系统中的一个身份标识&#xff0c;每个用户都有自己的用户名和密码。每个…

chatgpt赋能python:Python编程炒股软件:优秀的股票市场分析工具

Python 编程炒股软件&#xff1a;优秀的股票市场分析工具 Python 编程语言一直以来在数据分析和科学计算领域处于领先地位。由于它强大的数据处理能力和易于使用的编程语言特性&#xff0c;Python成为了许多股票市场分析工具的首选。 现在&#xff0c;越来越多的投资者使用Py…

RocketMQ 学习教程——(二)SpringBoot 集成 RocketMQ

文章目录 添加 RocketMQ 依赖消费者 ConsumerYAML 配置创建监听器消息过滤Tag 过滤 生产者 ProducerYAML 配置发送同步消息发送异步消息发送单向消息发送延迟消息发送顺序消息发送批量消息发送集合消息 添加 RocketMQ 依赖 在 Maven 仓库【https://mvnrepository.com/】中搜索 …

Latex在同一figure中排版多张图片的方法

Latex在同一figure中排版多张图片的方法 主要使用了minipage&#xff08;子图&#xff09;语法。minipage可以嵌套&#xff0c;子图还可以分解为更多子图&#xff0c;功能很好玩&#xff0c;无聊可以自己试试。下面介绍几种常用效果的实现方法。 并排显示两张图&#xff0c;并…

StarRocks 中的数据模型和索引使用

一、StarRocks 数据模型 StarRocks 支持四种数据模型&#xff0c;分别是明细模型 (Duplicate Key Model)、聚合模型 (Aggregate Key Model)、更新模型 (Unique Key Model) 和主键模型 (Primary Key Model)。 1.1 明细模型 明细模型是默认的建表模型。如果在建表时未指定任何…

chatgpt赋能python:Python自动截屏教程

Python 自动截屏教程 介绍 Python 是一种高级程序设计语言&#xff0c;已广泛用于各种应用中&#xff0c;从 Web 开发到机器学习都有很多案例。其中&#xff0c;Python 的截屏功能得到了越来越多的关注&#xff0c;因为在很多应用场景中&#xff0c;自动截屏可以帮助我们更有…

【JVM】11. 垃圾回收及回收算法算法

文章目录 11.1. 垃圾回收概述11.1.1. 什么是垃圾&#xff1f;什么是垃圾&#xff1f; 11.1.2. 为什么需要GC11.1.3. 早期垃圾回收11.1.4. Java垃圾回收机制担忧GC主要关注的区域 11.2. 垃圾回收相关算法11.2.1. 标记阶段&#xff1a;引用计数算法方式一&#xff1a;引用计数算法…

C++数据结构:散列表简单实现(hash表)

文章目录 前言一、设计思想二、实现步骤1、定义节点2、定义Hash表类 三、数据示例总结 前言 散列表是一种常用的数据结构&#xff0c;它可以快速地存储和查找数据。散列表的基本思想是&#xff0c;将数据的关键字映射到一个有限的地址空间中&#xff0c;然后在该地址空间中存储…

Nacos源码-从Demo出发研究事件驱动与观察者模式的应用

在我们分析 Nacos 源码时&#xff0c;会看见大量的事件发布的动作&#xff0c;不管是客户端注册/下线、服务改变、服务订阅等等都是利用了事件发布。 下面我在自己的项目中&#xff0c;引入Nacos的依赖进行一个简单的demo的演示&#xff0c;我个人认为其和spring容器的listene…

Koa学习1:初始化项目

前言 作为前端开发者&#xff0c;最适合我们的后端就是node了&#xff0c;node的框架挺多的。选择Koa是因为国内用的挺多的、关于这方面的教程也很多、而且比较适合小项目。 学习教程是&#xff1a;【杰哥课堂】-项目实战-NodeKoa2从零搭建通用API服务 写这些文章&#xff0…

K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods

K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods 你已了解Pod以及如何通过ReplicaSets等资源部署它们以确保持续运行。虽然某些Pod可以独立完成工作&#xff0c;但现今许多应用程序需要响应外部请求。例如&#xff0c;在微服务的情况…

在Python中载入大量图片型数据集,与matlab结合使用时,如何解决RAM的占用爆炸性增长的问题

在Python中载入大量图片时&#xff0c;由于每张图片都会被转换成Numpy数组并存储在内存中&#xff0c;因此可能会导致RAM的占用爆炸性增长。为了减少RAM的使用&#xff0c;可以考虑采用以下方法&#xff1a; Python和Matlab结合使用。首先&#xff0c;可以使用Python的Pillow库…

【Linux】遇事不决,可先点灯,LED驱动的进化之路---1

【Linux】遇事不决&#xff0c;可先点灯&#xff0c;LED驱动的进化之路---1 前言&#xff1a; 一、最简单的LED驱动程序 1.1 字符设备驱动程序框架 1.2 程序实战 1.2.1 驱动程序&#xff08;led_drive_simple.c&#xff09; 1.2.2 应用程序&#xff08;led_test_simple.c…

C#,码海拾贝(25)——求解“三对角线方程组”的“追赶法”之C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static partial class LEquations { /// <summary> /…

Apache Kafka - 理解Kafka内部原理

文章目录 Kafka的实现机制1. 集群成员关系&#xff1a;2. 控制器*&#xff1a;3. Kafka的复制&#xff1a;4. 请求处理&#xff1a;5. 物理存储&#xff1a; 导图 Kafka的实现机制 作为Kafka专家&#xff0c;我很高兴为您深入解释Kafka的实现机制。我将从以下几个方面对Kafka进…

ARM体系结构与异常处理

目录 一、ARM体系架构 1、ARM公司概述 ARM的含义 ARM公司 2.ARM产品系列 3.指令、指令集 指令 指令集 ARM指令集 ARM指令集 Thumb指令集 &#xff08;属于ARM指令集&#xff09; 4.编译原理 5.ARM数据类型 字节序 大端对齐 小端对齐 …

VTK安装和运行

创建日期: 2019-04-02 09:19:00 开始 学习资源 官方网站&#xff1a;https://vtk.org/ GitHub&#xff1a;https://github.com/Kitware/VTK 官方教程&#xff1a;https://vtk.org/Wiki/VTK/Tutorials 官方文档&#xff1a;https://vtk.org/documentation/ 用户手册&#…

RocketMQ 学习教程——(一)安装 RocketMQ

文章目录 RocketMQ 安装下载安装上传服务器配置环境变量修改 runserver.sh修改 runbroker.sh修改 broker.conf启动 安装 RocketMQ 控制台安装Linux 防火墙命令 Docker 安装 RocketMQ拉取镜像启动 NameServer 服务启动 Broker 服务启动控制台 RocketMQ 官网&#xff1a; http://…

​【编写UI自动化测试集】Appium+Python+Unittest+HTMLRunner​

简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以python文件模式执行脚本生成测试报告 下载与安装 下载需要自动化测试的App并安装到手机 获取AppPackage和AppActivity 方法一 有源码的…

算法11.从暴力递归到动态规划4

算法|11.从暴力递归到动态规划4 1.最长公共子序列 题意&#xff1a;给定两个字符串str1和str2&#xff0c;返回这两个字符串的最长公共子序列长度 比如 &#xff1a; str1 “a12b3c456d”,str2 “1ef23ghi4j56k” 最长公共子序列是“123456”&#xff0c;所以返回长度6 解…