제 3 자에 잘못 설계된 수업 JAR
이 있으며 개인 분야 중 하나에 액세스해야 합니다. 예를 들어 왜 개인 필드를 선택해야합니까?
class IWasDesignedPoorly {
private Hashtable stuffIWant;
}
IWasDesignedPoorly obj = ...;
리플렉션을 사용하여 값을 얻으려면 어떻게 stuffIWant
해야합니까?
답변
개인 필드에 액세스하려면 클래스의 선언 된 필드 에서 가져 와서 액세스 할 수 있어야합니다.
Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException
편집 : aperkins 가 댓글을 달았 듯이 필드에 액세스하고 액세스 가능으로 설정하고 값을 검색하면 Exception
s 를 던질 수 있습니다 . 단지 확인 해야 할 예외는 위에 설명되어 있습니다.
는 NoSuchFieldException
당신이 선언 된 필드에 해당하지 않은 이름으로 필드에 대한 요구한다면 던져 질 것이다.
obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException
이 IllegalAccessException
분야에 액세스 할 수없는 있다면 비공개이며, 놓치고를 통해 액세스 가능하지 않은 경우 (예를 들어, 던져 질 것이다 f.setAccessible(true)
선을.
RuntimeException
발생 될 수 있습니다들 중 하나입니다 SecurityException
(JVM의이 경우의 SecurityManager
당신이 필드의 접근성을 변경할 수 없습니다), 또는 IllegalArgumentException
당신이하지 필드의 클래스의 유형의 개체에 액세스에게 필드를 시도하고있는 경우, S :
f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type
답변
FieldUtils
Apache Commons-lang3에서 시도하십시오 .
FieldUtils.readField(object, fieldName, true);
답변
리플렉션 만이 문제를 해결할 수있는 유일한 방법은 아닙니다 (클래스 / 컴포넌트의 개인 기능 / 행동에 액세스하는 것임)
다른 해결책은 .jar에서 클래스를 추출하고 Jode 또는 Jad를 사용하여 디 컴파일 하고 필드를 변경하거나 액세서를 추가 한 다음 원래 .jar에 대해 다시 컴파일하는 것입니다. 그런 다음 새 .class를 .jar
클래스 경로 앞에 놓거나에 다시 삽입하십시오 .jar
. jar 유틸리티를 사용하면 기존 .jar을 추출하고 다시 삽입 할 수 있습니다.
아래에 언급 된 것처럼, 이는 단순히 필드에 액세스 / 변경하는 것이 아니라 개인 상태에 액세스 / 변경하는 더 넓은 문제를 해결합니다.
이것은 필요 .jar
하지 물론, 서명 할 수 있습니다.
답변
아직 언급되지 않은 다른 옵션 : Groovy 사용하십시오 . Groovy를 사용하면 언어 디자인의 부작용으로 프라이빗 인스턴스 변수에 액세스 할 수 있습니다. 현장에 게터가 있든 없든 상관없이
def obj = new IWasDesignedPoorly()
def hashTable = obj.getStuffIWant()
답변
Java 에서 Reflection을 사용하면 private/public
한 클래스의 모든 필드와 메소드를 다른 클래스에 액세스 할 수 있지만 섹션 단점 의 Oracle 문서 에 따라 다음과 같은 권장 사항이 있습니다.
“리플렉션을 사용하면 개인 필드 및 메소드에 액세스하는 것과 같이 비 반사 코드에서 불법적 인 작업을 코드에서 수행 할 수 있으므로 리플렉션을 사용하면 예기치 않은 부작용이 발생하여 코드가 제대로 작동하지 않아 이식성이 떨어질 수 있습니다. “추상화를 중단하고 플랫폼 업그레이드로 동작이 변경 될 수 있습니다.”
다음은 리플렉션의 기본 개념을 보여주는 코드 스냅 샷입니다.
Reflection1.java
public class Reflection1{
private int i = 10;
public void methoda()
{
System.out.println("method1");
}
public void methodb()
{
System.out.println("method2");
}
public void methodc()
{
System.out.println("method3");
}
}
Reflection2.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection2{
public static void main(String ar[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
Method[] mthd = Reflection1.class.getMethods(); // for axis the methods
Field[] fld = Reflection1.class.getDeclaredFields(); // for axis the fields
// Loop for get all the methods in class
for(Method mthd1:mthd)
{
System.out.println("method :"+mthd1.getName());
System.out.println("parametes :"+mthd1.getReturnType());
}
// Loop for get all the Field in class
for(Field fld1:fld)
{
fld1.setAccessible(true);
System.out.println("field :"+fld1.getName());
System.out.println("type :"+fld1.getType());
System.out.println("value :"+fld1.getInt(new Reflaction1()));
}
}
}
그것이 도움이되기를 바랍니다.
답변
oxbow_lakes가 언급했듯이 리플렉션을 사용하여 액세스 제한을 피할 수 있습니다 (SecurityManager에서 허용한다고 가정).
즉,이 클래스가 너무 나쁘게 설계되어 해커에게 의지하게되면 대안을 찾아야 할 것입니다. 이 작은 해킹으로 인해 몇 시간이 절약 될 수 있지만 비용이 얼마나 들까 요?
답변
Soot Java Optimization 프레임 워크를 사용하여 바이트 코드를 직접 수정하십시오.
http://www.sable.mcgill.ca/soot/
그을음은 Java로 완전히 작성되었으며 새로운 Java 버전에서 작동합니다.