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

📄 methodwriter.java

📁 jboss规则引擎
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
                                        0,
                                        -1,
                                        -1 );
        }
        return size;
    }

    /**
     * Puts the bytecode of this method in the given byte vector.
     * 
     * @param out the byte vector into which the bytecode of this method must be
     *        copied.
     */
    final void put(final ByteVector out) {
        out.putShort( this.access ).putShort( this.name ).putShort( this.desc );
        if ( this.classReaderOffset != 0 ) {
            out.putByteArray( this.cw.cr.b,
                              this.classReaderOffset,
                              this.classReaderLength );
            return;
        }
        int attributeCount = 0;
        if ( this.code.length > 0 ) {
            ++attributeCount;
        }
        if ( this.exceptionCount > 0 ) {
            ++attributeCount;
        }
        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
            ++attributeCount;
        }
        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
            ++attributeCount;
        }
        if ( this.cw.version == Opcodes.V1_4 ) {
            if ( (this.access & Opcodes.ACC_VARARGS) != 0 ) {
                ++attributeCount;
            }
            if ( (this.access & Opcodes.ACC_BRIDGE) != 0 ) {
                ++attributeCount;
            }
        }
        if ( this.signature != null ) {
            ++attributeCount;
        }
        if ( this.annd != null ) {
            ++attributeCount;
        }
        if ( this.anns != null ) {
            ++attributeCount;
        }
        if ( this.ianns != null ) {
            ++attributeCount;
        }
        if ( this.panns != null ) {
            ++attributeCount;
        }
        if ( this.ipanns != null ) {
            ++attributeCount;
        }
        if ( this.attrs != null ) {
            attributeCount += this.attrs.getCount();
        }
        out.putShort( attributeCount );
        if ( this.code.length > 0 ) {
            int size = 12 + this.code.length + 8 * this.catchCount;
            if ( this.localVar != null ) {
                size += 8 + this.localVar.length;
            }
            if ( this.localVarType != null ) {
                size += 8 + this.localVarType.length;
            }
            if ( this.lineNumber != null ) {
                size += 8 + this.lineNumber.length;
            }
            if ( this.cattrs != null ) {
                size += this.cattrs.getSize( this.cw,
                                             this.code.data,
                                             this.code.length,
                                             this.maxStack,
                                             this.maxLocals );
            }
            out.putShort( this.cw.newUTF8( "Code" ) ).putInt( size );
            out.putShort( this.maxStack ).putShort( this.maxLocals );
            out.putInt( this.code.length ).putByteArray( this.code.data,
                                                         0,
                                                         this.code.length );
            out.putShort( this.catchCount );
            if ( this.catchCount > 0 ) {
                Handler h = this.catchTable;
                while ( h != null ) {
                    out.putShort( h.start.position ).putShort( h.end.position ).putShort( h.handler.position ).putShort( h.type );
                    h = h.next;
                }
            }
            attributeCount = 0;
            if ( this.localVar != null ) {
                ++attributeCount;
            }
            if ( this.localVarType != null ) {
                ++attributeCount;
            }
            if ( this.lineNumber != null ) {
                ++attributeCount;
            }
            if ( this.cattrs != null ) {
                attributeCount += this.cattrs.getCount();
            }
            out.putShort( attributeCount );
            if ( this.localVar != null ) {
                out.putShort( this.cw.newUTF8( "LocalVariableTable" ) );
                out.putInt( this.localVar.length + 2 ).putShort( this.localVarCount );
                out.putByteArray( this.localVar.data,
                                  0,
                                  this.localVar.length );
            }
            if ( this.localVarType != null ) {
                out.putShort( this.cw.newUTF8( "LocalVariableTypeTable" ) );
                out.putInt( this.localVarType.length + 2 ).putShort( this.localVarTypeCount );
                out.putByteArray( this.localVarType.data,
                                  0,
                                  this.localVarType.length );
            }
            if ( this.lineNumber != null ) {
                out.putShort( this.cw.newUTF8( "LineNumberTable" ) );
                out.putInt( this.lineNumber.length + 2 ).putShort( this.lineNumberCount );
                out.putByteArray( this.lineNumber.data,
                                  0,
                                  this.lineNumber.length );
            }
            if ( this.cattrs != null ) {
                this.cattrs.put( this.cw,
                                 this.code.data,
                                 this.code.length,
                                 this.maxLocals,
                                 this.maxStack,
                                 out );
            }
        }
        if ( this.exceptionCount > 0 ) {
            out.putShort( this.cw.newUTF8( "Exceptions" ) ).putInt( 2 * this.exceptionCount + 2 );
            out.putShort( this.exceptionCount );
            for ( int i = 0; i < this.exceptionCount; ++i ) {
                out.putShort( this.exceptions[i] );
            }
        }
        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
            out.putShort( this.cw.newUTF8( "Synthetic" ) ).putInt( 0 );
        }
        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
            out.putShort( this.cw.newUTF8( "Deprecated" ) ).putInt( 0 );
        }
        if ( this.cw.version == Opcodes.V1_4 ) {
            if ( (this.access & Opcodes.ACC_VARARGS) != 0 ) {
                out.putShort( this.cw.newUTF8( "Varargs" ) ).putInt( 0 );
            }
            if ( (this.access & Opcodes.ACC_BRIDGE) != 0 ) {
                out.putShort( this.cw.newUTF8( "Bridge" ) ).putInt( 0 );
            }
        }
        if ( this.signature != null ) {
            out.putShort( this.cw.newUTF8( "Signature" ) ).putInt( 2 ).putShort( this.cw.newUTF8( this.signature ) );
        }
        if ( this.annd != null ) {
            out.putShort( this.cw.newUTF8( "AnnotationDefault" ) );
            out.putInt( this.annd.length );
            out.putByteArray( this.annd.data,
                              0,
                              this.annd.length );
        }
        if ( this.anns != null ) {
            out.putShort( this.cw.newUTF8( "RuntimeVisibleAnnotations" ) );
            this.anns.put( out );
        }
        if ( this.ianns != null ) {
            out.putShort( this.cw.newUTF8( "RuntimeInvisibleAnnotations" ) );
            this.ianns.put( out );
        }
        if ( this.panns != null ) {
            out.putShort( this.cw.newUTF8( "RuntimeVisibleParameterAnnotations" ) );
            AnnotationWriter.put( this.panns,
                                  out );
        }
        if ( this.ipanns != null ) {
            out.putShort( this.cw.newUTF8( "RuntimeInvisibleParameterAnnotations" ) );
            AnnotationWriter.put( this.ipanns,
                                  out );
        }
        if ( this.attrs != null ) {
            this.attrs.put( this.cw,
                            null,
                            0,
                            -1,
                            -1,
                            out );
        }
    }

    // ------------------------------------------------------------------------
    // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
    // ------------------------------------------------------------------------

    /**
     * Resizes the designated instructions, while keeping jump offsets and
     * instruction addresses consistent. This may require to resize other
     * existing instructions, or even to introduce new instructions: for
     * example, increasing the size of an instruction by 2 at the middle of a
     * method can increases the offset of an IFEQ instruction from 32766 to
     * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
     * 32765. This, in turn, may require to increase the size of another jump
     * instruction, and so on... All these operations are handled automatically
     * by this method. <p> <i>This method must be called after all the method
     * that is being built has been visited</i>. In particular, the
     * {@link Label Label} objects used to construct the method are no longer
     * valid after this method has been called.
     * 
     * @param indexes current positions of the instructions to be resized. Each
     *        instruction must be designated by the index of its <i>last</i>
     *        byte, plus one (or, in other words, by the index of the <i>first</i>
     *        byte of the <i>next</i> instruction).
     * @param sizes the number of bytes to be <i>added</i> to the above
     *        instructions. More precisely, for each i &lt; <tt>len</tt>,
     *        <tt>sizes</tt>[i] bytes will be added at the end of the
     *        instruction designated by <tt>indexes</tt>[i] or, if
     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
     *        bytes of the instruction will be removed (the instruction size
     *        <i>must not</i> become negative or null). The gaps introduced by
     *        this method must be filled in "manually" in {@link #code code}
     *        method.
     * @param len the number of instruction to be resized. Must be smaller than
     *        or equal to <tt>indexes</tt>.length and <tt>sizes</tt>.length.
     * @return the <tt>indexes</tt> array, which now contains the new
     *         positions of the resized instructions (designated as above).
     */
    private int[] resizeInstructions(final int[] indexes,
                                     final int[] sizes,
                                     final int len) {
        byte[] b = this.code.data; // bytecode of the method
        int u, v, label; // indexes in b
        int i, j; // loop indexes

        /*
         * 1st step: As explained above, resizing an instruction may require to
         * resize another one, which may require to resize yet another one, and
         * so on. The first step of the algorithm consists in finding all the
         * instructions that need to be resized, without modifying the code.
         * This is done by the following "fix point" algorithm:
         * 
         * Parse the code to find the jump instructions whose offset will need
         * more than 2 bytes to be stored (the future offset is computed from
         * the current offset and from the number of bytes that will be inserted
         * or removed between the source and target instructions). For each such
         * instruction, adds an entry in (a copy of) the indexes and sizes
         * arrays (if this has not already been done in a previous iteration!).
         * 
         * If at least one entry has been added during the previous step, go
         * back to the beginning, otherwise stop.
         * 
         * In fact the real algorithm is complicated by the fact that the size
         * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
         * position in the bytecode (because of padding). In order to ensure the
         * convergence of the algorithm, the number of bytes to be added or
         * removed from these instructions is over estimated during the previous
         * loop, and computed exactly only after the loop is finished (this
         * requires another pass to parse the bytecode of the method).
         */
        int[] allIndexes = new int[len]; // copy of indexes
        int[] allSizes = new int[len]; // copy of sizes
        boolean[] resize; // instructions to be resized
        int newOffset; // future offset of a jump instruction

        System.arraycopy( indexes,
                          0,
                          allIndexes,
                          0,
                          len );
        System.arraycopy( sizes,
                          0,
                          allSizes,
                          0,
                          len );
        resize = new boolean[this.code.length];

        // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
        int state = 3;
        do {
            if ( state == 3 ) {
                state = 2;
            }
            u = 0;
            while ( u < b.length ) {
                int opcode = b[u] & 0xFF; // opcode of current instruction
                int insert = 0; // bytes to be added after this instruction

                switch ( ClassWriter.TYPE[opcode] ) {
                    case ClassWriter.NOARG_INSN :
                    case ClassWriter.IMPLVAR_INSN :
                        u += 1;
                        break;
                    case ClassWriter.LABEL_INSN :
                        if ( opcode > 201 ) {
                            // converts temporary opcodes 202 to 217, 218 and
                            // 219 to IFEQ ... JSR (inclusive), IFNULL and
                            // IFNONNULL
                            opcode = opcode < 218 ? opcode - 49 : opcode - 20;
                            label = u + readUnsignedShort( b,
                                                           u + 1 );
                        } else {
                            label = u + readShort( b,
                                                   u + 1 );
                        }
                        newOffset = getNewOffset( allIndexes,
                                                  allSizes,
                                                  u,
                                                  label );
                        if ( newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE ) {
                            if ( !resize[u] ) {
                                if ( opcode == Opcodes.GOTO || opcode == Opcodes.JSR ) {
                                    // two additional bytes will be required to
                                    // replace this GOTO or JSR instruction with
                                    // a GOTO_W or a JSR_W
                                    insert = 2;
                                } else {
             

⌨️ 快捷键说明

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