sourcecode

Java 리플렉션 - set Accessible(true)의 영향

copyscript 2022. 10. 7. 21:50
반응형

Java 리플렉션 - set Accessible(true)의 영향

주석을 사용하여 클래스의 필드 값을 동적으로 설정합니다.퍼블릭, 프로텍트, 프라이빗을 불문하고 이 작업을 하고 싶기 때문에 저는 콜링입니다.setAccessible(true)[ Field ]오브젝트에서는 항상set()방법.제 질문은 이 시스템이 어떤 영향을 미치는지입니다.setAccessible()필드 자체에 문의할 수 있습니까?

구체적으로는 개인 필드라고 하면, 이 코드 세트입니다.setAccessible(true)코드의 다른 장소에서 리플렉션으로 같은 필드를 취득하는 경우, 이미 필드에 액세스 할 수 있습니까?또는,getDeclaredFields()그리고.getDeclaredField()메서드는 매번 Field 객체의 새 인스턴스를 반환합니까?

질문을 하는 또 다른 방법은 제가 전화를 해서setAccessible(true)작업을 마친 후 원래 값으로 되돌리는 것이 얼마나 중요합니까?

와 함께setAccessible()의 동작을 변경합니다.AccessibleObject(즉,Fieldinstance. 단, 클래스의 실제 필드는 아닙니다.다음은 매뉴얼(발췌)입니다.

의 값true반사된 오브젝트가 Java 언어 액세스컨트롤을 사용할 때 체크하지 않도록 합니다.

실행 가능한 예를 다음에 제시하겠습니다.

public class FieldAccessible {
    public static class MyClass {
        private String theField;
    }

    public static void main(String[] args) throws Exception {
        MyClass myClass = new MyClass();
        Field field1 = myClass.getClass().getDeclaredField("theField");
        field1.setAccessible(true);
        System.out.println(field1.get(myClass)); // no exception
        Field field2 = myClass.getClass().getDeclaredField("theField");
        System.out.println(field2.get(myClass)); // IllegalAccessException
    }

}

getDeclaredField메서드는 매번 새 개체를 반환해야 합니다. 이 개체에 가변 변수가 있기 때문입니다.accessible플래그를 리셋할 필요가 없습니다.자세한 내용은 이 블로그 투고에서 확인할 수 있습니다.

다른 포스터에서 보듯이setAccessible의 해당 인스턴스에만 해당됩니다.java.lang.reflect.Field따라서 접근성을 원래 상태로 되돌릴 필요가 없습니다.

하지만...

전화를 받고 싶은 경우field.setAccessible(true)지속성을 가지려면 기본 방법을 사용해야 합니다.java.lang.Class그리고.java.lang.reflect.Field. 일반 대면 방식에서 복사 파일을 전송합니다.Field예를 들어, 당신이 무언가를 할 때마다 그것은 "감소"됩니다.class.getField(name)

import java.lang.reflect.*;
import sun.reflect.FieldAccessor;

public class Reflect {
    private static Method privateGetDeclaredFields;
    private static Method getFieldAccessor;

    public static Field[] fields(Class<?> clazz) throws Exception {
        return (Field[]) privateGetDeclaredFields.invoke(clazz, false);
    }

    public static <T> T get(Object instance, Field field) throws Exception {
        return ((FieldAccessor) getFieldAccessor.invoke(field, instance)).get(instance);
    }

    public static void set(Object instance, Field field, Object value) throws Exception {
        ((FieldAccessor) getFieldAccessor.invoke(field, instance)).set(instance, value);
    }

    static {
        try {
            // These are used to access the direct Field instances instead of the copies you normally get through #getDeclaredFields.
            privateGetDeclaredFields = Class.class.getDeclaredMethod("privateGetDeclaredFields", boolean.class);
            privateGetDeclaredFields.setAccessible(true);
            getFieldAccessor = Field.class.getDeclaredMethod("getFieldAccessor", Object.class);
            getFieldAccessor.setAccessible(true);
        } catch (Exception e) {
            // Should only occur if the internals change.
            e.printStackTrace();
        }
    }
}

업데이트: 이 구현은 Java 8용이며, 이후 버전에서는 백엔드가 변경되어 이 문제가 해결되었습니다.이 전략을 계속 진행하려면 동일한 개념이 적용됩니다.

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

public class PrivateVariableAcc {

    public static void main(String[] args) throws Exception {
        PrivateVarTest myClass = new PrivateVarTest();
        Field field1 = myClass.getClass().getDeclaredField("a");
        field1.setAccessible(true);
        System.out.println("This is access the private field-"
            + field1.get(myClass));
        Method mm = myClass.getClass().getDeclaredMethod("getA");
        mm.setAccessible(true);
        System.out.println("This is calling the private method-"
            + mm.invoke(myClass, null));
    }

}

언급URL : https://stackoverflow.com/questions/10638826/java-reflection-impact-of-setaccessibletrue

반응형