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

📄 classreader.java

📁 jboss规则引擎
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/***
 * ASM: a very small and fast Java bytecode manipulation framework
 * Copyright (c) 2000-2005 INRIA, France Telecom
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.drools.asm;

import java.io.IOException;
import java.io.InputStream;

/**
 * A Java class parser to make a {@link ClassVisitor} visit an existing class.
 * This class parses a byte array conforming to the Java class file format and
 * calls the appropriate visit methods of a given class visitor for each field,
 * method and bytecode instruction encountered.
 * 
 * @author Eric Bruneton
 * @author Eugene Kuleshov
 */
public class ClassReader {

    /**
     * The class to be parsed. <i>The content of this array must not be
     * modified. This field is intended for {@link Attribute} sub classes, and
     * is normally not needed by class generators or adapters.</i>
     */
    public final byte[] b;

    /**
     * The start index of each constant pool item in {@link #b b}, plus one.
     * The one byte offset skips the constant pool item tag that indicates its
     * type.
     */
    private int[]       items;

    /**
     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
     * which GREATLY improves performances (by a factor 2 to 3). This caching
     * strategy could be extended to all constant pool items, but its benefit
     * would not be so great for these items (because they are much less
     * expensive to parse than CONSTANT_Utf8 items).
     */
    private String[]    strings;

    /**
     * Maximum length of the strings contained in the constant pool of the
     * class.
     */
    private int         maxStringLength;

    /**
     * Start index of the class header information (access, name...) in
     * {@link #b b}.
     */
    public final int    header;

    // ------------------------------------------------------------------------
    // Constructors
    // ------------------------------------------------------------------------

    /**
     * Constructs a new {@link ClassReader} object.
     * 
     * @param b the bytecode of the class to be read.
     */
    public ClassReader(final byte[] b) {
        this( b,
              0,
              b.length );
    }

    /**
     * Constructs a new {@link ClassReader} object.
     * 
     * @param b the bytecode of the class to be read.
     * @param off the start offset of the class data.
     * @param len the length of the class data.
     */
    public ClassReader(final byte[] b,
                       final int off,
                       final int len) {
        this.b = b;
        // parses the constant pool
        this.items = new int[readUnsignedShort( off + 8 )];
        final int ll = this.items.length;
        this.strings = new String[ll];
        int max = 0;
        int index = off + 10;
        for ( int i = 1; i < ll; ++i ) {
            this.items[i] = index + 1;
            final int tag = b[index];
            int size;
            switch ( tag ) {
                case ClassWriter.FIELD :
                case ClassWriter.METH :
                case ClassWriter.IMETH :
                case ClassWriter.INT :
                case ClassWriter.FLOAT :
                case ClassWriter.NAME_TYPE :
                    size = 5;
                    break;
                case ClassWriter.LONG :
                case ClassWriter.DOUBLE :
                    size = 9;
                    ++i;
                    break;
                case ClassWriter.UTF8 :
                    size = 3 + readUnsignedShort( index + 1 );
                    if ( size > max ) {
                        max = size;
                    }
                    break;
                // case ClassWriter.CLASS:
                // case ClassWriter.STR:
                default :
                    size = 3;
                    break;
            }
            index += size;
        }
        this.maxStringLength = max;
        // the class header information starts just after the constant pool
        this.header = index;
    }

    /**
     * Copies the constant pool data into the given {@link ClassWriter}. Should
     * be called before the {@link #accept(ClassVisitor,boolean)} method.
     * 
     * @param classWriter the {@link ClassWriter} to copy constant pool into.
     */
    void copyPool(final ClassWriter classWriter) {
        final char[] buf = new char[this.maxStringLength];
        final int ll = this.items.length;
        final Item[] items2 = new Item[ll];
        for ( int i = 1; i < ll; i++ ) {
            int index = this.items[i];
            final int tag = this.b[index - 1];
            final Item item = new Item( i );
            int nameType;
            switch ( tag ) {
                case ClassWriter.FIELD :
                case ClassWriter.METH :
                case ClassWriter.IMETH :
                    nameType = this.items[readUnsignedShort( index + 2 )];
                    item.set( tag,
                              readClass( index,
                                         buf ),
                              readUTF8( nameType,
                                        buf ),
                              readUTF8( nameType + 2,
                                        buf ) );
                    break;

                case ClassWriter.INT :
                    item.set( readInt( index ) );
                    break;

                case ClassWriter.FLOAT :
                    item.set( Float.intBitsToFloat( readInt( index ) ) );
                    break;

                case ClassWriter.NAME_TYPE :
                    item.set( tag,
                              readUTF8( index,
                                        buf ),
                              readUTF8( index + 2,
                                        buf ),
                              null );
                    break;

                case ClassWriter.LONG :
                    item.set( readLong( index ) );
                    ++i;
                    break;

                case ClassWriter.DOUBLE :
                    item.set( Double.longBitsToDouble( readLong( index ) ) );
                    ++i;
                    break;

                case ClassWriter.UTF8 : {
                    String s = this.strings[i];
                    if ( s == null ) {
                        index = this.items[i];
                        s = this.strings[i] = readUTF( index + 2,
                                                       readUnsignedShort( index ),
                                                       buf );
                    }
                    item.set( tag,
                              s,
                              null,
                              null );
                }
                    break;

                // case ClassWriter.STR:
                // case ClassWriter.CLASS:
                default :
                    item.set( tag,
                              readUTF8( index,
                                        buf ),
                              null,
                              null );
                    break;
            }

            final int index2 = item.hashCode % items2.length;
            item.next = items2[index2];
            items2[index2] = item;
        }

        final int off = this.items[1] - 1;
        classWriter.pool.putByteArray( this.b,
                                       off,
                                       this.header - off );
        classWriter.items = items2;
        classWriter.threshold = (int) (0.75d * ll);
        classWriter.index = ll;
    }

    /**
     * Constructs a new {@link ClassReader} object.
     * 
     * @param is an input stream from which to read the class.
     * @throws IOException if a problem occurs during reading.
     */
    public ClassReader(final InputStream is) throws IOException {
        this( readClass( is ) );
    }

    /**
     * Constructs a new {@link ClassReader} object.
     * 
     * @param name the fully qualified name of the class to be read.
     * @throws IOException if an exception occurs during reading.
     */
    public ClassReader(final String name) throws IOException {
        this( ClassLoader.getSystemResourceAsStream( name.replace( '.',
                                                                   '/' ) + ".class" ) );
    }

    /**
     * Reads the bytecode of a class.
     * 
     * @param is an input stream from which to read the class.
     * @return the bytecode read from the given input stream.
     * @throws IOException if a problem occurs during reading.
     */
    private static byte[] readClass(final InputStream is) throws IOException {
        if ( is == null ) {
            throw new IOException( "Class not found" );
        }
        byte[] b = new byte[is.available()];
        int len = 0;
        while ( true ) {
            final int n = is.read( b,
                                   len,
                                   b.length - len );
            if ( n == -1 ) {
                if ( len < b.length ) {
                    final byte[] c = new byte[len];
                    System.arraycopy( b,
                                      0,
                                      c,
                                      0,
                                      len );
                    b = c;
                }
                return b;
            }
            len += n;
            if ( len == b.length ) {

⌨️ 快捷键说明

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