langtools/src/share/classes/sun/tools/javap/ClassData.java
changeset 10 06bc494ca11e
child 656 4718b910737c
equal deleted inserted replaced
0:fd16c54261b3 10:06bc494ca11e
       
     1 /*
       
     2  * Copyright 2002-2004 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 
       
    27 package sun.tools.javap;
       
    28 
       
    29 import java.util.*;
       
    30 import java.io.*;
       
    31 
       
    32 /**
       
    33  * Central data repository of the Java Disassembler.
       
    34  * Stores all the information in java class file.
       
    35  *
       
    36  * @author  Sucheta Dambalkar (Adopted code from jdis)
       
    37  */
       
    38 public class ClassData implements RuntimeConstants {
       
    39 
       
    40     private int magic;
       
    41     private int minor_version;
       
    42     private int major_version;
       
    43     private int cpool_count;
       
    44     private Object cpool[];
       
    45     private int access;
       
    46     private int this_class = 0;;
       
    47     private int super_class;
       
    48     private int interfaces_count;
       
    49     private int[] interfaces = new int[0];;
       
    50     private int fields_count;
       
    51     private FieldData[] fields;
       
    52     private int methods_count;
       
    53     private MethodData[] methods;
       
    54     private InnerClassData[] innerClasses;
       
    55     private int attributes_count;
       
    56     private AttrData[] attrs;
       
    57     private String classname;
       
    58     private String superclassname;
       
    59     private int source_cpx=0;
       
    60     private byte tags[];
       
    61     private Hashtable indexHashAscii = new Hashtable();
       
    62     private String pkgPrefix="";
       
    63     private int pkgPrefixLen=0;
       
    64 
       
    65     /**
       
    66      * Read classfile to disassemble.
       
    67      */
       
    68     public ClassData(InputStream infile){
       
    69         try{
       
    70             this.read(new DataInputStream(infile));
       
    71         }catch (FileNotFoundException ee) {
       
    72             error("cant read file");
       
    73         }catch (Error ee) {
       
    74             ee.printStackTrace();
       
    75             error("fatal error");
       
    76         } catch (Exception ee) {
       
    77             ee.printStackTrace();
       
    78             error("fatal exception");
       
    79         }
       
    80     }
       
    81 
       
    82     /**
       
    83      * Reads and stores class file information.
       
    84      */
       
    85     public void read(DataInputStream in) throws IOException {
       
    86         // Read the header
       
    87         magic = in.readInt();
       
    88         if (magic != JAVA_MAGIC) {
       
    89             throw new ClassFormatError("wrong magic: " +
       
    90                                        toHex(magic) + ", expected " +
       
    91                                        toHex(JAVA_MAGIC));
       
    92         }
       
    93         minor_version = in.readShort();
       
    94         major_version = in.readShort();
       
    95         if (major_version != JAVA_VERSION) {
       
    96         }
       
    97 
       
    98         // Read the constant pool
       
    99         readCP(in);
       
   100         access = in.readUnsignedShort();
       
   101         this_class = in.readUnsignedShort();
       
   102         super_class = in.readUnsignedShort();
       
   103 
       
   104         //Read interfaces.
       
   105         interfaces_count = in.readUnsignedShort();
       
   106         if(interfaces_count > 0){
       
   107             interfaces = new int[interfaces_count];
       
   108         }
       
   109         for (int i = 0; i < interfaces_count; i++) {
       
   110             interfaces[i]=in.readShort();
       
   111         }
       
   112 
       
   113         // Read the fields
       
   114         readFields(in);
       
   115 
       
   116         // Read the methods
       
   117         readMethods(in);
       
   118 
       
   119         // Read the attributes
       
   120         attributes_count = in.readUnsignedShort();
       
   121         attrs=new AttrData[attributes_count];
       
   122         for (int k = 0; k < attributes_count; k++) {
       
   123             int name_cpx=in.readUnsignedShort();
       
   124             if (getTag(name_cpx)==CONSTANT_UTF8
       
   125                 && getString(name_cpx).equals("SourceFile")
       
   126                 ){      if (in.readInt()!=2)
       
   127                     throw new ClassFormatError("invalid attr length");
       
   128                 source_cpx=in.readUnsignedShort();
       
   129                 AttrData attr=new AttrData(this);
       
   130                 attr.read(name_cpx);
       
   131                 attrs[k]=attr;
       
   132 
       
   133             } else if (getTag(name_cpx)==CONSTANT_UTF8
       
   134                        && getString(name_cpx).equals("InnerClasses")
       
   135                        ){       int length=in.readInt();
       
   136                        int num=in.readUnsignedShort();
       
   137                        if (2+num*8 != length)
       
   138                            throw new ClassFormatError("invalid attr length");
       
   139                        innerClasses=new InnerClassData[num];
       
   140                        for (int j = 0; j < num; j++) {
       
   141                            InnerClassData innerClass=new InnerClassData(this);
       
   142                            innerClass.read(in);
       
   143                            innerClasses[j]=innerClass;
       
   144                        }
       
   145                        AttrData attr=new AttrData(this);
       
   146                        attr.read(name_cpx);
       
   147                        attrs[k]=attr;
       
   148             } else {
       
   149                 AttrData attr=new AttrData(this);
       
   150                 attr.read(name_cpx, in);
       
   151                 attrs[k]=attr;
       
   152             }
       
   153         }
       
   154         in.close();
       
   155     } // end ClassData.read()
       
   156 
       
   157     /**
       
   158      * Reads and stores constant pool info.
       
   159      */
       
   160     void readCP(DataInputStream in) throws IOException {
       
   161         cpool_count = in.readUnsignedShort();
       
   162         tags = new byte[cpool_count];
       
   163         cpool = new Object[cpool_count];
       
   164         for (int i = 1; i < cpool_count; i++) {
       
   165             byte tag = in.readByte();
       
   166 
       
   167             switch(tags[i] = tag) {
       
   168             case CONSTANT_UTF8:
       
   169                 String str=in.readUTF();
       
   170                 indexHashAscii.put(cpool[i] = str, new Integer(i));
       
   171                 break;
       
   172             case CONSTANT_INTEGER:
       
   173                 cpool[i] = new Integer(in.readInt());
       
   174                 break;
       
   175             case CONSTANT_FLOAT:
       
   176                 cpool[i] = new Float(in.readFloat());
       
   177                 break;
       
   178             case CONSTANT_LONG:
       
   179                 cpool[i++] = new Long(in.readLong());
       
   180                 break;
       
   181             case CONSTANT_DOUBLE:
       
   182                 cpool[i++] = new Double(in.readDouble());
       
   183                 break;
       
   184             case CONSTANT_CLASS:
       
   185             case CONSTANT_STRING:
       
   186                 cpool[i] = new CPX(in.readUnsignedShort());
       
   187                 break;
       
   188 
       
   189             case CONSTANT_FIELD:
       
   190             case CONSTANT_METHOD:
       
   191             case CONSTANT_INTERFACEMETHOD:
       
   192             case CONSTANT_NAMEANDTYPE:
       
   193                 cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
       
   194                 break;
       
   195 
       
   196             case 0:
       
   197             default:
       
   198                 throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
       
   199             }
       
   200         }
       
   201     }
       
   202 
       
   203     /**
       
   204      * Reads and strores field info.
       
   205      */
       
   206     protected void readFields(DataInputStream in) throws IOException {
       
   207         int fields_count = in.readUnsignedShort();
       
   208         fields=new FieldData[fields_count];
       
   209         for (int k = 0; k < fields_count; k++) {
       
   210             FieldData field=new FieldData(this);
       
   211             field.read(in);
       
   212             fields[k]=field;
       
   213         }
       
   214     }
       
   215 
       
   216     /**
       
   217      * Reads and strores Method info.
       
   218      */
       
   219     protected void readMethods(DataInputStream in) throws IOException {
       
   220         int methods_count = in.readUnsignedShort();
       
   221         methods=new MethodData[methods_count];
       
   222         for (int k = 0; k < methods_count ; k++) {
       
   223             MethodData method=new MethodData(this);
       
   224             method.read(in);
       
   225             methods[k]=method;
       
   226         }
       
   227     }
       
   228 
       
   229     /**
       
   230      * get a string
       
   231      */
       
   232     public String getString(int n) {
       
   233         return (n == 0) ? null : (String)cpool[n];
       
   234     }
       
   235 
       
   236     /**
       
   237      * get the type of constant given an index
       
   238      */
       
   239     public byte getTag(int n) {
       
   240         try{
       
   241             return tags[n];
       
   242         } catch (ArrayIndexOutOfBoundsException e) {
       
   243             return (byte)100;
       
   244         }
       
   245     }
       
   246 
       
   247     static final String hexString="0123456789ABCDEF";
       
   248 
       
   249     public static char hexTable[]=hexString.toCharArray();
       
   250 
       
   251     static String toHex(long val, int width) {
       
   252         StringBuffer s = new StringBuffer();
       
   253         for (int i=width-1; i>=0; i--)
       
   254             s.append(hexTable[((int)(val>>(4*i)))&0xF]);
       
   255         return "0x"+s.toString();
       
   256     }
       
   257 
       
   258     static String toHex(long val) {
       
   259         int width;
       
   260         for (width=16; width>0; width--) {
       
   261             if ((val>>(width-1)*4)!=0) break;
       
   262         }
       
   263         return toHex(val, width);
       
   264     }
       
   265 
       
   266     static String toHex(int val) {
       
   267         int width;
       
   268         for (width=8; width>0; width--) {
       
   269             if ((val>>(width-1)*4)!=0) break;
       
   270         }
       
   271         return toHex(val, width);
       
   272     }
       
   273 
       
   274     public void error(String msg) {
       
   275         System.err.println("ERROR:" +msg);
       
   276     }
       
   277 
       
   278     /**
       
   279      * Returns the name of this class.
       
   280      */
       
   281     public String getClassName() {
       
   282         String res=null;
       
   283         if (this_class==0) {
       
   284             return res;
       
   285         }
       
   286         int tcpx;
       
   287         try {
       
   288             if (tags[this_class]!=CONSTANT_CLASS) {
       
   289                 return res; //"<CP["+cpx+"] is not a Class> ";
       
   290             }
       
   291             tcpx=((CPX)cpool[this_class]).cpx;
       
   292         } catch (ArrayIndexOutOfBoundsException e) {
       
   293             return res; // "#"+cpx+"// invalid constant pool index";
       
   294         } catch (Throwable e) {
       
   295             return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
       
   296         }
       
   297 
       
   298         try {
       
   299             return (String)(cpool[tcpx]);
       
   300         } catch (ArrayIndexOutOfBoundsException e) {
       
   301             return  res; // "class #"+scpx+"// invalid constant pool index";
       
   302         } catch (ClassCastException e) {
       
   303             return  res; // "class #"+scpx+"// invalid constant pool reference";
       
   304         } catch (Throwable e) {
       
   305             return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
       
   306         }
       
   307 
       
   308     }
       
   309 
       
   310     /**
       
   311      * Returns the name of class at perticular index.
       
   312      */
       
   313     public String getClassName(int cpx) {
       
   314         String res="#"+cpx;
       
   315         if (cpx==0) {
       
   316             return res;
       
   317         }
       
   318         int scpx;
       
   319         try {
       
   320             if (tags[cpx]!=CONSTANT_CLASS) {
       
   321                 return res; //"<CP["+cpx+"] is not a Class> ";
       
   322             }
       
   323             scpx=((CPX)cpool[cpx]).cpx;
       
   324         } catch (ArrayIndexOutOfBoundsException e) {
       
   325             return res; // "#"+cpx+"// invalid constant pool index";
       
   326         } catch (Throwable e) {
       
   327             return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
       
   328         }
       
   329         res="#"+scpx;
       
   330         try {
       
   331             return (String)(cpool[scpx]);
       
   332         } catch (ArrayIndexOutOfBoundsException e) {
       
   333             return  res; // "class #"+scpx+"// invalid constant pool index";
       
   334         } catch (ClassCastException e) {
       
   335             return  res; // "class #"+scpx+"// invalid constant pool reference";
       
   336         } catch (Throwable e) {
       
   337             return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
       
   338         }
       
   339     }
       
   340 
       
   341     /**
       
   342      * Returns true if it is a class
       
   343      */
       
   344     public boolean isClass() {
       
   345         if((access & ACC_INTERFACE) == 0) return true;
       
   346         return false;
       
   347     }
       
   348 
       
   349     /**
       
   350      * Returns true if it is a interface.
       
   351      */
       
   352     public boolean isInterface(){
       
   353         if((access & ACC_INTERFACE) != 0) return true;
       
   354         return false;
       
   355     }
       
   356 
       
   357     /**
       
   358      * Returns true if this member is public, false otherwise.
       
   359      */
       
   360     public boolean isPublic(){
       
   361         return (access & ACC_PUBLIC) != 0;
       
   362     }
       
   363 
       
   364     /**
       
   365      * Returns the access of this class or interface.
       
   366      */
       
   367     public String[] getAccess(){
       
   368         Vector v = new Vector();
       
   369         if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
       
   370         if ((access & ACC_FINAL)    !=0) v.addElement("final");
       
   371         if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
       
   372         String[] accflags = new String[v.size()];
       
   373         v.copyInto(accflags);
       
   374         return accflags;
       
   375     }
       
   376 
       
   377     /**
       
   378      * Returns list of innerclasses.
       
   379      */
       
   380     public InnerClassData[] getInnerClasses(){
       
   381         return innerClasses;
       
   382     }
       
   383 
       
   384     /**
       
   385      * Returns list of attributes.
       
   386      */
       
   387     public AttrData[] getAttributes(){
       
   388         return attrs;
       
   389     }
       
   390 
       
   391     /**
       
   392      * Returns true if superbit is set.
       
   393      */
       
   394     public boolean isSuperSet(){
       
   395         if ((access & ACC_SUPER)   !=0) return true;
       
   396         return false;
       
   397     }
       
   398 
       
   399     /**
       
   400      * Returns super class name.
       
   401      */
       
   402     public String getSuperClassName(){
       
   403         String res=null;
       
   404         if (super_class==0) {
       
   405             return res;
       
   406         }
       
   407         int scpx;
       
   408         try {
       
   409             if (tags[super_class]!=CONSTANT_CLASS) {
       
   410                 return res; //"<CP["+cpx+"] is not a Class> ";
       
   411             }
       
   412             scpx=((CPX)cpool[super_class]).cpx;
       
   413         } catch (ArrayIndexOutOfBoundsException e) {
       
   414             return res; // "#"+cpx+"// invalid constant pool index";
       
   415         } catch (Throwable e) {
       
   416             return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
       
   417         }
       
   418 
       
   419         try {
       
   420             return (String)(cpool[scpx]);
       
   421         } catch (ArrayIndexOutOfBoundsException e) {
       
   422             return  res; // "class #"+scpx+"// invalid constant pool index";
       
   423         } catch (ClassCastException e) {
       
   424             return  res; // "class #"+scpx+"// invalid constant pool reference";
       
   425         } catch (Throwable e) {
       
   426             return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
       
   427         }
       
   428     }
       
   429 
       
   430     /**
       
   431      * Returns list of super interfaces.
       
   432      */
       
   433     public String[] getSuperInterfaces(){
       
   434         String interfacenames[] = new String[interfaces.length];
       
   435         int interfacecpx = -1;
       
   436         for(int i = 0; i < interfaces.length; i++){
       
   437             interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
       
   438             interfacenames[i] = (String)(cpool[interfacecpx]);
       
   439         }
       
   440         return interfacenames;
       
   441     }
       
   442 
       
   443     /**
       
   444      * Returns string at prticular constant pool index.
       
   445      */
       
   446     public String getStringValue(int cpoolx) {
       
   447         try {
       
   448             return ((String)cpool[cpoolx]);
       
   449         } catch (ArrayIndexOutOfBoundsException e) {
       
   450             return "//invalid constant pool index:"+cpoolx;
       
   451         } catch (ClassCastException e) {
       
   452             return "//invalid constant pool ref:"+cpoolx;
       
   453         }
       
   454     }
       
   455 
       
   456     /**
       
   457      * Returns list of field info.
       
   458      */
       
   459     public  FieldData[] getFields(){
       
   460         return fields;
       
   461     }
       
   462 
       
   463     /**
       
   464      * Returns list of method info.
       
   465      */
       
   466     public  MethodData[] getMethods(){
       
   467         return methods;
       
   468     }
       
   469 
       
   470     /**
       
   471      * Returns constant pool entry at that index.
       
   472      */
       
   473     public CPX2 getCpoolEntry(int cpx){
       
   474         return ((CPX2)(cpool[cpx]));
       
   475     }
       
   476 
       
   477     public Object getCpoolEntryobj(int cpx){
       
   478         return (cpool[cpx]);
       
   479     }
       
   480 
       
   481     /**
       
   482      * Returns index of this class.
       
   483      */
       
   484     public int getthis_cpx(){
       
   485         return this_class;
       
   486     }
       
   487 
       
   488     public String TagString (int tag) {
       
   489         String res=Tables.tagName(tag);
       
   490         if (res==null)  return "BOGUS_TAG:"+tag;
       
   491         return res;
       
   492     }
       
   493 
       
   494     /**
       
   495      * Returns string at that index.
       
   496      */
       
   497     public String StringValue(int cpx) {
       
   498         if (cpx==0) return "#0";
       
   499         int tag;
       
   500         Object x;
       
   501         String suffix="";
       
   502         try {
       
   503             tag=tags[cpx];
       
   504             x=cpool[cpx];
       
   505         } catch (IndexOutOfBoundsException e) {
       
   506             return "<Incorrect CP index:"+cpx+">";
       
   507         }
       
   508 
       
   509         if (x==null) return "<NULL>";
       
   510         switch (tag) {
       
   511         case CONSTANT_UTF8: {
       
   512             StringBuffer sb=new StringBuffer();
       
   513             String s=(String)x;
       
   514             for (int k=0; k<s.length(); k++) {
       
   515                 char c=s.charAt(k);
       
   516                 switch (c) {
       
   517                 case '\t': sb.append('\\').append('t'); break;
       
   518                 case '\n': sb.append('\\').append('n'); break;
       
   519                 case '\r': sb.append('\\').append('r'); break;
       
   520                 case '\"': sb.append('\\').append('\"'); break;
       
   521                 default: sb.append(c);
       
   522                 }
       
   523             }
       
   524             return sb.toString();
       
   525         }
       
   526         case CONSTANT_DOUBLE: {
       
   527             Double d=(Double)x;
       
   528             String sd=d.toString();
       
   529             return sd+"d";
       
   530         }
       
   531         case CONSTANT_FLOAT: {
       
   532             Float f=(Float)x;
       
   533             String sf=(f).toString();
       
   534             return sf+"f";
       
   535         }
       
   536         case CONSTANT_LONG: {
       
   537             Long ln = (Long)x;
       
   538             return ln.toString()+'l';
       
   539         }
       
   540         case CONSTANT_INTEGER: {
       
   541             Integer in = (Integer)x;
       
   542             return in.toString();
       
   543         }
       
   544         case CONSTANT_CLASS:
       
   545             return javaName(getClassName(cpx));
       
   546         case CONSTANT_STRING:
       
   547             return StringValue(((CPX)x).cpx);
       
   548         case CONSTANT_FIELD:
       
   549         case CONSTANT_METHOD:
       
   550         case CONSTANT_INTERFACEMETHOD:
       
   551             //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
       
   552              return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
       
   553 
       
   554         case CONSTANT_NAMEANDTYPE:
       
   555             return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
       
   556         default:
       
   557             return "UnknownTag"; //TBD
       
   558         }
       
   559     }
       
   560 
       
   561     /**
       
   562      * Returns resolved java type name.
       
   563      */
       
   564     public String javaName(String name) {
       
   565         if( name==null) return "null";
       
   566         int len=name.length();
       
   567         if (len==0) return "\"\"";
       
   568         int cc='/';
       
   569     fullname: { // xxx/yyy/zzz
       
   570             int cp;
       
   571             for (int k=0; k<len; k += Character.charCount(cp)) {
       
   572                 cp=name.codePointAt(k);
       
   573                 if (cc=='/') {
       
   574                     if (!Character.isJavaIdentifierStart(cp)) break fullname;
       
   575                 } else if (cp!='/') {
       
   576                     if (!Character.isJavaIdentifierPart(cp)) break fullname;
       
   577                 }
       
   578                 cc=cp;
       
   579             }
       
   580             return name;
       
   581         }
       
   582         return "\""+name+"\"";
       
   583     }
       
   584 
       
   585     public String getName(int cpx) {
       
   586         String res;
       
   587         try {
       
   588             return javaName((String)cpool[cpx]); //.replace('/','.');
       
   589         } catch (ArrayIndexOutOfBoundsException e) {
       
   590             return "<invalid constant pool index:"+cpx+">";
       
   591         } catch (ClassCastException e) {
       
   592             return "<invalid constant pool ref:"+cpx+">";
       
   593         }
       
   594     }
       
   595 
       
   596     /**
       
   597      * Returns unqualified class name.
       
   598      */
       
   599     public String getShortClassName(int cpx) {
       
   600         String classname=javaName(getClassName(cpx));
       
   601         pkgPrefixLen=classname.lastIndexOf("/")+1;
       
   602         if (pkgPrefixLen!=0) {
       
   603             pkgPrefix=classname.substring(0,pkgPrefixLen);
       
   604             if (classname.startsWith(pkgPrefix)) {
       
   605                 return classname.substring(pkgPrefixLen);
       
   606             }
       
   607         }
       
   608         return classname;
       
   609     }
       
   610 
       
   611     /**
       
   612      * Returns source file name.
       
   613      */
       
   614     public String getSourceName(){
       
   615         return getName(source_cpx);
       
   616     }
       
   617 
       
   618     /**
       
   619      * Returns package name.
       
   620      */
       
   621     public String getPkgName(){
       
   622         String classname=getClassName(this_class);
       
   623         pkgPrefixLen=classname.lastIndexOf("/")+1;
       
   624         if (pkgPrefixLen!=0) {
       
   625             pkgPrefix=classname.substring(0,pkgPrefixLen);
       
   626             return("package  "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
       
   627         }else return null;
       
   628     }
       
   629 
       
   630     /**
       
   631      * Returns total constant pool entry count.
       
   632      */
       
   633     public int getCpoolCount(){
       
   634         return cpool_count;
       
   635     }
       
   636 
       
   637     public String StringTag(int cpx) {
       
   638         byte tag=0;
       
   639         String str=null;
       
   640         try {
       
   641             if (cpx==0) throw new IndexOutOfBoundsException();
       
   642             tag=tags[cpx];
       
   643             return      TagString(tag);
       
   644         } catch (IndexOutOfBoundsException e) {
       
   645             str="Incorrect CP index:"+cpx;
       
   646         }
       
   647         return str;
       
   648     }
       
   649 
       
   650     /**
       
   651      * Returns minor version of class file.
       
   652      */
       
   653     public int getMinor_version(){
       
   654         return minor_version;
       
   655     }
       
   656 
       
   657     /**
       
   658      * Returns major version of class file.
       
   659      */
       
   660     public int getMajor_version(){
       
   661         return major_version;
       
   662     }
       
   663 }