《Java字节码格式详??/a>?a href="http://www.aygfsteel.com/DLevin/archive/2011/09/05/358034.html">《Java字节码格式详??/a>?a href="http://www.aygfsteel.com/DLevin/archive/2011/09/05/358035.html">《Java字节码格式详??/a>
在构建ClassReader实例Ӟ它首先保存字节码二进制数lbQ然后创建items数组Q数l的长度在字节码数组的第8?个字节指定(最前面4个字节是数CAFEBABEQ之?个字节是ơ版本号Q再?个字节是ȝ本号Q,每个item表示帔R池项在字节码数组的偏U量?Q常量池中每个项?个字节的type和紧跟的字节数组表示Q常量池Ҏ12U类型,其中CONSTANT_FieldRef_Info、CONSTANT_MethodRef_Info、CONSTANT_InterfaceMethodRef_Info、CONSTANT_NameAndType_Info包括其类型字节占?个字节,另外4个字节每2个字节ؓ字段、方法等所在的cR其名称、描q符在当前常量池中CONSTANT_Utf8_Infocd的引用;CONSTANT_Integer_Info、CONSTANT_Float_Info包括其类型字节占?个字节,另外四个字节为其对应的|CONSTANT_Class_Info、CONSTANT_String_Info包括其类型字节占?个字节,另外两个字节为在当前帔R池CONSTANT_Utf8_Info的索引QCONSTANT_Utf8_InfocdW?个字节表C类型,W??个字节ؓ该项所表示的字W串的长度)QCONSTANT_Double_Info、CONSTANT_Long_Info加类型字节ؓ9个字QmaxStringLength表示最长的UTF8cd的常量池的|用于军_在解析CONSTANT_Utf8_InfocdҎ最大需要的字符数组Qheader表示帔R池之后的字节码的W一个字节?br />
在调用ClassReader的acceptҎӞ它解析字节码中常量池之后的所有元素。紧接着帔R池的2个字节是该类的access标签QACC_PUBLIC、ACC_FINAL{;之后2个字节ؓ当前cd在常量池CONSTANT_Utf8_Infocd的烦引;之后2个字节ؓ其父cd在常量池CONSTANT_Utf8_Infocd的烦引(索引?表示父类为nullQ即直接l承自Objectc)Q再之后为其实现的接口数长度和对应各个接口名在常量池中CONSTANT_Utf8_Infocd的烦引|暂时先蟩qField和Method定义信息Q解析类的attribute表,它用两个字节表达attribute数组的长度,每个attribute中最前面2个字节是attribute名称QSourceFileQ读取sourceFile|、InnerClassesQ暂时纪录v始烦引)、EnclosingMethodQ纪录当前匿名类、本地类包含者类名以及包含者的Ҏ名和描述W)、SignatureQ类的签名信息,用于范型Q、RuntimeVisibleAnnotationsQ暂时纪录v始烦引)、DeprecatedQ表识属性)、SyntheticQ标识属性)、SourceDebugExtensionQؓ调试器提供的自定义扩展信息,d成一个字W串Q、RuntimeInvisibleAnnotationsQ暂时纪录v始烦引)Q对其他不识别的属性,U录成Attribute链,如果attribute名称W合在accept中attribute数组中指定的attribute名,则替换传入的attribute数组对应的项Q根据解析出来的信息调用以下visitҎQ?br />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);
依次解析RuntimeVisibleAnnotations和RuntimeInvisibleAnnotations属性,首先解析定义的Annotation的描q符以及q行时可见flagQ返回用戯定义的AnnotationVisitorQ?br />AnnotationVisitor visitAnnotation(String desc, boolean visible);
Ҏ个定义的AnnotationQ解析其键值对QƈҎ不同的Annotation字段D用AnnotationVisitor中的ҎQ在所有解析结束后Q调用AnnotationVisitor.visitEndҎQ?br />public interface AnnotationVisitor {
// 对基本类型的数组Q依焉用该ҎQvisitArray只是在非基本cd时调用?/span>
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链表Q非标准的Attribute定义Q,Ҏ个Attribute实例Q调用ClassVisitor中的visitAttributeҎQ?br />void visitAttribute(Attribute attr);
Attributecd含type字段和一个字节数l:
public class Attribute {
public final String type;
byte[] value;
Attribute next;
}
Ҏ个InnerClasses属性,解析q调用ClassVisitor的visitInnerClassҎQ该属性事实上保存了所有其直接内部cM及它本n到最层cȝ路径Q:
void visitInnerClass(String name, String outerName, String innerName, int access);
解析字段Q它紧跟接口数组定义之后Q最前面?个字节ؓ字段数组的长度,Ҏ个字D,前面2个字节ؓ讉Kflag定义Q再?个字节ؓName索引Q以?个字节的描述W烦引,然后解析其Attribute信息QConstantValue、Signature、Deprecated、Synthetic、RuntimeVisibleAnnotations、RuntimeInvisibleAnnotations以及非标准定义的Attribute链,而后调用ClassVisitor的visitFieldҎQ返回FieldVisitor实例Q?br />// 其中value为静态字D늚初始化|寚w静态字D,它的初始化必ȝ构造函数实玎ͼQ如果没有初始化|该gؓnull?/span>
FieldVisitor visitField(int access, String name, String desc, String signature, Object value);
对返回的FieldVisitor依次对其Annotation以及非标准Attribute解析Q调用其visitҎQƈ在完成后调用它的visitEndҎQ?br />public interface FieldVisitor {
AnnotationVisitor visitAnnotation(String desc, boolean visible);
void visitAttribute(Attribute attr);
void visitEnd();
}
解析Ҏ定义Q它紧跟字段定义之后Q最前面?个字节ؓҎ数组长度Q对每个ҎQ前?个字节ؓ讉Kflag定义Q再?个字节ؓName索引Q以?个字节的Ҏ描述W烦引,然后解析其Attribute信息QCode、Exceptions、Signature、Deprecated、RuntimeVisibleAnnotations、AnnotationDefault、Synthetic、RuntimeInvisibleAnnotations、RuntimeVisibleParameterAnnotations、RuntimeInvisibleParameterAnnotations以及非标准定义的Attribute链,如果存在Exceptions属性,解析其异常类数组Q之后调用ClassVisitor的visitMethodҎQ返回MethodVisitor实例Q?br />MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions);
AnnotationDefault为对Annotation定义时指定默认值的解析Q然后依ơ解析RuntimeVisibleAnnotations、RuntimeInvisibleAnnotations、RuntimeVisibleParameterAnnotations、RuntimeInvisibleParameterAnnotations{属性,调用相关AnnotationVisitor的visitҎQ对非标准定义的Attribute链,依次调用MethodVisitor的visitAttributeҎQ?br />public interface MethodVisitor {
AnnotationVisitor visitAnnotationDefault();
AnnotationVisitor visitAnnotation(String desc, boolean visible);
AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible);
void visitAttribute(Attribute attr);
}
对Code属性解析,d2个字节的最深栈大小、最大local变量数、code占用字节敎ͼ调用MethodVisitor的visitCode()Ҏ表示开始解析Code属性,Ҏ条指令,创徏一个Label实例q构成Label数组Q解析Code属性中的异常表Q对每个异常,调用visitTryCatchBlockҎQ?br />void visitTryCatchBlock(Label start, Label end, Label handler, String type);
Label包含以下信息Q?br />/**
* 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、LineNumberTable、StackMapTable、StackMap以及非标准定义的Attribute链,Ҏ个Label调用其visitLineNumberҎ以及Ҏ个Frame调用visitFrameҎQƈ且对相应的指令调用相应的ҎQ?br />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ҎQ?br />void visitEnd();
ClassWriter实现
ClassWriterl承自ClassVisitor接口Q可以用它调用其相应的visitҎ动态的构造一个字节码cR它包含以下字段信息Q?br />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;
}

]]>