运维开发网

[01][01][04][01] setAccessible方法

运维开发网 https://www.qedev.com 2020-10-17 08:37 出处:51CTO 作者:mb5f8940fa05f66
1. 背景 2. setAccessible方法详解 3. setAccessible方法使用 1. 背景 在测试枚举类型实现单例模式能抵抗反射机制破解的代码中,看constructor.setAccessible(true)代码,不明白其用途 2. setAccessible方法详解 setAccessible并不是在Field中的,而是在AccessibleObject中,A
  • 1. 背景
  • 2. setAccessible方法详解
    • 3. setAccessible方法使用

1. 背景

在测试枚举类型实现单例模式能抵抗反射机制破解的代码中,看constructor.setAccessible(true)代码,不明白其用途

2. setAccessible方法详解

setAccessible并不是在Field中的,而是在AccessibleObject中,AccessibleObject类是Field(字段),Method(方法),Constructor(构造器)类的基类,它提供反射对象绕过Java语言权限控制检查的权限

public static void setAccessible(AccessibleObject[] array, boolean flag)
    throws SecurityException {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
    for (int i = 0; i < array.length; i++) {
        setAccessible0(array[i], flag);
    }
}

public void setAccessible(boolean flag) throws SecurityException {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
    setAccessible0(this, flag);
}

private static void setAccessible0(AccessibleObject obj, boolean flag)
    throws SecurityException
{
    if (obj instanceof Constructor && flag == true) {
        Constructor<?> c = (Constructor<?>)obj;
        if (c.getDeclaringClass() == Class.class) {
            throw new SecurityException("Cannot make a java.lang.Class" +
                                        " constructor accessible");
        }
    }
    obj.override = flag;
}

setAccessible(AccessibleObject[] array, boolean flag)第一个参数array ,就是要设置flag标志位的Field/Method/Constructor对象的数组,第二个参数flag,将array数组的所有Field/Method/Constructor对象设置为flag标识符的新值

3. setAccessible方法使用

在测试了中方别对私有构造方法,私有方法,私有字段设置不检验权限

  • 访问权限类

    @Data
    @AllArgsConstructor

    @NoArgsConstructor

    public class User {

    private Long id;

    private String name;

    private Integer age;

    private Double score;

    private String testMethod(){

    return "abcd";

    }

    }

  • 测试类

    public class SetAccessibleTest {
    public static void main(String[] args) {

    try {

    Class<?> clazz = User.class;

    Constructor constructor = clazz.getDeclaredConstructor(null);

    // 私有构造方法设置不检查权限

    constructor.setAccessible(true);

    User user = (User) constructor.newInstance();

    // 所有私有属性的方法设置不检查权限

    Method[] methods = clazz.getDeclaredMethods();

    AccessibleObject.setAccessible(methods, true);

    // 所有私有属性的字段设置不检查权限

    Field[] fields = clazz.getDeclaredFields();

    AccessibleObject.setAccessible(fields, true);

    fields[0].setLong(user,1L);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

由于JDK的安全检查耗时较多,所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的效果

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号