src/share/classes/com/sun/tools/javap/ConstantWriter.java

Tue, 03 Jun 2008 13:26:47 -0700

author
jjg
date
Tue, 03 Jun 2008 13:26:47 -0700
changeset 46
7708bd6d800d
child 54
eaf608c64fec
permissions
-rw-r--r--

4075303: Use javap to enquire aboput a specific inner class
4348375: Javap is not internationalized
4459541: "javap -l" shows line numbers as signed short; they should be unsigned
4501660: change diagnostic of -help as 'print this help message and exit'
4776241: unused source file in javap...
4870651: javap should recognize generics, varargs, enum
4876942: javap invoked without args does not print help screen
4880663: javap could output whitespace between class name and opening brace
4975569: javap doesn't print new flag bits
6271787: javap dumps LocalVariableTypeTable attribute in hex, needs to print a table
6305779: javap: support annotations
6439940: Clean up javap implementation
6469569: wrong check of searchpath in JavapEnvironment
6474890: javap does not open .zip files in -classpath
6587786: Javap throws error : "ERROR:Could not find <classname>" for JRE classes
6622215: javap ignores certain relevant access flags
6622216: javap names some attributes incorrectly
6622232: javap gets whitespace confused
6622260: javap prints negative bytes incorrectly in hex
Reviewed-by: ksrini

     1 /*
     2  * Copyright 2007 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  */
    26 package com.sun.tools.javap;
    28 import com.sun.tools.classfile.ClassFile;
    29 import com.sun.tools.classfile.ConstantPool;
    30 import com.sun.tools.classfile.ConstantPoolException;
    32 import static com.sun.tools.classfile.ConstantPool.*;
    34 /*
    35  *  Write a constant pool entry.
    36  *
    37  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    38  *  you write code that depends on this, you do so at your own risk.
    39  *  This code and its internal interfaces are subject to change or
    40  *  deletion without notice.</b>
    41  */
    42 public class ConstantWriter extends BasicWriter {
    43     static ConstantWriter instance(Context context) {
    44         ConstantWriter instance = context.get(ConstantWriter.class);
    45         if (instance == null)
    46             instance = new ConstantWriter(context);
    47         return instance;
    48     }
    50     protected ConstantWriter(Context context) {
    51         super(context);
    52         context.put(ConstantWriter.class, this);
    53         classWriter = ClassWriter.instance(context);
    54         options = Options.instance(context);
    55     }
    57     void writeConstantPool() {
    58         ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer,Void>() {
    59             public Integer visitClass(CONSTANT_Class_info info, Void p) {
    60                 println("#" + info.name_index + ";\t//  " + stringValue(info));
    61                 return 1;
    62             }
    64             public Integer visitDouble(CONSTANT_Double_info info, Void p) {
    65                 println(stringValue(info) + ";");
    66                 return 2;
    67             }
    69             public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
    70                 println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t//  " + stringValue(info));
    71                 return 1;
    72             }
    74             public Integer visitFloat(CONSTANT_Float_info info, Void p) {
    75                 println(stringValue(info) + ";");
    76                 return 1;
    77             }
    79             public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
    80                 println(stringValue(info) + ";");
    81                 return 1;
    82             }
    84             public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
    85                 println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t//  " + stringValue(info));
    86                 return 1;
    87             }
    89             public Integer visitLong(CONSTANT_Long_info info, Void p) {
    90                 println(stringValue(info) + ";");
    91                 return 2;
    92             }
    94             public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
    95                 String tab = (options.compat ? "" : "\t"); // BUG 6622232 javap gets whitespace confused
    96                 println("#" + info.name_index + ":#" + info.type_index + ";" + tab + "//  " + stringValue(info));
    97                 return 1;
    98             }
   100             public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
   101                 println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t//  " + stringValue(info));
   102                 return 1;
   103             }
   105             public Integer visitString(CONSTANT_String_info info, Void p) {
   106                 println("#" + info.string_index + ";\t//  " + stringValue(info));
   107                 return 1;
   108             }
   110             public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
   111                 println(stringValue(info) + ";");
   112                 return 1;
   113             }
   115         };
   116         println("  Constant pool:");
   117         ConstantPool constant_pool = classWriter.getClassFile().constant_pool;
   118         int cpx = 1;
   119         while (cpx < constant_pool.size()) {
   120             try {
   121                 CPInfo cpInfo = constant_pool.get(cpx);
   122                 print("const #" + cpx + " = " + tagName(cpInfo.getTag()) + "\t");
   123                 cpx += cpInfo.accept(v, null);
   124             } catch (ConstantPool.InvalidIndex ex) {
   125                 print("const #" + cpx); // should not happen
   126             }
   127         }
   128     }
   130     void write(int cpx) {
   131         ClassFile classFile = classWriter.getClassFile();
   132         if (cpx == 0) {
   133             print("#0");
   134             return;
   135         }
   137         CPInfo cpInfo;
   138         try {
   139             cpInfo = classFile.constant_pool.get(cpx);
   140         } catch (ConstantPoolException e) {
   141             print("#" + cpx);
   142             return;
   143         }
   145         int tag = cpInfo.getTag();
   146         switch (tag) {
   147             case CONSTANT_Methodref:
   148             case CONSTANT_InterfaceMethodref:
   149             case CONSTANT_Fieldref:
   150                 // simplify references within this class
   151                 CPRefInfo ref = (CPRefInfo) cpInfo;
   152                 try {
   153                     if (ref.class_index == classFile.this_class)
   154                          cpInfo = classFile.constant_pool.get(ref.name_and_type_index);
   155                 } catch (ConstantPool.InvalidIndex e) {
   156                     // ignore, for now
   157                 }
   158         }
   159         print(tagName(tag) + " " + stringValue(cpInfo));
   160     }
   162     String tagName(int tag) {
   163         switch (tag) {
   164             case CONSTANT_Utf8:
   165                 return "Asciz";
   166             case CONSTANT_Integer:
   167                 return "int";
   168             case CONSTANT_Float:
   169                 return "float";
   170             case CONSTANT_Long:
   171                 return "long";
   172             case CONSTANT_Double:
   173                 return "double";
   174             case CONSTANT_Class:
   175                 return "class";
   176             case CONSTANT_String:
   177                 return "String";
   178             case CONSTANT_Fieldref:
   179                 return "Field";
   180             case CONSTANT_Methodref:
   181                 return "Method";
   182             case CONSTANT_InterfaceMethodref:
   183                 return "InterfaceMethod";
   184             case CONSTANT_NameAndType:
   185                 return "NameAndType";
   186             default:
   187                 return "unknown tag";
   188         }
   189     }
   191     String stringValue(int constant_pool_index) {
   192         ClassFile classFile = classWriter.getClassFile();
   193         try {
   194             return stringValue(classFile.constant_pool.get(constant_pool_index));
   195         } catch (ConstantPool.InvalidIndex e) {
   196             return report(e);
   197         }
   198     }
   200     String stringValue(CPInfo cpInfo) {
   201         return stringValueVisitor.visit(cpInfo);
   202     }
   204     StringValueVisitor stringValueVisitor = new StringValueVisitor();
   206     private class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
   207         public String visit(CPInfo info) {
   208             return info.accept(this, null);
   209         }
   211         public String visitClass(CONSTANT_Class_info info, Void p) {
   212             return getCheckedName(info);
   213         }
   215         String getCheckedName(CONSTANT_Class_info info) {
   216             try {
   217                 return checkName(info.getName());
   218             } catch (ConstantPoolException e) {
   219                 return report(e);
   220             }
   221         }
   223         public String visitDouble(CONSTANT_Double_info info, Void p) {
   224             return info.value + "d";
   225         }
   227         public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
   228             return visitRef(info, p);
   229         }
   231         public String visitFloat(CONSTANT_Float_info info, Void p) {
   232             return info.value + "f";
   233         }
   235         public String visitInteger(CONSTANT_Integer_info info, Void p) {
   236             return String.valueOf(info.value);
   237         }
   239         public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
   240             return visitRef(info, p);
   241         }
   243         public String visitLong(CONSTANT_Long_info info, Void p) {
   244             return info.value + "l";
   245         }
   247         public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
   248             return getCheckedName(info) + ":" + getType(info);
   249         }
   251         String getCheckedName(CONSTANT_NameAndType_info info) {
   252             try {
   253                 return checkName(info.getName());
   254             } catch (ConstantPoolException e) {
   255                 return report(e);
   256             }
   257         }
   259         String getType(CONSTANT_NameAndType_info info) {
   260             try {
   261                 return info.getType();
   262             } catch (ConstantPoolException e) {
   263                 return report(e);
   264             }
   265         }
   267         public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
   268             return visitRef(info, p);
   269         }
   271         public String visitString(CONSTANT_String_info info, Void p) {
   272             try {
   273                 ClassFile classFile = classWriter.getClassFile();
   274                 int string_index = info.string_index;
   275                 return stringValue(classFile.constant_pool.getUTF8Info(string_index));
   276             } catch (ConstantPoolException e) {
   277                 return report(e);
   278             }
   279         }
   281         public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
   282             String s = info.value;
   283             StringBuilder sb = new StringBuilder();
   284             for (int i = 0; i < s.length(); i++) {
   285                 char c = s.charAt(i);
   286                 switch (c) {
   287                     case '\t':
   288                         sb.append('\\').append('t');
   289                         break;
   290                     case '\n':
   291                         sb.append('\\').append('n');
   292                         break;
   293                     case '\r':
   294                         sb.append('\\').append('r');
   295                         break;
   296                     case '\"':
   297                         sb.append('\\').append('\"');
   298                         break;
   299                     default:
   300                         sb.append(c);
   301                 }
   302             }
   303             return sb.toString();
   304         }
   306         String visitRef(CPRefInfo info, Void p) {
   307             String cn = getCheckedClassName(info);
   308             String nat;
   309             try {
   310                 nat = stringValue(info.getNameAndTypeInfo());
   311             } catch (ConstantPoolException e) {
   312                 nat = report(e);
   313             }
   314             return cn + "." + nat;
   315         }
   317         String getCheckedClassName(CPRefInfo info) {
   318             try {
   319                 return checkName(info.getClassName());
   320             } catch (ConstantPoolException e) {
   321                 return report(e);
   322             }
   323         }
   324     }
   327     /* If name is a valid binary name, return it; otherwise quote it. */
   328     private static String checkName(String name) {
   329         if (name == null)
   330             return "null";
   332         int len = name.length();
   333         if (len == 0)
   334             return "\"\"";
   336         int cc = '/';
   337         int cp;
   338         for (int k = 0; k < len; k += Character.charCount(cp)) {
   339             cp = name.codePointAt(k);
   340             if ((cc == '/' && !Character.isJavaIdentifierStart(cp))
   341                     || (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
   342                 return "\"" + name + "\"";
   343             }
   344             cc = cp;
   345         }
   347         return name;
   348     }
   350     private ClassWriter classWriter;
   351     private Options options;
   352 }

mercurial