< prev index next >

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

Print this page

  27 
  28 import java.io.*;
  29 import java.net.URI;
  30 import java.net.URISyntaxException;
  31 import java.nio.CharBuffer;
  32 import java.nio.file.ClosedFileSystemException;
  33 import java.util.Arrays;
  34 import java.util.EnumSet;
  35 import java.util.HashMap;
  36 import java.util.HashSet;
  37 import java.util.Map;
  38 import java.util.Set;
  39 import java.util.function.IntFunction;
  40 
  41 import javax.lang.model.element.Modifier;
  42 import javax.lang.model.element.NestingKind;
  43 import javax.tools.JavaFileManager;
  44 import javax.tools.JavaFileObject;
  45 
  46 import com.sun.tools.javac.code.Source.Feature;

  47 import com.sun.tools.javac.comp.Annotate;
  48 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
  49 import com.sun.tools.javac.code.*;
  50 import com.sun.tools.javac.code.Directive.*;
  51 import com.sun.tools.javac.code.Lint.LintCategory;
  52 import com.sun.tools.javac.code.Scope.WriteableScope;
  53 import com.sun.tools.javac.code.Symbol.*;
  54 import com.sun.tools.javac.code.Symtab;
  55 import com.sun.tools.javac.code.Type.*;
  56 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
  57 import com.sun.tools.javac.file.BaseFileManager;
  58 import com.sun.tools.javac.file.PathFileObject;
  59 import com.sun.tools.javac.jvm.ClassFile.Version;
  60 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
  61 import com.sun.tools.javac.main.Option;
  62 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  63 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  64 import com.sun.tools.javac.util.*;
  65 import com.sun.tools.javac.util.DefinedBy.Api;
  66 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;

  88  *  If you write code that depends on this, you do so at your own risk.
  89  *  This code and its internal interfaces are subject to change or
  90  *  deletion without notice.</b>
  91  */
  92 public class ClassReader {
  93     /** The context key for the class reader. */
  94     protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
  95 
  96     public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
  97 
  98     private final Annotate annotate;
  99 
 100     /** Switch: verbose output.
 101      */
 102     boolean verbose;
 103 
 104     /** Switch: allow modules.
 105      */
 106     boolean allowModules;
 107 








 108     /** Switch: allow sealed
 109      */
 110     boolean allowSealedTypes;
 111 
 112     /** Switch: allow records
 113      */
 114     boolean allowRecords;
 115 
 116    /** Lint option: warn about classfile issues
 117      */
 118     boolean lintClassfile;
 119 
 120     /** Switch: preserve parameter names from the variable table.
 121      */
 122     public boolean saveParameterNames;
 123 
 124     /**
 125      * The currently selected profile.
 126      */
 127     public final Profile profile;

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




 280         allowRecords = Feature.RECORDS.allowedInSource(source);
 281         allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 282 
 283         saveParameterNames = options.isSet(PARAMETERS);
 284 
 285         profile = Profile.instance(context);
 286 
 287         typevars = WriteableScope.create(syms.noSymbol);
 288 
 289         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
 290 
 291         initAttributeReaders();
 292     }
 293 
 294     /** Add member to class unless it is synthetic.
 295      */
 296     private void enterMember(ClassSymbol c, Symbol sym) {
 297         // Synthetic members are not entered -- reason lost to history (optimization?).
 298         // Lambda methods must be entered because they may have inner classes (which reference them)
 299         if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))

 455             return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
 456         }
 457         case 'B':
 458             sigp++;
 459             return syms.byteType;
 460         case 'C':
 461             sigp++;
 462             return syms.charType;
 463         case 'D':
 464             sigp++;
 465             return syms.doubleType;
 466         case 'F':
 467             sigp++;
 468             return syms.floatType;
 469         case 'I':
 470             sigp++;
 471             return syms.intType;
 472         case 'J':
 473             sigp++;
 474             return syms.longType;

 475         case 'L':
 476             {
 477                 // int oldsigp = sigp;
 478                 Type t = classSigToType();
 479                 if (sigp < siglimit && signature[sigp] == '.')
 480                     throw badClassFile("deprecated inner class signature syntax " +
 481                                        "(please recompile from source)");
 482                 /*
 483                 System.err.println(" decoded " +
 484                                    new String(signature, oldsigp, sigp-oldsigp) +
 485                                    " => " + t + " outer " + t.outer());
 486                 */
 487                 return t;
 488             }
 489         case 'S':
 490             sigp++;
 491             return syms.shortType;
 492         case 'V':
 493             sigp++;
 494             return syms.voidType;

 516             return new MethodType(argtypes,
 517                                   restype,
 518                                   thrown.reverse(),
 519                                   syms.methodClass);
 520         case '<':
 521             typevars = typevars.dup(currentOwner);
 522             Type poly = new ForAll(sigToTypeParams(), sigToType());
 523             typevars = typevars.leave();
 524             return poly;
 525         default:
 526             throw badClassFile("bad.signature",
 527                                Convert.utf2string(signature, sigp, 10));
 528         }
 529     }
 530 
 531     byte[] signatureBuffer = new byte[0];
 532     int sbp = 0;
 533     /** Convert class signature to type, where signature is implicit.
 534      */
 535     Type classSigToType() {
 536         if (signature[sigp] != 'L')

 537             throw badClassFile("bad.class.signature",
 538                                Convert.utf2string(signature, sigp, 10));
 539         sigp++;
 540         Type outer = Type.noType;


 541         int startSbp = sbp;
 542 
 543         while (true) {
 544             final byte c = signature[sigp++];
 545             switch (c) {
 546 
 547             case ';': {         // end
 548                 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
 549                                                          startSbp,
 550                                                          sbp - startSbp));
 551 


 552                 try {
 553                     return (outer == Type.noType) ?
 554                             t.erasure(types) :
 555                         new ClassType(outer, List.nil(), t);



 556                 } finally {
 557                     sbp = startSbp;
 558                 }
 559             }
 560 
 561             case '<':           // generic arguments
 562                 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
 563                                                          startSbp,
 564                                                          sbp - startSbp));
 565                 outer = new ClassType(outer, sigToTypes('>'), t) {


 566                         boolean completed = false;
 567                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 568                         public Type getEnclosingType() {
 569                             if (!completed) {
 570                                 completed = true;
 571                                 tsym.apiComplete();
 572                                 Type enclosingType = tsym.type.getEnclosingType();
 573                                 if (enclosingType != Type.noType) {
 574                                     List<Type> typeArgs =
 575                                         super.getEnclosingType().allparams();
 576                                     List<Type> typeParams =
 577                                         enclosingType.allparams();
 578                                     if (typeParams.length() != typeArgs.length()) {
 579                                         // no "rare" types
 580                                         super.setEnclosingType(types.erasure(enclosingType));
 581                                     } else {
 582                                         super.setEnclosingType(types.subst(enclosingType,
 583                                                                            typeParams,
 584                                                                            typeArgs));
 585                                     }

 608                         signatureBuffer[sbp++] = (byte)'$';
 609                         break;
 610                     } else {
 611                         sbp = startSbp;
 612                         return outer;
 613                     }
 614                 case '.':
 615                     signatureBuffer[sbp++] = (byte)'$';
 616                     break;
 617                 default:
 618                     throw new AssertionError(signature[sigp-1]);
 619                 }
 620                 continue;
 621 
 622             case '.':
 623                 //we have seen an enclosing non-generic class
 624                 if (outer != Type.noType) {
 625                     t = enterClass(names.fromUtf(signatureBuffer,
 626                                                  startSbp,
 627                                                  sbp - startSbp));
 628                     outer = new ClassType(outer, List.nil(), t);


 629                 }
 630                 signatureBuffer[sbp++] = (byte)'$';
 631                 continue;
 632             case '/':
 633                 signatureBuffer[sbp++] = (byte)'.';
 634                 continue;
 635             default:
 636                 signatureBuffer[sbp++] = c;
 637                 continue;
 638             }
 639         }
 640     }
 641 
 642     /** Convert (implicit) signature to list of types
 643      *  until `terminator' is encountered.
 644      */
 645     List<Type> sigToTypes(char terminator) {
 646         List<Type> head = List.of(null);
 647         List<Type> tail = head;
 648         while (signature[sigp] != terminator)

 773         protected final Name name;
 774         protected final ClassFile.Version version;
 775         protected final Set<AttributeKind> kinds;
 776     }
 777 
 778     protected Set<AttributeKind> CLASS_ATTRIBUTE =
 779             EnumSet.of(AttributeKind.CLASS);
 780     protected Set<AttributeKind> MEMBER_ATTRIBUTE =
 781             EnumSet.of(AttributeKind.MEMBER);
 782     protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
 783             EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
 784 
 785     protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
 786 
 787     private void initAttributeReaders() {
 788         AttributeReader[] readers = {
 789             // v45.3 attributes
 790 
 791             new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
 792                 protected void read(Symbol sym, int attrLen) {











 793                     if (saveParameterNames)
 794                         ((MethodSymbol)sym).code = readCode(sym);
 795                     else
 796                         bp = bp + attrLen;
 797                 }
 798             },
 799 
 800             new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
 801                 protected void read(Symbol sym, int attrLen) {
 802                     Object v = poolReader.getConstant(nextChar());
 803                     // Ignore ConstantValue attribute if field not final.
 804                     if ((sym.flags() & FINAL) == 0) {
 805                         return;
 806                     }
 807                     VarSymbol var = (VarSymbol) sym;
 808                     switch (var.type.getTag()) {
 809                        case BOOLEAN:
 810                        case BYTE:
 811                        case CHAR:
 812                        case SHORT:

 953                         ClassSymbol c = (ClassSymbol) sym;
 954                         readingClassAttr = true;
 955                         try {
 956                             ClassType ct1 = (ClassType)c.type;
 957                             Assert.check(c == currentOwner);
 958                             ct1.typarams_field = poolReader.getName(nextChar())
 959                                     .map(ClassReader.this::sigToTypeParams);
 960                             ct1.supertype_field = sigToType();
 961                             ListBuffer<Type> is = new ListBuffer<>();
 962                             while (sigp != siglimit) is.append(sigToType());
 963                             ct1.interfaces_field = is.toList();
 964                         } finally {
 965                             readingClassAttr = false;
 966                         }
 967                     } else {
 968                         List<Type> thrown = sym.type.getThrownTypes();
 969                         sym.type = poolReader.getType(nextChar());
 970                         //- System.err.println(" # " + sym.type);
 971                         if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
 972                             sym.type.asMethodType().thrown = thrown;







 973 
 974                     }
 975                 }
 976             },
 977 
 978             // v49 annotation attributes
 979 
 980             new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
 981                 protected void read(Symbol sym, int attrLen) {
 982                     attachAnnotationDefault(sym);
 983                 }
 984             },
 985 
 986             new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
 987                 protected void read(Symbol sym, int attrLen) {
 988                     attachAnnotations(sym);
 989                 }
 990             },
 991 
 992             new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {

2211      */
2212     MethodSymbol readMethod() {
2213         long flags = adjustMethodFlags(nextChar());
2214         Name name = poolReader.getName(nextChar());
2215         Type type = poolReader.getType(nextChar());
2216         if (currentOwner.isInterface() &&
2217                 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2218             if (majorVersion > Version.V52.major ||
2219                     (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2220                 if ((flags & (STATIC | PRIVATE)) == 0) {
2221                     currentOwner.flags_field |= DEFAULT;
2222                     flags |= DEFAULT | ABSTRACT;
2223                 }
2224             } else {
2225                 //protect against ill-formed classfiles
2226                 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2227                                    Integer.toString(majorVersion),
2228                                    Integer.toString(minorVersion));
2229             }
2230         }







2231         validateMethodType(name, type);
2232         if (name == names.init && currentOwner.hasOuterInstance()) {
2233             // Sometimes anonymous classes don't have an outer
2234             // instance, however, there is no reliable way to tell so
2235             // we never strip this$n
2236             // ditto for local classes. Local classes that have an enclosing method set
2237             // won't pass the "hasOuterInstance" check above, but those that don't have an
2238             // enclosing method (i.e. from initializers) will pass that check.
2239             boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2240             if (!currentOwner.name.isEmpty() && !local)
2241                 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2242                                       type.getReturnType(),
2243                                       type.getThrownTypes(),
2244                                       syms.methodClass);
2245         }
2246         MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2247         if (types.isSignaturePolymorphic(m)) {
2248             m.flags_field |= SIGNATURE_POLYMORPHIC;
2249         }
2250         if (saveParameterNames)

2723         return flags;
2724     }
2725 
2726     long adjustMethodFlags(long flags) {
2727         if ((flags & ACC_BRIDGE) != 0) {
2728             flags &= ~ACC_BRIDGE;
2729             flags |= BRIDGE;
2730         }
2731         if ((flags & ACC_VARARGS) != 0) {
2732             flags &= ~ACC_VARARGS;
2733             flags |= VARARGS;
2734         }
2735         return flags;
2736     }
2737 
2738     long adjustClassFlags(long flags) {
2739         if ((flags & ACC_MODULE) != 0) {
2740             flags &= ~ACC_MODULE;
2741             flags |= MODULE;
2742         }
2743         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
















2744     }
2745 
2746     /**
2747      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2748      * The attribute is only the last component of the original filename, so is unlikely
2749      * to be valid as is, so operations other than those to access the name throw
2750      * UnsupportedOperationException
2751      */
2752     private static class SourceFileObject implements JavaFileObject {
2753 
2754         /** The file's name.
2755          */
2756         private final Name name;
2757 
2758         public SourceFileObject(Name name) {
2759             this.name = name;
2760         }
2761 
2762         @Override @DefinedBy(Api.COMPILER)
2763         public URI toUri() {

  27 
  28 import java.io.*;
  29 import java.net.URI;
  30 import java.net.URISyntaxException;
  31 import java.nio.CharBuffer;
  32 import java.nio.file.ClosedFileSystemException;
  33 import java.util.Arrays;
  34 import java.util.EnumSet;
  35 import java.util.HashMap;
  36 import java.util.HashSet;
  37 import java.util.Map;
  38 import java.util.Set;
  39 import java.util.function.IntFunction;
  40 
  41 import javax.lang.model.element.Modifier;
  42 import javax.lang.model.element.NestingKind;
  43 import javax.tools.JavaFileManager;
  44 import javax.tools.JavaFileObject;
  45 
  46 import com.sun.tools.javac.code.Source.Feature;
  47 import com.sun.tools.javac.code.Type.ClassType.Flavor;
  48 import com.sun.tools.javac.comp.Annotate;
  49 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
  50 import com.sun.tools.javac.code.*;
  51 import com.sun.tools.javac.code.Directive.*;
  52 import com.sun.tools.javac.code.Lint.LintCategory;
  53 import com.sun.tools.javac.code.Scope.WriteableScope;
  54 import com.sun.tools.javac.code.Symbol.*;
  55 import com.sun.tools.javac.code.Symtab;
  56 import com.sun.tools.javac.code.Type.*;
  57 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
  58 import com.sun.tools.javac.file.BaseFileManager;
  59 import com.sun.tools.javac.file.PathFileObject;
  60 import com.sun.tools.javac.jvm.ClassFile.Version;
  61 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
  62 import com.sun.tools.javac.main.Option;
  63 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  64 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  65 import com.sun.tools.javac.util.*;
  66 import com.sun.tools.javac.util.DefinedBy.Api;
  67 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;

  89  *  If you write code that depends on this, you do so at your own risk.
  90  *  This code and its internal interfaces are subject to change or
  91  *  deletion without notice.</b>
  92  */
  93 public class ClassReader {
  94     /** The context key for the class reader. */
  95     protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
  96 
  97     public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
  98 
  99     private final Annotate annotate;
 100 
 101     /** Switch: verbose output.
 102      */
 103     boolean verbose;
 104 
 105     /** Switch: allow modules.
 106      */
 107     boolean allowModules;
 108 
 109     /** Switch: allow primitive classes.
 110      */
 111     boolean allowPrimitiveClasses;
 112 
 113     /** Switch: allow value classes.
 114      */
 115     boolean allowValueClasses;
 116 
 117     /** Switch: allow sealed
 118      */
 119     boolean allowSealedTypes;
 120 
 121     /** Switch: allow records
 122      */
 123     boolean allowRecords;
 124 
 125    /** Lint option: warn about classfile issues
 126      */
 127     boolean lintClassfile;
 128 
 129     /** Switch: preserve parameter names from the variable table.
 130      */
 131     public boolean saveParameterNames;
 132 
 133     /**
 134      * The currently selected profile.
 135      */
 136     public final Profile profile;

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

 468             return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
 469         }
 470         case 'B':
 471             sigp++;
 472             return syms.byteType;
 473         case 'C':
 474             sigp++;
 475             return syms.charType;
 476         case 'D':
 477             sigp++;
 478             return syms.doubleType;
 479         case 'F':
 480             sigp++;
 481             return syms.floatType;
 482         case 'I':
 483             sigp++;
 484             return syms.intType;
 485         case 'J':
 486             sigp++;
 487             return syms.longType;
 488         case 'Q':
 489         case 'L':
 490             {
 491                 // int oldsigp = sigp;
 492                 Type t = classSigToType();
 493                 if (sigp < siglimit && signature[sigp] == '.')
 494                     throw badClassFile("deprecated inner class signature syntax " +
 495                                        "(please recompile from source)");
 496                 /*
 497                 System.err.println(" decoded " +
 498                                    new String(signature, oldsigp, sigp-oldsigp) +
 499                                    " => " + t + " outer " + t.outer());
 500                 */
 501                 return t;
 502             }
 503         case 'S':
 504             sigp++;
 505             return syms.shortType;
 506         case 'V':
 507             sigp++;
 508             return syms.voidType;

 530             return new MethodType(argtypes,
 531                                   restype,
 532                                   thrown.reverse(),
 533                                   syms.methodClass);
 534         case '<':
 535             typevars = typevars.dup(currentOwner);
 536             Type poly = new ForAll(sigToTypeParams(), sigToType());
 537             typevars = typevars.leave();
 538             return poly;
 539         default:
 540             throw badClassFile("bad.signature",
 541                                Convert.utf2string(signature, sigp, 10));
 542         }
 543     }
 544 
 545     byte[] signatureBuffer = new byte[0];
 546     int sbp = 0;
 547     /** Convert class signature to type, where signature is implicit.
 548      */
 549     Type classSigToType() {
 550         byte prefix = signature[sigp];
 551         if (prefix != 'L' && prefix != 'Q')
 552             throw badClassFile("bad.class.signature",
 553                                Convert.utf2string(signature, sigp, 10));
 554         sigp++;
 555         Type outer = Type.noType;
 556         Name name;
 557         ClassType.Flavor flavor;
 558         int startSbp = sbp;
 559 
 560         while (true) {
 561             final byte c = signature[sigp++];
 562             switch (c) {
 563 
 564             case ';': {         // end
 565                 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
 566                                                          startSbp,
 567                                                          sbp - startSbp));
 568 
 569                 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
 570                 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
 571                 try {
 572                     if (outer == Type.noType) {
 573                         ClassType et = (ClassType) t.erasure(types);
 574                         // Todo: This spews out more objects than before, i.e no reuse with identical flavor
 575                         return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata(), flavor);
 576                     }
 577                     return new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
 578                 } finally {
 579                     sbp = startSbp;
 580                 }
 581             }
 582 
 583             case '<':           // generic arguments
 584                 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
 585                                                          startSbp,
 586                                                          sbp - startSbp));
 587                 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
 588                 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
 589                 outer = new ClassType(outer, sigToTypes('>'), t, TypeMetadata.EMPTY, flavor) {
 590                         boolean completed = false;
 591                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 592                         public Type getEnclosingType() {
 593                             if (!completed) {
 594                                 completed = true;
 595                                 tsym.apiComplete();
 596                                 Type enclosingType = tsym.type.getEnclosingType();
 597                                 if (enclosingType != Type.noType) {
 598                                     List<Type> typeArgs =
 599                                         super.getEnclosingType().allparams();
 600                                     List<Type> typeParams =
 601                                         enclosingType.allparams();
 602                                     if (typeParams.length() != typeArgs.length()) {
 603                                         // no "rare" types
 604                                         super.setEnclosingType(types.erasure(enclosingType));
 605                                     } else {
 606                                         super.setEnclosingType(types.subst(enclosingType,
 607                                                                            typeParams,
 608                                                                            typeArgs));
 609                                     }

 632                         signatureBuffer[sbp++] = (byte)'$';
 633                         break;
 634                     } else {
 635                         sbp = startSbp;
 636                         return outer;
 637                     }
 638                 case '.':
 639                     signatureBuffer[sbp++] = (byte)'$';
 640                     break;
 641                 default:
 642                     throw new AssertionError(signature[sigp-1]);
 643                 }
 644                 continue;
 645 
 646             case '.':
 647                 //we have seen an enclosing non-generic class
 648                 if (outer != Type.noType) {
 649                     t = enterClass(names.fromUtf(signatureBuffer,
 650                                                  startSbp,
 651                                                  sbp - startSbp));
 652                     // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
 653                     flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
 654                     outer = new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
 655                 }
 656                 signatureBuffer[sbp++] = (byte)'$';
 657                 continue;
 658             case '/':
 659                 signatureBuffer[sbp++] = (byte)'.';
 660                 continue;
 661             default:
 662                 signatureBuffer[sbp++] = c;
 663                 continue;
 664             }
 665         }
 666     }
 667 
 668     /** Convert (implicit) signature to list of types
 669      *  until `terminator' is encountered.
 670      */
 671     List<Type> sigToTypes(char terminator) {
 672         List<Type> head = List.of(null);
 673         List<Type> tail = head;
 674         while (signature[sigp] != terminator)

 799         protected final Name name;
 800         protected final ClassFile.Version version;
 801         protected final Set<AttributeKind> kinds;
 802     }
 803 
 804     protected Set<AttributeKind> CLASS_ATTRIBUTE =
 805             EnumSet.of(AttributeKind.CLASS);
 806     protected Set<AttributeKind> MEMBER_ATTRIBUTE =
 807             EnumSet.of(AttributeKind.MEMBER);
 808     protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
 809             EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
 810 
 811     protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
 812 
 813     private void initAttributeReaders() {
 814         AttributeReader[] readers = {
 815             // v45.3 attributes
 816 
 817             new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
 818                 protected void read(Symbol sym, int attrLen) {
 819                     if (allowPrimitiveClasses) {
 820                         if (sym.isConstructor()  && ((MethodSymbol) sym).type.getParameterTypes().size() == 0) {
 821                             int code_length = buf.getInt(bp + 4);
 822                             if ((code_length == 1 && buf.getByte( bp + 8) == (byte) ByteCodes.return_) ||
 823                                     (code_length == 5 && buf.getByte(bp + 8) == ByteCodes.aload_0 &&
 824                                         buf.getByte( bp + 9) == (byte) ByteCodes.invokespecial &&
 825                                                 buf.getByte( bp + 12) == (byte) ByteCodes.return_)) {
 826                                     sym.flags_field |= EMPTYNOARGCONSTR;
 827                             }
 828                         }
 829                     }
 830                     if (saveParameterNames)
 831                         ((MethodSymbol)sym).code = readCode(sym);
 832                     else
 833                         bp = bp + attrLen;
 834                 }
 835             },
 836 
 837             new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
 838                 protected void read(Symbol sym, int attrLen) {
 839                     Object v = poolReader.getConstant(nextChar());
 840                     // Ignore ConstantValue attribute if field not final.
 841                     if ((sym.flags() & FINAL) == 0) {
 842                         return;
 843                     }
 844                     VarSymbol var = (VarSymbol) sym;
 845                     switch (var.type.getTag()) {
 846                        case BOOLEAN:
 847                        case BYTE:
 848                        case CHAR:
 849                        case SHORT:

 990                         ClassSymbol c = (ClassSymbol) sym;
 991                         readingClassAttr = true;
 992                         try {
 993                             ClassType ct1 = (ClassType)c.type;
 994                             Assert.check(c == currentOwner);
 995                             ct1.typarams_field = poolReader.getName(nextChar())
 996                                     .map(ClassReader.this::sigToTypeParams);
 997                             ct1.supertype_field = sigToType();
 998                             ListBuffer<Type> is = new ListBuffer<>();
 999                             while (sigp != siglimit) is.append(sigToType());
1000                             ct1.interfaces_field = is.toList();
1001                         } finally {
1002                             readingClassAttr = false;
1003                         }
1004                     } else {
1005                         List<Type> thrown = sym.type.getThrownTypes();
1006                         sym.type = poolReader.getType(nextChar());
1007                         //- System.err.println(" # " + sym.type);
1008                         if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1009                             sym.type.asMethodType().thrown = thrown;
1010                         // Map value class factory methods back to constructors for the benefit of earlier pipeline stages
1011                         if (sym.kind == MTH  && sym.name == names.init && !sym.type.getReturnType().hasTag(TypeTag.VOID)) {
1012                             sym.type = new MethodType(sym.type.getParameterTypes(),
1013                                     syms.voidType,
1014                                     sym.type.getThrownTypes(),
1015                                     syms.methodClass);
1016                         }
1017 
1018                     }
1019                 }
1020             },
1021 
1022             // v49 annotation attributes
1023 
1024             new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1025                 protected void read(Symbol sym, int attrLen) {
1026                     attachAnnotationDefault(sym);
1027                 }
1028             },
1029 
1030             new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1031                 protected void read(Symbol sym, int attrLen) {
1032                     attachAnnotations(sym);
1033                 }
1034             },
1035 
1036             new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {

2255      */
2256     MethodSymbol readMethod() {
2257         long flags = adjustMethodFlags(nextChar());
2258         Name name = poolReader.getName(nextChar());
2259         Type type = poolReader.getType(nextChar());
2260         if (currentOwner.isInterface() &&
2261                 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2262             if (majorVersion > Version.V52.major ||
2263                     (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2264                 if ((flags & (STATIC | PRIVATE)) == 0) {
2265                     currentOwner.flags_field |= DEFAULT;
2266                     flags |= DEFAULT | ABSTRACT;
2267                 }
2268             } else {
2269                 //protect against ill-formed classfiles
2270                 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2271                                    Integer.toString(majorVersion),
2272                                    Integer.toString(minorVersion));
2273             }
2274         }
2275         if (name == names.init && ((flags & STATIC) != 0)) {
2276             flags &= ~STATIC;
2277             type = new MethodType(type.getParameterTypes(),
2278                     syms.voidType,
2279                     type.getThrownTypes(),
2280                     syms.methodClass);
2281         }
2282         validateMethodType(name, type);
2283         if (name == names.init && currentOwner.hasOuterInstance()) {
2284             // Sometimes anonymous classes don't have an outer
2285             // instance, however, there is no reliable way to tell so
2286             // we never strip this$n
2287             // ditto for local classes. Local classes that have an enclosing method set
2288             // won't pass the "hasOuterInstance" check above, but those that don't have an
2289             // enclosing method (i.e. from initializers) will pass that check.
2290             boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2291             if (!currentOwner.name.isEmpty() && !local)
2292                 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2293                                       type.getReturnType(),
2294                                       type.getThrownTypes(),
2295                                       syms.methodClass);
2296         }
2297         MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2298         if (types.isSignaturePolymorphic(m)) {
2299             m.flags_field |= SIGNATURE_POLYMORPHIC;
2300         }
2301         if (saveParameterNames)

2774         return flags;
2775     }
2776 
2777     long adjustMethodFlags(long flags) {
2778         if ((flags & ACC_BRIDGE) != 0) {
2779             flags &= ~ACC_BRIDGE;
2780             flags |= BRIDGE;
2781         }
2782         if ((flags & ACC_VARARGS) != 0) {
2783             flags &= ~ACC_VARARGS;
2784             flags |= VARARGS;
2785         }
2786         return flags;
2787     }
2788 
2789     long adjustClassFlags(long flags) {
2790         if ((flags & ACC_MODULE) != 0) {
2791             flags &= ~ACC_MODULE;
2792             flags |= MODULE;
2793         }
2794         if ((flags & ACC_PRIMITIVE) != 0) {
2795             flags &= ~ACC_PRIMITIVE;
2796             if (allowPrimitiveClasses) {
2797                 flags |= PRIMITIVE_CLASS;
2798             }
2799         }
2800         if ((flags & ACC_VALUE) != 0) {
2801             flags &= ~ACC_VALUE;
2802             if (allowValueClasses) {
2803                 flags |= VALUE_CLASS;
2804             }
2805         }
2806         if ((flags & ACC_IDENTITY) != 0) {
2807             flags &= ~ACC_IDENTITY;
2808             flags |= IDENTITY_TYPE;
2809         }
2810         return flags;
2811     }
2812 
2813     /**
2814      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2815      * The attribute is only the last component of the original filename, so is unlikely
2816      * to be valid as is, so operations other than those to access the name throw
2817      * UnsupportedOperationException
2818      */
2819     private static class SourceFileObject implements JavaFileObject {
2820 
2821         /** The file's name.
2822          */
2823         private final Name name;
2824 
2825         public SourceFileObject(Name name) {
2826             this.name = name;
2827         }
2828 
2829         @Override @DefinedBy(Api.COMPILER)
2830         public URI toUri() {
< prev index next >