2014-07-28 5 views
2

나는 ASM와 함께 일하고 있으며 일부 필드 쓰기를 추적하기 위해 클래스 파일을 조작하려고합니다. putfieldputstatic 명령어는 ASM에서 FieldInsnNode 클래스의 인스턴스이며, 런타임시 Field 오브젝트를 생성하고이 Field 오브젝트를 인수로 사용하는 다른 메소드를 호출하는 코드를 주입하려고합니다.ASM에서 putfield 또는 putstatic 명령어의 Field 인스턴스를 가져올 수 있습니까?

나는 간단한 자바 소스 코드를 컴파일하여 몇 가지 실험을했다 : 다음

package com.test.simple; 

public class Simple { 
    public int a,b; 

    public void foo() { 
     a = 20; 
     b = 10; 
    } 
} 

그리고 클래스 파일 검사 javap를 사용 : 여기

$ javap -c -l Simple.class 
Compiled from "Simple.java" 
public class com.test.simple.Simple { 
    public int a; 

    public int b; 

    public com.test.simple.Simple(); 
    Code: 
     0: aload_0  
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return   
    LineNumberTable: 
     line 3: 0 

    public void foo(); 
    Code: 
     0: aload_0  
     1: bipush  20 
     3: putfield  #2     // Field a:I 
     6: aload_0  
     7: bipush  10 
     9: putfield  #3     // Field b:I 
     12: return   
    LineNumberTable: 
     line 7: 0 
     line 8: 6 
     line 9: 12 
} 

내가 putfield의 실제로 다음에 있습니다 찾을 수 있습니다 뭔가 같은 #2, 내가 추측하는 상수 풀에 대한 참조입니다. 그래서 '돈 상수 필드에 대한 모든 세부 사항을 숨기고

그러나, ASM에, FieldInsnNode 단지 (name, 즉 ownerdesc)을 3 개 필드가 (그리고 나는 와일더는 상수 Field의 인스턴스가 실제로 추측이) 내 추측을 익히는 방법을 안다. 여기

내 질문은 : Field 객체는 상수 풀에 거짓말 경우

  • , 어떻게 그것을 검색하고 ASM에 스택에 밀어 수 있습니까?
  • 나는 Field 개체를 찾을 수없는 경우, (공용 생성자가 Field 위해가 없기 때문에) Field의 인스턴스를 인스턴스화 FieldInsnNode.nameFieldInsoNode.owner를 사용 할 수 있다는 것입니다?
  • 위의 모든 작업을 수행 할 수 없다면, 나는 적어도 FieldInsnNode.name을 인쇄 할 수 있으므로 적어도 어느 필드가 명령어 쓰기를하는지 알 수 있습니다. 하지만 모든 문자열도 상수 풀에있는 것처럼 보이므로 런타임시 String을 인스턴스화하는 몇 가지 지침을 어떻게 구축 할 수 있습니까?

답변

2

ldc 명령어를 사용하여 상수 풀에서 피연산자 스택으로 String 상수를로드하기 만하면됩니다. 그러나 당신은 Field s로 그렇게 할 수 없습니다. 가정과는 달리, 상수 풀에는 Field 인스턴스가 없습니다. JVM은 정상 작동을 위해 Reflection을 사용하지 않습니다.

putfield (기타) 명령의 연관된 상수 풀 항목은 간단히 말해서 ASM이 제공 한 정보, 소유자 클래스, 필드 이름 및 유형 서명을 포함하는 설명자를 나타냅니다.

는 이러한 정보로부터 Field 인스턴스가 당신이

ldc owner // a Class instance from constant pool 
ldc name // a String instance from constant pool 
invokevirtual java/lang/Class getDeclaredField (Ljava/lang/String;)Ljava/lang/reflect/Field; // returns the Field 

desc는 단순히 유형에 관계없이 고유 한 이름 필드를 반환 반사 여기에 무시 될 수있다 사용할 수 있습니다 얻으려면.

ASM 라이브러리는 위에서 설명한 명령 시퀀스를 구성하는 방법을 제공합니다.visitFieldInsnString이라는 소유자 클래스에 대해 you have to convert to a Type instance을 전달하기 전에 명령어를 생성하여 인스턴스 대신 해당 Class 인스턴스를 생성하려는 경우 클래스 이름이 포함되어 있음을 유의하십시오. 완성도를 들어


는 컴파일 타임에 필드에 대한 putfield 같은 정수 풀 포장 현장 운영에서 MethodHandle을 얻을 수있는 가능성이 자바 7로 시작하지만, 그 결과 핸들 만 캡슐화 필드를 실현합니다 invoke 메서드를 사용하지만 캡슐화 된 필드의 속성을 검사하지 않습니다. 이는 Java 8 이상에서 예약되었으므로 API method for converting such a MethodHandle to a Field을 소개하지만 Java 5로 시작하는 모든 JVM에서 위의 세 명령 시퀀스보다 간단하지 않습니다.

+0

내 링크는 ASM의 방문자 API를 가리키고 있지만 물론 ASM의 트리 API 동일한 개념을 따르므로 내 대답의 정보가 해당 API에 쉽게 적용될 수 있어야합니다. – Holger