javap/src/main/java/sun/tools/javap/JavapPrinter.java
author Jaroslav Tulach <jtulach@netbeans.org>
Fri, 09 Nov 2012 21:33:22 +0100
branchjavap
changeset 144 b06660b614db
child 145 525b0a571518
permissions -rw-r--r--
javap as of revision jdk6-4ab5d66aaf2b
     1 /*
     2  * Copyright (c) 2002, 2005, Oracle and/or its affiliates. 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 
    27 package sun.tools.javap;
    28 
    29 import java.util.*;
    30 import java.io.*;
    31 
    32 import static sun.tools.javap.RuntimeConstants.*;
    33 
    34 /**
    35  * Program to print information about class files
    36  *
    37  * @author  Sucheta Dambalkar
    38  */
    39 public class JavapPrinter {
    40     JavapEnvironment env;
    41     ClassData cls;
    42     byte[] code;
    43     String lP= "";
    44     PrintWriter out;
    45 
    46     public JavapPrinter(InputStream cname, PrintWriter out, JavapEnvironment env){
    47         this.out = out;
    48         this.cls =  new ClassData(cname);
    49         this.env = env;
    50     }
    51 
    52     /**
    53      *  Entry point to print class file information.
    54      */
    55     public void print(){
    56         printclassHeader();
    57         printfields();
    58         printMethods();
    59         printend();
    60     }
    61 
    62     /**
    63      * Print a description of the class (not members).
    64      */
    65     public void printclassHeader(){
    66         String srcName="";
    67         if ((srcName = cls.getSourceName()) != "null") // requires debug info
    68             out.println("Compiled from " + javaclassname(srcName));
    69 
    70         if(cls.isInterface())   {
    71             // The only useful access modifier of an interface is
    72             // public; interfaces are always marked as abstract and
    73             // cannot be final.
    74             out.print((cls.isPublic()?"public ":"") +
    75                       "interface "+ javaclassname(cls.getClassName()));
    76         }
    77         else if(cls.isClass()) {
    78             String []accflags =  cls.getAccess();
    79             printAccess(accflags);
    80             out.print("class "+ javaclassname(cls.getClassName()));
    81 
    82             if(cls.getSuperClassName() != null){
    83                 out.print(" extends " + javaclassname(cls.getSuperClassName()));
    84             }
    85         }
    86 
    87         String []interfacelist =  cls.getSuperInterfaces();
    88         if(interfacelist.length > 0){
    89             if(cls.isClass()) {
    90                 out.print(" implements ");
    91             }
    92             else if(cls.isInterface()){
    93                 out.print(" extends ");
    94             }
    95 
    96             for(int j = 0; j < interfacelist.length; j++){
    97                 out.print(javaclassname(interfacelist[j]));
    98 
    99                 if((j+1) < interfacelist.length) {
   100                     out.print(",");
   101                 }
   102             }
   103         }
   104 
   105         // Print class attribute information.
   106         if((env.showallAttr) || (env.showVerbose)){
   107             printClassAttributes();
   108         }
   109         // Print verbose output.
   110         if(env.showVerbose){
   111             printverbosecls();
   112         }
   113         out.println("{");
   114     }
   115 
   116     /**
   117      * Print verbose output.
   118      */
   119     public void printverbosecls(){
   120         out.println("  minor version: "+cls.getMinor_version());
   121         out.println("  major version: "+cls.getMajor_version());
   122         out.println("  Constant pool:");
   123         printcp();
   124         env.showallAttr = true;
   125     }
   126 
   127     /**
   128      * Print class attribute information.
   129      */
   130     public void printClassAttributes(){
   131         out.println();
   132         AttrData[] clsattrs = cls.getAttributes();
   133         for(int i = 0; i < clsattrs.length; i++){
   134             String clsattrname = clsattrs[i].getAttrName();
   135             if(clsattrname.equals("SourceFile")){
   136                 out.println("  SourceFile: "+ cls.getSourceName());
   137             }else if(clsattrname.equals("InnerClasses")){
   138                 printInnerClasses();
   139             }else {
   140                 printAttrData(clsattrs[i]);
   141             }
   142         }
   143     }
   144 
   145     /**
   146      * Print the fields
   147      */
   148     public void printfields(){
   149         FieldData[] fields = cls.getFields();
   150         for(int f = 0; f < fields.length; f++){
   151             String[] accflags = fields[f].getAccess();
   152             if(checkAccess(accflags)){
   153                 if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
   154                      ||  env.showInternalSigs || env.showallAttr)){
   155                     out.print("    ");
   156                 }
   157                 printAccess(accflags);
   158                 out.println(fields[f].getType()+" " +fields[f].getName()+";");
   159                 if (env.showInternalSigs) {
   160                     out.println("  Signature: " + (fields[f].getInternalSig()));
   161                 }
   162 
   163                 // print field attribute information.
   164                 if (env.showallAttr){
   165                     printFieldAttributes(fields[f]);
   166 
   167                 }
   168                 if((env.showDisassembled) || (env.showLineAndLocal)){
   169                     out.println();
   170                 }
   171             }
   172         }
   173     }
   174 
   175 
   176     /* print field attribute information. */
   177     public void printFieldAttributes(FieldData field){
   178         Vector fieldattrs = field.getAttributes();
   179         for(int j = 0; j < fieldattrs.size(); j++){
   180             String fieldattrname = ((AttrData)fieldattrs.elementAt(j)).getAttrName();
   181             if(fieldattrname.equals("ConstantValue")){
   182                 printConstantValue(field);
   183             }else if (fieldattrname.equals("Deprecated")){
   184                 out.println("Deprecated: "+ field.isDeprecated());
   185             }else if (fieldattrname.equals("Synthetic")){
   186                 out.println("  Synthetic: "+ field.isSynthetic());
   187             }else {
   188                 printAttrData((AttrData)fieldattrs.elementAt(j));
   189             }
   190         }
   191         out.println();
   192     }
   193 
   194     /**
   195      * Print the methods
   196      */
   197     public void printMethods(){
   198         MethodData[] methods = cls.getMethods();
   199         for(int m = 0; m < methods.length; m++){
   200             String[] accflags = methods[m].getAccess();
   201             if(checkAccess(accflags)){
   202                 if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
   203                      ||  env.showInternalSigs || env.showallAttr)){
   204                     out.print("    ");
   205                 }
   206                 printMethodSignature(methods[m], accflags);
   207                 printExceptions(methods[m]);
   208                 out.println(";");
   209 
   210                 // Print internal signature of method.
   211                 if (env.showInternalSigs){
   212                     out.println("  Signature: " + (methods[m].getInternalSig()));
   213                 }
   214 
   215                 //Print disassembled code.
   216                 if(env.showDisassembled && ! env.showallAttr) {
   217                     printcodeSequence(methods[m]);
   218                     printExceptionTable(methods[m]);
   219                     out.println();
   220                 }
   221 
   222                 // Print line and local variable attribute information.
   223                 if (env.showLineAndLocal) {
   224                     printLineNumTable(methods[m]);
   225                     printLocVarTable(methods[m]);
   226                     out.println();
   227                 }
   228 
   229                 // Print  method attribute information.
   230                 if (env.showallAttr){
   231                     printMethodAttributes(methods[m]);
   232                 }
   233             }
   234         }
   235     }
   236 
   237     /**
   238      * Print method signature.
   239      */
   240     public void printMethodSignature(MethodData method, String[] accflags){
   241         printAccess(accflags);
   242 
   243         if((method.getName()).equals("<init>")){
   244             out.print(javaclassname(cls.getClassName()));
   245             out.print(method.getParameters());
   246         }else if((method.getName()).equals("<clinit>")){
   247             out.print("{}");
   248         }else{
   249             out.print(method.getReturnType()+" ");
   250             out.print(method.getName());
   251             out.print(method.getParameters());
   252         }
   253     }
   254 
   255     /**
   256      * print method attribute information.
   257      */
   258     public void printMethodAttributes(MethodData method){
   259         Vector methodattrs = method.getAttributes();
   260         Vector codeattrs =  method.getCodeAttributes();
   261         for(int k = 0; k < methodattrs.size(); k++){
   262             String methodattrname = ((AttrData)methodattrs.elementAt(k)).getAttrName();
   263             if(methodattrname.equals("Code")){
   264                 printcodeSequence(method);
   265                 printExceptionTable(method);
   266                 for(int c = 0; c < codeattrs.size(); c++){
   267                     String codeattrname = ((AttrData)codeattrs.elementAt(c)).getAttrName();
   268                     if(codeattrname.equals("LineNumberTable")){
   269                         printLineNumTable(method);
   270                     }else if(codeattrname.equals("LocalVariableTable")){
   271                         printLocVarTable(method);
   272                     }else if(codeattrname.equals("StackMapTable")) {
   273                         // Java SE JSR 202 stack map tables
   274                         printStackMapTable(method);
   275                     }else if(codeattrname.equals("StackMap")) {
   276                         // Java ME CLDC stack maps
   277                         printStackMap(method);
   278                     } else {
   279                         printAttrData((AttrData)codeattrs.elementAt(c));
   280                     }
   281                 }
   282             }else if(methodattrname.equals("Exceptions")){
   283                 out.println("  Exceptions: ");
   284                 printExceptions(method);
   285             }else if (methodattrname.equals("Deprecated")){
   286                 out.println("  Deprecated: "+ method.isDeprecated());
   287             }else if (methodattrname.equals("Synthetic")){
   288                 out.println("  Synthetic: "+ method.isSynthetic());
   289             }else {
   290                 printAttrData((AttrData)methodattrs.elementAt(k));
   291             }
   292         }
   293         out.println();
   294     }
   295 
   296     /**
   297      * Print exceptions.
   298      */
   299     public void printExceptions(MethodData method){
   300         int []exc_index_table = method.get_exc_index_table();
   301         if (exc_index_table != null) {
   302             if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
   303                  ||  env.showInternalSigs || env.showallAttr)){
   304                 out.print("    ");
   305             }
   306             out.print("   throws ");
   307             int k;
   308             int l = exc_index_table.length;
   309 
   310             for (k=0; k<l; k++) {
   311                 out.print(javaclassname(cls.getClassName(exc_index_table[k])));
   312                 if (k<l-1) out.print(", ");
   313             }
   314         }
   315     }
   316 
   317     /**
   318      * Print code sequence.
   319      */
   320     public void  printcodeSequence(MethodData method){
   321         code = method.getCode();
   322         if(code != null){
   323             out.println("  Code:");
   324             if(env.showVerbose){
   325                 printVerboseHeader(method);
   326             }
   327 
   328             for (int pc=0; pc < code.length; ) {
   329                 out.print("   "+pc+":\t");
   330                 pc=pc+printInstr(pc);
   331                 out.println();
   332             }
   333         }
   334     }
   335 
   336     /**
   337      * Print instructions.
   338      */
   339     public int printInstr(int pc){
   340         int opcode = getUbyte(pc);
   341         int opcode2;
   342         String mnem;
   343         switch (opcode) {
   344         case opc_nonpriv:
   345         case opc_priv:
   346             opcode2 = getUbyte(pc+1);
   347             mnem=Tables.opcName((opcode<<8)+opcode2);
   348             if (mnem==null)
   349                 // assume all (even nonexistent) priv and nonpriv instructions
   350                 // are 2 bytes long
   351                 mnem=Tables.opcName(opcode)+" "+opcode2;
   352             out.print(mnem);
   353             return 2;
   354         case opc_wide: {
   355             opcode2 = getUbyte(pc+1);
   356             mnem=Tables.opcName((opcode<<8)+opcode2);
   357             if (mnem==null) {
   358                 // nonexistent opcode - but we have to print something
   359                 out.print("bytecode "+opcode);
   360                 return 1;
   361             }
   362             out.print(mnem+" "+getUShort(pc+2));
   363             if (opcode2==opc_iinc) {
   364                 out.print(", "+getShort(pc+4));
   365                 return 6;
   366             }
   367             return 4;
   368         }
   369         }
   370         mnem=Tables.opcName(opcode);
   371         if (mnem==null) {
   372             // nonexistent opcode - but we have to print something
   373             out.print("bytecode "+opcode);
   374             return 1;
   375         }
   376         if (opcode>opc_jsr_w) {
   377             // pseudo opcodes should be printed as bytecodes
   378             out.print("bytecode "+opcode);
   379             return 1;
   380         }
   381         out.print(Tables.opcName(opcode));
   382         switch (opcode) {
   383         case opc_aload: case opc_astore:
   384         case opc_fload: case opc_fstore:
   385         case opc_iload: case opc_istore:
   386         case opc_lload: case opc_lstore:
   387         case opc_dload: case opc_dstore:
   388         case opc_ret:
   389             out.print("\t"+getUbyte(pc+1));
   390             return  2;
   391         case opc_iinc:
   392             out.print("\t"+getUbyte(pc+1)+", "+getbyte(pc+2));
   393             return  3;
   394         case opc_tableswitch:{
   395             int tb=align(pc+1);
   396             int default_skip = getInt(tb); /* default skip pamount */
   397             int low = getInt(tb+4);
   398             int high = getInt(tb+8);
   399             int count = high - low;
   400             out.print("{ //"+low+" to "+high);
   401             for (int i = 0; i <= count; i++)
   402                 out.print( "\n\t\t" + (i+low) + ": "+lP+(pc+getInt(tb+12+4*i))+";");
   403             out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
   404             return tb-pc+16+count*4;
   405         }
   406 
   407         case opc_lookupswitch:{
   408             int tb=align(pc+1);
   409             int default_skip = getInt(tb);
   410             int npairs = getInt(tb+4);
   411             out.print("{ //"+npairs);
   412             for (int i = 1; i <= npairs; i++)
   413                 out.print("\n\t\t"+getInt(tb+i*8)
   414                                  +": "+lP+(pc+getInt(tb+4+i*8))+";"
   415                                  );
   416             out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
   417             return tb-pc+(npairs+1)*8;
   418         }
   419         case opc_newarray:
   420             int type=getUbyte(pc+1);
   421             switch (type) {
   422             case T_BOOLEAN:out.print(" boolean");break;
   423             case T_BYTE:   out.print(" byte");   break;
   424             case T_CHAR:   out.print(" char");   break;
   425             case T_SHORT:  out.print(" short");  break;
   426             case T_INT:    out.print(" int");    break;
   427             case T_LONG:   out.print(" long");   break;
   428             case T_FLOAT:  out.print(" float");  break;
   429             case T_DOUBLE: out.print(" double"); break;
   430             case T_CLASS:  out.print(" class"); break;
   431             default:       out.print(" BOGUS TYPE:"+type);
   432             }
   433             return 2;
   434 
   435         case opc_anewarray: {
   436             int index =  getUShort(pc+1);
   437             out.print("\t#"+index+"; //");
   438             PrintConstant(index);
   439             return 3;
   440         }
   441 
   442         case opc_sipush:
   443             out.print("\t"+getShort(pc+1));
   444             return 3;
   445 
   446         case opc_bipush:
   447             out.print("\t"+getbyte(pc+1));
   448             return 2;
   449 
   450         case opc_ldc: {
   451             int index = getUbyte(pc+1);
   452             out.print("\t#"+index+"; //");
   453             PrintConstant(index);
   454             return 2;
   455         }
   456 
   457         case opc_ldc_w: case opc_ldc2_w:
   458         case opc_instanceof: case opc_checkcast:
   459         case opc_new:
   460         case opc_putstatic: case opc_getstatic:
   461         case opc_putfield: case opc_getfield:
   462         case opc_invokevirtual:
   463         case opc_invokespecial:
   464         case opc_invokestatic: {
   465             int index = getUShort(pc+1);
   466             out.print("\t#"+index+"; //");
   467             PrintConstant(index);
   468             return 3;
   469         }
   470 
   471         case opc_invokeinterface: {
   472             int index = getUShort(pc+1), nargs=getUbyte(pc+3);
   473             out.print("\t#"+index+",  "+nargs+"; //");
   474             PrintConstant(index);
   475             return 5;
   476         }
   477 
   478         case opc_multianewarray: {
   479             int index = getUShort(pc+1), dimensions=getUbyte(pc+3);
   480             out.print("\t#"+index+",  "+dimensions+"; //");
   481             PrintConstant(index);
   482             return 4;
   483         }
   484         case opc_jsr: case opc_goto:
   485         case opc_ifeq: case opc_ifge: case opc_ifgt:
   486         case opc_ifle: case opc_iflt: case opc_ifne:
   487         case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge:
   488         case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt:
   489         case opc_if_acmpeq: case opc_if_acmpne:
   490         case opc_ifnull: case opc_ifnonnull:
   491             out.print("\t"+lP+(pc + getShort(pc+1)) );
   492             return 3;
   493 
   494         case opc_jsr_w:
   495         case opc_goto_w:
   496             out.print("\t"+lP+(pc + getInt(pc+1)));
   497             return 5;
   498 
   499         default:
   500             return 1;
   501         }
   502     }
   503     /**
   504      * Print code attribute details.
   505      */
   506     public void printVerboseHeader(MethodData method) {
   507         int argCount = method.getArgumentlength();
   508         if (!method.isStatic())
   509             ++argCount;  // for 'this'
   510 
   511         out.println("   Stack=" + method.getMaxStack()
   512                            + ", Locals=" + method.getMaxLocals()
   513                            + ", Args_size=" + argCount);
   514 
   515     }
   516 
   517 
   518     /**
   519      * Print the exception table for this method code
   520      */
   521     void printExceptionTable(MethodData method){//throws IOException
   522         Vector exception_table = method.getexception_table();
   523         if (exception_table.size() > 0) {
   524             out.println("  Exception table:");
   525             out.println("   from   to  target type");
   526             for (int idx = 0; idx < exception_table.size(); ++idx) {
   527                 TrapData handler = (TrapData)exception_table.elementAt(idx);
   528                 printFixedWidthInt(handler.start_pc, 6);
   529                 printFixedWidthInt(handler.end_pc, 6);
   530                 printFixedWidthInt(handler.handler_pc, 6);
   531                 out.print("   ");
   532                 int catch_cpx = handler.catch_cpx;
   533                 if (catch_cpx == 0) {
   534                     out.println("any");
   535                 }else {
   536                     out.print("Class ");
   537                     out.println(cls.getClassName(catch_cpx));
   538                     out.println("");
   539                 }
   540             }
   541         }
   542     }
   543 
   544     /**
   545      * Print LineNumberTable attribute information.
   546      */
   547     public void printLineNumTable(MethodData method) {
   548         int numlines = method.getnumlines();
   549         Vector lin_num_tb = method.getlin_num_tb();
   550         if( lin_num_tb.size() > 0){
   551             out.println("  LineNumberTable: ");
   552             for (int i=0; i<numlines; i++) {
   553                 LineNumData linnumtb_entry=(LineNumData)lin_num_tb.elementAt(i);
   554                 out.println("   line " + linnumtb_entry.line_number + ": "
   555                                + linnumtb_entry.start_pc);
   556             }
   557         }
   558         out.println();
   559     }
   560 
   561     /**
   562      * Print LocalVariableTable attribute information.
   563      */
   564     public void printLocVarTable(MethodData method){
   565         int siz = method.getloc_var_tbsize();
   566         if(siz > 0){
   567             out.println("  LocalVariableTable: ");
   568             out.print("   ");
   569             out.println("Start  Length  Slot  Name   Signature");
   570         }
   571         Vector loc_var_tb = method.getloc_var_tb();
   572 
   573         for (int i=0; i<siz; i++) {
   574             LocVarData entry=(LocVarData)loc_var_tb.elementAt(i);
   575 
   576             out.println("   "+entry.start_pc+"      "+entry.length+"      "+
   577                                entry.slot+"    "+cls.StringValue(entry.name_cpx)  +
   578                                "       "+cls.StringValue(entry.sig_cpx));
   579         }
   580         out.println();
   581     }
   582 
   583     /**
   584      * Print StackMap attribute information.
   585      */
   586     public void printStackMap(MethodData method) {
   587         StackMapData[] stack_map_tb = method.getStackMap();
   588         int number_of_entries = stack_map_tb.length;
   589         if (number_of_entries > 0) {
   590             out.println("  StackMap: number_of_entries = " + number_of_entries);
   591 
   592             for (StackMapData frame : stack_map_tb) {
   593                 frame.print(this);
   594             }
   595         }
   596        out.println();
   597     }
   598 
   599     /**
   600      * Print StackMapTable attribute information.
   601      */
   602     public void printStackMapTable(MethodData method) {
   603         StackMapTableData[] stack_map_tb = method.getStackMapTable();
   604         int number_of_entries = stack_map_tb.length;
   605         if (number_of_entries > 0) {
   606             out.println("  StackMapTable: number_of_entries = " + number_of_entries);
   607 
   608             for (StackMapTableData frame : stack_map_tb) {
   609                 frame.print(this);
   610             }
   611         }
   612         out.println();
   613     }
   614 
   615     void printMap(String name, int[] map) {
   616         out.print(name);
   617         for (int i=0; i<map.length; i++) {
   618             int fulltype = map[i];
   619             int type = fulltype & 0xFF;
   620             int argument = fulltype >> 8;
   621             switch (type) {
   622                 case ITEM_Object:
   623                     out.print(" ");
   624                     PrintConstant(argument);
   625                     break;
   626                 case ITEM_NewObject:
   627                     out.print(" " + Tables.mapTypeName(type));
   628                     out.print(" " + argument);
   629                     break;
   630                 default:
   631                     out.print(" " + Tables.mapTypeName(type));
   632             }
   633             out.print( (i==(map.length-1)? ' ' : ','));
   634         }
   635         out.println("]");
   636     }
   637 
   638     /**
   639      * Print ConstantValue attribute information.
   640      */
   641     public void printConstantValue(FieldData field){
   642         out.print("  Constant value: ");
   643         int cpx = (field.getConstantValueIndex());
   644         byte tag=0;
   645         try {
   646             tag=cls.getTag(cpx);
   647 
   648         } catch (IndexOutOfBoundsException e) {
   649             out.print("Error:");
   650             return;
   651         }
   652         switch (tag) {
   653         case CONSTANT_METHOD:
   654         case CONSTANT_INTERFACEMETHOD:
   655         case CONSTANT_FIELD: {
   656             CPX2 x = (CPX2)(cls.getCpoolEntry(cpx));
   657             if (x.cpx1 == cls.getthis_cpx()) {
   658                 // don't print class part for local references
   659                 cpx=x.cpx2;
   660             }
   661         }
   662         }
   663         out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
   664     }
   665 
   666     /**
   667      * Print InnerClass attribute information.
   668      */
   669     public void printInnerClasses(){//throws ioexception
   670 
   671         InnerClassData[] innerClasses = cls.getInnerClasses();
   672         if(innerClasses != null){
   673             if(innerClasses.length > 0){
   674                 out.print("  ");
   675                 out.println("InnerClass: ");
   676                 for(int i = 0 ; i < innerClasses.length; i++){
   677                     out.print("   ");
   678                     //access
   679                     String[] accflags = innerClasses[i].getAccess();
   680                     if(checkAccess(accflags)){
   681                         printAccess(accflags);
   682                         if (innerClasses[i].inner_name_index!=0) {
   683                             out.print("#"+innerClasses[i].inner_name_index+"= ");
   684                         }
   685                         out.print("#"+innerClasses[i].inner_class_info_index);
   686                         if (innerClasses[i].outer_class_info_index!=0) {
   687                             out.print(" of #"+innerClasses[i].outer_class_info_index);
   688                         }
   689                         out.print("; //");
   690                         if (innerClasses[i].inner_name_index!=0) {
   691                             out.print(cls.getName(innerClasses[i].inner_name_index)+"=");
   692                         }
   693                         PrintConstant(innerClasses[i].inner_class_info_index);
   694                         if (innerClasses[i].outer_class_info_index!=0) {
   695                             out.print(" of ");
   696                             PrintConstant(innerClasses[i].outer_class_info_index);
   697                         }
   698                         out.println();
   699                     }
   700                 }
   701 
   702             }
   703         }
   704     }
   705 
   706     /**
   707      * Print constant pool information.
   708      */
   709     public void printcp(){
   710         int cpx = 1 ;
   711 
   712         while (cpx < cls.getCpoolCount()) {
   713             out.print("const #"+cpx+" = ");
   714             cpx+=PrintlnConstantEntry(cpx);
   715         }
   716         out.println();
   717     }
   718 
   719     /**
   720      * Print constant pool entry information.
   721      */
   722     public int PrintlnConstantEntry(int cpx) {
   723         int size=1;
   724         byte tag=0;
   725         try {
   726             tag=cls.getTag(cpx);
   727         } catch (IndexOutOfBoundsException e) {
   728             out.println("  <Incorrect CP index>");
   729             return 1;
   730         }
   731         out.print(cls.StringTag(cpx)+"\t");
   732         Object x=cls.getCpoolEntryobj(cpx);
   733         if (x==null) {
   734             switch (tag) {
   735             case CONSTANT_LONG:
   736             case CONSTANT_DOUBLE:
   737                 size=2;
   738             }
   739             out.println("null;");
   740             return size;
   741         }
   742         String str=cls.StringValue(cpx);
   743 
   744         switch (tag) {
   745         case CONSTANT_CLASS:
   746         case CONSTANT_STRING:
   747             out.println("#"+(((CPX)x).cpx)+";\t//  "+str);
   748             break;
   749         case CONSTANT_FIELD:
   750         case CONSTANT_METHOD:
   751         case CONSTANT_INTERFACEMETHOD:
   752             out.println("#"+((CPX2)x).cpx1+".#"+((CPX2)x).cpx2+";\t//  "+str);
   753             break;
   754         case CONSTANT_NAMEANDTYPE:
   755             out.println("#"+((CPX2)x).cpx1+":#"+((CPX2)x).cpx2+";//  "+str);
   756             break;
   757         case CONSTANT_LONG:
   758         case CONSTANT_DOUBLE:
   759             size=2;
   760         default:
   761             out.println(str+";");
   762         }
   763         return size;
   764     }
   765 
   766     /**
   767      * Checks access of class, field or method.
   768      */
   769     public boolean checkAccess(String accflags[]){
   770 
   771         boolean ispublic = false;
   772         boolean isprotected = false;
   773         boolean isprivate = false;
   774         boolean ispackage = false;
   775 
   776         for(int i= 0; i < accflags.length; i++){
   777             if(accflags[i].equals("public")) ispublic = true;
   778             else if (accflags[i].equals("protected")) isprotected = true;
   779             else if (accflags[i].equals("private")) isprivate = true;
   780         }
   781 
   782         if(!(ispublic || isprotected || isprivate)) ispackage = true;
   783 
   784         if((env.showAccess == env.PUBLIC) && (isprotected || isprivate || ispackage)) return false;
   785         else if((env.showAccess == env.PROTECTED) && (isprivate || ispackage)) return false;
   786         else if((env.showAccess == env.PACKAGE) && (isprivate)) return false;
   787         else return true;
   788     }
   789 
   790     /**
   791      * Prints access of class, field or method.
   792      */
   793     public void printAccess(String []accflags){
   794         for(int j = 0; j < accflags.length; j++){
   795             out.print(accflags[j]+" ");
   796         }
   797     }
   798 
   799     /**
   800      * Print an integer so that it takes 'length' characters in
   801      * the output.  Temporary until formatting code is stable.
   802      */
   803     public void printFixedWidthInt(long x, int length) {
   804         CharArrayWriter baStream = new CharArrayWriter();
   805         PrintWriter pStream = new PrintWriter(baStream);
   806         pStream.print(x);
   807         String str = baStream.toString();
   808         for (int cnt = length - str.length(); cnt > 0; --cnt)
   809             out.print(' ');
   810         out.print(str);
   811     }
   812 
   813     protected int getbyte (int pc) {
   814         return code[pc];
   815     }
   816 
   817     protected int getUbyte (int pc) {
   818         return code[pc]&0xFF;
   819     }
   820 
   821     int getShort (int pc) {
   822         return (code[pc]<<8) | (code[pc+1]&0xFF);
   823     }
   824 
   825     int getUShort (int pc) {
   826         return ((code[pc]<<8) | (code[pc+1]&0xFF))&0xFFFF;
   827     }
   828 
   829     protected int getInt (int pc) {
   830         return (getShort(pc)<<16) | (getShort(pc+2)&0xFFFF);
   831     }
   832 
   833     /**
   834      * Print constant value at that index.
   835      */
   836     void PrintConstant(int cpx) {
   837         if (cpx==0) {
   838             out.print("#0");
   839             return;
   840         }
   841         byte tag=0;
   842         try {
   843             tag=cls.getTag(cpx);
   844 
   845         } catch (IndexOutOfBoundsException e) {
   846             out.print("#"+cpx);
   847             return;
   848         }
   849         switch (tag) {
   850         case CONSTANT_METHOD:
   851         case CONSTANT_INTERFACEMETHOD:
   852         case CONSTANT_FIELD: {
   853             // CPX2 x=(CPX2)(cpool[cpx]);
   854             CPX2 x = (CPX2)(cls.getCpoolEntry(cpx));
   855             if (x.cpx1 == cls.getthis_cpx()) {
   856                 // don't print class part for local references
   857                 cpx=x.cpx2;
   858             }
   859         }
   860         }
   861         out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
   862     }
   863 
   864     protected static int  align (int n) {
   865         return (n+3) & ~3 ;
   866     }
   867 
   868     public void printend(){
   869         out.println("}");
   870         out.println();
   871     }
   872 
   873     public String javaclassname(String name){
   874         return name.replace('/','.');
   875     }
   876 
   877     /**
   878      * Print attribute data in hex.
   879      */
   880     public void printAttrData(AttrData attr){
   881         byte []data = attr.getData();
   882         int i = 0;
   883         int j = 0;
   884         out.print("  "+attr.getAttrName()+": ");
   885         out.println("length = " + cls.toHex(attr.datalen));
   886 
   887         out.print("   ");
   888 
   889 
   890         while (i < data.length){
   891             String databytestring = cls.toHex(data[i]);
   892             if(databytestring.equals("0x")) out.print("00");
   893             else if(databytestring.substring(2).length() == 1){
   894                 out.print("0"+databytestring.substring(2));
   895             } else{
   896                 out.print(databytestring.substring(2));
   897             }
   898 
   899              j++;
   900             if(j == 16) {
   901                 out.println();
   902                 out.print("   ");
   903                 j = 0;
   904             }
   905             else out.print(" ");
   906             i++;
   907         }
   908         out.println();
   909     }
   910 }