< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java

Print this page

  45 import javax.tools.JavaFileManager;
  46 import javax.tools.JavaFileObject;
  47 
  48 import com.sun.tools.javac.code.Source;
  49 import com.sun.tools.javac.code.Source.Feature;
  50 import com.sun.tools.javac.comp.Annotate;
  51 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
  52 import com.sun.tools.javac.code.*;
  53 import com.sun.tools.javac.code.Directive.*;
  54 import com.sun.tools.javac.code.Lint.LintCategory;
  55 import com.sun.tools.javac.code.Scope.WriteableScope;
  56 import com.sun.tools.javac.code.Symbol.*;
  57 import com.sun.tools.javac.code.Symtab;
  58 import com.sun.tools.javac.code.Type.*;
  59 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
  60 import com.sun.tools.javac.file.BaseFileManager;
  61 import com.sun.tools.javac.file.PathFileObject;
  62 import com.sun.tools.javac.jvm.ClassFile.Version;
  63 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
  64 import com.sun.tools.javac.main.Option;

  65 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  66 import com.sun.tools.javac.resources.CompilerProperties.Warnings;

  67 import com.sun.tools.javac.util.*;
  68 import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
  69 import com.sun.tools.javac.util.DefinedBy.Api;
  70 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  71 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  72 
  73 import static com.sun.tools.javac.code.Flags.*;
  74 import static com.sun.tools.javac.code.Kinds.Kind.*;
  75 
  76 import com.sun.tools.javac.code.Scope.LookupKind;
  77 

  78 import static com.sun.tools.javac.code.TypeTag.ARRAY;
  79 import static com.sun.tools.javac.code.TypeTag.CLASS;
  80 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
  81 import static com.sun.tools.javac.jvm.ClassFile.*;
  82 import static com.sun.tools.javac.jvm.ClassFile.Version.*;
  83 
  84 import static com.sun.tools.javac.main.Option.PARAMETERS;
  85 
  86 /** This class provides operations to read a classfile into an internal
  87  *  representation. The internal representation is anchored in a
  88  *  ClassSymbol which contains in its scope symbol representations
  89  *  for all other definitions in the classfile. Top-level Classes themselves
  90  *  appear as members of the scopes of PackageSymbols.
  91  *
  92  *  <p><b>This is NOT part of any supported API.
  93  *  If you write code that depends on this, you do so at your own risk.
  94  *  This code and its internal interfaces are subject to change or
  95  *  deletion without notice.</b>
  96  */
  97 public class ClassReader {
  98     /** The context key for the class reader. */
  99     protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
 100 
 101     public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
 102 
 103     private final Annotate annotate;
 104 
 105     /** Switch: verbose output.
 106      */
 107     boolean verbose;
 108 
 109     /** Switch: allow modules.
 110      */
 111     boolean allowModules;
 112 




 113     /** Switch: allow sealed
 114      */
 115     boolean allowSealedTypes;
 116 
 117     /** Switch: allow records
 118      */
 119     boolean allowRecords;
 120 
 121    /** Lint option: warn about classfile issues
 122      */
 123     boolean lintClassfile;
 124 
 125     /** Switch: warn (instead of error) on illegal UTF-8
 126      */
 127     boolean warnOnIllegalUtf8;
 128 
 129     /** Switch: preserve parameter names from the variable table.
 130      */
 131     public boolean saveParameterNames;
 132 

 267     protected ClassReader(Context context) {
 268         context.put(classReaderKey, this);
 269         annotate = Annotate.instance(context);
 270         names = Names.instance(context);
 271         syms = Symtab.instance(context);
 272         types = Types.instance(context);
 273         fileManager = context.get(JavaFileManager.class);
 274         if (fileManager == null)
 275             throw new AssertionError("FileManager initialization error");
 276         diagFactory = JCDiagnostic.Factory.instance(context);
 277         dcfh = DeferredCompletionFailureHandler.instance(context);
 278 
 279         log = Log.instance(context);
 280 
 281         Options options = Options.instance(context);
 282         verbose         = options.isSet(Option.VERBOSE);
 283 
 284         Source source = Source.instance(context);
 285         preview = Preview.instance(context);
 286         allowModules     = Feature.MODULES.allowedInSource(source);


 287         allowRecords = Feature.RECORDS.allowedInSource(source);
 288         allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 289         warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
 290 
 291         saveParameterNames = options.isSet(PARAMETERS);
 292 
 293         profile = Profile.instance(context);
 294 
 295         typevars = WriteableScope.create(syms.noSymbol);
 296 
 297         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
 298 
 299         initAttributeReaders();
 300     }
 301 
 302     /** Add member to class unless it is synthetic.
 303      */
 304     private void enterMember(ClassSymbol c, Symbol sym) {
 305         // Synthetic members are not entered -- reason lost to history (optimization?).
 306         // Lambda methods must be entered because they may have inner classes (which reference them)

 549                                   syms.methodClass);
 550         case '<':
 551             typevars = typevars.dup(currentOwner);
 552             Type poly = new ForAll(sigToTypeParams(), sigToType());
 553             typevars = typevars.leave();
 554             return poly;
 555         default:
 556             throw badClassFile("bad.signature", quoteBadSignature());
 557         }
 558     }
 559 
 560     byte[] signatureBuffer = new byte[0];
 561     int sbp = 0;
 562     /** Convert class signature to type, where signature is implicit.
 563      */
 564     Type classSigToType() {
 565         if (signature[sigp] != 'L')
 566             throw badClassFile("bad.class.signature", quoteBadSignature());
 567         sigp++;
 568         Type outer = Type.noType;

 569         int startSbp = sbp;
 570 
 571         while (true) {
 572             final byte c = signature[sigp++];
 573             switch (c) {
 574 
 575             case ';': {         // end
 576                 ClassSymbol t = enterClass(readName(signatureBuffer,
 577                                                          startSbp,
 578                                                          sbp - startSbp));
 579 
 580                 try {
 581                     return (outer == Type.noType) ?
 582                             t.erasure(types) :
 583                         new ClassType(outer, List.nil(), t);


 584                 } finally {
 585                     sbp = startSbp;
 586                 }
 587             }
 588 
 589             case '<':           // generic arguments
 590                 ClassSymbol t = enterClass(readName(signatureBuffer,
 591                                                          startSbp,
 592                                                          sbp - startSbp));
 593                 outer = new ClassType(outer, sigToTypes('>'), t) {
 594                         boolean completed = false;
 595                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 596                         public Type getEnclosingType() {
 597                             if (!completed) {
 598                                 completed = true;
 599                                 tsym.apiComplete();
 600                                 Type enclosingType = tsym.type.getEnclosingType();
 601                                 if (enclosingType != Type.noType) {
 602                                     List<Type> typeArgs =
 603                                         super.getEnclosingType().allparams();
 604                                     List<Type> typeParams =
 605                                         enclosingType.allparams();
 606                                     if (typeParams.length() != typeArgs.length()) {
 607                                         // no "rare" types
 608                                         super.setEnclosingType(types.erasure(enclosingType));
 609                                     } else {
 610                                         super.setEnclosingType(types.subst(enclosingType,
 611                                                                            typeParams,
 612                                                                            typeArgs));
 613                                     }

 636                         signatureBuffer[sbp++] = (byte)'$';
 637                         break;
 638                     } else {
 639                         sbp = startSbp;
 640                         return outer;
 641                     }
 642                 case '.':
 643                     signatureBuffer[sbp++] = (byte)'$';
 644                     break;
 645                 default:
 646                     throw new AssertionError(signature[sigp-1]);
 647                 }
 648                 continue;
 649 
 650             case '.':
 651                 //we have seen an enclosing non-generic class
 652                 if (outer != Type.noType) {
 653                     t = enterClass(readName(signatureBuffer,
 654                                                  startSbp,
 655                                                  sbp - startSbp));
 656                     outer = new ClassType(outer, List.nil(), t);
 657                 }
 658                 signatureBuffer[sbp++] = (byte)'$';
 659                 continue;
 660             case '/':
 661                 signatureBuffer[sbp++] = (byte)'.';
 662                 continue;
 663             default:
 664                 signatureBuffer[sbp++] = c;
 665                 continue;
 666             }
 667         }
 668     }
 669 
 670     /** Quote a bogus signature for display inside an error message.
 671      */
 672     String quoteBadSignature() {
 673         String sigString;
 674         try {
 675             sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE);
 676         } catch (InvalidUtfException e) {

3113         } finally {
3114             interimUses = List.nil();
3115             interimProvides = List.nil();
3116             missingTypeVariables = List.nil();
3117             foundTypeVariables = List.nil();
3118             filling = false;
3119         }
3120     }
3121 
3122     /** We can only read a single class file at a time; this
3123      *  flag keeps track of when we are currently reading a class
3124      *  file.
3125      */
3126     public boolean filling = false;
3127 
3128 /************************************************************************
3129  * Adjusting flags
3130  ***********************************************************************/
3131 
3132     long adjustFieldFlags(long flags) {





3133         return flags;
3134     }
3135 
3136     long adjustMethodFlags(long flags) {
3137         if ((flags & ACC_BRIDGE) != 0) {
3138             flags &= ~ACC_BRIDGE;
3139             flags |= BRIDGE;
3140         }
3141         if ((flags & ACC_VARARGS) != 0) {
3142             flags &= ~ACC_VARARGS;
3143             flags |= VARARGS;
3144         }
3145         return flags;
3146     }
3147 
3148     long adjustClassFlags(long flags) {

3149         if ((flags & ACC_MODULE) != 0) {
3150             flags &= ~ACC_MODULE;
3151             flags |= MODULE;
3152         }
3153         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded






3154     }
3155 
3156     /**
3157      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
3158      * The attribute is only the last component of the original filename, so is unlikely
3159      * to be valid as is, so operations other than those to access the name throw
3160      * UnsupportedOperationException
3161      */
3162     private static class SourceFileObject implements JavaFileObject {
3163 
3164         /** The file's name.
3165          */
3166         private final Name name;
3167 
3168         public SourceFileObject(Name name) {
3169             this.name = name;
3170         }
3171 
3172         @Override @DefinedBy(Api.COMPILER)
3173         public URI toUri() {

  45 import javax.tools.JavaFileManager;
  46 import javax.tools.JavaFileObject;
  47 
  48 import com.sun.tools.javac.code.Source;
  49 import com.sun.tools.javac.code.Source.Feature;
  50 import com.sun.tools.javac.comp.Annotate;
  51 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
  52 import com.sun.tools.javac.code.*;
  53 import com.sun.tools.javac.code.Directive.*;
  54 import com.sun.tools.javac.code.Lint.LintCategory;
  55 import com.sun.tools.javac.code.Scope.WriteableScope;
  56 import com.sun.tools.javac.code.Symbol.*;
  57 import com.sun.tools.javac.code.Symtab;
  58 import com.sun.tools.javac.code.Type.*;
  59 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
  60 import com.sun.tools.javac.file.BaseFileManager;
  61 import com.sun.tools.javac.file.PathFileObject;
  62 import com.sun.tools.javac.jvm.ClassFile.Version;
  63 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
  64 import com.sun.tools.javac.main.Option;
  65 import com.sun.tools.javac.resources.CompilerProperties;
  66 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  67 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  68 import com.sun.tools.javac.tree.JCTree;
  69 import com.sun.tools.javac.util.*;
  70 import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
  71 import com.sun.tools.javac.util.DefinedBy.Api;
  72 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  73 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  74 
  75 import static com.sun.tools.javac.code.Flags.*;
  76 import static com.sun.tools.javac.code.Kinds.Kind.*;
  77 
  78 import com.sun.tools.javac.code.Scope.LookupKind;
  79 
  80 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  81 import static com.sun.tools.javac.code.TypeTag.ARRAY;
  82 import static com.sun.tools.javac.code.TypeTag.CLASS;
  83 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
  84 import static com.sun.tools.javac.jvm.ClassFile.*;
  85 import static com.sun.tools.javac.jvm.ClassFile.Version.*;
  86 
  87 import static com.sun.tools.javac.main.Option.PARAMETERS;
  88 
  89 /** This class provides operations to read a classfile into an internal
  90  *  representation. The internal representation is anchored in a
  91  *  ClassSymbol which contains in its scope symbol representations
  92  *  for all other definitions in the classfile. Top-level Classes themselves
  93  *  appear as members of the scopes of PackageSymbols.
  94  *
  95  *  <p><b>This is NOT part of any supported API.
  96  *  If you write code that depends on this, you do so at your own risk.
  97  *  This code and its internal interfaces are subject to change or
  98  *  deletion without notice.</b>
  99  */
 100 public class ClassReader {
 101     /** The context key for the class reader. */
 102     protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
 103 
 104     public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
 105 
 106     private final Annotate annotate;
 107 
 108     /** Switch: verbose output.
 109      */
 110     boolean verbose;
 111 
 112     /** Switch: allow modules.
 113      */
 114     boolean allowModules;
 115 
 116     /** Switch: allow value classes.
 117      */
 118     boolean allowValueClasses;
 119 
 120     /** Switch: allow sealed
 121      */
 122     boolean allowSealedTypes;
 123 
 124     /** Switch: allow records
 125      */
 126     boolean allowRecords;
 127 
 128    /** Lint option: warn about classfile issues
 129      */
 130     boolean lintClassfile;
 131 
 132     /** Switch: warn (instead of error) on illegal UTF-8
 133      */
 134     boolean warnOnIllegalUtf8;
 135 
 136     /** Switch: preserve parameter names from the variable table.
 137      */
 138     public boolean saveParameterNames;
 139 

 274     protected ClassReader(Context context) {
 275         context.put(classReaderKey, this);
 276         annotate = Annotate.instance(context);
 277         names = Names.instance(context);
 278         syms = Symtab.instance(context);
 279         types = Types.instance(context);
 280         fileManager = context.get(JavaFileManager.class);
 281         if (fileManager == null)
 282             throw new AssertionError("FileManager initialization error");
 283         diagFactory = JCDiagnostic.Factory.instance(context);
 284         dcfh = DeferredCompletionFailureHandler.instance(context);
 285 
 286         log = Log.instance(context);
 287 
 288         Options options = Options.instance(context);
 289         verbose         = options.isSet(Option.VERBOSE);
 290 
 291         Source source = Source.instance(context);
 292         preview = Preview.instance(context);
 293         allowModules     = Feature.MODULES.allowedInSource(source);
 294         allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 295                 Feature.VALUE_CLASSES.allowedInSource(source);
 296         allowRecords = Feature.RECORDS.allowedInSource(source);
 297         allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 298         warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
 299 
 300         saveParameterNames = options.isSet(PARAMETERS);
 301 
 302         profile = Profile.instance(context);
 303 
 304         typevars = WriteableScope.create(syms.noSymbol);
 305 
 306         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
 307 
 308         initAttributeReaders();
 309     }
 310 
 311     /** Add member to class unless it is synthetic.
 312      */
 313     private void enterMember(ClassSymbol c, Symbol sym) {
 314         // Synthetic members are not entered -- reason lost to history (optimization?).
 315         // Lambda methods must be entered because they may have inner classes (which reference them)

 558                                   syms.methodClass);
 559         case '<':
 560             typevars = typevars.dup(currentOwner);
 561             Type poly = new ForAll(sigToTypeParams(), sigToType());
 562             typevars = typevars.leave();
 563             return poly;
 564         default:
 565             throw badClassFile("bad.signature", quoteBadSignature());
 566         }
 567     }
 568 
 569     byte[] signatureBuffer = new byte[0];
 570     int sbp = 0;
 571     /** Convert class signature to type, where signature is implicit.
 572      */
 573     Type classSigToType() {
 574         if (signature[sigp] != 'L')
 575             throw badClassFile("bad.class.signature", quoteBadSignature());
 576         sigp++;
 577         Type outer = Type.noType;
 578         Name name;
 579         int startSbp = sbp;
 580 
 581         while (true) {
 582             final byte c = signature[sigp++];
 583             switch (c) {
 584 
 585             case ';': {         // end
 586                 ClassSymbol t = enterClass(readName(signatureBuffer,
 587                                                          startSbp,
 588                                                          sbp - startSbp));
 589 
 590                 try {
 591                     if (outer == Type.noType) {
 592                         ClassType et = (ClassType) t.erasure(types);
 593                         return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata());
 594                     }
 595                     return new ClassType(outer, List.nil(), t, List.nil());
 596                 } finally {
 597                     sbp = startSbp;
 598                 }
 599             }
 600 
 601             case '<':           // generic arguments
 602                 ClassSymbol t = enterClass(readName(signatureBuffer,
 603                                                          startSbp,
 604                                                          sbp - startSbp));
 605                 outer = new ClassType(outer, sigToTypes('>'), t, List.nil()) {
 606                         boolean completed = false;
 607                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 608                         public Type getEnclosingType() {
 609                             if (!completed) {
 610                                 completed = true;
 611                                 tsym.apiComplete();
 612                                 Type enclosingType = tsym.type.getEnclosingType();
 613                                 if (enclosingType != Type.noType) {
 614                                     List<Type> typeArgs =
 615                                         super.getEnclosingType().allparams();
 616                                     List<Type> typeParams =
 617                                         enclosingType.allparams();
 618                                     if (typeParams.length() != typeArgs.length()) {
 619                                         // no "rare" types
 620                                         super.setEnclosingType(types.erasure(enclosingType));
 621                                     } else {
 622                                         super.setEnclosingType(types.subst(enclosingType,
 623                                                                            typeParams,
 624                                                                            typeArgs));
 625                                     }

 648                         signatureBuffer[sbp++] = (byte)'$';
 649                         break;
 650                     } else {
 651                         sbp = startSbp;
 652                         return outer;
 653                     }
 654                 case '.':
 655                     signatureBuffer[sbp++] = (byte)'$';
 656                     break;
 657                 default:
 658                     throw new AssertionError(signature[sigp-1]);
 659                 }
 660                 continue;
 661 
 662             case '.':
 663                 //we have seen an enclosing non-generic class
 664                 if (outer != Type.noType) {
 665                     t = enterClass(readName(signatureBuffer,
 666                                                  startSbp,
 667                                                  sbp - startSbp));
 668                     outer = new ClassType(outer, List.nil(), t, List.nil());
 669                 }
 670                 signatureBuffer[sbp++] = (byte)'$';
 671                 continue;
 672             case '/':
 673                 signatureBuffer[sbp++] = (byte)'.';
 674                 continue;
 675             default:
 676                 signatureBuffer[sbp++] = c;
 677                 continue;
 678             }
 679         }
 680     }
 681 
 682     /** Quote a bogus signature for display inside an error message.
 683      */
 684     String quoteBadSignature() {
 685         String sigString;
 686         try {
 687             sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE);
 688         } catch (InvalidUtfException e) {

3125         } finally {
3126             interimUses = List.nil();
3127             interimProvides = List.nil();
3128             missingTypeVariables = List.nil();
3129             foundTypeVariables = List.nil();
3130             filling = false;
3131         }
3132     }
3133 
3134     /** We can only read a single class file at a time; this
3135      *  flag keeps track of when we are currently reading a class
3136      *  file.
3137      */
3138     public boolean filling = false;
3139 
3140 /************************************************************************
3141  * Adjusting flags
3142  ***********************************************************************/
3143 
3144     long adjustFieldFlags(long flags) {
3145         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3146         if (allowValueClasses && previewClassFile && (flags & ACC_STRICT) != 0) {
3147             flags &= ~ACC_STRICT;
3148             flags |= STRICT;
3149         }
3150         return flags;
3151     }
3152 
3153     long adjustMethodFlags(long flags) {
3154         if ((flags & ACC_BRIDGE) != 0) {
3155             flags &= ~ACC_BRIDGE;
3156             flags |= BRIDGE;
3157         }
3158         if ((flags & ACC_VARARGS) != 0) {
3159             flags &= ~ACC_VARARGS;
3160             flags |= VARARGS;
3161         }
3162         return flags;
3163     }
3164 
3165     long adjustClassFlags(long flags) {
3166         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3167         if ((flags & ACC_MODULE) != 0) {
3168             flags &= ~ACC_MODULE;
3169             flags |= MODULE;
3170         }
3171         if ((flags & ACC_IDENTITY) != 0 || (majorVersion < V66.major && (flags & INTERFACE) == 0)) {
3172             flags |= IDENTITY_TYPE;
3173         } else if ((flags & INTERFACE) == 0 && allowValueClasses && previewClassFile && majorVersion >= V66.major) {
3174             flags |= VALUE_CLASS;
3175         }
3176         flags &= ~ACC_IDENTITY; // ACC_IDENTITY and SYNCHRONIZED bits overloaded
3177         return flags;
3178     }
3179 
3180     /**
3181      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
3182      * The attribute is only the last component of the original filename, so is unlikely
3183      * to be valid as is, so operations other than those to access the name throw
3184      * UnsupportedOperationException
3185      */
3186     private static class SourceFileObject implements JavaFileObject {
3187 
3188         /** The file's name.
3189          */
3190         private final Name name;
3191 
3192         public SourceFileObject(Name name) {
3193             this.name = name;
3194         }
3195 
3196         @Override @DefinedBy(Api.COMPILER)
3197         public URI toUri() {
< prev index next >