spring源码分析之spring-core asm概述
ASM是什么?
ASM?is an all purpose Java bytecode manipulation and analysis framework. It can be used to modify existing classes or dynamically generate classes, directly in binary form. Provided common transformations and analysis algorithms allow to easily assemble custom complex transformations and code analysis tools.
ASM offer similar functionality as other bytecode frameworks, but it is focused on simplicity of use and performance. Because it was designed and implemented to be as small and as fast as possible, it makes it very attractive for using in dynamic systems*.
(*) ASM can of course be used in a static way too.
如何學(xué)習(xí)ASM?
The best way to learn to use ASM is to write a Java source file that is equivalent to what you want to generate and then use the ASMifier mode of the?Bytecode Outline?plugin for Eclipse (or the?ASMifier?tool) to see the equivalent ASM code. If you want to implement a class transformer, write two Java source files (before and after transformation) and use the compare view of the plugin in ASMifier mode to compare the equivalent ASM code.
ASM的核心
在ASM的核心實(shí)現(xiàn)中,它主要有以下幾個(gè)類、接口(在org.objectweb.asm包中):
ClassReader類:字節(jié)碼的讀取與分析引擎。它采用類似SAX的事件讀取機(jī)制,每當(dāng)有事件發(fā)生時(shí),調(diào)用注冊的ClassVisitor、AnnotationVisitor、FieldVisitor、MethodVisitor做相應(yīng)的處理。
ClassVisitor接口:定義在讀取Class字節(jié)碼時(shí)會(huì)觸發(fā)的事件,如類頭解析完成、注解解析、字段解析、方法解析等。
AnnotationVisitor接口:定義在解析注解時(shí)會(huì)觸發(fā)的事件,如解析到一個(gè)基本值類型的注解、enum值類型的注解、Array值類型的注解、注解值類型的注解等。
A visitor to visit a Java annotation. The methods of this class must be called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> | <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.FieldVisitor接口:定義在解析字段時(shí)觸發(fā)的事件,如解析到字段上的注解、解析到字段相關(guān)的屬性等。
MethodVisitor接口:定義在解析方法時(shí)觸發(fā)的事件,如方法上的注解、屬性、代碼等。
ClassWriter類:它實(shí)現(xiàn)了ClassVisitor接口,用于拼接字節(jié)碼。
AnnotationWriter類:它實(shí)現(xiàn)了AnnotationVisitor接口,用于拼接注解相關(guān)字節(jié)碼。
FieldWriter類:它實(shí)現(xiàn)了FieldVisitor接口,用于拼接字段相關(guān)字節(jié)碼。
MethodWriter類:它實(shí)現(xiàn)了MethodVisitor接口,用于拼接方法相關(guān)字節(jié)碼。
SignatureReader類:對類定義、字段定義、方法定義、本地變量定義的簽名的解析。Signature因范型引入,用于存儲(chǔ)范型定義時(shí)的元數(shù)據(jù)(因?yàn)檫@些元數(shù)據(jù)在運(yùn)行時(shí)會(huì)被擦除)。
SignatureVisitor接口:定義在解析Signature時(shí)會(huì)觸發(fā)的事件,如正常的Type參數(shù)、類或接口的邊界等。
SignatureWriter類:它實(shí)現(xiàn)了SignatureVisitor接口,用于拼接范型相關(guān)字節(jié)碼。
Attribute類:字節(jié)碼中屬性的類抽象。
ByteVector類:字節(jié)碼二進(jìn)制存儲(chǔ)的容器。
Opcodes接口:字節(jié)碼指令的一些常量定義。
Type類:類型相關(guān)的常量定義以及一些基于其上的操作。
JVM操作在ASM中的定義
/*** Defines the JVM opcodes, access flags and array type codes. This interface* does not define all the JVM opcodes because some opcodes are automatically* handled. For example, the xLOAD and xSTORE opcodes are automatically replaced* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n* opcodes are therefore not defined in this interface. Likewise for LDC,* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and* JSR_W.* * @author Eric Bruneton* @author Eugene Kuleshov*/ public interface Opcodes {// ASM API versionsint ASM4 = 4 << 16 | 0 << 8 | 0;int ASM5 = 5 << 16 | 0 << 8 | 0;// versionsint V1_1 = 3 << 16 | 45;int V1_2 = 0 << 16 | 46;int V1_3 = 0 << 16 | 47;int V1_4 = 0 << 16 | 48;int V1_5 = 0 << 16 | 49;int V1_6 = 0 << 16 | 50;int V1_7 = 0 << 16 | 51;int V1_8 = 0 << 16 | 52;// access flagsint ACC_PUBLIC = 0x0001; // class, field, methodint ACC_PRIVATE = 0x0002; // class, field, methodint ACC_PROTECTED = 0x0004; // class, field, methodint ACC_STATIC = 0x0008; // field, methodint ACC_FINAL = 0x0010; // class, field, method, parameterint ACC_SUPER = 0x0020; // classint ACC_SYNCHRONIZED = 0x0020; // methodint ACC_VOLATILE = 0x0040; // fieldint ACC_BRIDGE = 0x0040; // methodint ACC_VARARGS = 0x0080; // methodint ACC_TRANSIENT = 0x0080; // fieldint ACC_NATIVE = 0x0100; // methodint ACC_INTERFACE = 0x0200; // classint ACC_ABSTRACT = 0x0400; // class, methodint ACC_STRICT = 0x0800; // methodint ACC_SYNTHETIC = 0x1000; // class, field, method, parameterint ACC_ANNOTATION = 0x2000; // classint ACC_ENUM = 0x4000; // class(?) field innerint ACC_MANDATED = 0x8000; // parameter// ASM specific pseudo access flagsint ACC_DEPRECATED = 0x20000; // class, field, method// types for NEWARRAYint T_BOOLEAN = 4;int T_CHAR = 5;int T_FLOAT = 6;int T_DOUBLE = 7;int T_BYTE = 8;int T_SHORT = 9;int T_INT = 10;int T_LONG = 11;// tags for Handleint H_GETFIELD = 1;int H_GETSTATIC = 2;int H_PUTFIELD = 3;int H_PUTSTATIC = 4;int H_INVOKEVIRTUAL = 5;int H_INVOKESTATIC = 6;int H_INVOKESPECIAL = 7;int H_NEWINVOKESPECIAL = 8;int H_INVOKEINTERFACE = 9;// stack map frame types/*** Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.*/int F_NEW = -1;/*** Represents a compressed frame with complete frame data.*/int F_FULL = 0;/*** Represents a compressed frame where locals are the same as the locals in* the previous frame, except that additional 1-3 locals are defined, and* with an empty stack.*/int F_APPEND = 1;/*** Represents a compressed frame where locals are the same as the locals in* the previous frame, except that the last 1-3 locals are absent and with* an empty stack.*/int F_CHOP = 2;/*** Represents a compressed frame with exactly the same locals as the* previous frame and with an empty stack.*/int F_SAME = 3;/*** Represents a compressed frame with exactly the same locals as the* previous frame and with a single value on the stack.*/int F_SAME1 = 4;// Do not try to change the following code to use auto-boxing,// these values are compared by reference and not by value// The constructor of Integer was deprecated in 9// but we are stuck with it by backward compatibility@SuppressWarnings("deprecation") Integer TOP = new Integer(0);@SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);@SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);@SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);@SuppressWarnings("deprecation") Integer LONG = new Integer(4);@SuppressWarnings("deprecation") Integer NULL = new Integer(5);@SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);// opcodes // visit method (- = idem)int NOP = 0; // visitInsnint ACONST_NULL = 1; // -int ICONST_M1 = 2; // -int ICONST_0 = 3; // -int ICONST_1 = 4; // -int ICONST_2 = 5; // -int ICONST_3 = 6; // -int ICONST_4 = 7; // -int ICONST_5 = 8; // -int LCONST_0 = 9; // -int LCONST_1 = 10; // -int FCONST_0 = 11; // -int FCONST_1 = 12; // -int FCONST_2 = 13; // -int DCONST_0 = 14; // -int DCONST_1 = 15; // -int BIPUSH = 16; // visitIntInsnint SIPUSH = 17; // -int LDC = 18; // visitLdcInsn// int LDC_W = 19; // -// int LDC2_W = 20; // -int ILOAD = 21; // visitVarInsnint LLOAD = 22; // -int FLOAD = 23; // -int DLOAD = 24; // -int ALOAD = 25; // -// int ILOAD_0 = 26; // -// int ILOAD_1 = 27; // -// int ILOAD_2 = 28; // -// int ILOAD_3 = 29; // -// int LLOAD_0 = 30; // -// int LLOAD_1 = 31; // -// int LLOAD_2 = 32; // -// int LLOAD_3 = 33; // -// int FLOAD_0 = 34; // -// int FLOAD_1 = 35; // -// int FLOAD_2 = 36; // -// int FLOAD_3 = 37; // -// int DLOAD_0 = 38; // -// int DLOAD_1 = 39; // -// int DLOAD_2 = 40; // -// int DLOAD_3 = 41; // -// int ALOAD_0 = 42; // -// int ALOAD_1 = 43; // -// int ALOAD_2 = 44; // -// int ALOAD_3 = 45; // -int IALOAD = 46; // visitInsnint LALOAD = 47; // -int FALOAD = 48; // -int DALOAD = 49; // -int AALOAD = 50; // -int BALOAD = 51; // -int CALOAD = 52; // -int SALOAD = 53; // -int ISTORE = 54; // visitVarInsnint LSTORE = 55; // -int FSTORE = 56; // -int DSTORE = 57; // -int ASTORE = 58; // -// int ISTORE_0 = 59; // -// int ISTORE_1 = 60; // -// int ISTORE_2 = 61; // -// int ISTORE_3 = 62; // -// int LSTORE_0 = 63; // -// int LSTORE_1 = 64; // -// int LSTORE_2 = 65; // -// int LSTORE_3 = 66; // -// int FSTORE_0 = 67; // -// int FSTORE_1 = 68; // -// int FSTORE_2 = 69; // -// int FSTORE_3 = 70; // -// int DSTORE_0 = 71; // -// int DSTORE_1 = 72; // -// int DSTORE_2 = 73; // -// int DSTORE_3 = 74; // -// int ASTORE_0 = 75; // -// int ASTORE_1 = 76; // -// int ASTORE_2 = 77; // -// int ASTORE_3 = 78; // -int IASTORE = 79; // visitInsnint LASTORE = 80; // -int FASTORE = 81; // -int DASTORE = 82; // -int AASTORE = 83; // -int BASTORE = 84; // -int CASTORE = 85; // -int SASTORE = 86; // -int POP = 87; // -int POP2 = 88; // -int DUP = 89; // -int DUP_X1 = 90; // -int DUP_X2 = 91; // -int DUP2 = 92; // -int DUP2_X1 = 93; // -int DUP2_X2 = 94; // -int SWAP = 95; // -int IADD = 96; // -int LADD = 97; // -int FADD = 98; // -int DADD = 99; // -int ISUB = 100; // -int LSUB = 101; // -int FSUB = 102; // -int DSUB = 103; // -int IMUL = 104; // -int LMUL = 105; // -int FMUL = 106; // -int DMUL = 107; // -int IDIV = 108; // -int LDIV = 109; // -int FDIV = 110; // -int DDIV = 111; // -int IREM = 112; // -int LREM = 113; // -int FREM = 114; // -int DREM = 115; // -int INEG = 116; // -int LNEG = 117; // -int FNEG = 118; // -int DNEG = 119; // -int ISHL = 120; // -int LSHL = 121; // -int ISHR = 122; // -int LSHR = 123; // -int IUSHR = 124; // -int LUSHR = 125; // -int IAND = 126; // -int LAND = 127; // -int IOR = 128; // -int LOR = 129; // -int IXOR = 130; // -int LXOR = 131; // -int IINC = 132; // visitIincInsnint I2L = 133; // visitInsnint I2F = 134; // -int I2D = 135; // -int L2I = 136; // -int L2F = 137; // -int L2D = 138; // -int F2I = 139; // -int F2L = 140; // -int F2D = 141; // -int D2I = 142; // -int D2L = 143; // -int D2F = 144; // -int I2B = 145; // -int I2C = 146; // -int I2S = 147; // -int LCMP = 148; // -int FCMPL = 149; // -int FCMPG = 150; // -int DCMPL = 151; // -int DCMPG = 152; // -int IFEQ = 153; // visitJumpInsnint IFNE = 154; // -int IFLT = 155; // -int IFGE = 156; // -int IFGT = 157; // -int IFLE = 158; // -int IF_ICMPEQ = 159; // -int IF_ICMPNE = 160; // -int IF_ICMPLT = 161; // -int IF_ICMPGE = 162; // -int IF_ICMPGT = 163; // -int IF_ICMPLE = 164; // -int IF_ACMPEQ = 165; // -int IF_ACMPNE = 166; // -int GOTO = 167; // -int JSR = 168; // -int RET = 169; // visitVarInsnint TABLESWITCH = 170; // visiTableSwitchInsnint LOOKUPSWITCH = 171; // visitLookupSwitchint IRETURN = 172; // visitInsnint LRETURN = 173; // -int FRETURN = 174; // -int DRETURN = 175; // -int ARETURN = 176; // -int RETURN = 177; // -int GETSTATIC = 178; // visitFieldInsnint PUTSTATIC = 179; // -int GETFIELD = 180; // -int PUTFIELD = 181; // -int INVOKEVIRTUAL = 182; // visitMethodInsnint INVOKESPECIAL = 183; // -int INVOKESTATIC = 184; // -int INVOKEINTERFACE = 185; // -int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsnint NEW = 187; // visitTypeInsnint NEWARRAY = 188; // visitIntInsnint ANEWARRAY = 189; // visitTypeInsnint ARRAYLENGTH = 190; // visitInsnint ATHROW = 191; // -int CHECKCAST = 192; // visitTypeInsnint INSTANCEOF = 193; // -int MONITORENTER = 194; // visitInsnint MONITOREXIT = 195; // -// int WIDE = 196; // NOT VISITEDint MULTIANEWARRAY = 197; // visitMultiANewArrayInsnint IFNULL = 198; // visitJumpInsnint IFNONNULL = 199; // -// int GOTO_W = 200; // -// int JSR_W = 201; // - }?
參考文獻(xiàn):
【1】http://asm.ow2.org/
【2】http://www.blogjava.net/DLevin/archive/2014/06/25/414292.html
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/5652181.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的spring源码分析之spring-core asm概述的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何用UE(UltraEdit)删除重复
- 下一篇: cglib源码分析--转