2017-01-04 2 views
1

클래스에 추가 한 정수 배열 필드에 액세스하기 위해 바이트 코드 도구를 사용하고 싶습니다. 이렇게하려면 클래스 파일에서 필드 색인이 필요하지만 찾을 수 없습니다. 바이트 코드에서 사용하기 위해 Javassist를 사용하여 클래스에서 선언 된 필드의 인덱스를 가져옵니다.

는 대신,보다 상세하게 설명하기 (원하는 인덱스가 나는 로컬 변수 테이블에서 잡고 한 선언 된 지역의 정수이다) :

desired = Server.rand.nextInt(4); 

내가하고 싶은 :

desired = _MyField[Server.rand.nextInt(_MyField.length)]; 
은 JASM에서

가 될 것이라고 : 필드와 Javassist를 사용하여 추가

// field reference to later access an index in the array 
aload <local variable index of "this"> (push reference of class) 
getfield <fieldindex> (pop reference, push field reference to stack) 

// rand is a public static field in class Server 
getstatic java.util.Random com.wurmonline.server.Server.rand 

// field reference to pass to arraylength and the Random.nextInt(int) call 
aload <local variable index of "this"> 
getfield <fieldindex> (push reference of array) 

arraylength (pop reference, push array.length value) 
invokevirtual int java.util.Random.nextInt(int) (pop length for rng, push index) 
iaload (pop index, push integer value from array index) 
istore <index of local variable "desired"> (pop value, store in variable) 

을했다 SB는 StringBuil입니다 필드 이니셜 라이저를 포함하는 der. "새로운 INT [] {N, N, N, N, N};") :

ctClass.addField(
    new CtField(
      HookManager.getInstance().getClassPool().get("[I"), 
      "_OtherServerMissions", 
      ctClass), 
    sb.toString()); 

DirtyJOE, Java8/주요 클래스 파일 버전 (52)와 함께 작동 바이트 코드 편집기를 사용하여 클래스 파일을 보면, 필드에 대한 색인 값을 찾을 수 없습니다. CtField 또는 해당 AttributeInfo를 사용하여 찾을 수도 없습니다.

for (CtField ctField : ctClass.getDeclaredFields()) 

그래서 저는 fieldindex를 어디에서 가져올 지 궁금합니다.

나는 그 문제에 익숙한 가난한 영혼들에 대한 설명이 분명하기를 바란다.

답변

0

때로는 문제를 다른 사람들에게 설명하는 방식으로 문제를 작성하는 데 도움이됩니다.

GETFIELD opcode로 전달 된 FIELDINDEX는 클래스의 상수 풀에 대한 참조입니다. FieldrefInfo를 클래스의 상수 풀에 추가해야합니다. addFieldrefInfo()의 반환 값은 상수 풀의 인덱스입니다.

ConstPool constPool = ctClass.getClassFile().getConstPool(); 

[...] 

sb = new StringBuilder(); 
sb.append("new int[] { "); 
for (int i : _OtherServerMissions) 
    sb.append(String.format("%d,", i)); 
sb.deleteCharAt(sb.lastIndexOf(",")); 
sb.append(" };"); 

ctClass.addField(
     new CtField(
       HookManager.getInstance().getClassPool().get("[I"), 
       "_OtherServerMissions", 
       ctClass), 
     sb.toString()); 

int otherFieldIndex = constPool.addFieldrefInfo(constPool.getThisClassInfo(), "_OtherServerMissions", "[I"); 
logger.log(Level.INFO, "Added OtherFieldIndex as " + otherFieldIndex); 

당신은 또한 (해당하는 경우) GETFIELD를 사용하기 전에 스택에 클래스 인스턴스의 참조를 밀어, "이"의 인덱스를 확인해야합니다.

int thisIndex = -1; 
LocalVariableAttribute lva = (LocalVariableAttribute)generateMission 
    .getMethodInfo() 
    .getCodeAttribute() 
    .getAttribute(LocalVariableAttribute.tag); 

for (int i = 0; thisIndex < 0 && i < lva.tableLength(); i++) { 
    if (lva.variableName(i).equals("this")) 
     thisIndex = lva.index(i); 
} 

로컬 변수 테이블에 이미 없으면이 시점에서 추가하는 방법을 모르겠습니다. 또는 어떻게 일반적으로 로컬 변수 테이블에 정확히 추가 할 것인가. 아는 사람이라면 언제든지 코멘트를 남겨주세요 (충분한 포인트가 있다면, duh ...).

이제 고정 질문에 여기에 설명 된 값과 함께 사용되는 올바른 Java 어셈블리 코드가 포함됩니다.

관련 문제