[java安全]反射

文章目录

    • [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.mfbz.cn/a/26454.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自动化测试selenium环境搭建

自动化测试工具selenium搭建 1. 自动化和selenium基本概念 1) 什么是自动化?为什么要做自动化&#xff1f; 自动化测试能够代替一部分的手工测试&#xff0c;自动化测试能够提高测试的效率。随着项目功能的增加&#xff0c;版本越来越多&#xff0c;版本的回归测试的压力也…

MySQL架构简介

MySQL是系统架构中最常见的中间件&#xff0c;主要由Server层&#xff08;连接器Connectors、连接池Connection Pool、查询缓存query cache、分析器Parser、优化器Optimizer、执行器、binlog&#xff09;以及存储引擎层组成。 MySQL架构简介 连接器 与客户端建立连接、认证身…

论文笔记:Graph neural networks: A review of methods and applications

1 GNN的设计pipeline 1.1 获取图结构 结构化场景 图结构在应用问题中是已知的 比如分子结构、物理系统非结构化场景 图结构在应用问题中是未知的 需要根据任务人为地建图 1.2 判断图的类型 & 尺寸 图的类型 有向图/无向图//异构图/同构图 图中的点和边类型是不是一样的…

LearnOpenGL-高级OpenGL-8.高级GLSL

本人初学者&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 文章目录 高级GLSLGLSL的内建变量在顶点着色器的内建变量gl_PointSizegl_VertexID 在片段着色器的内建变量gl_FragCoordgl_FrontFacinggl_FragDepth 接口块Uniform缓冲对象Uniform块布局使用Uniform缓冲简…

基于QT的智能家居中控系统的简明设计

文章目录 系统总体说明主板UI设计后续改进与完善 系统总体说明 系统采用 “主从式架构” &#xff0c;即一主多从式&#xff0c;该智能居家控制系统的主要功能包括登录功能、注册功能、音乐播放功能、时间显示、日历显示、温度湿度光照气压海拔数据等环境指标数据显示等。   …

Linux之理解文件系统——文件的管理

文章目录 前言一、磁盘1.磁盘的物理结构2.磁盘的存储结构3.磁盘的逻辑结构 二、文件系统与inode1.文件在磁盘中是如何存储的&#xff1f;2.对文件进行操作 三、软硬链接1.软链接创建软链接&#xff1a;inode删除软链接&#xff1a;软链接的作用&#xff1a; 2.硬链接创建硬链接…

堆(堆排序 模拟堆)

目录 一、堆的数据结构二、堆的操作方法往下调整的示意图往上调整的示意图相关功能的实现思路1.插入一个数2.求最小值3.删除最小值4.删除任意一个元素5.修改任意一个元素 三、堆的实战运用堆排序模拟堆 一、堆的数据结构 堆是一个完全二叉树&#xff1a;除了最后一层结点以外&…

3ds MAX 基本体建模,长方体、圆柱体和球体

3ds MAX基本页面如下&#xff1a; 生成新的几何体在右侧&#xff1a; 选择生成的对象类型即可&#xff0c;以下为例子&#xff1a; 1、长方体建模 选择建立的对象类型为长方形 在 任意一个窗口绘制&#xff0c;鼠标滑动 这里选择左上角的俯视图 松开鼠标后&#xff0c;可以…

第18章 JQuery DataTables初始化渲染显示与排序

1 System.Linq.AsyncIEnumerableExtensions (Data\Extensions\AsyncIEnumerableExtensions.cs) namespace System.Linq { /// <summary> /// 【异步枚举数扩展--类】 /// <remarks> /// 摘要&#xff1a; /// 该类通过对System.Linq.Async中方法的自定义扩展…

C++进阶 —— set

目录 一&#xff0c;set介绍 二&#xff0c;set使用 一&#xff0c;set介绍 set是按照特定次序存储元素的关联式容器&#xff0c;元素不可重复&#xff1b;set中的元素不能在容器中修改(元素总是const)&#xff0c;但是可从容器中插入和删除它们&#xff1b;set中的元素总是按…

【测试报告】个人博客系统自动化测试报告

文章目录 项目背景项目功能测试计划功能测试测试用例执行测试的操作步骤 自动化测试设计的模块、自动化运行的结果、问题定位的结果自动化测试优点 项目背景 对于一个程序员来说&#xff0c;定期整理总结并写博客是不可或缺的步骤&#xff0c;不管是对近期新掌握的技术或者是遇…

代码随想录算法训练营第五十三天 | 力扣 1143.最长公共子序列, 1035.不相交的线, 53. 最大子序和

1143.最长公共子序列 题目 1143. 最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符…

SpringBoot——原理(自动配置+原理分析-源码跟踪)

源码跟踪 从Springboot的启动类进入&#xff0c;进行分析. 源码跟踪技巧 在以后接触各种框架的时候&#xff0c;如果需要查看源码&#xff0c;需要找到关键点和核心流程&#xff0c;先在宏观对整个原理和流程有一个认识&#xff0c;之后再去了解其中的细节。 按住Ctrl左键进…

怎么实现常用网络接口自动化测试框架应用?

一、RESTful&#xff08;resource representational state transfer)类型接口测试 (一&#xff09;GUI界面测试工具&#xff1a;jmeter 1、添加线程组 2、添加http请求 3、为线程组添加察看结果树 4、写入接口参数并运行 5、在查看结果树窗口查看结果 6、多组数据可增加CSVDat…

基于物理信息的神经网络(Physics-informed Neural Networks;PINNs)Part-1(简单介绍)

【摘要】 基于物理信息的神经网络&#xff08;Physics-informed Neural Networks&#xff0c;简称PINNs&#xff09;&#xff0c;是一类用于解决有监督学习任务的神经网络&#xff0c;它不仅能够像传统神经网络一样学习到训练数据样本的分布规律&#xff0c;而且能够学习到数学…

UFS 2 -UFS架构简介2

UFS 2 -UFS架构简介2 1 UFS架构简介1.1 System Boot and Enumeration1.2 UFS Interconnect (UIC) Layer1.2.1 UFS Physical Layer Signals1.2.2 MIPI UniPro1.2.3 MIPI UniPro Related Attributes 1.3 UFS Transport Protocol (UTP) Layer1.3.1 Architectural Model1.3.1.1 Cli…

图解max{X,Y}和min{X,Y}并求相关概率

图解max{X,Y}和min{X,Y}并求相关概率 对max{X,Y}或min{X,Y}进行分解再求解 P ( m a x { X , Y } ≥ c ) P [ ( X ≥ c ) ∪ ( Y ≥ c ) ] P ( m a x { X , Y } ≤ c ) P [ ( X ≤ c ) ∩ ( Y ≤ c ) ] P ( m i n { X , Y } ≥ c ) P [ ( X ≥ c ) ∩ ( Y ≥ c ) ] P ( m i…

k8s功能优势应用场景介绍(一)

一&#xff0c;K8S功能: 1、数据卷 pod中容器之间共享数据&#xff0c;可以使用数据卷 2、应用程序健康检查 容器内服务可能进程阻塞无法处理请求&#xff0c;可以设置监控检查策略保证应用健壮性 3、复制应用程序实例 控制器维护着pod副本数量&#xff0c;保证一个pod或一组同…

C++11 auto类型推导

1.类型推导 C11引入了auto 和 decltype 关键字实现类型推导&#xff0c;通过这两个关键字不仅能方便地获取复杂的类型&#xff0c;而且还能简化书写&#xff0c;提高编码效率。 auto 类型推导的语法和规则 在之前的 C 版本中&#xff0c;auto 关键字用来指明变量的存储类型…

Allure测试报告定制全攻略,优化你的Web自动化测试框架!

目录 前言&#xff1a; 1. Allure测试报告简介 2. Web自动化测试框架简介 3. 封装Web自动化框架 3.1 安装Selenium 3.2 封装Selenium 3.3 定制Allure测试报告 3.3.1 适配翻译插件 3.3.2 定制测试报告样式 4. 示例代码 5. 总结 前言&#xff1a; 随着现在Web应用的普…