`

ASM4.0源码走读之三 readCode方法分析方法代码

阅读更多

        继第一篇,我们来看看readCode的代码:

    private void readCode(final MethodVisitor mv, final Context context, int u) {
        // reads the header
        byte[] b = this.b;
        char[] c = context.buffer;//这个buffer长度为maxStringLength
        int maxStack = readUnsignedShort(u);//maxStack值
        int maxLocals = readUnsignedShort(u + 2);//max locals 值
        int codeLength = readInt(u + 4);//代码长度
        u += 8;


        // reads the bytecode to find the labels
        int codeStart = u;
        int codeEnd = u + codeLength;
        Label[] labels = context.labels = new Label[codeLength + 2];//为啥+2?
        readLabel(codeLength + 1, labels);
        while (u < codeEnd) {
            int offset = u - codeStart;
            int opcode = b[u] & 0xFF;
            switch (ClassWriter.TYPE[opcode]) {
            case ClassWriter.NOARG_INSN:
            case ClassWriter.IMPLVAR_INSN:
                u += 1;
                break;
            case ClassWriter.LABEL_INSN:
                readLabel(offset + readShort(u + 1), labels);
                u += 3;
                break;
            case ClassWriter.LABELW_INSN:
                readLabel(offset + readInt(u + 1), labels);
                u += 5;
                break;
            case ClassWriter.WIDE_INSN:
                opcode = b[u + 1] & 0xFF;
                if (opcode == Opcodes.IINC) {
                    u += 6;
                } else {
                    u += 4;
                }
                break;
            case ClassWriter.TABL_INSN:
                // skips 0 to 3 padding bytes
                u = u + 4 - (offset & 3);
                // reads instruction
                readLabel(offset + readInt(u), labels);
                for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
                    readLabel(offset + readInt(u + 12), labels);
                    u += 4;
                }
                u += 12;
                break;
            case ClassWriter.LOOK_INSN:
                // skips 0 to 3 padding bytes
                u = u + 4 - (offset & 3);
                // reads instruction
                readLabel(offset + readInt(u), labels);
                for (int i = readInt(u + 4); i > 0; --i) {
                    readLabel(offset + readInt(u + 12), labels);
                    u += 8;
                }
                u += 8;
                break;
            case ClassWriter.VAR_INSN:
            case ClassWriter.SBYTE_INSN:
            case ClassWriter.LDC_INSN:
                u += 2;
                break;
            case ClassWriter.SHORT_INSN:
            case ClassWriter.LDCW_INSN:
            case ClassWriter.FIELDORMETH_INSN:
            case ClassWriter.TYPE_INSN:
            case ClassWriter.IINC_INSN:
                u += 3;
                break;
            case ClassWriter.ITFMETH_INSN:
            case ClassWriter.INDYMETH_INSN:
                u += 5;
                break;
            // case MANA_INSN:
            default:
                u += 4;
                break;
            }
        }


        // reads the try catch entries to find the labels, and also visits them
        for (int i = readUnsignedShort(u); i > 0; --i) {
            Label start = readLabel(readUnsignedShort(u + 2), labels);
            Label end = readLabel(readUnsignedShort(u + 4), labels);
            Label handler = readLabel(readUnsignedShort(u + 6), labels);
            String type = readUTF8(items[readUnsignedShort(u + 8)], c);
            mv.visitTryCatchBlock(start, end, handler, type);
            u += 8;
        }
        u += 2;


        // reads the code attributes
        int[] tanns = null; // start index of each visible type annotation
        int[] itanns = null; // start index of each invisible type annotation
        int tann = 0; // current index in tanns array
        int itann = 0; // current index in itanns array
        int ntoff = -1; // next visible type annotation code offset
        int nitoff = -1; // next invisible type annotation code offset
        int varTable = 0;
        int varTypeTable = 0;
        boolean zip = true;
        boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
        int stackMap = 0;
        int stackMapSize = 0;
        int frameCount = 0;
        Context frame = null;
        Attribute attributes = null;


        for (int i = readUnsignedShort(u); i > 0; --i) {
            String attrName = readUTF8(u + 2, c);
            if ("LocalVariableTable".equals(attrName)) {
                if ((context.flags & SKIP_DEBUG) == 0) {
                    varTable = u + 8;
                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
                        int label = readUnsignedShort(v + 10);
                        if (labels[label] == null) {
                            readLabel(label, labels).status |= Label.DEBUG;
                        }
                        label += readUnsignedShort(v + 12);
                        if (labels[label] == null) {
                            readLabel(label, labels).status |= Label.DEBUG;
                        }
                        v += 10;
                    }
                }
            } else if ("LocalVariableTypeTable".equals(attrName)) {
                varTypeTable = u + 8;
            } else if ("LineNumberTable".equals(attrName)) {
                if ((context.flags & SKIP_DEBUG) == 0) {
                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
                        int label = readUnsignedShort(v + 10);
                        if (labels[label] == null) {
                            readLabel(label, labels).status |= Label.DEBUG;
                        }
                        labels[label].line = readUnsignedShort(v + 12);
                        v += 4;
                    }
                }
            } else if (ANNOTATIONS
                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
                tanns = readTypeAnnotations(mv, context, u + 8, true);
                ntoff = tann >= tanns.length
                        || readUnsignedShort(tanns[tann]) < 0x86 ? -1
                        : readUnsignedShort(tanns[tann] + 2);
            } else if (ANNOTATIONS
                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
                itanns = readTypeAnnotations(mv, context, u + 8, false);
                nitoff = itann >= itanns.length
                        || readUnsignedShort(itanns[itann]) < 0x86 ? -1
                        : readUnsignedShort(itanns[itann] + 2);
            } else if (FRAMES && "StackMapTable".equals(attrName)) {
                if ((context.flags & SKIP_FRAMES) == 0) {
                    stackMap = u + 10;//stackMap位置后边是stack_map_frame类型的entries,10 = attribute_count(u2)、attribute_name_index(u2)、attribute_length(u4)、number_of_entries(u2)
                    stackMapSize = readInt(u + 4);//stackMapSize是attribute_length
                    frameCount = readUnsignedShort(u + 8);//
                }
                /*
                 * here we do not extract the labels corresponding to the
                 * attribute content. This would require a full parsing of the
                 * attribute, which would need to be repeated in the second
                 * phase (see below). Instead the content of the attribute is
                 * read one frame at a time (i.e. after a frame has been
                 * visited, the next frame is read), and the labels it contains
                 * are also extracted one frame at a time. Thanks to the
                 * ordering of frames, having only a "one frame lookahead" is
                 * not a problem, i.e. it is not possible to see an offset
                 * smaller than the offset of the current insn and for which no
                 * Label exist.
                 */
                /*
                 * This is not true for UNINITIALIZED type offsets. We solve
                 * this by parsing the stack map table without a full decoding
                 * (see below).
                 */
            } else if (FRAMES && "StackMap".equals(attrName)) {
                if ((context.flags & SKIP_FRAMES) == 0) {
                    zip = false;
                    stackMap = u + 10;
                    stackMapSize = readInt(u + 4);
                    frameCount = readUnsignedShort(u + 8);
                }
                /*
                 * IMPORTANT! here we assume that the frames are ordered, as in
                 * the StackMapTable attribute, although this is not guaranteed
                 * by the attribute format.
                 */
            } else {
                for (int j = 0; j < context.attrs.length; ++j) {
                    if (context.attrs[j].type.equals(attrName)) {
                        Attribute attr = context.attrs[j].read(this, u + 8,
                                readInt(u + 4), c, codeStart - 8, labels);
                        if (attr != null) {
                            attr.next = attributes;
                            attributes = attr;
                        }
                    }
                }
            }
            u += 6 + readInt(u + 4);
        }
        u += 2;


        // generates the first (implicit) stack map frame
        if (FRAMES && (stackMap != 0 || unzip)) {
            /*
             * for the first explicit frame the offset is not offset_delta + 1
             * but only offset_delta; setting the implicit frame offset to -1
             * allow the use of the "offset_delta + 1" rule in all cases
             */
            frame = context;
            frame.offset = -1;
            frame.mode = 0;
            frame.localCount = 0;
            frame.localDiff = 0;
            frame.stackCount = 0;
            frame.local = new Object[maxLocals];
            frame.stack = new Object[maxStack];
            if (unzip) {
                getImplicitFrame(context);
            }
        }
        if (FRAMES && stackMap != 0) {
            /*
             * Finds labels for UNINITIALIZED frame types. Instead of decoding
             * each element of the stack map table, we look for 3 consecutive
             * bytes that "look like" an UNINITIALIZED type (tag 8, offset
             * within code bounds, NEW instruction at this offset). We may find
             * false positives (i.e. not real UNINITIALIZED types), but this
             * should be rare, and the only consequence will be the creation of
             * an unneeded label. This is better than creating a label for each
             * NEW instruction, and faster than fully decoding the whole stack
             * map table.
             */
            for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
                if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
                    int v = readUnsignedShort(i + 1);
                    if (v >= 0 && v < codeLength) {
                        if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
                            readLabel(v, labels);
                        }
                    }
                }
            }
        }


        // visits the instructions
        u = codeStart;
        while (u < codeEnd) {
            int offset = u - codeStart;


            // visits the label and line number for this offset, if any
            Label l = labels[offset];
            if (l != null) {
                mv.visitLabel(l);
                if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
                    mv.visitLineNumber(l.line, l);
                }
            }


            // visits the frame(s) for this offset, if any
            while (FRAMES && frame != null
                    && (frame.offset == offset || frame.offset == -1)) {
                // if there is a frame for this offset, makes the visitor visit
                // it, and reads the next frame if there is one.
                if (!zip || unzip) {
                    mv.visitFrame(Opcodes.F_NEW, frame.localCount, frame.local,
                            frame.stackCount, frame.stack);
                } else if (frame.offset != -1) {
                    mv.visitFrame(frame.mode, frame.localDiff, frame.local,
                            frame.stackCount, frame.stack);
                }
                if (frameCount > 0) {
                    stackMap = readFrame(stackMap, zip, unzip, frame);
                    --frameCount;
                } else {
                    frame = null;
                }
            }


            // visits the instruction at this offset
            int opcode = b[u] & 0xFF;
            switch (ClassWriter.TYPE[opcode]) {
            case ClassWriter.NOARG_INSN:
                mv.visitInsn(opcode);
                u += 1;
                break;
            case ClassWriter.IMPLVAR_INSN:
                if (opcode > Opcodes.ISTORE) {
                    opcode -= 59; // ISTORE_0
                    mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
                            opcode & 0x3);
                } else {
                    opcode -= 26; // ILOAD_0
                    mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
                }
                u += 1;
                break;
            case ClassWriter.LABEL_INSN:
                mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
                u += 3;
                break;
            case ClassWriter.LABELW_INSN:
                mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
                u += 5;
                break;
            case ClassWriter.WIDE_INSN:
                opcode = b[u + 1] & 0xFF;
                if (opcode == Opcodes.IINC) {
                    mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
                    u += 6;
                } else {
                    mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
                    u += 4;
                }
                break;
            case ClassWriter.TABL_INSN: {
                // skips 0 to 3 padding bytes
                u = u + 4 - (offset & 3);
                // reads instruction
                int label = offset + readInt(u);
                int min = readInt(u + 4);
                int max = readInt(u + 8);
                Label[] table = new Label[max - min + 1];
                u += 12;
                for (int i = 0; i < table.length; ++i) {
                    table[i] = labels[offset + readInt(u)];
                    u += 4;
                }
                mv.visitTableSwitchInsn(min, max, labels[label], table);
                break;
            }
            case ClassWriter.LOOK_INSN: {
                // skips 0 to 3 padding bytes
                u = u + 4 - (offset & 3);
                // reads instruction
                int label = offset + readInt(u);
                int len = readInt(u + 4);
                int[] keys = new int[len];
                Label[] values = new Label[len];
                u += 8;
                for (int i = 0; i < len; ++i) {
                    keys[i] = readInt(u);
                    values[i] = labels[offset + readInt(u + 4)];
                    u += 8;
                }
                mv.visitLookupSwitchInsn(labels[label], keys, values);
                break;
            }
            case ClassWriter.VAR_INSN:
                mv.visitVarInsn(opcode, b[u + 1] & 0xFF);
                u += 2;
                break;
            case ClassWriter.SBYTE_INSN:
                mv.visitIntInsn(opcode, b[u + 1]);
                u += 2;
                break;
            case ClassWriter.SHORT_INSN:
                mv.visitIntInsn(opcode, readShort(u + 1));
                u += 3;
                break;
            case ClassWriter.LDC_INSN:
                mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c));
                u += 2;
                break;
            case ClassWriter.LDCW_INSN:
                mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c));
                u += 3;
                break;
            case ClassWriter.FIELDORMETH_INSN:
            case ClassWriter.ITFMETH_INSN: {
                int cpIndex = items[readUnsignedShort(u + 1)];
                String iowner = readClass(cpIndex, c);
                cpIndex = items[readUnsignedShort(cpIndex + 2)];
                String iname = readUTF8(cpIndex, c);
                String idesc = readUTF8(cpIndex + 2, c);
                if (opcode < Opcodes.INVOKEVIRTUAL) {
                    mv.visitFieldInsn(opcode, iowner, iname, idesc);
                } else {
                    mv.visitMethodInsn(opcode, iowner, iname, idesc);
                }
                if (opcode == Opcodes.INVOKEINTERFACE) {
                    u += 5;
                } else {
                    u += 3;
                }
                break;
            }
            case ClassWriter.INDYMETH_INSN: {
                int cpIndex = items[readUnsignedShort(u + 1)];
                int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)];
                Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c);
                int bsmArgCount = readUnsignedShort(bsmIndex + 2);
                Object[] bsmArgs = new Object[bsmArgCount];
                bsmIndex += 4;
                for (int i = 0; i < bsmArgCount; i++) {
                    bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c);
                    bsmIndex += 2;
                }
                cpIndex = items[readUnsignedShort(cpIndex + 2)];
                String iname = readUTF8(cpIndex, c);
                String idesc = readUTF8(cpIndex + 2, c);
                mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
                u += 5;
                break;
            }
            case ClassWriter.TYPE_INSN:
                mv.visitTypeInsn(opcode, readClass(u + 1, c));
                u += 3;
                break;
            case ClassWriter.IINC_INSN:
                mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]);
                u += 3;
                break;
            // case MANA_INSN:
            default:
                mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF);
                u += 4;
                break;
            }


            // visit the instruction annotations, if any
            while (tanns != null && tann < tanns.length && ntoff <= offset) {
                if (ntoff == offset) {
                    int v = readAnnotationTarget(context, tanns[tann]);
                    readAnnotationValues(v + 2, c, true,
                            mv.visitInsnAnnotation(context.target,
                                    context.path, readUTF8(v, c), true));
                }
                ntoff = ++tann >= tanns.length
                        || readUnsignedShort(tanns[tann]) < 0x86 ? -1
                        : readUnsignedShort(tanns[tann] + 2);
            }
            while (itanns != null && itann < itanns.length && nitoff <= offset) {
                if (nitoff == offset) {
                    int v = readAnnotationTarget(context, itanns[itann]);
                    readAnnotationValues(v + 2, c, true,
                            mv.visitInsnAnnotation(context.target,
                                    context.path, readUTF8(v, c), false));
                }
                nitoff = ++itann >= itanns.length
                        || readUnsignedShort(itanns[itann]) < 0x86 ? -1
                        : readUnsignedShort(itanns[itann] + 2);
            }
        }
        if (labels[codeLength] != null) {
            mv.visitLabel(labels[codeLength]);
        }


        // visits the local variable tables
        if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) {
            int[] typeTable = null;
            if (varTypeTable != 0) {
                u = varTypeTable + 2;
                typeTable = new int[readUnsignedShort(varTypeTable) * 3];
                for (int i = typeTable.length; i > 0;) {
                    typeTable[--i] = u + 6; // signature
                    typeTable[--i] = readUnsignedShort(u + 8); // index
                    typeTable[--i] = readUnsignedShort(u); // start
                    u += 10;
                }
            }
            u = varTable + 2;
            for (int i = readUnsignedShort(varTable); i > 0; --i) {
                int start = readUnsignedShort(u);
                int length = readUnsignedShort(u + 2);
                int index = readUnsignedShort(u + 8);
                String vsignature = null;
                if (typeTable != null) {
                    for (int j = 0; j < typeTable.length; j += 3) {
                        if (typeTable[j] == start && typeTable[j + 1] == index) {
                            vsignature = readUTF8(typeTable[j + 2], c);
                            break;
                        }
                    }
                }
                mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c),
                        vsignature, labels[start], labels[start + length],
                        index);
                u += 10;
            }
        }


        // visits the local variables type annotations
        if (tanns != null) {
            for (int i = 0; i < tanns.length; ++i) {
                if ((readUnsignedShort(tanns[i]) & 0xFC) == 0x80) {
                    int v = readAnnotationTarget(context, tanns[i]);
                    v = readAnnotationValues(v + 2, c, true,
                            mv.visitLocalVariableAnnotation(context.target,
                                    context.path, context.start, context.end,
                                    context.index, readUTF8(v, c), true));
                }
            }
        }
        if (itanns != null) {
            for (int i = 0; i < itanns.length; ++i) {
                if ((readUnsignedShort(itanns[i]) & 0xFC) == 0x80) {
                    int v = readAnnotationTarget(context, itanns[i]);
                    v = readAnnotationValues(v + 2, c, true,
                            mv.visitLocalVariableAnnotation(context.target,
                                    context.path, context.start, context.end,
                                    context.index, readUTF8(v, c), false));
                }
            }
        }


        // visits the code attributes
        while (attributes != null) {
            Attribute attr = attributes.next;
            attributes.next = null;
            mv.visitAttribute(attributes);
            attributes = attr;
        }


        // visits the max stack and max locals values
        mv.visitMaxs(maxStack, maxLocals);
    }

        ASM4.0在readCode里有个局部变量Label[] labels,同时也指向org.objectweb.asm.Context.labels;是通过调用org.objectweb.asm.ClassReader .readLabel(int, Label[]) 来操作的

        ASM2.2.3里边是access方法里边有一个操作Label[] labels局部变量,直接在access内读写的

 

        4.0中的labels数组,是在访问了某些指令的时候,会构造一个label:

        1、代码指令类:

     if类、goto、jsr的目标地址;
     goto_w、jsr_w的目标地址;
     tableswitch、lookupswitch目标地址、默认目标地址;

        2、异常表类

    start_pc、end_pc、handler_pc

        3、code属性的属性

    LocalVariableTable,每个变量的start_pc和start_pc + length
    LineNumberTable,指令索引、行号
    未知属性表
    StackMapTable,初始帧、栈帧表每一帧,帧类型(2个)
    RuntimeVisibleTypeAnnotations
    RuntimeInvisibleTypeAnnotations

       接下来看看asm是如何读取常量池信息的,asm根据常量池项对应的常量池索引,根据常量池索引得到其值在class文件type数组的偏移量,然后从class文件的byte数组中读取到相应长度的值,要特别注意的是float和double值的存储是按照ieee的格式存储的,所以这里在解析的时候会进行一次转换:

    /**
     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
     * method is intended for {@link Attribute} sub classes, and is normally not
     * needed by class generators or adapters.</i>
     * 
     * @param item
     *            the index of a constant pool item.
     * @param buf
     *            buffer to be used to read the item. This buffer must be
     *            sufficiently large. It is not automatically resized.
     * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
     *         {@link String}, {@link Type} or {@link Handle} corresponding to
     *         the given constant pool item.
     */
    public Object readConst(final int item, final char[] buf) {
        int index = items[item];
        switch (b[index - 1]) {
        case ClassWriter.INT://基本类型获取的都是值本身
            return new Integer(readInt(index));
        case ClassWriter.FLOAT:
            return new Float(Float.intBitsToFloat(readInt(index)));
        case ClassWriter.LONG:
            return new Long(readLong(index));
        case ClassWriter.DOUBLE:
            return new Double(Double.longBitsToDouble(readLong(index)));
        case ClassWriter.CLASS://class里边存储的是Type类型
            return Type.getObjectType(readUTF8(index, buf));
        case ClassWriter.STR:
            return readUTF8(index, buf);
        case ClassWriter.MTYPE:
            return Type.getMethodType(readUTF8(index, buf));
        default: // case ClassWriter.HANDLE_BASE + [1..9]:
            int tag = readByte(index);
            int[] items = this.items;
            int cpIndex = items[readUnsignedShort(index + 1)];
            String owner = readClass(cpIndex, buf);
            cpIndex = items[readUnsignedShort(cpIndex + 2)];
            String name = readUTF8(cpIndex, buf);
            String desc = readUTF8(cpIndex + 2, buf);
            return new Handle(tag, owner, name, desc);
        }
    }

         在MethodNode中,常量值会被转换成一个LdcInsnNode节点存储,节点的cst值就是常量值。

 《未完待续》

分享到:
评论
1 楼 demoxshiroki 2014-12-05  
楼主写的不错,在读asm源代码,看到楼主这条路线,少走不少弯路,thank you

相关推荐

    ASM4.0 中文教程与多种字节码编程实战案例

    内容包含ASM4.0中文手册,以及四种ASM常见的字节码操作应用范例,包含最新版本的ASM9.2的jar包,包含asm-9.2.jar,asm-commons-9.2.jar,asm-util-9.2.jar。 学习文章地址 ...

    asm4.0全家福

    标题中的“asm4.0全家福”指的是ASM库的一个完整版本集合,ASM是一个Java字节码操控和分析框架,主要用于动态生成类或者增强已有类的功能。这个“全家福”包括了ASM库的主要组件,分别是: 1. **asm-4.0**: 这是ASM...

    asm4.0_RC1-bin

    2. **代码分析**:ASM不仅可以生成字节码,还能分析已经存在的字节码,帮助开发者理解类和方法的行为,这对于代码混淆、性能优化以及调试有着重要的作用。 3. **低级别操作**:ASM提供了对类结构的底层访问,包括...

    asm-tree-4.0.zip_asm4.0

    标题中的"asm-tree-4.0.zip_asm4.0"提到了ASM库的特定版本,ASM是一个Java字节码操控和分析框架,主要用于动态代理、字节码转换以及代码分析等场景。ASM 4.0是这个库的一个版本,可能包含了一些针对性能和功能的改进...

    ASM4使用指南 - ASM 4 Guide 中文版

    ASM 4 使用指南中文版。ASM是Java字节码的工业级库。长期以来一直没有中文版。这下好了,中文版横空出世。感兴趣的同学可以投递简历 mars # oneapm ....ASM 4.0 A Java bytecode engineering library

    spring-asm-repack-4.0.jar

    spring 3.2.5版本源码使用的,构建的时候使用如下描述 因为英文不太好,大概意思可能是什么asm4.0版本使用的spring 在spring4中已经重新包装了asm在spring-core的核心包里,当然我这解释不标准 看下满原文构建的描述...

    asm-4.0.jar

    asm-4.0.jar

    asm操作指南(中文)

    ASM作为一款强大的Java字节码操纵框架,不仅具备高效处理字节码的能力,还能广泛应用于各种实际开发场景中,从简单的代码生成到复杂的程序分析和转换。对于希望在不改变源代码的情况下对Java应用程序进行改进的...

    asm-all-4.0.jar.zip

    标题中的"asm-all-4.0.jar.zip"指的是一个压缩包文件,该文件包含了ASM库的一个集合,版本为4.0。ASM是一个Java字节码操控和分析框架,主要用于动态生成类或者增强已有类的功能。ASM库广泛应用于字节码级别的编程,...

    asm-util-4.0_RC1.jar.zip

    ASM是一个Java字节码操控和分析框架,广泛用于动态代理、代码分析和转换等场景。ASM Util是ASM框架的一个扩展,提供了更多实用工具和功能。 在描述中,我们看到了“asm”、“util”、“4.0_RC1”和“jar.zip包下载...

    asm5.1源码-eclipse工程

    asm5.1源码 eclipse工程

    asm-4.2-API文档-中文版.zip

    赠送jar包:asm-4.2.jar; 赠送原API文档:asm-4.2-javadoc.jar; 赠送源代码:asm-4.2-sources.jar; 赠送Maven依赖信息文件:asm-4.2.pom; 包含翻译后的API文档:asm-4.2-javadoc-API文档-中文(简体)版.zip; ...

    asm5.1源码和jar

    ASM是一个Java字节码操控和分析框架,常用于动态代理、代码生成以及字节码级别的程序分析和修改。ASM库提供了对Java字节码的低级别访问,使得开发者可以直接操作和构建类文件,这对于理解Java虚拟机的工作原理,或者...

    asm5.0 源码+demo+doc

    ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。 与 BCEL 和 SERL 不同,ASM 提供了更为现代的编程模型。对于 ASM 来说,Java class 被描述为一棵树;使用 “Visitor” 模式...

    Mader.C.ASM(中国龙语言学机器码式编译器4.0)源码

    《Mader.C.ASM(中国龙语言学机器码式编译器4.0)源码》是关于计算机编程领域的一款特殊编译器的源代码,主要用于将高级语言转化为机器码,以便计算机能够直接执行。这款编译器是4.0版本,意味着它经过了多次迭代和...

    asm-4.0_RC1.jar.zip

    ASM是一个Java字节码操控和分析框架,常用于动态代理、代码分析以及转换等场景。ASM库能够直接读取和写入Java类的字节码,使得开发者可以在运行时动态生成和修改类。"asm-4.0_RC1.jar.zip" 是ASM库的4.0_RC1版本的...

    asm-all-4.0.jar

    2. **代码分析**:通过对字节码的解析,可以进行性能监控、代码安全检查等任务。 3. **字节码优化**:在运行时对代码进行优化,例如去除无用的代码或提升性能。 4. **框架实现**:许多框架如Hibernate、Spring等,都...

    ASM源码

    ASM源码很好用,可以破解任何软件

    ASM IDE源码

    - **调试技巧**:通过阅读和分析ASM IDE的源码,可以学习到调试工具的实现方法和调试策略。 - **性能优化**:了解IDE如何优化编译和链接过程,有助于提升自身汇编代码的效率。 - **扩展与定制**:熟悉源码后,...

    JavaEE源代码 asm-attrs

    JavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-...

Global site tag (gtag.js) - Google Analytics