zoukankan      html  css  js  c++  java
  • open jdk javap对于class文件的解析分析

    package sun.tools.javap;
    
    import java.util.*;
    import java.io.*;
    
    /**
     * Central data repository of the Java Disassembler.
     * Stores all the information in java class file.
     *
     * @author  Sucheta Dambalkar (Adopted code from jdis)
     */
    public class ClassData implements RuntimeConstants {
    
        private int magic;
        private int minor_version;
        private int major_version;
        private int cpool_count;
        private Object cpool[];
        private int access;
        private int this_class = 0;;
        private int super_class;
        private int interfaces_count;
        private int[] interfaces = new int[0];;
        private int fields_count;
        private FieldData[] fields;
        private int methods_count;
        private MethodData[] methods;
        private InnerClassData[] innerClasses;
        private int attributes_count;
        private AttrData[] attrs;
        private String classname;
        private String superclassname;
        private int source_cpx=0;
        private byte tags[];
        private Hashtable indexHashAscii = new Hashtable();
        private String pkgPrefix="";
        private int pkgPrefixLen=0;
    
        /**
         * Read classfile to disassemble.
         */
        public ClassData(InputStream infile){
            try{
                this.read(new DataInputStream(infile));
            }catch (FileNotFoundException ee) {
                error("cant read file");
            }catch (Error ee) {
                ee.printStackTrace();
                error("fatal error");
            } catch (Exception ee) {
                ee.printStackTrace();
                error("fatal exception");
            }
        }
    
        /**
         * Reads and stores class file information.
         */
        public void read(DataInputStream in) throws IOException {
            // Read the header
            magic = in.readInt();//先读取魔法数,值为0xcafebabe,以此来区分是否为java class文件
            if (magic != JAVA_MAGIC) { 
                throw new ClassFormatError("wrong magic: " +
                                           toHex(magic) + ", expected " +
                                           toHex(JAVA_MAGIC));
            }
            minor_version = in.readShort();
            major_version = in.readShort();
            if (major_version != JAVA_VERSION) {//class文件版本号,现在我的jdk版本里面配置的是45,JAVA_MINOR_VERSION为3
            }
    
            // Read the constant pool
            readCP(in);//读取常量池
            access = in.readUnsignedShort();//访问标识字段,标识是否为public,final,abstract等很多访问控制
            this_class = in.readUnsignedShort();//类的常量池索引项
            super_class = in.readUnsignedShort();//父类的常量池索引项
    
            //Read interfaces.
            interfaces_count = in.readUnsignedShort();//接口个数
            if(interfaces_count > 0){
                interfaces = new int[interfaces_count];
            }
            for (int i = 0; i < interfaces_count; i++) {
                interfaces[i]=in.readShort();//每个接口的常量池索引项
            }
    
            // Read the fields
            readFields(in);//读取类字段
    
            // Read the methods
            readMethods(in);//读取类的方法信息
    
            // Read the attributes
            attributes_count = in.readUnsignedShort(); //读取类的属性信息
            attrs=new AttrData[attributes_count];
            for (int k = 0; k < attributes_count; k++) {
                int name_cpx=in.readUnsignedShort();
                if (getTag(name_cpx)==CONSTANT_UTF8
                    && getString(name_cpx).equals("SourceFile")
                    ){      if (in.readInt()!=2)
                        throw new ClassFormatError("invalid attr length");
                    source_cpx=in.readUnsignedShort();
                    AttrData attr=new AttrData(this);
                    attr.read(name_cpx);
                    attrs[k]=attr;
    
                } else if (getTag(name_cpx)==CONSTANT_UTF8
                           && getString(name_cpx).equals("InnerClasses")
                           ){       int length=in.readInt();
                           int num=in.readUnsignedShort();
                           if (2+num*8 != length)
                               throw new ClassFormatError("invalid attr length");
                           innerClasses=new InnerClassData[num];
                           for (int j = 0; j < num; j++) {
                               InnerClassData innerClass=new InnerClassData(this);
                               innerClass.read(in);
                               innerClasses[j]=innerClass;
                           }
                           AttrData attr=new AttrData(this);
                           attr.read(name_cpx);
                           attrs[k]=attr;
                } else {
                    AttrData attr=new AttrData(this);
                    attr.read(name_cpx, in);
                    attrs[k]=attr;
                }
            }
            in.close();
        } // end ClassData.read()
    
        /**
         * Reads and stores constant pool info.
         */
        void readCP(DataInputStream in) throws IOException {
            cpool_count = in.readUnsignedShort();
            tags = new byte[cpool_count];
            cpool = new Object[cpool_count];
            for (int i = 1; i < cpool_count; i++) {
                byte tag = in.readByte();
    
                switch(tags[i] = tag) {
                case CONSTANT_UTF8:
                    String str=in.readUTF();
                    indexHashAscii.put(cpool[i] = str, new Integer(i));
                    break;
                case CONSTANT_INTEGER:
                    cpool[i] = new Integer(in.readInt());
                    break;
                case CONSTANT_FLOAT:
                    cpool[i] = new Float(in.readFloat());
                    break;
                case CONSTANT_LONG:
                    cpool[i++] = new Long(in.readLong());
                    break;
                case CONSTANT_DOUBLE:
                    cpool[i++] = new Double(in.readDouble());
                    break;
                case CONSTANT_CLASS:
                case CONSTANT_STRING:
                    cpool[i] = new CPX(in.readUnsignedShort());
                    break;
    
                case CONSTANT_FIELD:
                case CONSTANT_METHOD:
                case CONSTANT_INTERFACEMETHOD:
                case CONSTANT_NAMEANDTYPE:
                    cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
                    break;
    
                case 0:
                default:
                    throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
                }
            }
        }
    
        /**
         * Reads and strores field info.
         */
        protected void readFields(DataInputStream in) throws IOException {
            int fields_count = in.readUnsignedShort();
            fields=new FieldData[fields_count];
            for (int k = 0; k < fields_count; k++) {
                FieldData field=new FieldData(this);
                field.read(in);
                fields[k]=field;
            }
        }
    
        /**
         * Reads and strores Method info.
         */
        protected void readMethods(DataInputStream in) throws IOException {
            int methods_count = in.readUnsignedShort();
            methods=new MethodData[methods_count];
            for (int k = 0; k < methods_count ; k++) {
                MethodData method=new MethodData(this);
                method.read(in);
                methods[k]=method;
            }
        }
    
        /**
         * get a string
         */
        public String getString(int n) {
            return (n == 0) ? null : (String)cpool[n];
        }
    
        /**
         * get the type of constant given an index
         */
        public byte getTag(int n) {
            try{
                return tags[n];
            } catch (ArrayIndexOutOfBoundsException e) {
                return (byte)100;
            }
        }
    
        static final String hexString="0123456789ABCDEF";
    
        public static char hexTable[]=hexString.toCharArray();
    
        static String toHex(long val, int width) {
            StringBuffer s = new StringBuffer();
            for (int i=width-1; i>=0; i--)
                s.append(hexTable[((int)(val>>(4*i)))&0xF]);
            return "0x"+s.toString();
        }
    
        static String toHex(long val) {
            int width;
            for (width=16; width>0; width--) {
                if ((val>>(width-1)*4)!=0) break;
            }
            return toHex(val, width);
        }
    
        static String toHex(int val) {
            int width;
            for (width=8; width>0; width--) {
                if ((val>>(width-1)*4)!=0) break;
            }
            return toHex(val, width);
        }
    
        public void error(String msg) {
            System.err.println("ERROR:" +msg);
        }
    
        /**
         * Returns the name of this class.
         */
        public String getClassName() {
            String res=null;
            if (this_class==0) {
                return res;
            }
            int tcpx;
            try {
                if (tags[this_class]!=CONSTANT_CLASS) {
                    return res; //"<CP["+cpx+"] is not a Class> ";
                }
                tcpx=((CPX)cpool[this_class]).cpx;
            } catch (ArrayIndexOutOfBoundsException e) {
                return res; // "#"+cpx+"// invalid constant pool index";
            } catch (Throwable e) {
                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
            }
    
            try {
                return (String)(cpool[tcpx]);
            } catch (ArrayIndexOutOfBoundsException e) {
                return  res; // "class #"+scpx+"// invalid constant pool index";
            } catch (ClassCastException e) {
                return  res; // "class #"+scpx+"// invalid constant pool reference";
            } catch (Throwable e) {
                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
            }
    
        }
    
        /**
         * Returns the name of class at perticular index.
         */
        public String getClassName(int cpx) {
            String res="#"+cpx;
            if (cpx==0) {
                return res;
            }
            int scpx;
            try {
                if (tags[cpx]!=CONSTANT_CLASS) {
                    return res; //"<CP["+cpx+"] is not a Class> ";
                }
                scpx=((CPX)cpool[cpx]).cpx;
            } catch (ArrayIndexOutOfBoundsException e) {
                return res; // "#"+cpx+"// invalid constant pool index";
            } catch (Throwable e) {
                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
            }
            res="#"+scpx;
            try {
                return (String)(cpool[scpx]);
            } catch (ArrayIndexOutOfBoundsException e) {
                return  res; // "class #"+scpx+"// invalid constant pool index";
            } catch (ClassCastException e) {
                return  res; // "class #"+scpx+"// invalid constant pool reference";
            } catch (Throwable e) {
                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
            }
        }
    
        /**
         * Returns true if it is a class
         */
        public boolean isClass() {
            if((access & ACC_INTERFACE) == 0) return true;
            return false;
        }
    
        /**
         * Returns true if it is a interface.
         */
        public boolean isInterface(){
            if((access & ACC_INTERFACE) != 0) return true;
            return false;
        }
    
        /**
         * Returns true if this member is public, false otherwise.
         */
        public boolean isPublic(){
            return (access & ACC_PUBLIC) != 0;
        }
    
        /**
         * Returns the access of this class or interface.
         */
        public String[] getAccess(){
            Vector v = new Vector();
            if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
            if ((access & ACC_FINAL)    !=0) v.addElement("final");
            if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
            String[] accflags = new String[v.size()];
            v.copyInto(accflags);
            return accflags;
        }
    
        /**
         * Returns list of innerclasses.
         */
        public InnerClassData[] getInnerClasses(){
            return innerClasses;
        }
    
        /**
         * Returns list of attributes.
         */
        public AttrData[] getAttributes(){
            return attrs;
        }
    
        /**
         * Returns true if superbit is set.
         */
        public boolean isSuperSet(){
            if ((access & ACC_SUPER)   !=0) return true;
            return false;
        }
    
        /**
         * Returns super class name.
         */
        public String getSuperClassName(){
            String res=null;
            if (super_class==0) {
                return res;
            }
            int scpx;
            try {
                if (tags[super_class]!=CONSTANT_CLASS) {
                    return res; //"<CP["+cpx+"] is not a Class> ";
                }
                scpx=((CPX)cpool[super_class]).cpx;
            } catch (ArrayIndexOutOfBoundsException e) {
                return res; // "#"+cpx+"// invalid constant pool index";
            } catch (Throwable e) {
                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
            }
    
            try {
                return (String)(cpool[scpx]);
            } catch (ArrayIndexOutOfBoundsException e) {
                return  res; // "class #"+scpx+"// invalid constant pool index";
            } catch (ClassCastException e) {
                return  res; // "class #"+scpx+"// invalid constant pool reference";
            } catch (Throwable e) {
                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
            }
        }
    
        /**
         * Returns list of super interfaces.
         */
        public String[] getSuperInterfaces(){
            String interfacenames[] = new String[interfaces.length];
            int interfacecpx = -1;
            for(int i = 0; i < interfaces.length; i++){
                interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
                interfacenames[i] = (String)(cpool[interfacecpx]);
            }
            return interfacenames;
        }
    
        /**
         * Returns string at prticular constant pool index.
         */
        public String getStringValue(int cpoolx) {
            try {
                return ((String)cpool[cpoolx]);
            } catch (ArrayIndexOutOfBoundsException e) {
                return "//invalid constant pool index:"+cpoolx;
            } catch (ClassCastException e) {
                return "//invalid constant pool ref:"+cpoolx;
            }
        }
    
        /**
         * Returns list of field info.
         */
        public  FieldData[] getFields(){
            return fields;
        }
    
        /**
         * Returns list of method info.
         */
        public  MethodData[] getMethods(){
            return methods;
        }
    
        /**
         * Returns constant pool entry at that index.
         */
        public CPX2 getCpoolEntry(int cpx){
            return ((CPX2)(cpool[cpx]));
        }
    
        public Object getCpoolEntryobj(int cpx){
            return (cpool[cpx]);
        }
    
        /**
         * Returns index of this class.
         */
        public int getthis_cpx(){
            return this_class;
        }
    
        public String TagString (int tag) {
            String res=Tables.tagName(tag);
            if (res==null)  return "BOGUS_TAG:"+tag;
            return res;
        }
    
        /**
         * Returns string at that index.
         */
        public String StringValue(int cpx) {
            if (cpx==0) return "#0";
            int tag;
            Object x;
            String suffix="";
            try {
                tag=tags[cpx];
                x=cpool[cpx];
            } catch (IndexOutOfBoundsException e) {
                return "<Incorrect CP index:"+cpx+">";
            }
    
            if (x==null) return "<NULL>";
            switch (tag) {
            case CONSTANT_UTF8: {
                StringBuffer sb=new StringBuffer();
                String s=(String)x;
                for (int k=0; k<s.length(); k++) {
                    char c=s.charAt(k);
                    switch (c) {
                    case '\t': sb.append('\\').append('t'); break;
                    case '\n': sb.append('\\').append('n'); break;
                    case '\r': sb.append('\\').append('r'); break;
                    case '\"': sb.append('\\').append('\"'); break;
                    default: sb.append(c);
                    }
                }
                return sb.toString();
            }
            case CONSTANT_DOUBLE: {
                Double d=(Double)x;
                String sd=d.toString();
                return sd+"d";
            }
            case CONSTANT_FLOAT: {
                Float f=(Float)x;
                String sf=(f).toString();
                return sf+"f";
            }
            case CONSTANT_LONG: {
                Long ln = (Long)x;
                return ln.toString()+'l';
            }
            case CONSTANT_INTEGER: {
                Integer in = (Integer)x;
                return in.toString();
            }
            case CONSTANT_CLASS:
                return javaName(getClassName(cpx));
            case CONSTANT_STRING:
                return StringValue(((CPX)x).cpx);
            case CONSTANT_FIELD:
            case CONSTANT_METHOD:
            case CONSTANT_INTERFACEMETHOD:
                //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
                 return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
    
            case CONSTANT_NAMEANDTYPE:
                return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
            default:
                return "UnknownTag"; //TBD
            }
        }
    
        /**
         * Returns resolved java type name.
         */
        public String javaName(String name) {
            if( name==null) return "null";
            int len=name.length();
            if (len==0) return "\"\"";
            int cc='/';
        fullname: { // xxx/yyy/zzz
                int cp;
                for (int k=0; k<len; k += Character.charCount(cp)) {
                    cp=name.codePointAt(k);
                    if (cc=='/') {
                        if (!Character.isJavaIdentifierStart(cp)) break fullname;
                    } else if (cp!='/') {
                        if (!Character.isJavaIdentifierPart(cp)) break fullname;
                    }
                    cc=cp;
                }
                return name;
            }
            return "\""+name+"\"";
        }
    
        public String getName(int cpx) {
            String res;
            try {
                return javaName((String)cpool[cpx]); //.replace('/','.');
            } catch (ArrayIndexOutOfBoundsException e) {
                return "<invalid constant pool index:"+cpx+">";
            } catch (ClassCastException e) {
                return "<invalid constant pool ref:"+cpx+">";
            }
        }
    
        /**
         * Returns unqualified class name.
         */
        public String getShortClassName(int cpx) {
            String classname=javaName(getClassName(cpx));
            pkgPrefixLen=classname.lastIndexOf("/")+1;
            if (pkgPrefixLen!=0) {
                pkgPrefix=classname.substring(0,pkgPrefixLen);
                if (classname.startsWith(pkgPrefix)) {
                    return classname.substring(pkgPrefixLen);
                }
            }
            return classname;
        }
    
        /**
         * Returns source file name.
         */
        public String getSourceName(){
            return getName(source_cpx);
        }
    
        /**
         * Returns package name.
         */
        public String getPkgName(){
            String classname=getClassName(this_class);
            pkgPrefixLen=classname.lastIndexOf("/")+1;
            if (pkgPrefixLen!=0) {
                pkgPrefix=classname.substring(0,pkgPrefixLen);
                return("package  "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
            }else return null;
        }
    
        /**
         * Returns total constant pool entry count.
         */
        public int getCpoolCount(){
            return cpool_count;
        }
    
        public String StringTag(int cpx) {
            byte tag=0;
            String str=null;
            try {
                if (cpx==0) throw new IndexOutOfBoundsException();
                tag=tags[cpx];
                return      TagString(tag);
            } catch (IndexOutOfBoundsException e) {
                str="Incorrect CP index:"+cpx;
            }
            return str;
        }
    
        /**
         * Returns minor version of class file.
         */
        public int getMinor_version(){
            return minor_version;
        }
    
        /**
         * Returns major version of class file.
         */
        public int getMajor_version(){
            return major_version;
        }
        
        public static void main(String[] args) throws FileNotFoundException{
        	System.out.println(new ClassData(new FileInputStream(new File("E:\\logs\\Example.class"))));
        }
    }
    


    读取类的field信息的类:
    package sun.tools.javap;
    
    import java.util.*;
    import java.io.*;
    
    /**
     * Strores field data informastion.
     *
     * @author  Sucheta Dambalkar (Adopted code from jdis)
     */
    
    public class FieldData implements RuntimeConstants  {
    
        ClassData cls;
        int access;
        int name_index;
        int descriptor_index;
        int attributes_count;
        int value_cpx=0;
        boolean isSynthetic=false;
        boolean isDeprecated=false;
        Vector attrs;
    
        public FieldData(ClassData cls){
            this.cls=cls;
        }
    
        /**
         * Read and store field info.
         */
        public void read(DataInputStream in) throws IOException {
            access = in.readUnsignedShort();
            name_index = in.readUnsignedShort();
            descriptor_index = in.readUnsignedShort();
            // Read the attributes
            int attributes_count = in.readUnsignedShort();
            attrs=new Vector(attributes_count);
            for (int i = 0; i < attributes_count; i++) {
                int attr_name_index=in.readUnsignedShort();
                if (cls.getTag(attr_name_index)!=CONSTANT_UTF8) continue;
                String attr_name=cls.getString(attr_name_index);
                if (attr_name.equals("ConstantValue")){
                    if (in.readInt()!=2)
                        throw new ClassFormatError("invalid ConstantValue attr length");
                    value_cpx=in.readUnsignedShort();
                    AttrData attr=new AttrData(cls);
                    attr.read(attr_name_index);
                    attrs.addElement(attr);
                } else if (attr_name.equals("Synthetic")){
                    if (in.readInt()!=0)
                        throw new ClassFormatError("invalid Synthetic attr length");
                    isSynthetic=true;
                    AttrData attr=new AttrData(cls);
                    attr.read(attr_name_index);
                    attrs.addElement(attr);
                } else if (attr_name.equals("Deprecated")){
                    if (in.readInt()!=0)
                        throw new ClassFormatError("invalid Synthetic attr length");
                    isDeprecated = true;
                    AttrData attr=new AttrData(cls);
                    attr.read(attr_name_index);
                    attrs.addElement(attr);
                } else {
                    AttrData attr=new AttrData(cls);
                    attr.read(attr_name_index, in);
                    attrs.addElement(attr);
                }
            }
    
        }  // end read
    
        /**
         * Returns access of a field.
         */
        public String[] getAccess(){
            Vector v = new Vector();
            if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
            if ((access & ACC_PRIVATE)   !=0) v.addElement("private");
            if ((access & ACC_PROTECTED)   !=0) v.addElement("protected");
            if ((access & ACC_STATIC)   !=0) v.addElement("static");
            if ((access & ACC_FINAL)    !=0) v.addElement("final");
            if ((access & ACC_VOLATILE) !=0) v.addElement("volatile");
            if ((access & ACC_TRANSIENT) !=0) v.addElement("transient");
            String[] accflags = new String[v.size()];
            v.copyInto(accflags);
            return accflags;
        }
    
        /**
         * Returns name of a field.
         */
        public String getName(){
            return cls.getStringValue(name_index);
        }
    
        /**
         * Returns internal signature of a field
         */
        public String getInternalSig(){
            return cls.getStringValue(descriptor_index);
        }
    
        /**
         * Returns java type signature of a field.
         */
        public String getType(){
            return new TypeSignature(getInternalSig()).getFieldType();
        }
    
        /**
         * Returns true if field is synthetic.
         */
        public boolean isSynthetic(){
            return isSynthetic;
        }
    
        /**
         * Returns true if field is deprecated.
         */
        public boolean isDeprecated(){
            return isDeprecated;
        }
    
        /**
         * Returns index of constant value in cpool.
         */
        public int getConstantValueIndex(){
            return (value_cpx);
        }
    
        /**
         * Returns list of attributes of field.
         */
        public Vector getAttributes(){
            return attrs;
        }
    }
    

    读取类的方法

    import java.util.*;
    import java.io.*;
    
    import static sun.tools.javap.RuntimeConstants.*;
    
    /**
     * Strores method data informastion.
     *
     * @author  Sucheta Dambalkar (Adopted code from jdis)
     */
    public class MethodData {
    
        ClassData cls;
        int access;
        int name_index;
        int descriptor_index;
        int attributes_count;
        byte[] code;
        Vector exception_table = new Vector(0);
        Vector lin_num_tb = new Vector(0);
        Vector loc_var_tb = new Vector(0);
        StackMapTableData[] stackMapTable;
        StackMapData[] stackMap;
        int[] exc_index_table=null;
        Vector attrs=new Vector(0);
        Vector code_attrs=new Vector(0);
        int max_stack,  max_locals;
        boolean isSynthetic=false;
        boolean isDeprecated=false;
    
        public MethodData(ClassData cls){
            this.cls=cls;
        }
    
        /**
         * Read method info.
         */
        public void read(DataInputStream in) throws IOException {
            access = in.readUnsignedShort();
            name_index=in.readUnsignedShort();
            descriptor_index =in.readUnsignedShort();
            int attributes_count = in.readUnsignedShort();
            for (int i = 0; i < attributes_count; i++) {
                int attr_name_index=in.readUnsignedShort();
    
            readAttr: {
                    if (cls.getTag(attr_name_index)==CONSTANT_UTF8) {
                        String  attr_name=cls.getString(attr_name_index);
                        if ( attr_name.equals("Code")){
                            readCode (in);
                            AttrData attr=new AttrData(cls);
                            attr.read(attr_name_index);
                            attrs.addElement(attr);
                            break readAttr;
                        } else if ( attr_name.equals("Exceptions")){
                            readExceptions(in);
                            AttrData attr=new AttrData(cls);
                            attr.read(attr_name_index);
                            attrs.addElement(attr);
                            break readAttr;
                        } else if (attr_name.equals("Synthetic")){
                            if (in.readInt()!=0)
                                throw new ClassFormatError("invalid Synthetic attr length");
                            isSynthetic=true;
                            AttrData attr=new AttrData(cls);
                            attr.read(attr_name_index);
                            attrs.addElement(attr);
                            break readAttr;
                        } else if (attr_name.equals("Deprecated")){
                            if (in.readInt()!=0)
                                throw new ClassFormatError("invalid Synthetic attr length");
                            isDeprecated = true;
                            AttrData attr=new AttrData(cls);
                            attr.read(attr_name_index);
                            attrs.addElement(attr);
                            break readAttr;
                        }
                    }
                    AttrData attr=new AttrData(cls);
                    attr.read(attr_name_index, in);
                    attrs.addElement(attr);
                }
            }
        }
    
        /**
         * Read code attribute info.
         */
        public void readCode(DataInputStream in) throws IOException {
    
            int attr_length = in.readInt();
            max_stack=in.readUnsignedShort();
            max_locals=in.readUnsignedShort();
            int codelen=in.readInt();
    
            code=new byte[codelen];
            int totalread = 0;
            while(totalread < codelen){
                totalread += in.read(code, totalread, codelen-totalread);
            }
            //      in.read(code, 0, codelen);
            int clen = 0;
            readExceptionTable(in);
            int code_attributes_count = in.readUnsignedShort();
    
            for (int k = 0 ; k < code_attributes_count ; k++) {
                int table_name_index=in.readUnsignedShort();
                int table_name_tag=cls.getTag(table_name_index);
                AttrData attr=new AttrData(cls);
                if (table_name_tag==CONSTANT_UTF8) {
                    String table_name_tstr=cls.getString(table_name_index);
                    if (table_name_tstr.equals("LineNumberTable")) {
                        readLineNumTable(in);
                        attr.read(table_name_index);
                    } else if (table_name_tstr.equals("LocalVariableTable")) {
                        readLocVarTable(in);
                        attr.read(table_name_index);
                    } else if (table_name_tstr.equals("StackMapTable")) {
                        readStackMapTable(in);
                        attr.read(table_name_index);
                    } else if (table_name_tstr.equals("StackMap")) {
                        readStackMap(in);
                        attr.read(table_name_index);
                    } else {
                        attr.read(table_name_index, in);
                    }
                    code_attrs.addElement(attr);
                    continue;
                }
    
                attr.read(table_name_index, in);
                code_attrs.addElement(attr);
            }
        }
    
        /**
         * Read exception table info.
         */
        void readExceptionTable (DataInputStream in) throws IOException {
            int exception_table_len=in.readUnsignedShort();
            exception_table=new Vector(exception_table_len);
            for (int l = 0; l < exception_table_len; l++) {
                exception_table.addElement(new TrapData(in, l));
            }
        }
    
        /**
         * Read LineNumberTable attribute info.
         */
        void readLineNumTable (DataInputStream in) throws IOException {
            int attr_len = in.readInt(); // attr_length
            int lin_num_tb_len = in.readUnsignedShort();
            lin_num_tb=new Vector(lin_num_tb_len);
            for (int l = 0; l < lin_num_tb_len; l++) {
                lin_num_tb.addElement(new LineNumData(in));
            }
        }
    
        /**
         * Read LocalVariableTable attribute info.
         */
        void readLocVarTable (DataInputStream in) throws IOException {
            int attr_len=in.readInt(); // attr_length
            int loc_var_tb_len = in.readUnsignedShort();
            loc_var_tb = new Vector(loc_var_tb_len);
            for (int l = 0; l < loc_var_tb_len; l++) {
                loc_var_tb.addElement(new LocVarData(in));
            }
        }
    
        /**
         * Read Exception attribute info.
         */
        public void readExceptions(DataInputStream in) throws IOException {
            int attr_len=in.readInt(); // attr_length in prog
            int num_exceptions = in.readUnsignedShort();
            exc_index_table=new int[num_exceptions];
            for (int l = 0; l < num_exceptions; l++) {
                int exc=in.readShort();
                exc_index_table[l]=exc;
            }
        }
    
        /**
         * Read StackMapTable attribute info.
         */
        void readStackMapTable(DataInputStream in) throws IOException {
            int attr_len = in.readInt();  //attr_length
            int stack_map_tb_len = in.readUnsignedShort();
            stackMapTable = new StackMapTableData[stack_map_tb_len];
            for (int i=0; i<stack_map_tb_len; i++) {
                stackMapTable[i] = StackMapTableData.getInstance(in, this);
            }
        }
    
        /**
         * Read StackMap attribute info.
         */
        void readStackMap(DataInputStream in) throws IOException {
            int attr_len = in.readInt();  //attr_length
            int stack_map_len = in.readUnsignedShort();
            stackMap = new StackMapData[stack_map_len];
            for (int i = 0; i<stack_map_len; i++) {
                stackMap[i] = new StackMapData(in, this);
            }
        }
    
        /**
         * Return access of the method.
         */
        public String[] getAccess(){
    
            Vector v = new Vector();
            if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
            if ((access & ACC_PRIVATE)   !=0) v.addElement("private");
            if ((access & ACC_PROTECTED)   !=0) v.addElement("protected");
            if ((access & ACC_STATIC)   !=0) v.addElement("static");
            if ((access & ACC_FINAL)    !=0) v.addElement("final");
            if ((access & ACC_SYNCHRONIZED) !=0) v.addElement("synchronized");
            if ((access & ACC_NATIVE) !=0) v.addElement("native");
            if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
            if ((access & ACC_STRICT) !=0) v.addElement("strictfp");
    
            String[] accflags = new String[v.size()];
            v.copyInto(accflags);
            return accflags;
        }
    
        /**
         * Return name of the method.
         */
        public String getName(){
            return cls.getStringValue(name_index);
        }
    
        /**
         * Return internal siganature of the method.
         */
        public String getInternalSig(){
            return cls.getStringValue(descriptor_index);
        }
    
        /**
         * Return java return type signature of method.
         */
        public String getReturnType(){
    
            String rttype = (new TypeSignature(getInternalSig())).getReturnType();
            return rttype;
        }
    
        /**
         * Return java type parameter signature.
         */
        public String getParameters(){
            String ptype = (new TypeSignature(getInternalSig())).getParameters();
    
            return ptype;
        }
    
        /**
         * Return code attribute data of a method.
         */
        public byte[] getCode(){
            return code;
        }
    
        /**
         * Return LineNumberTable size.
         */
        public int getnumlines(){
            return lin_num_tb.size();
        }
    
        /**
         * Return LineNumberTable
         */
        public Vector getlin_num_tb(){
            return lin_num_tb;
        }
    
        /**
         * Return LocalVariableTable size.
         */
        public int getloc_var_tbsize(){
            return loc_var_tb.size();
        }
    
    
        /**
         * Return LocalVariableTable.
         */
        public Vector getloc_var_tb(){
            return loc_var_tb;
        }
    
        /**
         * Return StackMap.
         */
        public StackMapData[] getStackMap() {
            return stackMap;
        }
    
        /**
         * Return StackMapTable.
         */
        public StackMapTableData[] getStackMapTable() {
            return stackMapTable;
        }
    
        /**
         * Return number of arguments of that method.
         */
        public int getArgumentlength(){
            return new TypeSignature(getInternalSig()).getArgumentlength();
        }
    
        /**
         * Return true if method is static
         */
        public boolean isStatic(){
            if ((access & ACC_STATIC)   !=0) return true;
            return false;
        }
    
    
        /**
         * Return max depth of operand stack.
         */
        public int getMaxStack(){
            return  max_stack;
        }
    
    
        /**
         * Return number of local variables.
         */
        public int getMaxLocals(){
            return max_locals;
        }
    
    
        /**
         * Return exception index table in Exception attribute.
         */
        public int []get_exc_index_table(){
            return  exc_index_table;
        }
    
    
        /**
         * Return exception table in code attributre.
         */
        public Vector getexception_table(){
            return exception_table;
        }
    
    
        /**
         * Return method attributes.
         */
        public Vector getAttributes(){
            return attrs;
        }
    
    
        /**
         * Return code attributes.
         */
        public Vector getCodeAttributes(){
            return code_attrs;
        }
    
    
        /**
         * Return true if method id synthetic.
         */
        public boolean isSynthetic(){
            return isSynthetic;
        }
    
    
        /**
         * Return true if method is deprecated.
         */
        public boolean isDeprecated(){
            return isDeprecated;
        }
    }
    

    我们将下面这个class文件解析之后的数据如下:过程很简单,有兴趣的大家调试一遍就知道了。

    import java.io.PrintStream;
    
    public class AsmAopExample$Foo
    {
      public static void execute()
      {
        AsmAopExample.Monitor.start(); System.out.println("test changed method name");
        try {
          Thread.sleep(10L);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
        AsmAopExample.Monitor.end();
      }
    }




     


  • 相关阅读:
    Android 添加cookie
    解决安卓TextView异常换行,参差不齐等问题
    Java遍历List的时候删除item
    android setCompoundDrawables 不显示问题
    Git 操作的一些场景
    C# 函数参数中的this
    Git 常用命令
    C# 判断程序是否执行 进行启动或前台显示
    在窗体中嵌入 应用程序
    byte[] 转 2进制字符串
  • 原文地址:https://www.cnblogs.com/secbook/p/2655143.html
Copyright © 2011-2022 走看看