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

1223                     }
1224                     ((ClassSymbol) sym).setRecordComponents(components.toList());
1225                 }
1226             },
1227             new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) {
1228                 @Override
1229                 protected boolean accepts(AttributeKind kind) {
1230                     return super.accepts(kind) && allowSealedTypes;
1231                 }
1232                 protected void read(Symbol sym, int attrLen) {
1233                     if (sym.kind == TYP) {
1234                         ListBuffer<Symbol> subtypes = new ListBuffer<>();
1235                         int numberOfPermittedSubtypes = nextChar();
1236                         for (int i = 0; i < numberOfPermittedSubtypes; i++) {
1237                             subtypes.add(poolReader.getClass(nextChar()));
1238                         }
1239                         ((ClassSymbol)sym).permitted = subtypes.toList();
1240                     }
1241                 }
1242             },













1243         };
1244 
1245         for (AttributeReader r: readers)
1246             attributeReaders.put(r.name, r);
1247     }
1248 
1249     protected void readEnclosingMethodAttr(Symbol sym) {
1250         // sym is a nested class with an "Enclosing Method" attribute
1251         // remove sym from it's current owners scope and place it in
1252         // the scope specified by the attribute
1253         sym.owner.members().remove(sym);
1254         ClassSymbol self = (ClassSymbol)sym;
1255         ClassSymbol c = poolReader.getClass(nextChar());
1256         NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null);
1257 
1258         if (c.members_field == null || c.kind != TYP)
1259             throw badClassFile("bad.enclosing.class", self, c);
1260 
1261         MethodSymbol m = findMethod(nt, c.members_field, self.flags());
1262         if (nt != null && m == null)

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)

  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 sealed
 114      */
 115     boolean allowSealedTypes;
 116 
 117     /** Switch: allow records
 118      */
 119     boolean allowRecords;
 120 
 121    /** Lint option: warn about classfile issues
 122      */
 123     boolean lintClassfile;
 124 
 125     /** Switch: preserve parameter names from the variable table.
 126      */
 127     public boolean saveParameterNames;
 128 
 129     /**
 130      * The currently selected profile.
 131      */
 132     public final Profile profile;

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

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

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

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

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

 983                         ClassSymbol c = (ClassSymbol) sym;
 984                         readingClassAttr = true;
 985                         try {
 986                             ClassType ct1 = (ClassType)c.type;
 987                             Assert.check(c == currentOwner);
 988                             ct1.typarams_field = poolReader.getName(nextChar())
 989                                     .map(ClassReader.this::sigToTypeParams);
 990                             ct1.supertype_field = sigToType();
 991                             ListBuffer<Type> is = new ListBuffer<>();
 992                             while (sigp != siglimit) is.append(sigToType());
 993                             ct1.interfaces_field = is.toList();
 994                         } finally {
 995                             readingClassAttr = false;
 996                         }
 997                     } else {
 998                         List<Type> thrown = sym.type.getThrownTypes();
 999                         sym.type = poolReader.getType(nextChar());
1000                         //- System.err.println(" # " + sym.type);
1001                         if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1002                             sym.type.asMethodType().thrown = thrown;
1003                         if (sym.kind == MTH  && sym.name == names.init && sym.owner.isPrimitiveClass()) {
1004                             sym.type = new MethodType(sym.type.getParameterTypes(),
1005                                     syms.voidType,
1006                                     sym.type.getThrownTypes(),
1007                                     syms.methodClass);
1008                         }
1009 
1010                     }
1011                 }
1012             },
1013 
1014             // v49 annotation attributes
1015 
1016             new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1017                 protected void read(Symbol sym, int attrLen) {
1018                     attachAnnotationDefault(sym);
1019                 }
1020             },
1021 
1022             new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1023                 protected void read(Symbol sym, int attrLen) {
1024                     attachAnnotations(sym);
1025                 }
1026             },
1027 
1028             new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {

1259                     }
1260                     ((ClassSymbol) sym).setRecordComponents(components.toList());
1261                 }
1262             },
1263             new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) {
1264                 @Override
1265                 protected boolean accepts(AttributeKind kind) {
1266                     return super.accepts(kind) && allowSealedTypes;
1267                 }
1268                 protected void read(Symbol sym, int attrLen) {
1269                     if (sym.kind == TYP) {
1270                         ListBuffer<Symbol> subtypes = new ListBuffer<>();
1271                         int numberOfPermittedSubtypes = nextChar();
1272                         for (int i = 0; i < numberOfPermittedSubtypes; i++) {
1273                             subtypes.add(poolReader.getClass(nextChar()));
1274                         }
1275                         ((ClassSymbol)sym).permitted = subtypes.toList();
1276                     }
1277                 }
1278             },
1279             new AttributeReader(names.JavaFlags, V61, CLASS_ATTRIBUTE) {
1280                 @Override
1281                 protected boolean accepts(AttributeKind kind) {
1282                     return super.accepts(kind) && allowPrimitiveClasses;
1283                 }
1284                 protected void read(Symbol sym, int attrLen) {
1285                     if (sym.kind == TYP) {
1286                         int extendedFlags = nextChar();
1287                         if ((extendedFlags & ACC_REF_DEFAULT) != 0)
1288                         ((ClassSymbol)sym).flags_field |= REFERENCE_FAVORING;
1289                     }
1290                 }
1291             }
1292         };
1293 
1294         for (AttributeReader r: readers)
1295             attributeReaders.put(r.name, r);
1296     }
1297 
1298     protected void readEnclosingMethodAttr(Symbol sym) {
1299         // sym is a nested class with an "Enclosing Method" attribute
1300         // remove sym from it's current owners scope and place it in
1301         // the scope specified by the attribute
1302         sym.owner.members().remove(sym);
1303         ClassSymbol self = (ClassSymbol)sym;
1304         ClassSymbol c = poolReader.getClass(nextChar());
1305         NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null);
1306 
1307         if (c.members_field == null || c.kind != TYP)
1308             throw badClassFile("bad.enclosing.class", self, c);
1309 
1310         MethodSymbol m = findMethod(nt, c.members_field, self.flags());
1311         if (nt != null && m == null)

2260      */
2261     MethodSymbol readMethod() {
2262         long flags = adjustMethodFlags(nextChar());
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 (name == names.init && ((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 (name == names.init && 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)

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