< 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;
 495         case 'Z':
 496             sigp++;
 497             return syms.booleanType;

 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) {

1298         if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1299             throw badClassFile("bad.enclosing.method", self);
1300         int index = 1;
1301         while (index < simpleBinaryName.length() &&
1302                isAsciiDigit(simpleBinaryName.charAt(index)))
1303             index++;
1304         return names.fromString(simpleBinaryName.substring(index));
1305     }
1306 
1307     private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1308         if (nt == null)
1309             return null;
1310 
1311         MethodType type = nt.type.asMethodType();
1312 
1313         for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1314             if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1315                 return (MethodSymbol)sym;
1316         }
1317 
1318         if (nt.name != names.init)
1319             // not a constructor
1320             return null;
1321         if ((flags & INTERFACE) != 0)
1322             // no enclosing instance
1323             return null;
1324         if (nt.type.getParameterTypes().isEmpty())
1325             // no parameters
1326             return null;
1327 
1328         // A constructor of an inner class.
1329         // Remove the first argument (the enclosing instance)
1330         nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1331                                  nt.type.getReturnType(),
1332                                  nt.type.getThrownTypes(),
1333                                  syms.methodClass));
1334         // Try searching again
1335         return findMethod(nt, scope, flags);
1336     }
1337 
1338     /** Similar to Types.isSameType but avoids completion */

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







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

2262             currentOwner = prevOwner;
2263         }
2264         validateMethodType(name, m.type);
2265         setParameters(m, type);
2266 
2267         if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1)
2268             throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m);
2269         if ((flags & VARARGS) != 0) {
2270             final Type last = type.getParameterTypes().last();
2271             if (last == null || !last.hasTag(ARRAY)) {
2272                 m.flags_field &= ~VARARGS;
2273                 throw badClassFile("malformed.vararg.method", m);
2274             }
2275         }
2276 
2277         return m;
2278     }
2279 
2280     void validateMethodType(Name name, Type t) {
2281         if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
2282             (name == names.init && !t.getReturnType().hasTag(TypeTag.VOID))) {
2283             throw badClassFile("method.descriptor.invalid", name);
2284         }
2285     }
2286 
2287     private List<Type> adjustMethodParams(long flags, List<Type> args) {
2288         if (args.isEmpty()) {
2289             return args;
2290         }
2291         boolean isVarargs = (flags & VARARGS) != 0;
2292         if (isVarargs) {
2293             Type varargsElem = args.last();
2294             ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2295             for (Type t : args) {
2296                 adjustedArgs.append(t != varargsElem ?
2297                     t :
2298                     ((ArrayType)t).makeVarargs());
2299             }
2300             args = adjustedArgs.toList();
2301         }
2302         return args.tail;

2332      *
2333      * <p>The type of the symbol may have changed while reading the
2334      * method attributes (see the Signature attribute). This may be
2335      * because of generic information or because anonymous synthetic
2336      * parameters were added.   The original type (as read from the
2337      * method descriptor) is used to help guess the existence of
2338      * anonymous synthetic parameters.
2339      */
2340     void setParameters(MethodSymbol sym, Type jvmType) {
2341         // If we get parameter names from MethodParameters, then we
2342         // don't need to skip.
2343         int firstParam = 0;
2344         if (!sawMethodParameters) {
2345             firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2346             // the code in readMethod may have skipped the first
2347             // parameter when setting up the MethodType. If so, we
2348             // make a corresponding allowance here for the position of
2349             // the first parameter.  Note that this assumes the
2350             // skipped parameter has a width of 1 -- i.e. it is not
2351             // a double width type (long or double.)
2352             if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2353                 // Sometimes anonymous classes don't have an outer
2354                 // instance, however, there is no reliable way to tell so
2355                 // we never strip this$n
2356                 if (!currentOwner.name.isEmpty())
2357                     firstParam += 1;
2358             }
2359 
2360             if (sym.type != jvmType) {
2361                 // reading the method attributes has caused the
2362                 // symbol's type to be changed. (i.e. the Signature
2363                 // attribute.)  This may happen if there are hidden
2364                 // (synthetic) parameters in the descriptor, but not
2365                 // in the Signature.  The position of these hidden
2366                 // parameters is unspecified; for now, assume they are
2367                 // at the beginning, and so skip over them. The
2368                 // primary case for this is two hidden parameters
2369                 // passed into Enum constructors.
2370                 int skip = Code.width(jvmType.getParameterTypes())
2371                         - Code.width(sym.type.getParameterTypes());
2372                 firstParam += skip;

2480         return syms.enterClass(currentModule, name, owner);
2481     }
2482 
2483     /** Read contents of a given class symbol `c'. Both external and internal
2484      *  versions of an inner class are read.
2485      */
2486     void readClass(ClassSymbol c) {
2487         ClassType ct = (ClassType)c.type;
2488 
2489         // allocate scope for members
2490         c.members_field = WriteableScope.create(c);
2491 
2492         // prepare type variable table
2493         typevars = typevars.dup(currentOwner);
2494         if (ct.getEnclosingType().hasTag(CLASS))
2495             enterTypevars(c.owner, ct.getEnclosingType());
2496 
2497         // read flags, or skip if this is an inner class
2498         long f = nextChar();
2499         long flags = adjustClassFlags(f);








2500         if ((flags & MODULE) == 0) {
2501             if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
2502             // read own class name and check that it matches
2503             currentModule = c.packge().modle;
2504             ClassSymbol self = poolReader.getClass(nextChar());
2505             if (c != self) {
2506                 throw badClassFile("class.file.wrong.class",
2507                                    self.flatname);
2508             }
2509         } else {
2510             if (majorVersion < Version.V53.major) {
2511                 throw badClassFile("anachronistic.module.info",
2512                         Integer.toString(majorVersion),
2513                         Integer.toString(minorVersion));
2514             }
2515             c.flags_field = flags;
2516             if (c.owner.kind != MDL) {
2517                 throw badClassFile("module.info.definition.expected");
2518             }
2519             currentModule = (ModuleSymbol) c.owner;

2726  * Adjusting flags
2727  ***********************************************************************/
2728 
2729     long adjustFieldFlags(long flags) {
2730         return flags;
2731     }
2732 
2733     long adjustMethodFlags(long flags) {
2734         if ((flags & ACC_BRIDGE) != 0) {
2735             flags &= ~ACC_BRIDGE;
2736             flags |= BRIDGE;
2737         }
2738         if ((flags & ACC_VARARGS) != 0) {
2739             flags &= ~ACC_VARARGS;
2740             flags |= VARARGS;
2741         }
2742         return flags;
2743     }
2744 
2745     long adjustClassFlags(long flags) {



2746         if ((flags & ACC_MODULE) != 0) {
2747             flags &= ~ACC_MODULE;
2748             flags |= MODULE;
2749         }
2750         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
















2751     }
2752 
2753     /**
2754      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2755      * The attribute is only the last component of the original filename, so is unlikely
2756      * to be valid as is, so operations other than those to access the name throw
2757      * UnsupportedOperationException
2758      */
2759     private static class SourceFileObject implements JavaFileObject {
2760 
2761         /** The file's name.
2762          */
2763         private final Name name;
2764 
2765         public SourceFileObject(Name name) {
2766             this.name = name;
2767         }
2768 
2769         @Override @DefinedBy(Api.COMPILER)
2770         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 = Feature.PRIMITIVE_CLASSES.allowedInSource(source) && options.isSet("enablePrimitiveClasses");
 290         allowValueClasses = Feature.VALUE_CLASSES.allowedInSource(source);
 291         allowRecords = Feature.RECORDS.allowedInSource(source);
 292         allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 293 
 294         saveParameterNames = options.isSet(PARAMETERS);
 295 
 296         profile = Profile.instance(context);
 297 
 298         typevars = WriteableScope.create(syms.noSymbol);
 299 
 300         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
 301 
 302         initAttributeReaders();
 303     }
 304 
 305     /** Add member to class unless it is synthetic.
 306      */
 307     private void enterMember(ClassSymbol c, Symbol sym) {
 308         // Synthetic members are not entered -- reason lost to history (optimization?).
 309         // Lambda methods must be entered because they may have inner classes (which reference them)
 310         if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))

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

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

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

 801         protected final Name name;
 802         protected final ClassFile.Version version;
 803         protected final Set<AttributeKind> kinds;
 804     }
 805 
 806     protected Set<AttributeKind> CLASS_ATTRIBUTE =
 807             EnumSet.of(AttributeKind.CLASS);
 808     protected Set<AttributeKind> MEMBER_ATTRIBUTE =
 809             EnumSet.of(AttributeKind.MEMBER);
 810     protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
 811             EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
 812 
 813     protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
 814 
 815     private void initAttributeReaders() {
 816         AttributeReader[] readers = {
 817             // v45.3 attributes
 818 
 819             new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
 820                 protected void read(Symbol sym, int attrLen) {
 821                     if (sym.isInitOrVNew() && sym.type.getParameterTypes().size() == 0) {
 822                         int code_length = buf.getInt(bp + 4);
 823                         if ((code_length == 1 && buf.getByte(bp + 8) == (byte) ByteCodes.return_) ||
 824                                 (code_length == 5 && buf.getByte(bp + 8) == ByteCodes.aload_0 &&
 825                                     buf.getByte(bp + 9) == (byte) ByteCodes.invokespecial &&
 826                                             buf.getByte(bp + 12) == (byte) ByteCodes.return_)) {
 827                                 sym.flags_field |= EMPTYNOARGCONSTR;
 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.vnew && !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) {

1342         if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1343             throw badClassFile("bad.enclosing.method", self);
1344         int index = 1;
1345         while (index < simpleBinaryName.length() &&
1346                isAsciiDigit(simpleBinaryName.charAt(index)))
1347             index++;
1348         return names.fromString(simpleBinaryName.substring(index));
1349     }
1350 
1351     private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1352         if (nt == null)
1353             return null;
1354 
1355         MethodType type = nt.type.asMethodType();
1356 
1357         for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1358             if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1359                 return (MethodSymbol)sym;
1360         }
1361 
1362         if (!names.isInitOrVNew(nt.name))
1363             // not a constructor
1364             return null;
1365         if ((flags & INTERFACE) != 0)
1366             // no enclosing instance
1367             return null;
1368         if (nt.type.getParameterTypes().isEmpty())
1369             // no parameters
1370             return null;
1371 
1372         // A constructor of an inner class.
1373         // Remove the first argument (the enclosing instance)
1374         nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1375                                  nt.type.getReturnType(),
1376                                  nt.type.getThrownTypes(),
1377                                  syms.methodClass));
1378         // Try searching again
1379         return findMethod(nt, scope, flags);
1380     }
1381 
1382     /** Similar to Types.isSameType but avoids completion */

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

2313             currentOwner = prevOwner;
2314         }
2315         validateMethodType(name, m.type);
2316         setParameters(m, type);
2317 
2318         if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1)
2319             throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m);
2320         if ((flags & VARARGS) != 0) {
2321             final Type last = type.getParameterTypes().last();
2322             if (last == null || !last.hasTag(ARRAY)) {
2323                 m.flags_field &= ~VARARGS;
2324                 throw badClassFile("malformed.vararg.method", m);
2325             }
2326         }
2327 
2328         return m;
2329     }
2330 
2331     void validateMethodType(Name name, Type t) {
2332         if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
2333             ((name == names.init || name == names.vnew) && !t.getReturnType().hasTag(TypeTag.VOID))) {
2334             throw badClassFile("method.descriptor.invalid", name);
2335         }
2336     }
2337 
2338     private List<Type> adjustMethodParams(long flags, List<Type> args) {
2339         if (args.isEmpty()) {
2340             return args;
2341         }
2342         boolean isVarargs = (flags & VARARGS) != 0;
2343         if (isVarargs) {
2344             Type varargsElem = args.last();
2345             ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2346             for (Type t : args) {
2347                 adjustedArgs.append(t != varargsElem ?
2348                     t :
2349                     ((ArrayType)t).makeVarargs());
2350             }
2351             args = adjustedArgs.toList();
2352         }
2353         return args.tail;

2383      *
2384      * <p>The type of the symbol may have changed while reading the
2385      * method attributes (see the Signature attribute). This may be
2386      * because of generic information or because anonymous synthetic
2387      * parameters were added.   The original type (as read from the
2388      * method descriptor) is used to help guess the existence of
2389      * anonymous synthetic parameters.
2390      */
2391     void setParameters(MethodSymbol sym, Type jvmType) {
2392         // If we get parameter names from MethodParameters, then we
2393         // don't need to skip.
2394         int firstParam = 0;
2395         if (!sawMethodParameters) {
2396             firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2397             // the code in readMethod may have skipped the first
2398             // parameter when setting up the MethodType. If so, we
2399             // make a corresponding allowance here for the position of
2400             // the first parameter.  Note that this assumes the
2401             // skipped parameter has a width of 1 -- i.e. it is not
2402             // a double width type (long or double.)
2403             if (names.isInitOrVNew(sym.name) && currentOwner.hasOuterInstance()) {
2404                 // Sometimes anonymous classes don't have an outer
2405                 // instance, however, there is no reliable way to tell so
2406                 // we never strip this$n
2407                 if (!currentOwner.name.isEmpty())
2408                     firstParam += 1;
2409             }
2410 
2411             if (sym.type != jvmType) {
2412                 // reading the method attributes has caused the
2413                 // symbol's type to be changed. (i.e. the Signature
2414                 // attribute.)  This may happen if there are hidden
2415                 // (synthetic) parameters in the descriptor, but not
2416                 // in the Signature.  The position of these hidden
2417                 // parameters is unspecified; for now, assume they are
2418                 // at the beginning, and so skip over them. The
2419                 // primary case for this is two hidden parameters
2420                 // passed into Enum constructors.
2421                 int skip = Code.width(jvmType.getParameterTypes())
2422                         - Code.width(sym.type.getParameterTypes());
2423                 firstParam += skip;

2531         return syms.enterClass(currentModule, name, owner);
2532     }
2533 
2534     /** Read contents of a given class symbol `c'. Both external and internal
2535      *  versions of an inner class are read.
2536      */
2537     void readClass(ClassSymbol c) {
2538         ClassType ct = (ClassType)c.type;
2539 
2540         // allocate scope for members
2541         c.members_field = WriteableScope.create(c);
2542 
2543         // prepare type variable table
2544         typevars = typevars.dup(currentOwner);
2545         if (ct.getEnclosingType().hasTag(CLASS))
2546             enterTypevars(c.owner, ct.getEnclosingType());
2547 
2548         // read flags, or skip if this is an inner class
2549         long f = nextChar();
2550         long flags = adjustClassFlags(f);
2551         if (c == syms.objectType.tsym) {
2552             flags &= ~IDENTITY_TYPE; // jlO lacks identity even while being a concrete class.
2553         }
2554         if ((flags & PRIMITIVE_CLASS) != 0) {
2555             if (!allowPrimitiveClasses || (flags & (FINAL | PRIMITIVE_CLASS | IDENTITY_TYPE)) != (FINAL | PRIMITIVE_CLASS)) {
2556                 throw badClassFile("bad.access.flags", Flags.toString(flags));
2557             }
2558         }
2559         if ((flags & MODULE) == 0) {
2560             if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
2561             // read own class name and check that it matches
2562             currentModule = c.packge().modle;
2563             ClassSymbol self = poolReader.getClass(nextChar());
2564             if (c != self) {
2565                 throw badClassFile("class.file.wrong.class",
2566                                    self.flatname);
2567             }
2568         } else {
2569             if (majorVersion < Version.V53.major) {
2570                 throw badClassFile("anachronistic.module.info",
2571                         Integer.toString(majorVersion),
2572                         Integer.toString(minorVersion));
2573             }
2574             c.flags_field = flags;
2575             if (c.owner.kind != MDL) {
2576                 throw badClassFile("module.info.definition.expected");
2577             }
2578             currentModule = (ModuleSymbol) c.owner;

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