记录学习Java反射

admin 2024年8月29日22:40:37评论16 views字数 8630阅读28分46秒阅读模式

本篇文章记录学习Java反射 。 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性

获取Class类

根据类名:类名.class根据对象:对象.getClass()根据全限定类名:Class.forName(全限定类名)

package 反射;  import java.lang.reflect.InvocationTargetException;  public class demo {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {          Test test = new Test();          System.out.println(test);          // .class根据类名 获取class对象          Class s = Test.class;          System.out.println(s);          // .getClass 根据对象,获取class对象          Class s1 = new Test().getClass();          System.out.println(s1);          // .forName          Class s2 = Class.forName("反射.Test");          System.out.println(s2);      }  }

记录学习Java反射

获取Class类中的构造方法 getConstructor

获取Constructor对象是通过Class类中的方法获取的,Class类与Constructor相关的主要方法如下:

方法名称 方法说明
forName(String ClassName) 返回与带有给定字符串名的类或接口相关联的 Class 对象。
getConstructor(Class<>.. parameterTypes) 返回指定参数类型、具有public访问权限的构造函数对象
getConstructors() 返回所有具有public访问权限的构造函数的Constructor对象数组
getDeclaredConstructor(Class<>.. parameterTypes) 返回指定参数类型、所有声明的(包括private)构造函数对象
getDeclaredConstructors() 返回所有声明的(包括private)构造函数对象
newInstance() 调用无参构造器创建此 Class 对象所表示的类的一个新实例。

获取一个无参的构造方法

在Test 类中设置了,无参的构造方法

package 反射;  public class Test {      // 定义成员变量      public String name="xiaomi";      public int age = 18;      public Test(){      }  //    public Test(String name){  //        this.name = name;  //    }      public String getName() {          return name;      }      public void setName(String name) {          this.name = name;      }      public int getAge() {          return age;      }      public void setAge(int age) {          this.age = age;      }  }
package 反射;  import java.lang.reflect.InvocationTargetException;  import java.lang.reflect.Method;  public class demo {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {          try {              //  .forName 根据全限名称获取class对象              Class<?> clazz = Class.forName("反射.Test");              // 获取一个无参的构造方法             Object instance = clazz.getConstructor().newInstance();              System.out.println("构造方法的类:"+clazz.getName());          } catch (Exception e) {              e.printStackTrace();          }      }  }

获取一个有参的构造方法

Test类中构造方法,接收了一个String类型的变量

public Test(String name){      this.name = name;  }

在getConstructor 中要定义一个 String.class

package 反射;  import java.lang.reflect.InvocationTargetException;  import java.lang.reflect.Method;  public class demo {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {          try {              //  .forName 根据全限名称获取class对象              Class<?> clazz = Class.forName("反射.Test");              // getConstructor 获取构造方法              Object instance = clazz.getConstructor(String.class).newInstance("我是构造方法");              String name = (String) clazz.getMethod("getName").invoke(instance);              System.out.println(name);          } catch (Exception e) {              e.printStackTrace();          }      }  }

记录学习Java反射

获取Class类中的私有 (private) 构造方法 getDeclaredConstructor

示例

package 反射;  public class Test2 {      // 定义成员变量      public String name="xiaomi";      public int age = 18;      private Test2(){      }      public String getName() {          return name;      }      public void setName(String name) {          this.name = name;      }      public int getAge() {          return age;      }      public void setAge(int age) {          this.age = age;      }  }
package 反射;  import java.lang.reflect.Constructor;  import java.lang.reflect.InvocationTargetException;  public class demo2 {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {          try {              Class<?> clazz = Class.forName("反射.Test2");              Constructor<?> constructor = clazz.getDeclaredConstructor();              constructor.setAccessible(true);              Object ins = constructor.newInstance();              String name = (String) clazz.getMethod("getName").invoke(ins);              System.out.println(name);          }catch (Exception e){              e.printStackTrace();          }      }  }

记录学习Java反射

获取class类中 Method 方法

下面是Class类获取Method对象相关的方法:

方法名称 方法说明
getDeclaredMethod() 返回一个指定参数的Method对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。public private
getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
getMethod() 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。public
getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

例如:我需要获取Test类中的getName方法

package 反射;  import java.lang.reflect.InvocationTargetException;  import java.lang.reflect.Method;  public class demo {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {          try {              //  .forName 根据全限名称获取class对象              Class<?> clazz = Class.forName("反射.Test");              // getConstructor 获取构造方法              Object instance = clazz.getConstructor(String.class).newInstance("name 是 getName ");              String name = (String) clazz.getMethod("getName").invoke(instance);              System.out.println(name);          } catch (Exception e) {              e.printStackTrace();          }      }  }

记录学习Java反射

获取class类中的FieId

Class类与Field对象相关方法如下:

方法返回值 方法名称 方法说明
Field getDeclaredField(String name) 获取指定name名称的(包含private修饰的)字段,不包括继承的字段
Field[] getDeclaredFields() 获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段
Field getField(String name) 获取指定name名称、具有public修饰的字段,包含继承字段
Field[] getFields() 获取修饰符为public的字段,包含继承字段
package 反射;  import java.lang.reflect.Field;  public class demoFieId {      public static void main(String[] args) {          try {              Class<?> clazz = Class.forName("反射.Test2");              Test2 st= (Test2) clazz.newInstance();              Field name = clazz.getField("name");              // 修改name的值              name.set(st,"wdd");              System.out.println(st.name.toString());          }catch (Exception e){              e.printStackTrace();          }      }  }

记录学习Java反射

使用反射系统执行命令类

获取类的⽅法: forName 实例化类对象的⽅法: newInstance 获取函数的⽅法: getMethod 执⾏函数的⽅法: invoke

getMethod 系列方法获取的是当前类中所有公共方法,包括从父类继承的方法 getDeclaredMethod 系列方法获取的是当前类中“声明”的方法,是实在写在这个类里的,包括私有的方法,但从父类里继承来的就不包含了

invoke 的作用是执行方法,它的第一个参数是:
如果这个方法是一个普通方法,那么第一个参数是类对象
如果这个方法是一个静态方法,那么第一个参数是类

创建恶意的类,用来演示forName 反射加载类

创建执行弹出计算器的类

package reflex.test;  public class calc {      static {          try {              Runtime rt = Runtime.getRuntime();              String[] commands = {"calc.exe"};              Process pc = rt.exec(commands);              pc.waitFor();          } catch (Exception e) {              // do nothing          }      }  }

通过Class.forName 反射加载恶意类,实现命令执行

package reflex.test;  import java.lang.reflect.InvocationTargetException;  public class demo1 {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {          Class clazz = Class.forName("reflex.test.calc"); //通过forName 反射通用calc恶意类      }  }

java.lang.Runtime

单列模式 getRuntime

Runtime类就是单例模式,我们只能通过 Runtime.getRuntime() 来获取到 Runtime 对象。

package 反射;  import java.lang.reflect.Constructor;  import java.lang.reflect.InvocationTargetException;  public class cmd {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {         try{          // java.lang.Runtime          // 使用反射 java.lang.Runtime 执行calc          Class<?> clazz = Class.forName("java.lang.Runtime");         clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz),"calc");         }catch (Exception e){              e.printStackTrace();          }      }  }

记录学习Java反射

private 私有Runtime

package 反射;  import java.lang.reflect.Constructor;  import java.lang.reflect.InvocationTargetException;  public class cmd {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {         try{             Class<?> clazz = Class.forName("java.lang.Runtime");             Constructor<?> m = clazz.getDeclaredConstructor();             m.setAccessible(true);             clazz.getMethod("exec", String.class).invoke(m.newInstance(),"calc");         }catch (Exception e){              e.printStackTrace();          }      }  }

记录学习Java反射

java.lang.ProcessBuilder

ProcessBuilder有两个构造函数

public ProcessBuilder(List<String> command) {      if (command == null)          throw new NullPointerException();      this.command = command;  }  /**   * Constructs a process builder with the specified operating * system program and arguments.  This is a convenience * constructor that sets the process builder's command to a string * list containing the same strings as the {@code command} * array, in the same order.  It is not checked whether * {@code command} corresponds to a valid operating system * command. * * @param command a string array containing the program and its arguments   */public ProcessBuilder(String... command) {      this.command = new ArrayList<>(command.length);      for (String arg : command)          this.command.add(arg);  }

正常调用 ProcessBuilder

ProcessBuilder p = new ProcessBuilder();  p.command("calc").start();

反射调用 ProcessBuilder

ProcessBuilder List.class

package reflex.test;  import java.io.IOException;  import java.lang.reflect.InvocationTargetException;  import java.util.Arrays;  import java.util.List;  public class demo4 {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {          Class classz = Class.forName("java.lang.ProcessBuilder");          classz.getMethod("start").invoke(classz.getConstructor(List.class).newInstance(Arrays.asList("calc.exe")));      }  }

记录学习Java反射

ProcessBuilder String[].class

package 反射;  import java.lang.reflect.Constructor;  import java.lang.reflect.InvocationTargetException;  public class demo3 {      public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {          try{              Class<?> clazz = Class.forName("java.lang.ProcessBuilder");              clazz.getMethod("start").invoke(clazz.getConstructor(String[].class).newInstance(new String[][]{{"calc.exe"}}));          }catch (Exception e){              e.printStackTrace();          }      }  }

记录学习Java反射

原文始发于微信公众号(安全逐梦人):记录学习Java反射

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年8月29日22:40:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记录学习Java反射https://cn-sec.com/archives/3108959.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息