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

Tue, 08 Jul 2008 17:14:22 -0700

author
jjg
date
Tue, 08 Jul 2008 17:14:22 -0700
changeset 65
0d4aa3c00af5
parent 54
eaf608c64fec
child 87
fd1d361ae294
permissions
-rw-r--r--

6715757: javap does not print "extends java.lang.Object"
Reviewed-by: ksrini

     1 /*
     2  * Copyright 2007-2008 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 java.util.Collection;
    29 import java.util.List;
    31 import com.sun.tools.classfile.AccessFlags;
    32 import com.sun.tools.classfile.Attribute;
    33 import com.sun.tools.classfile.Attributes;
    34 import com.sun.tools.classfile.ClassFile;
    35 import com.sun.tools.classfile.Code_attribute;
    36 import com.sun.tools.classfile.ConstantPool;
    37 import com.sun.tools.classfile.ConstantPoolException;
    38 import com.sun.tools.classfile.Descriptor;
    39 import com.sun.tools.classfile.DescriptorException;
    40 import com.sun.tools.classfile.Exceptions_attribute;
    41 import com.sun.tools.classfile.Field;
    42 import com.sun.tools.classfile.Method;
    43 import com.sun.tools.classfile.Signature;
    44 import com.sun.tools.classfile.Signature_attribute;
    45 import com.sun.tools.classfile.SourceFile_attribute;
    46 import com.sun.tools.classfile.Type;
    48 import static com.sun.tools.classfile.AccessFlags.*;
    50 /*
    51  *  The main javap class to write the contents of a class file as text.
    52  *
    53  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    54  *  you write code that depends on this, you do so at your own risk.
    55  *  This code and its internal interfaces are subject to change or
    56  *  deletion without notice.</b>
    57  */
    58 public class ClassWriter extends BasicWriter {
    59     static ClassWriter instance(Context context) {
    60         ClassWriter instance = context.get(ClassWriter.class);
    61         if (instance == null)
    62             instance = new ClassWriter(context);
    63         return instance;
    64     }
    66     protected ClassWriter(Context context) {
    67         super(context);
    68         context.put(ClassWriter.class, this);
    69         options = Options.instance(context);
    70         attrWriter = AttributeWriter.instance(context);
    71         codeWriter = CodeWriter.instance(context);
    72         constantWriter = ConstantWriter.instance(context);
    73     }
    75     ClassFile getClassFile() {
    76         return classFile;
    77     }
    79     Method getMethod() {
    80         return method;
    81     }
    83     public void write(ClassFile cf) {
    84         classFile = cf;
    85         constant_pool = classFile.constant_pool;
    87         Attribute sfa = cf.getAttribute(Attribute.SourceFile);
    88         if (sfa instanceof SourceFile_attribute) {
    89             println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\"");
    90         }
    92         String name = getJavaName(classFile);
    93         AccessFlags flags = cf.access_flags;
    95         writeModifiers(flags.getClassModifiers());
    97         if (classFile.isClass())
    98             print("class ");
    99         else if (classFile.isInterface())
   100             print("interface ");
   102         print(name);
   104         Signature_attribute sigAttr = getSignature(cf.attributes);
   105         if (sigAttr == null) {
   106             // use info from class file header
   107             if (classFile.isClass() && classFile.super_class != 0 ) {
   108                 String sn = getJavaSuperclassName(cf);
   109                 print(" extends ");
   110                 print(sn);
   111             }
   112             for (int i = 0; i < classFile.interfaces.length; i++) {
   113                 print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ",");
   114                 print(getJavaInterfaceName(classFile, i));
   115             }
   116         } else {
   117             try {
   118                 Type t = sigAttr.getParsedSignature().getType(constant_pool);
   119                 // The signature parser cannot disambiguate between a
   120                 // FieldType and a ClassSignatureType that only contains a superclass type.
   121                 if (t instanceof Type.ClassSigType)
   122                     print(t);
   123                 else {
   124                     print(" extends ");
   125                     print(t);
   126                 }
   127             } catch (ConstantPoolException e) {
   128                 print(report(e));
   129             }
   130         }
   132         if (options.verbose) {
   133             println();
   134             attrWriter.write(cf, cf.attributes, constant_pool);
   135             println("  minor version: " + cf.minor_version);
   136             println("  major version: " + cf.major_version);
   137             if (!options.compat)
   138               writeList("  flags: ", flags.getClassFlags(), NEWLINE);
   139             constantWriter.writeConstantPool();
   140             println();
   141         } else {
   142             if (!options.compat)
   143                 print(" ");
   144         }
   146         println("{");
   147         writeFields();
   148         writeMethods();
   149         println("}");
   150         println();
   151     }
   153     void writeFields() {
   154         for (Field f: classFile.fields) {
   155             writeField(f);
   156         }
   157     }
   159     void writeField(Field f) {
   160         if (!options.checkAccess(f.access_flags))
   161             return;
   163         if (!(options.showLineAndLocalVariableTables
   164                 || options.showDisassembled
   165                 || options.verbose
   166                 || options.showInternalSignatures
   167                 || options.showAllAttrs)) {
   168             print("    ");
   169         }
   171         AccessFlags flags = f.access_flags;
   172         writeModifiers(flags.getFieldModifiers());
   173         Signature_attribute sigAttr = getSignature(f.attributes);
   174         if (sigAttr == null)
   175             print(getFieldType(f.descriptor));
   176         else {
   177             try {
   178                 Type t = sigAttr.getParsedSignature().getType(constant_pool);
   179                 print(t);
   180             } catch (ConstantPoolException e) {
   181                 // report error?
   182                 // fall back on non-generic descriptor
   183                 print(getFieldType(f.descriptor));
   184             }
   185         }
   186         print(" ");
   187         print(getFieldName(f));
   188         print(";");
   189         println();
   191         if (options.showInternalSignatures)
   192             println("  Signature: " + getValue(f.descriptor));
   194         if (options.verbose && !options.compat)
   195             writeList("  flags: ", flags.getFieldFlags(), NEWLINE);
   197         if (options.showAllAttrs) {
   198             for (Attribute attr: f.attributes)
   199                 attrWriter.write(f, attr, constant_pool);
   200             println();
   201         }
   203         if (options.showDisassembled || options.showLineAndLocalVariableTables)
   204             println();
   205     }
   207     void writeMethods() {
   208         for (Method m: classFile.methods)
   209             writeMethod(m);
   210     }
   212     void writeMethod(Method m) {
   213         if (!options.checkAccess(m.access_flags))
   214             return;
   216         method = m;
   218         if (!(options.showLineAndLocalVariableTables
   219                 || options.showDisassembled
   220                 || options.verbose
   221                 || options.showInternalSignatures
   222                 || options.showAllAttrs)) {
   223             print("    ");
   224         }
   226         AccessFlags flags = m.access_flags;
   228         Descriptor d;
   229         Type.MethodType methodType;
   230         List<? extends Type> methodExceptions;
   232         Signature_attribute sigAttr = getSignature(m.attributes);
   233         if (sigAttr == null) {
   234             d = m.descriptor;
   235             methodType = null;
   236             methodExceptions = null;
   237         } else {
   238             Signature methodSig = sigAttr.getParsedSignature();
   239             d = methodSig;
   240             try {
   241                 methodType = (Type.MethodType) methodSig.getType(constant_pool);
   242                 methodExceptions = methodType.throwsTypes;
   243                 if (methodExceptions != null && methodExceptions.size() == 0)
   244                     methodExceptions = null;
   245             } catch (ConstantPoolException e) {
   246                 // report error?
   247                 // fall back on standard descriptor
   248                 methodType = null;
   249                 methodExceptions = null;
   250             }
   251         }
   253         writeModifiers(flags.getMethodModifiers());
   254         if (methodType != null) {
   255             writeListIfNotEmpty("<", methodType.typeArgTypes, "> ");
   256         }
   257         if (getName(m).equals("<init>")) {
   258             print(getJavaName(classFile));
   259             print(getParameterTypes(d, flags));
   260         } else if (getName(m).equals("<clinit>")) {
   261             print("{}");
   262         } else {
   263             print(getReturnType(d));
   264             print(" ");
   265             print(getName(m));
   266             print(getParameterTypes(d, flags));
   267         }
   269         Attribute e_attr = m.attributes.get(Attribute.Exceptions);
   270         if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions
   271             if (e_attr instanceof Exceptions_attribute) {
   272                 Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
   273                 if (options.compat) { // Bug XXXXXXX whitespace
   274                     if (!(options.showLineAndLocalVariableTables
   275                             || options.showDisassembled
   276                             || options.verbose
   277                             || options.showInternalSignatures
   278                             || options.showAllAttrs)) {
   279                         print("    ");
   280                     }
   281                     print("  ");
   282                 }
   283                 print(" throws ");
   284                 if (methodExceptions != null) { // use generic list if available
   285                     writeList("", methodExceptions, "");
   286                 } else {
   287                     for (int i = 0; i < exceptions.number_of_exceptions; i++) {
   288                         if (i > 0)
   289                             print(", ");
   290                         print(getJavaException(exceptions, i));
   291                     }
   292                 }
   293             } else {
   294                 report("Unexpected or invalid value for Exceptions attribute");
   295             }
   296         }
   298         print(";");
   299         println();
   301         if (options.showInternalSignatures)
   302             println("  Signature: " + getValue(m.descriptor));
   304         if (options.verbose && !options.compat)
   305             writeList("  flags: ", flags.getMethodFlags(), NEWLINE);
   307         Code_attribute code = null;
   308         Attribute c_attr = m.attributes.get(Attribute.Code);
   309         if (c_attr != null) {
   310             if (c_attr instanceof Code_attribute)
   311                 code = (Code_attribute) c_attr;
   312             else
   313                 report("Unexpected or invalid value for Code attribute");
   314         }
   316         if (options.showDisassembled && !options.showAllAttrs) {
   317             if (code != null) {
   318                 println("  Code:");
   319                 codeWriter.writeInstrs(code);
   320                 codeWriter.writeExceptionTable(code);
   321             }
   322             println();
   323         }
   325         if (options.showLineAndLocalVariableTables) {
   326             if (code != null)
   327                 attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool);
   328             println();
   329             if (code != null)
   330                 attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool);
   331             println();
   332             println();
   333         }
   335         if (options.showAllAttrs) {
   336             Attribute[] attrs = m.attributes.attrs;
   337             for (Attribute attr: attrs)
   338                 attrWriter.write(m, attr, constant_pool);
   340 //            // the following condition is to mimic old javap
   341 //            if (!(attrs.length > 0 &&
   342 //                    attrs[attrs.length - 1] instanceof Exceptions_attribute))
   343             println();
   344         }
   345     }
   347     void writeModifiers(Collection<String> items) {
   348         for (Object item: items) {
   349             print(item);
   350             print(" ");
   351         }
   352     }
   354     void writeList(String prefix, Collection<?> items, String suffix) {
   355         print(prefix);
   356         String sep = "";
   357         for (Object item: items) {
   358             print(sep);
   359             print(item);
   360             sep = ", ";
   361         }
   362         print(suffix);
   363     }
   365     void writeListIfNotEmpty(String prefix, List<?> items, String suffix) {
   366         if (items != null && items.size() > 0)
   367             writeList(prefix, items, suffix);
   368     }
   370     Signature_attribute getSignature(Attributes attributes) {
   371         if (options.compat) // javap does not recognize recent attributes
   372             return null;
   373         return (Signature_attribute) attributes.get(Attribute.Signature);
   374     }
   376     String adjustVarargs(AccessFlags flags, String params) {
   377         if (flags.is(ACC_VARARGS) && !options.compat) {
   378             int i = params.lastIndexOf("[]");
   379             if (i > 0)
   380                 return params.substring(0, i) + "..." + params.substring(i+2);
   381         }
   383         return params;
   384     }
   386     String getJavaName(ClassFile cf) {
   387         try {
   388             return getJavaName(cf.getName());
   389         } catch (ConstantPoolException e) {
   390             return report(e);
   391         }
   392     }
   394     String getJavaSuperclassName(ClassFile cf) {
   395         try {
   396             return getJavaName(cf.getSuperclassName());
   397         } catch (ConstantPoolException e) {
   398             return report(e);
   399         }
   400     }
   402     String getJavaInterfaceName(ClassFile cf, int index) {
   403         try {
   404             return getJavaName(cf.getInterfaceName(index));
   405         } catch (ConstantPoolException e) {
   406             return report(e);
   407         }
   408     }
   410     String getFieldType(Descriptor d) {
   411         try {
   412             return d.getFieldType(constant_pool);
   413         } catch (ConstantPoolException e) {
   414             return report(e);
   415         } catch (DescriptorException e) {
   416             return report(e);
   417         }
   418     }
   420     String getReturnType(Descriptor d) {
   421         try {
   422             return d.getReturnType(constant_pool);
   423         } catch (ConstantPoolException e) {
   424             return report(e);
   425         } catch (DescriptorException e) {
   426             return report(e);
   427         }
   428     }
   430     String getParameterTypes(Descriptor d, AccessFlags flags) {
   431         try {
   432             return adjustVarargs(flags, d.getParameterTypes(constant_pool));
   433         } catch (ConstantPoolException e) {
   434             return report(e);
   435         } catch (DescriptorException e) {
   436             return report(e);
   437         }
   438     }
   440     String getJavaException(Exceptions_attribute attr, int index) {
   441         try {
   442             return getJavaName(attr.getException(index, constant_pool));
   443         } catch (ConstantPoolException e) {
   444             return report(e);
   445         }
   446     }
   448     String getValue(Descriptor d) {
   449         try {
   450             return d.getValue(constant_pool);
   451         } catch (ConstantPoolException e) {
   452             return report(e);
   453         }
   454     }
   456     String getFieldName(Field f) {
   457         try {
   458             return f.getName(constant_pool);
   459         } catch (ConstantPoolException e) {
   460             return report(e);
   461         }
   462     }
   464     String getName(Method m) {
   465         try {
   466             return m.getName(constant_pool);
   467         } catch (ConstantPoolException e) {
   468             return report(e);
   469         }
   470     }
   472     static String getJavaName(String name) {
   473         return name.replace('/', '.');
   474     }
   476     String getSourceFile(SourceFile_attribute attr) {
   477         try {
   478             return attr.getSourceFile(constant_pool);
   479         } catch (ConstantPoolException e) {
   480             return report(e);
   481         }
   482     }
   484     private Options options;
   485     private AttributeWriter attrWriter;
   486     private CodeWriter codeWriter;
   487     private ConstantWriter constantWriter;
   488     private ClassFile classFile;
   489     private ConstantPool constant_pool;
   490     private Method method;
   491     private static final String NEWLINE = System.getProperty("line.separator", "\n");
   492 }

mercurial