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

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)

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








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

2719  * Adjusting flags
2720  ***********************************************************************/
2721 
2722     long adjustFieldFlags(long flags) {
2723         return flags;
2724     }
2725 
2726     long adjustMethodFlags(long flags) {
2727         if ((flags & ACC_BRIDGE) != 0) {
2728             flags &= ~ACC_BRIDGE;
2729             flags |= BRIDGE;
2730         }
2731         if ((flags & ACC_VARARGS) != 0) {
2732             flags &= ~ACC_VARARGS;
2733             flags |= VARARGS;
2734         }
2735         return flags;
2736     }
2737 
2738     long adjustClassFlags(long flags) {



2739         if ((flags & ACC_MODULE) != 0) {
2740             flags &= ~ACC_MODULE;
2741             flags |= MODULE;
2742         }
2743         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
















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

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

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

 269     protected ClassReader(Context context) {
 270         context.put(classReaderKey, this);
 271         annotate = Annotate.instance(context);
 272         names = Names.instance(context);
 273         syms = Symtab.instance(context);
 274         types = Types.instance(context);
 275         fileManager = context.get(JavaFileManager.class);
 276         if (fileManager == null)
 277             throw new AssertionError("FileManager initialization error");
 278         diagFactory = JCDiagnostic.Factory.instance(context);
 279         dcfh = DeferredCompletionFailureHandler.instance(context);
 280 
 281         log = Log.instance(context);
 282 
 283         Options options = Options.instance(context);
 284         verbose         = options.isSet(Option.VERBOSE);
 285 
 286         Source source = Source.instance(context);
 287         preview = Preview.instance(context);
 288         allowModules     = Feature.MODULES.allowedInSource(source);
 289         allowPrimitiveClasses = 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.isConstructor()  && 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.init && !sym.type.getReturnType().hasTag(TypeTag.VOID)) {
1012                             sym.type = new MethodType(sym.type.getParameterTypes(),
1013                                     syms.voidType,
1014                                     sym.type.getThrownTypes(),
1015                                     syms.methodClass);
1016                         }
1017 
1018                     }
1019                 }
1020             },
1021 
1022             // v49 annotation attributes
1023 
1024             new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1025                 protected void read(Symbol sym, int attrLen) {
1026                     attachAnnotationDefault(sym);
1027                 }
1028             },
1029 
1030             new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1031                 protected void read(Symbol sym, int attrLen) {
1032                     attachAnnotations(sym);
1033                 }
1034             },
1035 
1036             new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {

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

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

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