27
28 import java.io.*;
29 import java.net.URI;
30 import java.net.URISyntaxException;
31 import java.nio.CharBuffer;
32 import java.nio.file.ClosedFileSystemException;
33 import java.util.Arrays;
34 import java.util.EnumSet;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.function.IntFunction;
40
41 import javax.lang.model.element.Modifier;
42 import javax.lang.model.element.NestingKind;
43 import javax.tools.JavaFileManager;
44 import javax.tools.JavaFileObject;
45
46 import com.sun.tools.javac.code.Source.Feature;
47 import com.sun.tools.javac.comp.Annotate;
48 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
49 import com.sun.tools.javac.code.*;
50 import com.sun.tools.javac.code.Directive.*;
51 import com.sun.tools.javac.code.Lint.LintCategory;
52 import com.sun.tools.javac.code.Scope.WriteableScope;
53 import com.sun.tools.javac.code.Symbol.*;
54 import com.sun.tools.javac.code.Symtab;
55 import com.sun.tools.javac.code.Type.*;
56 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
57 import com.sun.tools.javac.file.BaseFileManager;
58 import com.sun.tools.javac.file.PathFileObject;
59 import com.sun.tools.javac.jvm.ClassFile.Version;
60 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
61 import com.sun.tools.javac.main.Option;
62 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
63 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
64 import com.sun.tools.javac.util.*;
65 import com.sun.tools.javac.util.DefinedBy.Api;
66 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
88 * If you write code that depends on this, you do so at your own risk.
89 * This code and its internal interfaces are subject to change or
90 * deletion without notice.</b>
91 */
92 public class ClassReader {
93 /** The context key for the class reader. */
94 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
95
96 public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
97
98 private final Annotate annotate;
99
100 /** Switch: verbose output.
101 */
102 boolean verbose;
103
104 /** Switch: allow modules.
105 */
106 boolean allowModules;
107
108 /** Switch: allow sealed
109 */
110 boolean allowSealedTypes;
111
112 /** Switch: allow records
113 */
114 boolean allowRecords;
115
116 /** Lint option: warn about classfile issues
117 */
118 boolean lintClassfile;
119
120 /** Switch: preserve parameter names from the variable table.
121 */
122 public boolean saveParameterNames;
123
124 /**
125 * The currently selected profile.
126 */
127 public final Profile profile;
260 protected ClassReader(Context context) {
261 context.put(classReaderKey, this);
262 annotate = Annotate.instance(context);
263 names = Names.instance(context);
264 syms = Symtab.instance(context);
265 types = Types.instance(context);
266 fileManager = context.get(JavaFileManager.class);
267 if (fileManager == null)
268 throw new AssertionError("FileManager initialization error");
269 diagFactory = JCDiagnostic.Factory.instance(context);
270 dcfh = DeferredCompletionFailureHandler.instance(context);
271
272 log = Log.instance(context);
273
274 Options options = Options.instance(context);
275 verbose = options.isSet(Option.VERBOSE);
276
277 Source source = Source.instance(context);
278 preview = Preview.instance(context);
279 allowModules = Feature.MODULES.allowedInSource(source);
280 allowRecords = Feature.RECORDS.allowedInSource(source);
281 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
282
283 saveParameterNames = options.isSet(PARAMETERS);
284
285 profile = Profile.instance(context);
286
287 typevars = WriteableScope.create(syms.noSymbol);
288
289 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
290
291 initAttributeReaders();
292 }
293
294 /** Add member to class unless it is synthetic.
295 */
296 private void enterMember(ClassSymbol c, Symbol sym) {
297 // Synthetic members are not entered -- reason lost to history (optimization?).
298 // Lambda methods must be entered because they may have inner classes (which reference them)
299 if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
455 return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
456 }
457 case 'B':
458 sigp++;
459 return syms.byteType;
460 case 'C':
461 sigp++;
462 return syms.charType;
463 case 'D':
464 sigp++;
465 return syms.doubleType;
466 case 'F':
467 sigp++;
468 return syms.floatType;
469 case 'I':
470 sigp++;
471 return syms.intType;
472 case 'J':
473 sigp++;
474 return syms.longType;
475 case 'L':
476 {
477 // int oldsigp = sigp;
478 Type t = classSigToType();
479 if (sigp < siglimit && signature[sigp] == '.')
480 throw badClassFile("deprecated inner class signature syntax " +
481 "(please recompile from source)");
482 /*
483 System.err.println(" decoded " +
484 new String(signature, oldsigp, sigp-oldsigp) +
485 " => " + t + " outer " + t.outer());
486 */
487 return t;
488 }
489 case 'S':
490 sigp++;
491 return syms.shortType;
492 case 'V':
493 sigp++;
494 return syms.voidType;
495 case 'Z':
496 sigp++;
497 return syms.booleanType;
516 return new MethodType(argtypes,
517 restype,
518 thrown.reverse(),
519 syms.methodClass);
520 case '<':
521 typevars = typevars.dup(currentOwner);
522 Type poly = new ForAll(sigToTypeParams(), sigToType());
523 typevars = typevars.leave();
524 return poly;
525 default:
526 throw badClassFile("bad.signature",
527 Convert.utf2string(signature, sigp, 10));
528 }
529 }
530
531 byte[] signatureBuffer = new byte[0];
532 int sbp = 0;
533 /** Convert class signature to type, where signature is implicit.
534 */
535 Type classSigToType() {
536 if (signature[sigp] != 'L')
537 throw badClassFile("bad.class.signature",
538 Convert.utf2string(signature, sigp, 10));
539 sigp++;
540 Type outer = Type.noType;
541 int startSbp = sbp;
542
543 while (true) {
544 final byte c = signature[sigp++];
545 switch (c) {
546
547 case ';': { // end
548 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
549 startSbp,
550 sbp - startSbp));
551
552 try {
553 return (outer == Type.noType) ?
554 t.erasure(types) :
555 new ClassType(outer, List.nil(), t);
556 } finally {
557 sbp = startSbp;
558 }
559 }
560
561 case '<': // generic arguments
562 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
563 startSbp,
564 sbp - startSbp));
565 outer = new ClassType(outer, sigToTypes('>'), t) {
566 boolean completed = false;
567 @Override @DefinedBy(Api.LANGUAGE_MODEL)
568 public Type getEnclosingType() {
569 if (!completed) {
570 completed = true;
571 tsym.apiComplete();
572 Type enclosingType = tsym.type.getEnclosingType();
573 if (enclosingType != Type.noType) {
574 List<Type> typeArgs =
575 super.getEnclosingType().allparams();
576 List<Type> typeParams =
577 enclosingType.allparams();
578 if (typeParams.length() != typeArgs.length()) {
579 // no "rare" types
580 super.setEnclosingType(types.erasure(enclosingType));
581 } else {
582 super.setEnclosingType(types.subst(enclosingType,
583 typeParams,
584 typeArgs));
585 }
608 signatureBuffer[sbp++] = (byte)'$';
609 break;
610 } else {
611 sbp = startSbp;
612 return outer;
613 }
614 case '.':
615 signatureBuffer[sbp++] = (byte)'$';
616 break;
617 default:
618 throw new AssertionError(signature[sigp-1]);
619 }
620 continue;
621
622 case '.':
623 //we have seen an enclosing non-generic class
624 if (outer != Type.noType) {
625 t = enterClass(names.fromUtf(signatureBuffer,
626 startSbp,
627 sbp - startSbp));
628 outer = new ClassType(outer, List.nil(), t);
629 }
630 signatureBuffer[sbp++] = (byte)'$';
631 continue;
632 case '/':
633 signatureBuffer[sbp++] = (byte)'.';
634 continue;
635 default:
636 signatureBuffer[sbp++] = c;
637 continue;
638 }
639 }
640 }
641
642 /** Convert (implicit) signature to list of types
643 * until `terminator' is encountered.
644 */
645 List<Type> sigToTypes(char terminator) {
646 List<Type> head = List.of(null);
647 List<Type> tail = head;
648 while (signature[sigp] != terminator)
773 protected final Name name;
774 protected final ClassFile.Version version;
775 protected final Set<AttributeKind> kinds;
776 }
777
778 protected Set<AttributeKind> CLASS_ATTRIBUTE =
779 EnumSet.of(AttributeKind.CLASS);
780 protected Set<AttributeKind> MEMBER_ATTRIBUTE =
781 EnumSet.of(AttributeKind.MEMBER);
782 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
783 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
784
785 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
786
787 private void initAttributeReaders() {
788 AttributeReader[] readers = {
789 // v45.3 attributes
790
791 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
792 protected void read(Symbol sym, int attrLen) {
793 if (saveParameterNames)
794 ((MethodSymbol)sym).code = readCode(sym);
795 else
796 bp = bp + attrLen;
797 }
798 },
799
800 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
801 protected void read(Symbol sym, int attrLen) {
802 Object v = poolReader.getConstant(nextChar());
803 // Ignore ConstantValue attribute if field not final.
804 if ((sym.flags() & FINAL) == 0) {
805 return;
806 }
807 VarSymbol var = (VarSymbol) sym;
808 switch (var.type.getTag()) {
809 case BOOLEAN:
810 case BYTE:
811 case CHAR:
812 case SHORT:
953 ClassSymbol c = (ClassSymbol) sym;
954 readingClassAttr = true;
955 try {
956 ClassType ct1 = (ClassType)c.type;
957 Assert.check(c == currentOwner);
958 ct1.typarams_field = poolReader.getName(nextChar())
959 .map(ClassReader.this::sigToTypeParams);
960 ct1.supertype_field = sigToType();
961 ListBuffer<Type> is = new ListBuffer<>();
962 while (sigp != siglimit) is.append(sigToType());
963 ct1.interfaces_field = is.toList();
964 } finally {
965 readingClassAttr = false;
966 }
967 } else {
968 List<Type> thrown = sym.type.getThrownTypes();
969 sym.type = poolReader.getType(nextChar());
970 //- System.err.println(" # " + sym.type);
971 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
972 sym.type.asMethodType().thrown = thrown;
973
974 }
975 }
976 },
977
978 // v49 annotation attributes
979
980 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
981 protected void read(Symbol sym, int attrLen) {
982 attachAnnotationDefault(sym);
983 }
984 },
985
986 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
987 protected void read(Symbol sym, int attrLen) {
988 attachAnnotations(sym);
989 }
990 },
991
992 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1298 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1299 throw badClassFile("bad.enclosing.method", self);
1300 int index = 1;
1301 while (index < simpleBinaryName.length() &&
1302 isAsciiDigit(simpleBinaryName.charAt(index)))
1303 index++;
1304 return names.fromString(simpleBinaryName.substring(index));
1305 }
1306
1307 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1308 if (nt == null)
1309 return null;
1310
1311 MethodType type = nt.type.asMethodType();
1312
1313 for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1314 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1315 return (MethodSymbol)sym;
1316 }
1317
1318 if (nt.name != names.init)
1319 // not a constructor
1320 return null;
1321 if ((flags & INTERFACE) != 0)
1322 // no enclosing instance
1323 return null;
1324 if (nt.type.getParameterTypes().isEmpty())
1325 // no parameters
1326 return null;
1327
1328 // A constructor of an inner class.
1329 // Remove the first argument (the enclosing instance)
1330 nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1331 nt.type.getReturnType(),
1332 nt.type.getThrownTypes(),
1333 syms.methodClass));
1334 // Try searching again
1335 return findMethod(nt, scope, flags);
1336 }
1337
1338 /** Similar to Types.isSameType but avoids completion */
2216 MethodSymbol readMethod() {
2217 char rawFlags = nextChar();
2218 long flags = adjustMethodFlags(rawFlags);
2219 Name name = poolReader.getName(nextChar());
2220 Type type = poolReader.getType(nextChar());
2221 if (currentOwner.isInterface() &&
2222 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2223 if (majorVersion > Version.V52.major ||
2224 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2225 if ((flags & (STATIC | PRIVATE)) == 0) {
2226 currentOwner.flags_field |= DEFAULT;
2227 flags |= DEFAULT | ABSTRACT;
2228 }
2229 } else {
2230 //protect against ill-formed classfiles
2231 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2232 Integer.toString(majorVersion),
2233 Integer.toString(minorVersion));
2234 }
2235 }
2236 validateMethodType(name, type);
2237 if (name == names.init && currentOwner.hasOuterInstance()) {
2238 // Sometimes anonymous classes don't have an outer
2239 // instance, however, there is no reliable way to tell so
2240 // we never strip this$n
2241 // ditto for local classes. Local classes that have an enclosing method set
2242 // won't pass the "hasOuterInstance" check above, but those that don't have an
2243 // enclosing method (i.e. from initializers) will pass that check.
2244 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2245 if (!currentOwner.name.isEmpty() && !local)
2246 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2247 type.getReturnType(),
2248 type.getThrownTypes(),
2249 syms.methodClass);
2250 }
2251 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2252 if (types.isSignaturePolymorphic(m)) {
2253 m.flags_field |= SIGNATURE_POLYMORPHIC;
2254 }
2255 if (saveParameterNames)
2256 initParameterNames(m);
2257 Symbol prevOwner = currentOwner;
2262 currentOwner = prevOwner;
2263 }
2264 validateMethodType(name, m.type);
2265 setParameters(m, type);
2266
2267 if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1)
2268 throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m);
2269 if ((flags & VARARGS) != 0) {
2270 final Type last = type.getParameterTypes().last();
2271 if (last == null || !last.hasTag(ARRAY)) {
2272 m.flags_field &= ~VARARGS;
2273 throw badClassFile("malformed.vararg.method", m);
2274 }
2275 }
2276
2277 return m;
2278 }
2279
2280 void validateMethodType(Name name, Type t) {
2281 if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
2282 (name == names.init && !t.getReturnType().hasTag(TypeTag.VOID))) {
2283 throw badClassFile("method.descriptor.invalid", name);
2284 }
2285 }
2286
2287 private List<Type> adjustMethodParams(long flags, List<Type> args) {
2288 if (args.isEmpty()) {
2289 return args;
2290 }
2291 boolean isVarargs = (flags & VARARGS) != 0;
2292 if (isVarargs) {
2293 Type varargsElem = args.last();
2294 ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2295 for (Type t : args) {
2296 adjustedArgs.append(t != varargsElem ?
2297 t :
2298 ((ArrayType)t).makeVarargs());
2299 }
2300 args = adjustedArgs.toList();
2301 }
2302 return args.tail;
2332 *
2333 * <p>The type of the symbol may have changed while reading the
2334 * method attributes (see the Signature attribute). This may be
2335 * because of generic information or because anonymous synthetic
2336 * parameters were added. The original type (as read from the
2337 * method descriptor) is used to help guess the existence of
2338 * anonymous synthetic parameters.
2339 */
2340 void setParameters(MethodSymbol sym, Type jvmType) {
2341 // If we get parameter names from MethodParameters, then we
2342 // don't need to skip.
2343 int firstParam = 0;
2344 if (!sawMethodParameters) {
2345 firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2346 // the code in readMethod may have skipped the first
2347 // parameter when setting up the MethodType. If so, we
2348 // make a corresponding allowance here for the position of
2349 // the first parameter. Note that this assumes the
2350 // skipped parameter has a width of 1 -- i.e. it is not
2351 // a double width type (long or double.)
2352 if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2353 // Sometimes anonymous classes don't have an outer
2354 // instance, however, there is no reliable way to tell so
2355 // we never strip this$n
2356 if (!currentOwner.name.isEmpty())
2357 firstParam += 1;
2358 }
2359
2360 if (sym.type != jvmType) {
2361 // reading the method attributes has caused the
2362 // symbol's type to be changed. (i.e. the Signature
2363 // attribute.) This may happen if there are hidden
2364 // (synthetic) parameters in the descriptor, but not
2365 // in the Signature. The position of these hidden
2366 // parameters is unspecified; for now, assume they are
2367 // at the beginning, and so skip over them. The
2368 // primary case for this is two hidden parameters
2369 // passed into Enum constructors.
2370 int skip = Code.width(jvmType.getParameterTypes())
2371 - Code.width(sym.type.getParameterTypes());
2372 firstParam += skip;
2480 return syms.enterClass(currentModule, name, owner);
2481 }
2482
2483 /** Read contents of a given class symbol `c'. Both external and internal
2484 * versions of an inner class are read.
2485 */
2486 void readClass(ClassSymbol c) {
2487 ClassType ct = (ClassType)c.type;
2488
2489 // allocate scope for members
2490 c.members_field = WriteableScope.create(c);
2491
2492 // prepare type variable table
2493 typevars = typevars.dup(currentOwner);
2494 if (ct.getEnclosingType().hasTag(CLASS))
2495 enterTypevars(c.owner, ct.getEnclosingType());
2496
2497 // read flags, or skip if this is an inner class
2498 long f = nextChar();
2499 long flags = adjustClassFlags(f);
2500 if ((flags & MODULE) == 0) {
2501 if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
2502 // read own class name and check that it matches
2503 currentModule = c.packge().modle;
2504 ClassSymbol self = poolReader.getClass(nextChar());
2505 if (c != self) {
2506 throw badClassFile("class.file.wrong.class",
2507 self.flatname);
2508 }
2509 } else {
2510 if (majorVersion < Version.V53.major) {
2511 throw badClassFile("anachronistic.module.info",
2512 Integer.toString(majorVersion),
2513 Integer.toString(minorVersion));
2514 }
2515 c.flags_field = flags;
2516 if (c.owner.kind != MDL) {
2517 throw badClassFile("module.info.definition.expected");
2518 }
2519 currentModule = (ModuleSymbol) c.owner;
2726 * Adjusting flags
2727 ***********************************************************************/
2728
2729 long adjustFieldFlags(long flags) {
2730 return flags;
2731 }
2732
2733 long adjustMethodFlags(long flags) {
2734 if ((flags & ACC_BRIDGE) != 0) {
2735 flags &= ~ACC_BRIDGE;
2736 flags |= BRIDGE;
2737 }
2738 if ((flags & ACC_VARARGS) != 0) {
2739 flags &= ~ACC_VARARGS;
2740 flags |= VARARGS;
2741 }
2742 return flags;
2743 }
2744
2745 long adjustClassFlags(long flags) {
2746 if ((flags & ACC_MODULE) != 0) {
2747 flags &= ~ACC_MODULE;
2748 flags |= MODULE;
2749 }
2750 return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2751 }
2752
2753 /**
2754 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2755 * The attribute is only the last component of the original filename, so is unlikely
2756 * to be valid as is, so operations other than those to access the name throw
2757 * UnsupportedOperationException
2758 */
2759 private static class SourceFileObject implements JavaFileObject {
2760
2761 /** The file's name.
2762 */
2763 private final Name name;
2764
2765 public SourceFileObject(Name name) {
2766 this.name = name;
2767 }
2768
2769 @Override @DefinedBy(Api.COMPILER)
2770 public URI toUri() {
|
27
28 import java.io.*;
29 import java.net.URI;
30 import java.net.URISyntaxException;
31 import java.nio.CharBuffer;
32 import java.nio.file.ClosedFileSystemException;
33 import java.util.Arrays;
34 import java.util.EnumSet;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.function.IntFunction;
40
41 import javax.lang.model.element.Modifier;
42 import javax.lang.model.element.NestingKind;
43 import javax.tools.JavaFileManager;
44 import javax.tools.JavaFileObject;
45
46 import com.sun.tools.javac.code.Source.Feature;
47 import com.sun.tools.javac.code.Type.ClassType.Flavor;
48 import com.sun.tools.javac.comp.Annotate;
49 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
50 import com.sun.tools.javac.code.*;
51 import com.sun.tools.javac.code.Directive.*;
52 import com.sun.tools.javac.code.Lint.LintCategory;
53 import com.sun.tools.javac.code.Scope.WriteableScope;
54 import com.sun.tools.javac.code.Symbol.*;
55 import com.sun.tools.javac.code.Symtab;
56 import com.sun.tools.javac.code.Type.*;
57 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
58 import com.sun.tools.javac.file.BaseFileManager;
59 import com.sun.tools.javac.file.PathFileObject;
60 import com.sun.tools.javac.jvm.ClassFile.Version;
61 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
62 import com.sun.tools.javac.main.Option;
63 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
64 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
65 import com.sun.tools.javac.util.*;
66 import com.sun.tools.javac.util.DefinedBy.Api;
67 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
89 * If you write code that depends on this, you do so at your own risk.
90 * This code and its internal interfaces are subject to change or
91 * deletion without notice.</b>
92 */
93 public class ClassReader {
94 /** The context key for the class reader. */
95 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
96
97 public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
98
99 private final Annotate annotate;
100
101 /** Switch: verbose output.
102 */
103 boolean verbose;
104
105 /** Switch: allow modules.
106 */
107 boolean allowModules;
108
109 /** Switch: allow primitive classes.
110 */
111 boolean allowPrimitiveClasses;
112
113 /** Switch: allow value classes.
114 */
115 boolean allowValueClasses;
116
117 /** Switch: allow sealed
118 */
119 boolean allowSealedTypes;
120
121 /** Switch: allow records
122 */
123 boolean allowRecords;
124
125 /** Lint option: warn about classfile issues
126 */
127 boolean lintClassfile;
128
129 /** Switch: preserve parameter names from the variable table.
130 */
131 public boolean saveParameterNames;
132
133 /**
134 * The currently selected profile.
135 */
136 public final Profile profile;
269 protected ClassReader(Context context) {
270 context.put(classReaderKey, this);
271 annotate = Annotate.instance(context);
272 names = Names.instance(context);
273 syms = Symtab.instance(context);
274 types = Types.instance(context);
275 fileManager = context.get(JavaFileManager.class);
276 if (fileManager == null)
277 throw new AssertionError("FileManager initialization error");
278 diagFactory = JCDiagnostic.Factory.instance(context);
279 dcfh = DeferredCompletionFailureHandler.instance(context);
280
281 log = Log.instance(context);
282
283 Options options = Options.instance(context);
284 verbose = options.isSet(Option.VERBOSE);
285
286 Source source = Source.instance(context);
287 preview = Preview.instance(context);
288 allowModules = Feature.MODULES.allowedInSource(source);
289 allowPrimitiveClasses = Feature.PRIMITIVE_CLASSES.allowedInSource(source) && options.isSet("enablePrimitiveClasses");
290 allowValueClasses = Feature.VALUE_CLASSES.allowedInSource(source);
291 allowRecords = Feature.RECORDS.allowedInSource(source);
292 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
293
294 saveParameterNames = options.isSet(PARAMETERS);
295
296 profile = Profile.instance(context);
297
298 typevars = WriteableScope.create(syms.noSymbol);
299
300 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
301
302 initAttributeReaders();
303 }
304
305 /** Add member to class unless it is synthetic.
306 */
307 private void enterMember(ClassSymbol c, Symbol sym) {
308 // Synthetic members are not entered -- reason lost to history (optimization?).
309 // Lambda methods must be entered because they may have inner classes (which reference them)
310 if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
466 return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
467 }
468 case 'B':
469 sigp++;
470 return syms.byteType;
471 case 'C':
472 sigp++;
473 return syms.charType;
474 case 'D':
475 sigp++;
476 return syms.doubleType;
477 case 'F':
478 sigp++;
479 return syms.floatType;
480 case 'I':
481 sigp++;
482 return syms.intType;
483 case 'J':
484 sigp++;
485 return syms.longType;
486 case 'Q':
487 case 'L':
488 {
489 // int oldsigp = sigp;
490 if ((char) signature[sigp] == 'Q' && !allowPrimitiveClasses) {
491 throw badClassFile("bad.class.signature",
492 Convert.utf2string(signature, sigp, 10));
493 }
494 Type t = classSigToType();
495 if (sigp < siglimit && signature[sigp] == '.')
496 throw badClassFile("deprecated inner class signature syntax " +
497 "(please recompile from source)");
498 /*
499 System.err.println(" decoded " +
500 new String(signature, oldsigp, sigp-oldsigp) +
501 " => " + t + " outer " + t.outer());
502 */
503 return t;
504 }
505 case 'S':
506 sigp++;
507 return syms.shortType;
508 case 'V':
509 sigp++;
510 return syms.voidType;
511 case 'Z':
512 sigp++;
513 return syms.booleanType;
532 return new MethodType(argtypes,
533 restype,
534 thrown.reverse(),
535 syms.methodClass);
536 case '<':
537 typevars = typevars.dup(currentOwner);
538 Type poly = new ForAll(sigToTypeParams(), sigToType());
539 typevars = typevars.leave();
540 return poly;
541 default:
542 throw badClassFile("bad.signature",
543 Convert.utf2string(signature, sigp, 10));
544 }
545 }
546
547 byte[] signatureBuffer = new byte[0];
548 int sbp = 0;
549 /** Convert class signature to type, where signature is implicit.
550 */
551 Type classSigToType() {
552 byte prefix = signature[sigp];
553 if (prefix != 'L' && (!allowPrimitiveClasses || prefix != 'Q'))
554 throw badClassFile("bad.class.signature",
555 Convert.utf2string(signature, sigp, 10));
556 sigp++;
557 Type outer = Type.noType;
558 Name name;
559 ClassType.Flavor flavor;
560 int startSbp = sbp;
561
562 while (true) {
563 final byte c = signature[sigp++];
564 switch (c) {
565
566 case ';': { // end
567 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
568 startSbp,
569 sbp - startSbp));
570
571 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
572 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
573 try {
574 if (outer == Type.noType) {
575 ClassType et = (ClassType) t.erasure(types);
576 // Todo: This spews out more objects than before, i.e no reuse with identical flavor
577 return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata(), flavor);
578 }
579 return new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
580 } finally {
581 sbp = startSbp;
582 }
583 }
584
585 case '<': // generic arguments
586 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
587 startSbp,
588 sbp - startSbp));
589 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
590 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
591 outer = new ClassType(outer, sigToTypes('>'), t, TypeMetadata.EMPTY, flavor) {
592 boolean completed = false;
593 @Override @DefinedBy(Api.LANGUAGE_MODEL)
594 public Type getEnclosingType() {
595 if (!completed) {
596 completed = true;
597 tsym.apiComplete();
598 Type enclosingType = tsym.type.getEnclosingType();
599 if (enclosingType != Type.noType) {
600 List<Type> typeArgs =
601 super.getEnclosingType().allparams();
602 List<Type> typeParams =
603 enclosingType.allparams();
604 if (typeParams.length() != typeArgs.length()) {
605 // no "rare" types
606 super.setEnclosingType(types.erasure(enclosingType));
607 } else {
608 super.setEnclosingType(types.subst(enclosingType,
609 typeParams,
610 typeArgs));
611 }
634 signatureBuffer[sbp++] = (byte)'$';
635 break;
636 } else {
637 sbp = startSbp;
638 return outer;
639 }
640 case '.':
641 signatureBuffer[sbp++] = (byte)'$';
642 break;
643 default:
644 throw new AssertionError(signature[sigp-1]);
645 }
646 continue;
647
648 case '.':
649 //we have seen an enclosing non-generic class
650 if (outer != Type.noType) {
651 t = enterClass(names.fromUtf(signatureBuffer,
652 startSbp,
653 sbp - startSbp));
654 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
655 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
656 outer = new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
657 }
658 signatureBuffer[sbp++] = (byte)'$';
659 continue;
660 case '/':
661 signatureBuffer[sbp++] = (byte)'.';
662 continue;
663 default:
664 signatureBuffer[sbp++] = c;
665 continue;
666 }
667 }
668 }
669
670 /** Convert (implicit) signature to list of types
671 * until `terminator' is encountered.
672 */
673 List<Type> sigToTypes(char terminator) {
674 List<Type> head = List.of(null);
675 List<Type> tail = head;
676 while (signature[sigp] != terminator)
801 protected final Name name;
802 protected final ClassFile.Version version;
803 protected final Set<AttributeKind> kinds;
804 }
805
806 protected Set<AttributeKind> CLASS_ATTRIBUTE =
807 EnumSet.of(AttributeKind.CLASS);
808 protected Set<AttributeKind> MEMBER_ATTRIBUTE =
809 EnumSet.of(AttributeKind.MEMBER);
810 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
811 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
812
813 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
814
815 private void initAttributeReaders() {
816 AttributeReader[] readers = {
817 // v45.3 attributes
818
819 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
820 protected void read(Symbol sym, int attrLen) {
821 if (sym.isInitOrVNew() && sym.type.getParameterTypes().size() == 0) {
822 int code_length = buf.getInt(bp + 4);
823 if ((code_length == 1 && buf.getByte(bp + 8) == (byte) ByteCodes.return_) ||
824 (code_length == 5 && buf.getByte(bp + 8) == ByteCodes.aload_0 &&
825 buf.getByte(bp + 9) == (byte) ByteCodes.invokespecial &&
826 buf.getByte(bp + 12) == (byte) ByteCodes.return_)) {
827 sym.flags_field |= EMPTYNOARGCONSTR;
828 }
829 }
830 if (saveParameterNames)
831 ((MethodSymbol)sym).code = readCode(sym);
832 else
833 bp = bp + attrLen;
834 }
835 },
836
837 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
838 protected void read(Symbol sym, int attrLen) {
839 Object v = poolReader.getConstant(nextChar());
840 // Ignore ConstantValue attribute if field not final.
841 if ((sym.flags() & FINAL) == 0) {
842 return;
843 }
844 VarSymbol var = (VarSymbol) sym;
845 switch (var.type.getTag()) {
846 case BOOLEAN:
847 case BYTE:
848 case CHAR:
849 case SHORT:
990 ClassSymbol c = (ClassSymbol) sym;
991 readingClassAttr = true;
992 try {
993 ClassType ct1 = (ClassType)c.type;
994 Assert.check(c == currentOwner);
995 ct1.typarams_field = poolReader.getName(nextChar())
996 .map(ClassReader.this::sigToTypeParams);
997 ct1.supertype_field = sigToType();
998 ListBuffer<Type> is = new ListBuffer<>();
999 while (sigp != siglimit) is.append(sigToType());
1000 ct1.interfaces_field = is.toList();
1001 } finally {
1002 readingClassAttr = false;
1003 }
1004 } else {
1005 List<Type> thrown = sym.type.getThrownTypes();
1006 sym.type = poolReader.getType(nextChar());
1007 //- System.err.println(" # " + sym.type);
1008 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1009 sym.type.asMethodType().thrown = thrown;
1010 // Map value class factory methods back to constructors for the benefit of earlier pipeline stages
1011 if (sym.kind == MTH && sym.name == names.vnew && !sym.type.getReturnType().hasTag(TypeTag.VOID)) {
1012 sym.type = new MethodType(sym.type.getParameterTypes(),
1013 syms.voidType,
1014 sym.type.getThrownTypes(),
1015 syms.methodClass);
1016 }
1017
1018 }
1019 }
1020 },
1021
1022 // v49 annotation attributes
1023
1024 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1025 protected void read(Symbol sym, int attrLen) {
1026 attachAnnotationDefault(sym);
1027 }
1028 },
1029
1030 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1031 protected void read(Symbol sym, int attrLen) {
1032 attachAnnotations(sym);
1033 }
1034 },
1035
1036 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1342 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1343 throw badClassFile("bad.enclosing.method", self);
1344 int index = 1;
1345 while (index < simpleBinaryName.length() &&
1346 isAsciiDigit(simpleBinaryName.charAt(index)))
1347 index++;
1348 return names.fromString(simpleBinaryName.substring(index));
1349 }
1350
1351 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1352 if (nt == null)
1353 return null;
1354
1355 MethodType type = nt.type.asMethodType();
1356
1357 for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1358 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1359 return (MethodSymbol)sym;
1360 }
1361
1362 if (!names.isInitOrVNew(nt.name))
1363 // not a constructor
1364 return null;
1365 if ((flags & INTERFACE) != 0)
1366 // no enclosing instance
1367 return null;
1368 if (nt.type.getParameterTypes().isEmpty())
1369 // no parameters
1370 return null;
1371
1372 // A constructor of an inner class.
1373 // Remove the first argument (the enclosing instance)
1374 nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1375 nt.type.getReturnType(),
1376 nt.type.getThrownTypes(),
1377 syms.methodClass));
1378 // Try searching again
1379 return findMethod(nt, scope, flags);
1380 }
1381
1382 /** Similar to Types.isSameType but avoids completion */
2260 MethodSymbol readMethod() {
2261 char rawFlags = nextChar();
2262 long flags = adjustMethodFlags(rawFlags);
2263 Name name = poolReader.getName(nextChar());
2264 Type type = poolReader.getType(nextChar());
2265 if (currentOwner.isInterface() &&
2266 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2267 if (majorVersion > Version.V52.major ||
2268 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2269 if ((flags & (STATIC | PRIVATE)) == 0) {
2270 currentOwner.flags_field |= DEFAULT;
2271 flags |= DEFAULT | ABSTRACT;
2272 }
2273 } else {
2274 //protect against ill-formed classfiles
2275 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2276 Integer.toString(majorVersion),
2277 Integer.toString(minorVersion));
2278 }
2279 }
2280 if (names.isInitOrVNew(name) && ((flags & STATIC) != 0)) {
2281 flags &= ~STATIC;
2282 type = new MethodType(type.getParameterTypes(),
2283 syms.voidType,
2284 type.getThrownTypes(),
2285 syms.methodClass);
2286 }
2287 validateMethodType(name, type);
2288 if (names.isInitOrVNew(name) && currentOwner.hasOuterInstance()) {
2289 // Sometimes anonymous classes don't have an outer
2290 // instance, however, there is no reliable way to tell so
2291 // we never strip this$n
2292 // ditto for local classes. Local classes that have an enclosing method set
2293 // won't pass the "hasOuterInstance" check above, but those that don't have an
2294 // enclosing method (i.e. from initializers) will pass that check.
2295 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2296 if (!currentOwner.name.isEmpty() && !local)
2297 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2298 type.getReturnType(),
2299 type.getThrownTypes(),
2300 syms.methodClass);
2301 }
2302 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2303 if (types.isSignaturePolymorphic(m)) {
2304 m.flags_field |= SIGNATURE_POLYMORPHIC;
2305 }
2306 if (saveParameterNames)
2307 initParameterNames(m);
2308 Symbol prevOwner = currentOwner;
2313 currentOwner = prevOwner;
2314 }
2315 validateMethodType(name, m.type);
2316 setParameters(m, type);
2317
2318 if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1)
2319 throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m);
2320 if ((flags & VARARGS) != 0) {
2321 final Type last = type.getParameterTypes().last();
2322 if (last == null || !last.hasTag(ARRAY)) {
2323 m.flags_field &= ~VARARGS;
2324 throw badClassFile("malformed.vararg.method", m);
2325 }
2326 }
2327
2328 return m;
2329 }
2330
2331 void validateMethodType(Name name, Type t) {
2332 if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
2333 ((name == names.init || name == names.vnew) && !t.getReturnType().hasTag(TypeTag.VOID))) {
2334 throw badClassFile("method.descriptor.invalid", name);
2335 }
2336 }
2337
2338 private List<Type> adjustMethodParams(long flags, List<Type> args) {
2339 if (args.isEmpty()) {
2340 return args;
2341 }
2342 boolean isVarargs = (flags & VARARGS) != 0;
2343 if (isVarargs) {
2344 Type varargsElem = args.last();
2345 ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2346 for (Type t : args) {
2347 adjustedArgs.append(t != varargsElem ?
2348 t :
2349 ((ArrayType)t).makeVarargs());
2350 }
2351 args = adjustedArgs.toList();
2352 }
2353 return args.tail;
2383 *
2384 * <p>The type of the symbol may have changed while reading the
2385 * method attributes (see the Signature attribute). This may be
2386 * because of generic information or because anonymous synthetic
2387 * parameters were added. The original type (as read from the
2388 * method descriptor) is used to help guess the existence of
2389 * anonymous synthetic parameters.
2390 */
2391 void setParameters(MethodSymbol sym, Type jvmType) {
2392 // If we get parameter names from MethodParameters, then we
2393 // don't need to skip.
2394 int firstParam = 0;
2395 if (!sawMethodParameters) {
2396 firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2397 // the code in readMethod may have skipped the first
2398 // parameter when setting up the MethodType. If so, we
2399 // make a corresponding allowance here for the position of
2400 // the first parameter. Note that this assumes the
2401 // skipped parameter has a width of 1 -- i.e. it is not
2402 // a double width type (long or double.)
2403 if (names.isInitOrVNew(sym.name) && currentOwner.hasOuterInstance()) {
2404 // Sometimes anonymous classes don't have an outer
2405 // instance, however, there is no reliable way to tell so
2406 // we never strip this$n
2407 if (!currentOwner.name.isEmpty())
2408 firstParam += 1;
2409 }
2410
2411 if (sym.type != jvmType) {
2412 // reading the method attributes has caused the
2413 // symbol's type to be changed. (i.e. the Signature
2414 // attribute.) This may happen if there are hidden
2415 // (synthetic) parameters in the descriptor, but not
2416 // in the Signature. The position of these hidden
2417 // parameters is unspecified; for now, assume they are
2418 // at the beginning, and so skip over them. The
2419 // primary case for this is two hidden parameters
2420 // passed into Enum constructors.
2421 int skip = Code.width(jvmType.getParameterTypes())
2422 - Code.width(sym.type.getParameterTypes());
2423 firstParam += skip;
2531 return syms.enterClass(currentModule, name, owner);
2532 }
2533
2534 /** Read contents of a given class symbol `c'. Both external and internal
2535 * versions of an inner class are read.
2536 */
2537 void readClass(ClassSymbol c) {
2538 ClassType ct = (ClassType)c.type;
2539
2540 // allocate scope for members
2541 c.members_field = WriteableScope.create(c);
2542
2543 // prepare type variable table
2544 typevars = typevars.dup(currentOwner);
2545 if (ct.getEnclosingType().hasTag(CLASS))
2546 enterTypevars(c.owner, ct.getEnclosingType());
2547
2548 // read flags, or skip if this is an inner class
2549 long f = nextChar();
2550 long flags = adjustClassFlags(f);
2551 if (c == syms.objectType.tsym) {
2552 flags &= ~IDENTITY_TYPE; // jlO lacks identity even while being a concrete class.
2553 }
2554 if ((flags & PRIMITIVE_CLASS) != 0) {
2555 if (!allowPrimitiveClasses || (flags & (FINAL | PRIMITIVE_CLASS | IDENTITY_TYPE)) != (FINAL | PRIMITIVE_CLASS)) {
2556 throw badClassFile("bad.access.flags", Flags.toString(flags));
2557 }
2558 }
2559 if ((flags & MODULE) == 0) {
2560 if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
2561 // read own class name and check that it matches
2562 currentModule = c.packge().modle;
2563 ClassSymbol self = poolReader.getClass(nextChar());
2564 if (c != self) {
2565 throw badClassFile("class.file.wrong.class",
2566 self.flatname);
2567 }
2568 } else {
2569 if (majorVersion < Version.V53.major) {
2570 throw badClassFile("anachronistic.module.info",
2571 Integer.toString(majorVersion),
2572 Integer.toString(minorVersion));
2573 }
2574 c.flags_field = flags;
2575 if (c.owner.kind != MDL) {
2576 throw badClassFile("module.info.definition.expected");
2577 }
2578 currentModule = (ModuleSymbol) c.owner;
2785 * Adjusting flags
2786 ***********************************************************************/
2787
2788 long adjustFieldFlags(long flags) {
2789 return flags;
2790 }
2791
2792 long adjustMethodFlags(long flags) {
2793 if ((flags & ACC_BRIDGE) != 0) {
2794 flags &= ~ACC_BRIDGE;
2795 flags |= BRIDGE;
2796 }
2797 if ((flags & ACC_VARARGS) != 0) {
2798 flags &= ~ACC_VARARGS;
2799 flags |= VARARGS;
2800 }
2801 return flags;
2802 }
2803
2804 long adjustClassFlags(long flags) {
2805 if ((flags & (ABSTRACT | INTERFACE | ACC_VALUE | ACC_MODULE)) == 0) {
2806 flags |= ACC_IDENTITY;
2807 }
2808 if ((flags & ACC_MODULE) != 0) {
2809 flags &= ~ACC_MODULE;
2810 flags |= MODULE;
2811 }
2812 if ((flags & ACC_PRIMITIVE) != 0) {
2813 flags &= ~ACC_PRIMITIVE;
2814 if (allowPrimitiveClasses) {
2815 flags |= PRIMITIVE_CLASS;
2816 }
2817 }
2818 if ((flags & ACC_VALUE) != 0) {
2819 flags &= ~ACC_VALUE;
2820 if (allowValueClasses) {
2821 flags |= VALUE_CLASS;
2822 }
2823 }
2824 if ((flags & ACC_IDENTITY) != 0) {
2825 flags &= ~ACC_IDENTITY;
2826 flags |= IDENTITY_TYPE;
2827 }
2828 return flags;
2829 }
2830
2831 /**
2832 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2833 * The attribute is only the last component of the original filename, so is unlikely
2834 * to be valid as is, so operations other than those to access the name throw
2835 * UnsupportedOperationException
2836 */
2837 private static class SourceFileObject implements JavaFileObject {
2838
2839 /** The file's name.
2840 */
2841 private final Name name;
2842
2843 public SourceFileObject(Name name) {
2844 this.name = name;
2845 }
2846
2847 @Override @DefinedBy(Api.COMPILER)
2848 public URI toUri() {
|