ASM 소스 코드 학습 의 ClassReader,ClassVisitor 와 ClassWriter 상세 설명
ASM 은 자바 에서 비교적 유행 하 는 바이트 코드 를 읽 는 라 이브 러 리 로 바이트 코드 를 바탕 으로 코드 를 분석 하고 변환 하 는 데 사용 된다.읽 기와 쓰기 과정 에서 CGLIB 와 같은 컴 파일 된 바이트 코드 를 강화 하거나 수정 하기 위해 사용자 정의 논 리 를 추가 할 수 있 습 니 다.ASM 은 실행 할 때 자바 류 를 생 성하 고 변환 하 는 데 사용 되 며 오프라인 처리 도 포함 된다.ASM 은 짧 고 간결 하 며 속도 가 빠 르 기 때문에 실행 할 때 동적 으로 바이트 코드 를 생 성하 거나 변환 할 때 프로그램 속도 에 미 치 는 영향 을 피 할 수 있 으 며 부피 가 작 기 때문에 많은 메모리 가 제 한 된 환경 에서 사용 할 수 있다.
ASM 의 주요 장점 은 다음 과 같은 몇 가지 측면 을 포함한다.
1.또 하 나 는 작 지만 디자인 이 좋 고 모듈 화 된 API 이 며 사용 하기 쉽다.
2.좋 은 문 서 를 가지 고 있 으 며 eclipse 플러그 인 도 있 습 니 다.
3.최신 자바 버 전 을 지원 합 니 다.
4.짧 고 날렵 하 며 빠 르 고 건장 하 다.
5.새로운 사용자 에 게 지원 할 수 있 는 또 하나의 커 다란 사용자 커 뮤 니 티 입 니 다.
6.오픈 소스 허 가 는 거의 모든 방식 으로 사용 할 수 있 습 니 다.
ASM 에 대한 상세 한 소 개 는 참고 할 수 있 습 니 다.자바 바이트 프레임 ASM 깊이 있 는 학습
ASM 코어 디자인 일람
ASM 의 핵심 실현 에서 다음 과 같은 몇 가지 종류,인터페이스
org.objectweb.asm
가 있다.ClassReader 클래스:바이트 코드 의 읽 기와 분석 엔진.이 는 SAX 와 유사 한 이벤트 읽 기 메커니즘 을 사용 하여 이벤트 가 발생 할 때마다 등 록 된 ClassVisitor,AnnotationVisitor,FieldVisitor,MethodVisitor 를 호출 하여 해당 하 는 처 리 를 한다.
ClassVisitor 인터페이스:클래스 바이트 코드 를 읽 을 때 발생 하 는 이 벤트 를 정의 합 니 다.예 를 들 어 클래스 헤더 해석 완료,주해 해석,필드 해석,방법 해석 등 입 니 다.
AnnotationVisitor 인터페이스:주 해 를 해석 할 때 발생 하 는 이 벤트 를 정의 합 니 다.예 를 들 어 기본 값 형식의 주해,enum 값 형식의 주해,Array 값 형식의 주해,주해 값 유형의 주해 등 입 니 다.
FieldVisitor 인터페이스:필드 에 있 는 주 해 를 분석 하고 필드 와 관련 된 속성 을 분석 하 는 등 필드 를 분석 할 때 발생 하 는 이 벤트 를 정의 합 니 다.
MethodVisitor 인터페이스:방법 상의 주석,속성,코드 등 을 분석 할 때 발생 하 는 사건 을 정의 합 니 다.
ClassWriter 클래스:ClassVisitor 인 터 페 이 스 를 실현 하여 바이트 코드 를 맞 추 는 데 사용 합 니 다.
AnnotationWriter 클래스:AnnotationVisitor 인 터 페 이 스 를 실현 하여 관련 바이트 코드 를 맞 추 는 데 사용 합 니 다.
FieldWriter 클래스:필드 와 관련 된 바이트 코드 를 연결 하 는 데 사용 되 는 FieldVisitor 인 터 페 이 스 를 실현 합 니 다.
MethodWriter 클래스:MethodVisitor 인 터 페 이 스 를 실현 하여 연결 방법 과 관련 된 바이트 코드 를 사용 합 니 다.
SignatureReader 클래스:클래스 정의,필드 정의,방법 정의,로 컬 변수 정의 서명 에 대한 분석.Signature 는 범례 가 도입 되 어 범례 정 의 를 저장 할 때 메타 데 이 터 를 저장 합 니 다(이 메타 데 이 터 는 실행 할 때 지 워 지기 때 문 입 니 다).
SignatureVisitor 인터페이스:Signature 를 분석 할 때 발생 하 는 이벤트,예 를 들 어 정상 적 인 Type 파라미터,클래스 또는 인터페이스의 경계 등 을 정의 합 니 다.
SignatureWriter 클래스:SignatureVisitor 인 터 페 이 스 를 실현 하여 범례 와 관련 된 바이트 코드 를 맞 추 는 데 사용 합 니 다.
Attribute 클래스:바이트 코드 의 속성 클래스 추상.
ByteVector 클래스:바이트 바 이 너 리 저장 용기.
Opcodes 인터페이스:바이트 코드 명령 의 상수 정의
Type 클래스:유형 과 관련 된 상수 정의 및 그 에 기반 한 작업.
그들 사이 의 도표 관 계 는 다음 과 같다.
ClassReader 는 ASM 에서 가장 핵심 적 인 실현 으로 Class 바이트 코드 를 읽 고 해석 하 는 데 사 용 됩 니 다.
ClassReader 인 스 턴 스 를 구축 할 때 먼저 바이트 코드 바 이 너 리 배열 b 를 저장 한 다음 에 items 배열 을 만 듭 니 다.배열 의 길 이 는 바이트 배열 의 8,9 번 째 바이트 에서 지정 합 니 다.각 아 이 템 은 상수 탱크 항목 이 바이트 코드 배열 의 오프셋 에 1 을 추가 하 는 것 을 나타 낸다.FieldRef_Info、CONSTANT_MethodRef_Info、CONSTANT_InterfaceMethodRef_Info、CONSTANT_NameAndType_Info 는 그 유형의 바이트 가 5 개의 바이트 를 차지 하 는 것 을 포함 하고,다른 4 개의 바이트 가 2 개의 바이트 마다 필드,방법 등 이 있 는 클래스,그 이름,설명 자 는 현재 상수 탱크 에서 CONSTANTUtf8_Info 형식의 참조;CONSTANT_Integer_Info、CONSTANT_Float_Info 는 그 유형의 바이트 가 5 개의 바이트 를 차지 하고 다른 4 개의 바이트 가 대응 하 는 값 을 포함한다.CONSTANT_Class_Info、CONSTANT_String_Info 는 그 유형의 바이트 가 3 개의 바 이 트 를 차지 하 는 것 을 포함 하고,다른 두 바 이 트 는 현재 상수 탱크 인 CONSTANT 입 니 다.Utf8_Info 항목 의 색인;CONSTANT_Utf8_Info 형식 첫 번 째 바이트 표시 형식,두 번 째,세 번 째 바이트 가 이 항목 에 표 시 된 문자열 의 길이);CONSTANT_Double_Info、CONSTANT_Long_Info 에 형식 바이트 9 글자 추가 하기;maxStringLength 는 가장 긴 UTF 8 유형의 상수 탱크 항목 의 값 을 표시 합 니 다.CONSTANT 를 분석 하기 로 결정 합 니 다.Utf8_Info 형식 항목 에 가장 필요 한 문자 배열;header 는 상수 탱크 뒤의 바이트 번 호 를 나타 내 는 첫 번 째 바이트 입 니 다.
ClassReader 의 accept 방법 을 호출 할 때 바이트 코드 의 상수 풀 뒤의 모든 요 소 를 분석 합 니 다.상수 탱크 에 이 어 2 개의 바이트 가 이러한 access 태그 입 니 다:ACCPUBLIC、ACC_FINAL 등;이후 2 개의 바 이 트 는 현재 클래스 이름 이 상수 탱크 에서 CONSTANTUtf8_Info 형식의 색인;이후 2 개의 바이트 가 아버지 클래스 의 이름 으로 상수 지 CONSTANTUtf8_Info 형식의 색인(색인 값 0 은 부모 클래스 를 null 로 표시 합 니 다.즉,Object 클래스 에서 직접 계승 합 니 다).그 다음 에 이 루어 진 인터페이스 수의 길이 와 대응 하 는 각 인터페이스 이름 은 상수 탱크 에서 CONSTANTUtf8_Info 형식의 색인 값;Field 와 Method 정의 정 보 를 잠시 건 너 뛰 고 클래스 의 attribute 표를 해석 합 니 다.attribute 배열 의 길 이 를 두 바이트 로 표현 합 니 다.각 attribute 항목 의 맨 앞 에 있 는 두 바이트 는 attribute 이름 입 니 다.SourceFile(sourceFile 값 읽 기),InnerClasses(시작 색인 을 일시 적 으로 기록),Enclosing Method(현재 익명 클래스 기록,로 컬 클래스 는 클래스 이름과 포 함 된 방법 명 과 설명자),Signature(클래스 의 서명 정보,범례 에 사용),Runtime VisibleAnnotations(일시 적 으로 시작 색인 기록),Deprecated(속성 표시),Synthetic(표지 속성),SourceDebugExtension(디 버 거 에 제공 하 는 사용자 정의 확장 정 보 를 문자열 로 읽 습 니 다),Runtime Invisible Annotations(시작 색인 을 일시 적 으로 기록 합 니 다)는 다른 인식 되 지 않 는 속성 에 대해 Attribute 체인 으로 기록 합 니 다.attribute 이름 이 accept 에서 attribute 배열 에서 지정 한 attribute 이름 에 부합 되면 들 어 오 는 attribute 배열 에 대응 하 는 항목 을 교체 합 니 다.분 석 된 정보 에 따라 다음 visit 방법 을 호출 합 니 다.
void visit(int version, int access, String name, String signature, String superName, String[] interfaces);
// sourceFile, sourceDebug
void visitSource(String source, String debug);
// EnclosingMethod attribute: enclosingOwner, enclosingName, enclosingDesc.
// Note: only when the class has EnclosingMethod attribute, meaning the class is a local class or an anonymous class
void visitOuterClass(String owner, String name, String desc);
Runtime Visible Annotations 와 Runtime Invisible Annotations 속성 을 순서대로 분석 합 니 다.먼저 정 의 된 Annotation 의 설명자 와 실행 할 때 보 이 는 flag 를 분석 하고 사용자 정의 AnnotationVisitor 를 되 돌려 줍 니 다.
AnnotationVisitor visitAnnotation(String desc, boolean visible);
각 정 의 된 Annotation 에 대해 키 쌍 을 분석 하고 서로 다른 Annotation 필드 값 에 따라 Annotation Visitor 의 방법 을 호출 합 니 다.모든 해석 이 끝 난 후에 호출AnnotationVisitor.visitEnd
방법:
public interface AnnotationVisitor {
// , ,visitArray 。
void visit(String name, Object value);
void visitEnum(String name, String desc, String value);
AnnotationVisitor visitAnnotation(String name, String desc);
AnnotationVisitor visitArray(String name);
void visitEnd();
}
이전에 분 석 된 attribute 링크(표준 이 아 닌 Attribute 정의)는 모든 Attribute 인 스 턴 스 에 대해 ClassVisitor 의 visitAttribute 방법 을 호출 합 니 다.
void visitAttribute(Attribute attr);
Attribute 클래스 는 type 필드 와 바이트 배열 을 포함 합 니 다.
public class Attribute {
public final String type;
byte[] value;
Attribute next;
}
모든 InnerClasses 속성 에 대해 ClassVisitor 의 visitInnerClass 방법 을 분석 하고 호출 합 니 다(이 속성 은 사실상 모든 직접 내부 클래스 와 그 자체 가 최상 위 클래스 로 저장 되 어 있 습 니 다).
void visitInnerClass(String name, String outerName, String innerName, int access);
분석 필드 는 인터페이스 배열 의 정의 에 따라 맨 앞 에 있 는 2 개의 바이트 가 필드 배열 의 길이 입 니 다.각 필드,앞 에 있 는 2 개의 바이트 가 방문 flag 로 정의 되 고 그 다음 에 2 개의 바이트 가 Name 색인 이 며 2 개의 바이트 의 설명자 색인 입 니 다.그 다음 에 Attribute 정 보 를 분석 합 니 다.ConstantValue,Signature,Deprecated,Synthetic,Runtime Visible Annotations,Runtime Invisible Annotations 및 표준 정의 되 지 않 은 Attribute 체인 을 사용 한 후 ClassVisitor 의 visitField 방법 을 호출 하여 FieldVisitor 인 스 턴 스 를 되 돌려 줍 니 다.
// value ( , ), , null。
FieldVisitor visitField(int access, String name, String desc, String signature, Object value);
되 돌아 오 는 FieldVisitor 에 대해 서 는 Annotation 및 비 표준 Attribute 를 순서대로 분석 하고 visit 방법 을 호출 하 며 완 료 된 후에 visitEnd 방법 을 호출 합 니 다.
public interface FieldVisitor {
AnnotationVisitor visitAnnotation(String desc, boolean visible);
void visitAttribute(Attribute attr);
void visitEnd();
}
분석 방법 은 필드 정의 에 따라 맨 앞 에 있 는 2 개의 바이트 가 방법 배열 의 길이 로 정 의 됩 니 다.각 방법 에 대해 앞의 2 개의 바이트 가 flag 에 접근 하 는 것 으로 정 의 된 다음 에 2 개의 바이트 가 Name 색인 이 고 2 개의 바이트 의 방법 설명자 색인 인 다음 에 Attribute 메 시 지 를 분석 합 니 다.Code,Exceptions,Signature,Deprecated,Runtime Visible Annotations,AnnotationDefault,Synthetic,Runtime Invisible Annotations,Runtime Visible ParameterAnnotations,Runtime Invisible ParameterAnnotations 및 비 표준 정의 Attribute 체인 이 있 습 니 다.Exceptions 속성 이 존재 하면 이상 클래스 그룹 을 분석 한 다음 에 ClassVisitor 의 visitMethod 방법 을 호출 하여 MethodVisitor 인 스 턴 스 를 되 돌려 줍 니 다.
MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions);
AnnotationDefault 는 Annotation 을 정의 할 때 기본 값 을 지정 합 니 다.그 다음 에 Runtime Visible Annotations,Runtime Invisible Annotations,Runtime Visible ParameterAnnotations,Runtime Invisible ParameterAnnotations 등 속성 을 순서대로 분석 하고 관련 AnnotationVisitor 의 visit 방법 을 호출 합 니 다.표준 이 아 닌 Attribute 체인 에 대해 MethodVisitor 의 visitAttribute 방법 을 순서대로 호출 합 니 다.
public interface MethodVisitor {
AnnotationVisitor visitAnnotationDefault();
AnnotationVisitor visitAnnotation(String desc, boolean visible);
AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible);
void visitAttribute(Attribute attr);
}
Code 속성 에 대한 분석,2 바이트 의 가장 깊 은 스 택 크기,최대 local 변수,code 점용 바이트 수 를 읽 고 MethodVisitorvisitCode()
방법 으로 Code 속성 을 분석 하기 시 작 했 습 니 다.각 명령 에 대해 하나의 Label 인 스 턴 스 를 만 들 고 Label 배열 을 구성 합 니 다.Code 속성 중의 이상 표를 분석 하고 모든 이상 항목 에 대해 visitTry CatchBlock 방법 을 호출 합 니 다.
void visitTryCatchBlock(Label start, Label end, Label handler, String type);
라벨 은 다음 과 같은 정 보 를 포함 합 니 다:
/**
* A label represents a position in the bytecode of a method. Labels are used
* for jump, goto, and switch instructions, and for try catch blocks.
*
* @author Eric Bruneton
*/
public class Label {
public Object info;
int status;
int line;
int position;
private int referenceCount;
private int[] srcAndRefPositions;
int inputStackTop;
int outputStackMax;
Frame frame;
Label successor;
Edge successors;
Label next;
}
Code 속성 중의 내부 속성 정 보 를 분석 합 니 다:LocalVariableTable,LocalVariableTypeTable,Line NumberTable,StackMapTable,StackMap 및 비 표준 정의 Attribute 체인 은 모든 Label 에 visitLine Number 방법 과 모든 Frame 에 visitFrame 방법 을 호출 하고 해당 하 는 명령 에 해당 하 는 방법 을 호출 합 니 다.
void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack);
// Visits a zero operand instruction.
void visitInsn(int opcode);
// Visits an instruction with a single int operand.
void visitIntInsn(int opcode, int operand);
// Visits a local variable instruction. A local variable instruction is an instruction that loads or stores the value of a local variable.
void visitVarInsn(int opcode, int var);
// Visits a type instruction. A type instruction is an instruction that takes the internal name of a class as parameter.
void visitTypeInsn(int opcode, String type);
// Visits a field instruction. A field instruction is an instruction that loads or stores the value of a field of an object.
void visitFieldInsn(int opcode, String owner, String name, String desc);
// Visits a method instruction. A method instruction is an instruction that invokes a method.
void visitMethodInsn(int opcode, String owner, String name, String desc);
// Visits a jump instruction. A jump instruction is an instruction that may jump to another instruction.
void visitJumpInsn(int opcode, Label label);
// Visits a label. A label designates the instruction that will be visited just after it.
void visitLabel(Label label);
// Visits a LDC instruction.
void visitLdcInsn(Object cst);
// Visits an IINC instruction.
void visitIincInsn(int var, int increment);
// Visits a TABLESWITCH instruction.
void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels);
// Visits a LOOKUPSWITCH instruction.
void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels);
// Visits a MULTIANEWARRAY instruction.
void visitMultiANewArrayInsn(String desc, int dims);
// Visits a try catch block.
void visitTryCatchBlock(Label start, Label end, Label handler, String type);
void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index);
// Visits a line number declaration.
void visitLineNumber(int line, Label start);
// Visits the maximum stack size and the maximum number of local variables of the method.
void visitMaxs(int maxStack, int maxLocals);
마지막 으로 ClassVisitor 의 visitEnd 방법 을 호출 합 니 다:
void visitEnd();
ClassWriter 구현ClassWriter 는 ClassVisitor 인 터 페 이 스 를 계승 하여 해당 하 는 visit 방법 으로 동적 으로 바이트 코드 류 를 구성 할 수 있 습 니 다.다음 필드 정 보 를 포함 합 니 다:
public class ClassWriter implements ClassVisitor {
//The class reader from which this class writer was constructed, if any.
ClassReader cr;
//Minor and major version numbers of the class to be generated.
int version;
//Index of the next item to be added in the constant pool.
int index;
//The constant pool of this class.
final ByteVector pool;
//The constant pool's hash table data.
Item[] items;
//The threshold of the constant pool's hash table.
int threshold;
//A reusable key used to look for items in the {@link #items} hash table.
final Item key;
//A reusable key used to look for items in the {@link #items} hash table.
final Item key2;
//A reusable key used to look for items in the {@link #items} hash table.
final Item key3;
//A type table used to temporarily store internal names that will not necessarily be stored in the constant pool.
Item[] typeTable;
//Number of elements in the {@link #typeTable} array.
private short typeCount;
//The access flags of this class.
private int access;
//The constant pool item that contains the internal name of this class.
private int name;
//The internal name of this class.
String thisName;
//The constant pool item that contains the signature of this class.
private int signature;
//The constant pool item that contains the internal name of the super class of this class.
private int superName;
// Number of interfaces implemented or extended by this class or interface.
private int interfaceCount;
//The interfaces implemented or extended by this class or interface.
private int[] interfaces;
//The index of the constant pool item that contains the name of the source file from which this class was compiled.
private int sourceFile;
//The SourceDebug attribute of this class.
private ByteVector sourceDebug;
//The constant pool item that contains the name of the enclosing class of this class.
private int enclosingMethodOwner;
//The constant pool item that contains the name and descriptor of the enclosing method of this class.
private int enclosingMethod;
//The runtime visible annotations of this class.
private AnnotationWriter anns;
//The runtime invisible annotations of this class.
private AnnotationWriter ianns;
//The non standard attributes of this class.
private Attribute attrs;
//The number of entries in the InnerClasses attribute.
private int innerClassesCount;
//The InnerClasses attribute.
private ByteVector innerClasses;
//The fields of this class. These fields are stored in a linked list of {@link FieldWriter} objects, linked to each other by their {@link FieldWriter#next} field. This field stores the first element of this list.
FieldWriter firstField;
//This field stores the last element of this list.
FieldWriter lastField;
//The methods of this class. These methods are stored in a linked list of {@link MethodWriter} objects, linked to each other by their {@link MethodWriter#next} field. This field stores the first element of this list.
MethodWriter firstMethod;
//This field stores the last element of this list.
MethodWriter lastMethod;
//true if the maximum stack size and number of local variables must be automatically computed.
private final boolean computeMaxs;
//true if the stack map frames must be recomputed from scratch.
private final boolean computeFrames;
//true if the stack map tables of this class are invalid.
boolean invalidFrames;
}
총결산이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 남 겨 주 십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
java 바이트 프레임워크 ASM 바이트 조작 방법 분석앞서 ASM에 대한 자세한 설명을 드렸는데 필요한 분들은 여기를 클릭하시면 됩니다 JVM 유형 서명 대조표 Type Signature Java Type boolean byte char short int long fl...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.