⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classwriter.java

📁 jboss规则引擎
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
        //
        // // LABEL(W)_INSN instructions
        // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
        // b[i] = LABEL_INSN;
        // }
        // b[Constants.IFNULL] = LABEL_INSN;
        // b[Constants.IFNONNULL] = LABEL_INSN;
        // b[200] = LABELW_INSN; // GOTO_W
        // b[201] = LABELW_INSN; // JSR_W
        // // temporary opcodes used internally by ASM - see Label and
        // MethodWriter
        // for (i = 202; i < 220; ++i) {
        // b[i] = LABEL_INSN;
        // }
        //
        // // LDC(_W) instructions
        // b[Constants.LDC] = LDC_INSN;
        // b[19] = LDCW_INSN; // LDC_W
        // b[20] = LDCW_INSN; // LDC2_W
        //
        // // special instructions
        // b[Constants.IINC] = IINC_INSN;
        // b[Constants.TABLESWITCH] = TABL_INSN;
        // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
        // b[Constants.MULTIANEWARRAY] = MANA_INSN;
        // b[196] = WIDE_INSN; // WIDE
        //
        // for (i = 0; i < b.length; ++i) {
        // System.err.print((char)('A' + b[i]));
        // }
        // System.err.println();
    }

    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------

    /**
     * Constructs a new {@link ClassWriter ClassWriter} object.
     * 
     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
     *        maximum number of local variables must be automatically computed.
     *        If this flag is <tt>true</tt>, then the arguments of the
     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
     *        {@link MethodVisitor} returned by the
     *        {@link #visitMethod visitMethod} method will be ignored, and
     *        computed automatically from the signature and the bytecode of each
     *        method.
     */
    public ClassWriter(final boolean computeMaxs) {
        this( computeMaxs,
              false );
    }

    /**
     * Constructs a new {@link ClassWriter} object.
     * 
     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
     *        maximum number of local variables must be automatically computed.
     *        If this flag is <tt>true</tt>, then the arguments of the
     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
     *        {@link MethodVisitor} returned by the
     *        {@link #visitMethod visitMethod} method will be ignored, and
     *        computed automatically from the signature and the bytecode of each
     *        method.
     * @param skipUnknownAttributes <b>Deprecated</b>. The value of this
     *        parameter is ignored.
     */
    public ClassWriter(final boolean computeMaxs,
                       final boolean skipUnknownAttributes) {
        this.index = 1;
        this.pool = new ByteVector();
        this.items = new Item[256];
        this.threshold = (int) (0.75d * this.items.length);
        this.key = new Item();
        this.key2 = new Item();
        this.key3 = new Item();
        this.computeMaxs = computeMaxs;
    }

    /**
     * Constructs a new {@link ClassWriter} object and enables optimizations for
     * "mostly add" bytecode transformations. These optimizations are the
     * following:
     * 
     * <ul> <li>The constant pool from the original class is copied as is in
     * the new class, which saves time. New constant pool entries will be added
     * at the end if necessary, but unused constant pool entries <i>won't be
     * removed</i>.</li> <li>Methods that are not transformed are copied as
     * is in the new class, directly from the original class bytecode (i.e.
     * without emitting visit events for all the method instructions), which
     * saves a <i>lot</i> of time. Untransformed methods are detected by the
     * fact that the {@link ClassReader} receives {@link MethodVisitor} objects
     * that come from a {@link ClassWriter} (and not from a custom
     * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>
     * </ul>
     * 
     * @param classReader the {@link ClassReader} used to read the original
     *        class. It will be used to copy the entire constant pool from the
     *        original class and also to copy other fragments of original
     *        bytecode where applicable.
     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
     *        maximum number of local variables must be automatically computed.
     *        If this flag is <tt>true</tt>, then the arguments of the
     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
     *        {@link MethodVisitor} returned by the
     *        {@link #visitMethod visitMethod} method will be ignored, and
     *        computed automatically from the signature and the bytecode of each
     *        method.
     */
    public ClassWriter(final ClassReader classReader,
                       final boolean computeMaxs) {
        this( computeMaxs,
              false );
        classReader.copyPool( this );
        this.cr = classReader;
    }

    // ------------------------------------------------------------------------
    // Implementation of the ClassVisitor interface
    // ------------------------------------------------------------------------

    public void visit(final int version,
                      final int access,
                      final String name,
                      final String signature,
                      final String superName,
                      final String[] interfaces) {
        this.version = version;
        this.access = access;
        this.name = newClass( name );
        if ( signature != null ) {
            this.signature = newUTF8( signature );
        }
        this.superName = superName == null ? 0 : newClass( superName );
        if ( interfaces != null && interfaces.length > 0 ) {
            this.interfaceCount = interfaces.length;
            this.interfaces = new int[this.interfaceCount];
            for ( int i = 0; i < this.interfaceCount; ++i ) {
                this.interfaces[i] = newClass( interfaces[i] );
            }
        }
    }

    public void visitSource(final String file,
                            final String debug) {
        if ( file != null ) {
            this.sourceFile = newUTF8( file );
        }
        if ( debug != null ) {
            this.sourceDebug = new ByteVector().putUTF8( debug );
        }
    }

    public void visitOuterClass(final String owner,
                                final String name,
                                final String desc) {
        this.enclosingMethodOwner = newClass( owner );
        if ( name != null && desc != null ) {
            this.enclosingMethod = newNameType( name,
                                                desc );
        }
    }

    public AnnotationVisitor visitAnnotation(final String desc,
                                             final boolean visible) {
        final ByteVector bv = new ByteVector();
        // write type, and reserve space for values count
        bv.putShort( newUTF8( desc ) ).putShort( 0 );
        final AnnotationWriter aw = new AnnotationWriter( this,
                                                          true,
                                                          bv,
                                                          bv,
                                                          2 );
        if ( visible ) {
            aw.next = this.anns;
            this.anns = aw;
        } else {
            aw.next = this.ianns;
            this.ianns = aw;
        }
        return aw;
    }

    public void visitAttribute(final Attribute attr) {
        attr.next = this.attrs;
        this.attrs = attr;
    }

    public void visitInnerClass(final String name,
                                final String outerName,
                                final String innerName,
                                final int access) {
        if ( this.innerClasses == null ) {
            this.innerClasses = new ByteVector();
        }
        ++this.innerClassesCount;
        this.innerClasses.putShort( name == null ? 0 : newClass( name ) );
        this.innerClasses.putShort( outerName == null ? 0 : newClass( outerName ) );
        this.innerClasses.putShort( innerName == null ? 0 : newUTF8( innerName ) );
        this.innerClasses.putShort( access );
    }

    public FieldVisitor visitField(final int access,
                                   final String name,
                                   final String desc,
                                   final String signature,
                                   final Object value) {
        return new FieldWriter( this,
                                access,
                                name,
                                desc,
                                signature,
                                value );
    }

    public MethodVisitor visitMethod(final int access,
                                     final String name,
                                     final String desc,
                                     final String signature,
                                     final String[] exceptions) {
        return new MethodWriter( this,
                                 access,
                                 name,
                                 desc,
                                 signature,
                                 exceptions,
                                 this.computeMaxs );
    }

    public void visitEnd() {
    }

    // ------------------------------------------------------------------------
    // Other public methods
    // ------------------------------------------------------------------------

    /**
     * Returns the bytecode of the class that was build with this class writer.
     * 
     * @return the bytecode of the class that was build with this class writer.
     */
    public byte[] toByteArray() {
        // computes the real size of the bytecode of this class
        int size = 24 + 2 * this.interfaceCount;
        int nbFields = 0;
        FieldWriter fb = this.firstField;
        while ( fb != null ) {
            ++nbFields;
            size += fb.getSize();
            fb = fb.next;
        }
        int nbMethods = 0;
        MethodWriter mb = this.firstMethod;
        while ( mb != null ) {
            ++nbMethods;
            size += mb.getSize();
            mb = mb.next;
        }
        int attributeCount = 0;
        if ( this.signature != 0 ) {
            ++attributeCount;
            size += 8;
            newUTF8( "Signature" );
        }
        if ( this.sourceFile != 0 ) {
            ++attributeCount;
            size += 8;
            newUTF8( "SourceFile" );
        }
        if ( this.sourceDebug != null ) {
            ++attributeCount;
            size += this.sourceDebug.length + 4;
            newUTF8( "SourceDebugExtension" );
        }
        if ( this.enclosingMethodOwner != 0 ) {
            ++attributeCount;
            size += 10;
            newUTF8( "EnclosingMethod" );
        }
        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
            ++attributeCount;
            size += 6;
            newUTF8( "Deprecated" );
        }
        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.version & 0xffff) < Opcodes.V1_5 ) {
            ++attributeCount;
            size += 6;
            newUTF8( "Synthetic" );
        }
        if ( this.version == Opcodes.V1_4 ) {
            if ( (this.access & Opcodes.ACC_ANNOTATION) != 0 ) {
                ++attributeCount;
                size += 6;
                newUTF8( "Annotation" );
            }
            if ( (this.access & Opcodes.ACC_ENUM) != 0 ) {
                ++attributeCount;
                size += 6;
                newUTF8( "Enum" );
            }
        }
        if ( this.innerClasses != null ) {
            ++attributeCount;
            size += 8 + this.innerClasses.length;
            newUTF8( "InnerClasses" );
        }
        if ( this.anns != null ) {
            ++attributeCount;
            size += 8 + this.anns.getSize();
            newUTF8( "RuntimeVisibleAnnotations" );
        }
        if ( this.ianns != null ) {
            ++attributeCount;
            size += 8 + this.ianns.getSize();
            newUTF8( "RuntimeInvisibleAnnotations" );
        }
        if ( this.attrs != null ) {
            attributeCount += this.attrs.getCount();
            size += this.attrs.getSize( this,
                                        null,
                                        0,
                                        -1,
                                        -1 );
        }
        size += this.pool.length;
        // allocates a byte vector of this size, in order to avoid unnecessary
        // arraycopy operations in the ByteVector.enlarge() method
        final ByteVector out = new ByteVector( size );
        out.putInt( 0xCAFEBABE ).putInt( this.version );
        out.putShort( this.index ).putByteArray( this.pool.data,
                                                 0,
                                                 this.pool.length );
        out.putShort( this.access ).putShort( this.name ).putShort( this.superName );
        out.putShort( this.interfaceCount );
        for ( int i = 0; i < this.interfaceCount; ++i ) {
            out.putShort( this.interfaces[i] );
        }
        out.putShort( nbFields );
        fb = this.firstField;
        while ( fb != null ) {
            fb.put( out );
            fb = fb.next;
        }
        out.putShort( nbMethods );
        mb = this.firstMethod;
        while ( mb != null ) {
            mb.put( out );
            mb = mb.next;
        }
        out.putShort( attributeCount );
        if ( this.signature != 0 ) {
            out.putShort( newUTF8( "Signature" ) ).putInt( 2 ).putShort( this.signature );
        }
        if ( this.sourceFile != 0 ) {
            out.putShort( newUTF8( "SourceFile" ) ).putInt( 2 ).putShort( this.sourceFile );
        }
        if ( this.sourceDebug != null ) {
            final int len = this.sourceDebug.length - 2;
            out.putShort( newUTF8( "SourceDebugExtension" ) ).putInt( len );
            out.putByteArray( this.sourceDebug.data,
                              2,
                              len );
        }
        if ( this.enclosingMethodOwner != 0 ) {
            out.putShort( newUTF8( "EnclosingMethod" ) ).putInt( 4 );
            out.putShort( this.enclosingMethodOwner ).putShort( this.enclosingMethod );
        }
        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
            out.putShort( newUTF8( "Deprecated" ) ).putInt( 0 );
        }
        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.version & 0xffff) < Opcodes.V1_5 ) {
            out.putShort( newUTF8( "Synthetic" ) ).putInt( 0 );
        }
        if ( this.version == Opcodes.V1_4 ) {
            if ( (this.access & Opcodes.ACC_ANNOTATION) != 0 ) {
                out.putShort( newUTF8( "Annotation" ) ).putInt( 0 );
            }
            if ( (this.access & Opcodes.ACC_ENUM) != 0 ) {
                out.putShort( newUTF8( "Enum" ) ).putInt( 0 );
            }
        }
        if ( this.innerClasses != null ) {
            out.putShort( newUTF8( "InnerClasses" ) );
            out.putInt( this.innerClasses.length + 2 ).putShort( this.innerClassesCount );
            out.putByteArray( this.innerClasses.data,
                              0,
                              this.innerClasses.length );
        }
        if ( this.anns != null ) {
            out.putShort( newUTF8( "RuntimeVisibleAnnotations" ) );
            this.anns.put( out );
        }
        if ( this.ianns != null ) {
            out.putShort( newUTF8( "RuntimeInvisibleAnnotations" ) );
            this.ianns.put( out );
        }
        if ( this.attrs != null ) {
            this.attrs.put( this,
                            null,
                            0,
                            -1,
                            -1,
                            out );
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -