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;
47 import com.sun.tools.javac.code.Source.Feature;
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.ByteBuffer.UnderflowException;
67 import com.sun.tools.javac.util.DefinedBy.Api;
91 * If you write code that depends on this, you do so at your own risk.
92 * This code and its internal interfaces are subject to change or
93 * deletion without notice.</b>
94 */
95 public class ClassReader {
96 /** The context key for the class reader. */
97 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
98
99 public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
100
101 private final Annotate annotate;
102
103 /** Switch: verbose output.
104 */
105 boolean verbose;
106
107 /** Switch: allow modules.
108 */
109 boolean allowModules;
110
111 /** Switch: allow sealed
112 */
113 boolean allowSealedTypes;
114
115 /** Switch: allow records
116 */
117 boolean allowRecords;
118
119 /** Lint option: warn about classfile issues
120 */
121 boolean lintClassfile;
122
123 /** Switch: warn (instead of error) on illegal UTF-8
124 */
125 boolean warnOnIllegalUtf8;
126
127 /** Switch: preserve parameter names from the variable table.
128 */
129 public boolean saveParameterNames;
130
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 allowRecords = Feature.RECORDS.allowedInSource(source);
286 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
287 warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.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)
483 return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
484 }
485 case 'B':
486 sigp++;
487 return syms.byteType;
488 case 'C':
489 sigp++;
490 return syms.charType;
491 case 'D':
492 sigp++;
493 return syms.doubleType;
494 case 'F':
495 sigp++;
496 return syms.floatType;
497 case 'I':
498 sigp++;
499 return syms.intType;
500 case 'J':
501 sigp++;
502 return syms.longType;
503 case 'L':
504 {
505 // int oldsigp = sigp;
506 Type t = classSigToType();
507 if (sigp < siglimit && signature[sigp] == '.')
508 throw badClassFile("deprecated inner class signature syntax " +
509 "(please recompile from source)");
510 /*
511 System.err.println(" decoded " +
512 new String(signature, oldsigp, sigp-oldsigp) +
513 " => " + t + " outer " + t.outer());
514 */
515 return t;
516 }
517 case 'S':
518 sigp++;
519 return syms.shortType;
520 case 'V':
521 sigp++;
522 return syms.voidType;
523 case 'Z':
524 sigp++;
525 return syms.booleanType;
543 }
544 return new MethodType(argtypes,
545 restype,
546 thrown.reverse(),
547 syms.methodClass);
548 case '<':
549 typevars = typevars.dup(currentOwner);
550 Type poly = new ForAll(sigToTypeParams(), sigToType());
551 typevars = typevars.leave();
552 return poly;
553 default:
554 throw badClassFile("bad.signature", quoteBadSignature());
555 }
556 }
557
558 byte[] signatureBuffer = new byte[0];
559 int sbp = 0;
560 /** Convert class signature to type, where signature is implicit.
561 */
562 Type classSigToType() {
563 if (signature[sigp] != 'L')
564 throw badClassFile("bad.class.signature", quoteBadSignature());
565 sigp++;
566 Type outer = Type.noType;
567 int startSbp = sbp;
568
569 while (true) {
570 final byte c = signature[sigp++];
571 switch (c) {
572
573 case ';': { // end
574 ClassSymbol t = enterClass(readName(signatureBuffer,
575 startSbp,
576 sbp - startSbp));
577
578 try {
579 return (outer == Type.noType) ?
580 t.erasure(types) :
581 new ClassType(outer, List.nil(), t);
582 } finally {
583 sbp = startSbp;
584 }
585 }
586
587 case '<': // generic arguments
588 ClassSymbol t = enterClass(readName(signatureBuffer,
589 startSbp,
590 sbp - startSbp));
591 outer = new ClassType(outer, sigToTypes('>'), t) {
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(readName(signatureBuffer,
652 startSbp,
653 sbp - startSbp));
654 outer = new ClassType(outer, List.nil(), t);
655 }
656 signatureBuffer[sbp++] = (byte)'$';
657 continue;
658 case '/':
659 signatureBuffer[sbp++] = (byte)'.';
660 continue;
661 default:
662 signatureBuffer[sbp++] = c;
663 continue;
664 }
665 }
666 }
667
668 /** Quote a bogus signature for display inside an error message.
669 */
670 String quoteBadSignature() {
671 String sigString;
672 try {
673 sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE);
674 } catch (InvalidUtfException e) {
826 protected final Name name;
827 protected final ClassFile.Version version;
828 protected final Set<AttributeKind> kinds;
829 }
830
831 protected Set<AttributeKind> CLASS_ATTRIBUTE =
832 EnumSet.of(AttributeKind.CLASS);
833 protected Set<AttributeKind> MEMBER_ATTRIBUTE =
834 EnumSet.of(AttributeKind.MEMBER);
835 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
836 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
837
838 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
839
840 private void initAttributeReaders() {
841 AttributeReader[] readers = {
842 // v45.3 attributes
843
844 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
845 protected void read(Symbol sym, int attrLen) {
846 if (saveParameterNames)
847 ((MethodSymbol)sym).code = readCode(sym);
848 else
849 bp = bp + attrLen;
850 }
851 },
852
853 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
854 protected void read(Symbol sym, int attrLen) {
855 Object v = poolReader.getConstant(nextChar());
856 // Ignore ConstantValue attribute if field not final.
857 if ((sym.flags() & FINAL) == 0) {
858 return;
859 }
860 VarSymbol var = (VarSymbol) sym;
861 switch (var.type.getTag()) {
862 case BOOLEAN:
863 case BYTE:
864 case CHAR:
865 case SHORT:
1005 ClassSymbol c = (ClassSymbol) sym;
1006 readingClassAttr = true;
1007 try {
1008 ClassType ct1 = (ClassType)c.type;
1009 Assert.check(c == currentOwner);
1010 ct1.typarams_field = poolReader.getName(nextChar())
1011 .map(ClassReader.this::sigToTypeParams);
1012 ct1.supertype_field = sigToType();
1013 ListBuffer<Type> is = new ListBuffer<>();
1014 while (sigp != siglimit) is.append(sigToType());
1015 ct1.interfaces_field = is.toList();
1016 } finally {
1017 readingClassAttr = false;
1018 }
1019 } else {
1020 List<Type> thrown = sym.type.getThrownTypes();
1021 sym.type = poolReader.getType(nextChar());
1022 //- System.err.println(" # " + sym.type);
1023 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1024 sym.type.asMethodType().thrown = thrown;
1025
1026 }
1027 }
1028 },
1029
1030 // v49 annotation attributes
1031
1032 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1033 protected void read(Symbol sym, int attrLen) {
1034 attachAnnotationDefault(sym);
1035 }
1036 },
1037
1038 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1039 protected void read(Symbol sym, int attrLen) {
1040 attachAnnotations(sym);
1041 }
1042 },
1043
1044 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1358 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1359 throw badClassFile("bad.enclosing.method", self);
1360 int index = 1;
1361 while (index < simpleBinaryName.length() &&
1362 isAsciiDigit(simpleBinaryName.charAt(index)))
1363 index++;
1364 return names.fromString(simpleBinaryName.substring(index));
1365 }
1366
1367 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1368 if (nt == null)
1369 return null;
1370
1371 MethodType type = nt.type.asMethodType();
1372
1373 for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1374 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1375 return (MethodSymbol)sym;
1376 }
1377
1378 if (nt.name != names.init)
1379 // not a constructor
1380 return null;
1381 if ((flags & INTERFACE) != 0)
1382 // no enclosing instance
1383 return null;
1384 if (nt.type.getParameterTypes().isEmpty())
1385 // no parameters
1386 return null;
1387
1388 // A constructor of an inner class.
1389 // Remove the first argument (the enclosing instance)
1390 nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1391 nt.type.getReturnType(),
1392 nt.type.getThrownTypes(),
1393 syms.methodClass));
1394 // Try searching again
1395 return findMethod(nt, scope, flags);
1396 }
1397
1398 /** Similar to Types.isSameType but avoids completion */
2286 MethodSymbol readMethod() {
2287 char rawFlags = nextChar();
2288 long flags = adjustMethodFlags(rawFlags);
2289 Name name = poolReader.getName(nextChar());
2290 Type type = poolReader.getType(nextChar());
2291 if (currentOwner.isInterface() &&
2292 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2293 if (majorVersion > Version.V52.major ||
2294 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2295 if ((flags & (STATIC | PRIVATE)) == 0) {
2296 currentOwner.flags_field |= DEFAULT;
2297 flags |= DEFAULT | ABSTRACT;
2298 }
2299 } else {
2300 //protect against ill-formed classfiles
2301 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2302 Integer.toString(majorVersion),
2303 Integer.toString(minorVersion));
2304 }
2305 }
2306 validateMethodType(name, type);
2307 if (name == names.init && currentOwner.hasOuterInstance()) {
2308 // Sometimes anonymous classes don't have an outer
2309 // instance, however, there is no reliable way to tell so
2310 // we never strip this$n
2311 // ditto for local classes. Local classes that have an enclosing method set
2312 // won't pass the "hasOuterInstance" check above, but those that don't have an
2313 // enclosing method (i.e. from initializers) will pass that check.
2314 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2315 if (!currentOwner.name.isEmpty() && !local)
2316 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2317 type.getReturnType(),
2318 type.getThrownTypes(),
2319 syms.methodClass);
2320 }
2321 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2322 if (types.isSignaturePolymorphic(m)) {
2323 m.flags_field |= SIGNATURE_POLYMORPHIC;
2324 }
2325 if (saveParameterNames)
2326 initParameterNames(m);
2327 Symbol prevOwner = currentOwner;
2332 currentOwner = prevOwner;
2333 }
2334 validateMethodType(name, m.type);
2335 setParameters(m, type);
2336
2337 if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1)
2338 throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m);
2339 if ((flags & VARARGS) != 0) {
2340 final Type last = type.getParameterTypes().last();
2341 if (last == null || !last.hasTag(ARRAY)) {
2342 m.flags_field &= ~VARARGS;
2343 throw badClassFile("malformed.vararg.method", m);
2344 }
2345 }
2346
2347 return m;
2348 }
2349
2350 void validateMethodType(Name name, Type t) {
2351 if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
2352 (name == names.init && !t.getReturnType().hasTag(TypeTag.VOID))) {
2353 throw badClassFile("method.descriptor.invalid", name);
2354 }
2355 }
2356
2357 private List<Type> adjustMethodParams(long flags, List<Type> args) {
2358 if (args.isEmpty()) {
2359 return args;
2360 }
2361 boolean isVarargs = (flags & VARARGS) != 0;
2362 if (isVarargs) {
2363 Type varargsElem = args.last();
2364 ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2365 for (Type t : args) {
2366 adjustedArgs.append(t != varargsElem ?
2367 t :
2368 ((ArrayType)t).makeVarargs());
2369 }
2370 args = adjustedArgs.toList();
2371 }
2372 return args.tail;
2396
2397 /**
2398 * Set the parameters for a method symbol, including any names and
2399 * annotations that were read.
2400 *
2401 * <p>The type of the symbol may have changed while reading the
2402 * method attributes (see the Signature attribute). This may be
2403 * because of generic information or because anonymous synthetic
2404 * parameters were added. The original type (as read from the
2405 * method descriptor) is used to help guess the existence of
2406 * anonymous synthetic parameters.
2407 */
2408 void setParameters(MethodSymbol sym, Type jvmType) {
2409 int firstParamLvt = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2410 // the code in readMethod may have skipped the first
2411 // parameter when setting up the MethodType. If so, we
2412 // make a corresponding allowance here for the position of
2413 // the first parameter. Note that this assumes the
2414 // skipped parameter has a width of 1 -- i.e. it is not
2415 // a double width type (long or double.)
2416 if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2417 // Sometimes anonymous classes don't have an outer
2418 // instance, however, there is no reliable way to tell so
2419 // we never strip this$n
2420 if (!currentOwner.name.isEmpty())
2421 firstParamLvt += 1;
2422 }
2423
2424 if (sym.type != jvmType) {
2425 // reading the method attributes has caused the
2426 // symbol's type to be changed. (i.e. the Signature
2427 // attribute.) This may happen if there are hidden
2428 // (synthetic) parameters in the descriptor, but not
2429 // in the Signature. The position of these hidden
2430 // parameters is unspecified; for now, assume they are
2431 // at the beginning, and so skip over them. The
2432 // primary case for this is two hidden parameters
2433 // passed into Enum constructors.
2434 int skip = Code.width(jvmType.getParameterTypes())
2435 - Code.width(sym.type.getParameterTypes());
2436 firstParamLvt += skip;
2560 return syms.enterClass(currentModule, name, owner);
2561 }
2562
2563 /** Read contents of a given class symbol `c'. Both external and internal
2564 * versions of an inner class are read.
2565 */
2566 void readClass(ClassSymbol c) {
2567 ClassType ct = (ClassType)c.type;
2568
2569 // allocate scope for members
2570 c.members_field = WriteableScope.create(c);
2571
2572 // prepare type variable table
2573 typevars = typevars.dup(currentOwner);
2574 if (ct.getEnclosingType().hasTag(CLASS))
2575 enterTypevars(c.owner, ct.getEnclosingType());
2576
2577 // read flags, or skip if this is an inner class
2578 long f = nextChar();
2579 long flags = adjustClassFlags(f);
2580 if ((flags & MODULE) == 0) {
2581 if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
2582 // read own class name and check that it matches
2583 currentModule = c.packge().modle;
2584 ClassSymbol self = poolReader.getClass(nextChar());
2585 if (c != self) {
2586 throw badClassFile("class.file.wrong.class",
2587 self.flatname);
2588 }
2589 } else {
2590 if (majorVersion < Version.V53.major) {
2591 throw badClassFile("anachronistic.module.info",
2592 Integer.toString(majorVersion),
2593 Integer.toString(minorVersion));
2594 }
2595 c.flags_field = flags;
2596 if (c.owner.kind != MDL) {
2597 throw badClassFile("module.info.definition.expected");
2598 }
2599 currentModule = (ModuleSymbol) c.owner;
2817 * Adjusting flags
2818 ***********************************************************************/
2819
2820 long adjustFieldFlags(long flags) {
2821 return flags;
2822 }
2823
2824 long adjustMethodFlags(long flags) {
2825 if ((flags & ACC_BRIDGE) != 0) {
2826 flags &= ~ACC_BRIDGE;
2827 flags |= BRIDGE;
2828 }
2829 if ((flags & ACC_VARARGS) != 0) {
2830 flags &= ~ACC_VARARGS;
2831 flags |= VARARGS;
2832 }
2833 return flags;
2834 }
2835
2836 long adjustClassFlags(long flags) {
2837 if ((flags & ACC_MODULE) != 0) {
2838 flags &= ~ACC_MODULE;
2839 flags |= MODULE;
2840 }
2841 return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2842 }
2843
2844 /**
2845 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2846 * The attribute is only the last component of the original filename, so is unlikely
2847 * to be valid as is, so operations other than those to access the name throw
2848 * UnsupportedOperationException
2849 */
2850 private static class SourceFileObject implements JavaFileObject {
2851
2852 /** The file's name.
2853 */
2854 private final Name name;
2855
2856 public SourceFileObject(Name name) {
2857 this.name = name;
2858 }
2859
2860 @Override @DefinedBy(Api.COMPILER)
2861 public URI toUri() {
|
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;
47 import com.sun.tools.javac.code.Source.Feature;
48 import com.sun.tools.javac.code.Type.ClassType.Flavor;
49 import com.sun.tools.javac.comp.Annotate;
50 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
51 import com.sun.tools.javac.code.*;
52 import com.sun.tools.javac.code.Directive.*;
53 import com.sun.tools.javac.code.Lint.LintCategory;
54 import com.sun.tools.javac.code.Scope.WriteableScope;
55 import com.sun.tools.javac.code.Symbol.*;
56 import com.sun.tools.javac.code.Symtab;
57 import com.sun.tools.javac.code.Type.*;
58 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
59 import com.sun.tools.javac.file.BaseFileManager;
60 import com.sun.tools.javac.file.PathFileObject;
61 import com.sun.tools.javac.jvm.ClassFile.Version;
62 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
63 import com.sun.tools.javac.main.Option;
64 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
65 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
66 import com.sun.tools.javac.util.*;
67 import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
68 import com.sun.tools.javac.util.DefinedBy.Api;
92 * If you write code that depends on this, you do so at your own risk.
93 * This code and its internal interfaces are subject to change or
94 * deletion without notice.</b>
95 */
96 public class ClassReader {
97 /** The context key for the class reader. */
98 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
99
100 public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
101
102 private final Annotate annotate;
103
104 /** Switch: verbose output.
105 */
106 boolean verbose;
107
108 /** Switch: allow modules.
109 */
110 boolean allowModules;
111
112 /** Switch: allow primitive classes.
113 */
114 boolean allowPrimitiveClasses;
115
116 /** Switch: allow value classes.
117 */
118 boolean allowValueClasses;
119
120 /** Switch: allow sealed
121 */
122 boolean allowSealedTypes;
123
124 /** Switch: allow records
125 */
126 boolean allowRecords;
127
128 /** Lint option: warn about classfile issues
129 */
130 boolean lintClassfile;
131
132 /** Switch: warn (instead of error) on illegal UTF-8
133 */
134 boolean warnOnIllegalUtf8;
135
136 /** Switch: preserve parameter names from the variable table.
137 */
138 public boolean saveParameterNames;
139
274 protected ClassReader(Context context) {
275 context.put(classReaderKey, this);
276 annotate = Annotate.instance(context);
277 names = Names.instance(context);
278 syms = Symtab.instance(context);
279 types = Types.instance(context);
280 fileManager = context.get(JavaFileManager.class);
281 if (fileManager == null)
282 throw new AssertionError("FileManager initialization error");
283 diagFactory = JCDiagnostic.Factory.instance(context);
284 dcfh = DeferredCompletionFailureHandler.instance(context);
285
286 log = Log.instance(context);
287
288 Options options = Options.instance(context);
289 verbose = options.isSet(Option.VERBOSE);
290
291 Source source = Source.instance(context);
292 preview = Preview.instance(context);
293 allowModules = Feature.MODULES.allowedInSource(source);
294 allowPrimitiveClasses = Feature.PRIMITIVE_CLASSES.allowedInSource(source) && options.isSet("enablePrimitiveClasses");
295 allowValueClasses = Feature.VALUE_CLASSES.allowedInSource(source);
296 allowRecords = Feature.RECORDS.allowedInSource(source);
297 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
298 warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
299
300 saveParameterNames = options.isSet(PARAMETERS);
301
302 profile = Profile.instance(context);
303
304 typevars = WriteableScope.create(syms.noSymbol);
305
306 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
307
308 initAttributeReaders();
309 }
310
311 /** Add member to class unless it is synthetic.
312 */
313 private void enterMember(ClassSymbol c, Symbol sym) {
314 // Synthetic members are not entered -- reason lost to history (optimization?).
315 // Lambda methods must be entered because they may have inner classes (which reference them)
494 return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
495 }
496 case 'B':
497 sigp++;
498 return syms.byteType;
499 case 'C':
500 sigp++;
501 return syms.charType;
502 case 'D':
503 sigp++;
504 return syms.doubleType;
505 case 'F':
506 sigp++;
507 return syms.floatType;
508 case 'I':
509 sigp++;
510 return syms.intType;
511 case 'J':
512 sigp++;
513 return syms.longType;
514 case 'Q':
515 case 'L':
516 {
517 // int oldsigp = sigp;
518 if ((char) signature[sigp] == 'Q' && !allowPrimitiveClasses) {
519 throw badClassFile("bad.class.signature",
520 quoteBadSignature());
521 }
522 Type t = classSigToType();
523 if (sigp < siglimit && signature[sigp] == '.')
524 throw badClassFile("deprecated inner class signature syntax " +
525 "(please recompile from source)");
526 /*
527 System.err.println(" decoded " +
528 new String(signature, oldsigp, sigp-oldsigp) +
529 " => " + t + " outer " + t.outer());
530 */
531 return t;
532 }
533 case 'S':
534 sigp++;
535 return syms.shortType;
536 case 'V':
537 sigp++;
538 return syms.voidType;
539 case 'Z':
540 sigp++;
541 return syms.booleanType;
559 }
560 return new MethodType(argtypes,
561 restype,
562 thrown.reverse(),
563 syms.methodClass);
564 case '<':
565 typevars = typevars.dup(currentOwner);
566 Type poly = new ForAll(sigToTypeParams(), sigToType());
567 typevars = typevars.leave();
568 return poly;
569 default:
570 throw badClassFile("bad.signature", quoteBadSignature());
571 }
572 }
573
574 byte[] signatureBuffer = new byte[0];
575 int sbp = 0;
576 /** Convert class signature to type, where signature is implicit.
577 */
578 Type classSigToType() {
579 byte prefix = signature[sigp];
580 if (prefix != 'L' && (!allowPrimitiveClasses || prefix != 'Q'))
581 throw badClassFile("bad.class.signature", quoteBadSignature());
582 sigp++;
583 Type outer = Type.noType;
584 Name name;
585 ClassType.Flavor flavor;
586 int startSbp = sbp;
587
588 while (true) {
589 final byte c = signature[sigp++];
590 switch (c) {
591
592 case ';': { // end
593 ClassSymbol t = enterClass(readName(signatureBuffer,
594 startSbp,
595 sbp - startSbp));
596
597 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
598 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
599 try {
600 if (outer == Type.noType) {
601 ClassType et = (ClassType) t.erasure(types);
602 // Todo: This spews out more objects than before, i.e no reuse with identical flavor
603 return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata(), flavor);
604 }
605 return new ClassType(outer, List.nil(), t, List.nil(), flavor);
606 } finally {
607 sbp = startSbp;
608 }
609 }
610
611 case '<': // generic arguments
612 ClassSymbol t = enterClass(readName(signatureBuffer,
613 startSbp,
614 sbp - startSbp));
615 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
616 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
617 outer = new ClassType(outer, sigToTypes('>'), t, List.nil(), flavor) {
618 boolean completed = false;
619 @Override @DefinedBy(Api.LANGUAGE_MODEL)
620 public Type getEnclosingType() {
621 if (!completed) {
622 completed = true;
623 tsym.apiComplete();
624 Type enclosingType = tsym.type.getEnclosingType();
625 if (enclosingType != Type.noType) {
626 List<Type> typeArgs =
627 super.getEnclosingType().allparams();
628 List<Type> typeParams =
629 enclosingType.allparams();
630 if (typeParams.length() != typeArgs.length()) {
631 // no "rare" types
632 super.setEnclosingType(types.erasure(enclosingType));
633 } else {
634 super.setEnclosingType(types.subst(enclosingType,
635 typeParams,
636 typeArgs));
637 }
660 signatureBuffer[sbp++] = (byte)'$';
661 break;
662 } else {
663 sbp = startSbp;
664 return outer;
665 }
666 case '.':
667 signatureBuffer[sbp++] = (byte)'$';
668 break;
669 default:
670 throw new AssertionError(signature[sigp-1]);
671 }
672 continue;
673
674 case '.':
675 //we have seen an enclosing non-generic class
676 if (outer != Type.noType) {
677 t = enterClass(readName(signatureBuffer,
678 startSbp,
679 sbp - startSbp));
680 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
681 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
682 outer = new ClassType(outer, List.nil(), t, List.nil(), flavor);
683 }
684 signatureBuffer[sbp++] = (byte)'$';
685 continue;
686 case '/':
687 signatureBuffer[sbp++] = (byte)'.';
688 continue;
689 default:
690 signatureBuffer[sbp++] = c;
691 continue;
692 }
693 }
694 }
695
696 /** Quote a bogus signature for display inside an error message.
697 */
698 String quoteBadSignature() {
699 String sigString;
700 try {
701 sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE);
702 } catch (InvalidUtfException e) {
854 protected final Name name;
855 protected final ClassFile.Version version;
856 protected final Set<AttributeKind> kinds;
857 }
858
859 protected Set<AttributeKind> CLASS_ATTRIBUTE =
860 EnumSet.of(AttributeKind.CLASS);
861 protected Set<AttributeKind> MEMBER_ATTRIBUTE =
862 EnumSet.of(AttributeKind.MEMBER);
863 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
864 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
865
866 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
867
868 private void initAttributeReaders() {
869 AttributeReader[] readers = {
870 // v45.3 attributes
871
872 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
873 protected void read(Symbol sym, int attrLen) {
874 if (sym.isInitOrVNew() && sym.type.getParameterTypes().size() == 0) {
875 try {
876 int code_length = buf.getInt(bp + 4);
877 if ((code_length == 1 && buf.getByte(bp + 8) == (byte) ByteCodes.return_) ||
878 (code_length == 5 && buf.getByte(bp + 8) == ByteCodes.aload_0 &&
879 buf.getByte(bp + 9) == (byte) ByteCodes.invokespecial &&
880 buf.getByte(bp + 12) == (byte) ByteCodes.return_)) {
881 sym.flags_field |= EMPTYNOARGCONSTR;
882 }
883 } catch (UnderflowException e) {
884 throw badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength()));
885 }
886 }
887 if (saveParameterNames)
888 ((MethodSymbol)sym).code = readCode(sym);
889 else
890 bp = bp + attrLen;
891 }
892 },
893
894 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
895 protected void read(Symbol sym, int attrLen) {
896 Object v = poolReader.getConstant(nextChar());
897 // Ignore ConstantValue attribute if field not final.
898 if ((sym.flags() & FINAL) == 0) {
899 return;
900 }
901 VarSymbol var = (VarSymbol) sym;
902 switch (var.type.getTag()) {
903 case BOOLEAN:
904 case BYTE:
905 case CHAR:
906 case SHORT:
1046 ClassSymbol c = (ClassSymbol) sym;
1047 readingClassAttr = true;
1048 try {
1049 ClassType ct1 = (ClassType)c.type;
1050 Assert.check(c == currentOwner);
1051 ct1.typarams_field = poolReader.getName(nextChar())
1052 .map(ClassReader.this::sigToTypeParams);
1053 ct1.supertype_field = sigToType();
1054 ListBuffer<Type> is = new ListBuffer<>();
1055 while (sigp != siglimit) is.append(sigToType());
1056 ct1.interfaces_field = is.toList();
1057 } finally {
1058 readingClassAttr = false;
1059 }
1060 } else {
1061 List<Type> thrown = sym.type.getThrownTypes();
1062 sym.type = poolReader.getType(nextChar());
1063 //- System.err.println(" # " + sym.type);
1064 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1065 sym.type.asMethodType().thrown = thrown;
1066 // Map value class factory methods back to constructors for the benefit of earlier pipeline stages
1067 if (sym.kind == MTH && sym.name == names.vnew && !sym.type.getReturnType().hasTag(TypeTag.VOID)) {
1068 sym.type = new MethodType(sym.type.getParameterTypes(),
1069 syms.voidType,
1070 sym.type.getThrownTypes(),
1071 syms.methodClass);
1072 }
1073
1074 }
1075 }
1076 },
1077
1078 // v49 annotation attributes
1079
1080 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1081 protected void read(Symbol sym, int attrLen) {
1082 attachAnnotationDefault(sym);
1083 }
1084 },
1085
1086 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1087 protected void read(Symbol sym, int attrLen) {
1088 attachAnnotations(sym);
1089 }
1090 },
1091
1092 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1406 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1407 throw badClassFile("bad.enclosing.method", self);
1408 int index = 1;
1409 while (index < simpleBinaryName.length() &&
1410 isAsciiDigit(simpleBinaryName.charAt(index)))
1411 index++;
1412 return names.fromString(simpleBinaryName.substring(index));
1413 }
1414
1415 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1416 if (nt == null)
1417 return null;
1418
1419 MethodType type = nt.type.asMethodType();
1420
1421 for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1422 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1423 return (MethodSymbol)sym;
1424 }
1425
1426 if (!names.isInitOrVNew(nt.name))
1427 // not a constructor
1428 return null;
1429 if ((flags & INTERFACE) != 0)
1430 // no enclosing instance
1431 return null;
1432 if (nt.type.getParameterTypes().isEmpty())
1433 // no parameters
1434 return null;
1435
1436 // A constructor of an inner class.
1437 // Remove the first argument (the enclosing instance)
1438 nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1439 nt.type.getReturnType(),
1440 nt.type.getThrownTypes(),
1441 syms.methodClass));
1442 // Try searching again
1443 return findMethod(nt, scope, flags);
1444 }
1445
1446 /** Similar to Types.isSameType but avoids completion */
2334 MethodSymbol readMethod() {
2335 char rawFlags = nextChar();
2336 long flags = adjustMethodFlags(rawFlags);
2337 Name name = poolReader.getName(nextChar());
2338 Type type = poolReader.getType(nextChar());
2339 if (currentOwner.isInterface() &&
2340 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2341 if (majorVersion > Version.V52.major ||
2342 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2343 if ((flags & (STATIC | PRIVATE)) == 0) {
2344 currentOwner.flags_field |= DEFAULT;
2345 flags |= DEFAULT | ABSTRACT;
2346 }
2347 } else {
2348 //protect against ill-formed classfiles
2349 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2350 Integer.toString(majorVersion),
2351 Integer.toString(minorVersion));
2352 }
2353 }
2354 if (names.isInitOrVNew(name) && ((flags & STATIC) != 0)) {
2355 flags &= ~STATIC;
2356 type = new MethodType(type.getParameterTypes(),
2357 syms.voidType,
2358 type.getThrownTypes(),
2359 syms.methodClass);
2360 }
2361 validateMethodType(name, type);
2362 if (names.isInitOrVNew(name) && currentOwner.hasOuterInstance()) {
2363 // Sometimes anonymous classes don't have an outer
2364 // instance, however, there is no reliable way to tell so
2365 // we never strip this$n
2366 // ditto for local classes. Local classes that have an enclosing method set
2367 // won't pass the "hasOuterInstance" check above, but those that don't have an
2368 // enclosing method (i.e. from initializers) will pass that check.
2369 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2370 if (!currentOwner.name.isEmpty() && !local)
2371 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2372 type.getReturnType(),
2373 type.getThrownTypes(),
2374 syms.methodClass);
2375 }
2376 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2377 if (types.isSignaturePolymorphic(m)) {
2378 m.flags_field |= SIGNATURE_POLYMORPHIC;
2379 }
2380 if (saveParameterNames)
2381 initParameterNames(m);
2382 Symbol prevOwner = currentOwner;
2387 currentOwner = prevOwner;
2388 }
2389 validateMethodType(name, m.type);
2390 setParameters(m, type);
2391
2392 if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1)
2393 throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m);
2394 if ((flags & VARARGS) != 0) {
2395 final Type last = type.getParameterTypes().last();
2396 if (last == null || !last.hasTag(ARRAY)) {
2397 m.flags_field &= ~VARARGS;
2398 throw badClassFile("malformed.vararg.method", m);
2399 }
2400 }
2401
2402 return m;
2403 }
2404
2405 void validateMethodType(Name name, Type t) {
2406 if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
2407 ((name == names.init || name == names.vnew) && !t.getReturnType().hasTag(TypeTag.VOID))) {
2408 throw badClassFile("method.descriptor.invalid", name);
2409 }
2410 }
2411
2412 private List<Type> adjustMethodParams(long flags, List<Type> args) {
2413 if (args.isEmpty()) {
2414 return args;
2415 }
2416 boolean isVarargs = (flags & VARARGS) != 0;
2417 if (isVarargs) {
2418 Type varargsElem = args.last();
2419 ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2420 for (Type t : args) {
2421 adjustedArgs.append(t != varargsElem ?
2422 t :
2423 ((ArrayType)t).makeVarargs());
2424 }
2425 args = adjustedArgs.toList();
2426 }
2427 return args.tail;
2451
2452 /**
2453 * Set the parameters for a method symbol, including any names and
2454 * annotations that were read.
2455 *
2456 * <p>The type of the symbol may have changed while reading the
2457 * method attributes (see the Signature attribute). This may be
2458 * because of generic information or because anonymous synthetic
2459 * parameters were added. The original type (as read from the
2460 * method descriptor) is used to help guess the existence of
2461 * anonymous synthetic parameters.
2462 */
2463 void setParameters(MethodSymbol sym, Type jvmType) {
2464 int firstParamLvt = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2465 // the code in readMethod may have skipped the first
2466 // parameter when setting up the MethodType. If so, we
2467 // make a corresponding allowance here for the position of
2468 // the first parameter. Note that this assumes the
2469 // skipped parameter has a width of 1 -- i.e. it is not
2470 // a double width type (long or double.)
2471 if (names.isInitOrVNew(sym.name) && currentOwner.hasOuterInstance()) {
2472 // Sometimes anonymous classes don't have an outer
2473 // instance, however, there is no reliable way to tell so
2474 // we never strip this$n
2475 if (!currentOwner.name.isEmpty())
2476 firstParamLvt += 1;
2477 }
2478
2479 if (sym.type != jvmType) {
2480 // reading the method attributes has caused the
2481 // symbol's type to be changed. (i.e. the Signature
2482 // attribute.) This may happen if there are hidden
2483 // (synthetic) parameters in the descriptor, but not
2484 // in the Signature. The position of these hidden
2485 // parameters is unspecified; for now, assume they are
2486 // at the beginning, and so skip over them. The
2487 // primary case for this is two hidden parameters
2488 // passed into Enum constructors.
2489 int skip = Code.width(jvmType.getParameterTypes())
2490 - Code.width(sym.type.getParameterTypes());
2491 firstParamLvt += skip;
2615 return syms.enterClass(currentModule, name, owner);
2616 }
2617
2618 /** Read contents of a given class symbol `c'. Both external and internal
2619 * versions of an inner class are read.
2620 */
2621 void readClass(ClassSymbol c) {
2622 ClassType ct = (ClassType)c.type;
2623
2624 // allocate scope for members
2625 c.members_field = WriteableScope.create(c);
2626
2627 // prepare type variable table
2628 typevars = typevars.dup(currentOwner);
2629 if (ct.getEnclosingType().hasTag(CLASS))
2630 enterTypevars(c.owner, ct.getEnclosingType());
2631
2632 // read flags, or skip if this is an inner class
2633 long f = nextChar();
2634 long flags = adjustClassFlags(f);
2635 if (c == syms.objectType.tsym) {
2636 flags &= ~IDENTITY_TYPE; // jlO lacks identity even while being a concrete class.
2637 }
2638 if ((flags & PRIMITIVE_CLASS) != 0) {
2639 if (!allowPrimitiveClasses || (flags & (FINAL | PRIMITIVE_CLASS | IDENTITY_TYPE)) != (FINAL | PRIMITIVE_CLASS)) {
2640 throw badClassFile("bad.access.flags", Flags.toString(flags));
2641 }
2642 }
2643 if ((flags & MODULE) == 0) {
2644 if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
2645 // read own class name and check that it matches
2646 currentModule = c.packge().modle;
2647 ClassSymbol self = poolReader.getClass(nextChar());
2648 if (c != self) {
2649 throw badClassFile("class.file.wrong.class",
2650 self.flatname);
2651 }
2652 } else {
2653 if (majorVersion < Version.V53.major) {
2654 throw badClassFile("anachronistic.module.info",
2655 Integer.toString(majorVersion),
2656 Integer.toString(minorVersion));
2657 }
2658 c.flags_field = flags;
2659 if (c.owner.kind != MDL) {
2660 throw badClassFile("module.info.definition.expected");
2661 }
2662 currentModule = (ModuleSymbol) c.owner;
2880 * Adjusting flags
2881 ***********************************************************************/
2882
2883 long adjustFieldFlags(long flags) {
2884 return flags;
2885 }
2886
2887 long adjustMethodFlags(long flags) {
2888 if ((flags & ACC_BRIDGE) != 0) {
2889 flags &= ~ACC_BRIDGE;
2890 flags |= BRIDGE;
2891 }
2892 if ((flags & ACC_VARARGS) != 0) {
2893 flags &= ~ACC_VARARGS;
2894 flags |= VARARGS;
2895 }
2896 return flags;
2897 }
2898
2899 long adjustClassFlags(long flags) {
2900 if ((flags & (ABSTRACT | INTERFACE | ACC_VALUE | ACC_MODULE)) == 0) {
2901 flags |= ACC_IDENTITY;
2902 }
2903 if ((flags & ACC_MODULE) != 0) {
2904 flags &= ~ACC_MODULE;
2905 flags |= MODULE;
2906 }
2907 if ((flags & ACC_PRIMITIVE) != 0) {
2908 flags &= ~ACC_PRIMITIVE;
2909 if (allowPrimitiveClasses) {
2910 flags |= PRIMITIVE_CLASS;
2911 }
2912 }
2913 if ((flags & ACC_VALUE) != 0) {
2914 flags &= ~ACC_VALUE;
2915 if (allowValueClasses) {
2916 flags |= VALUE_CLASS;
2917 }
2918 }
2919 if ((flags & ACC_IDENTITY) != 0) {
2920 flags &= ~ACC_IDENTITY;
2921 flags |= IDENTITY_TYPE;
2922 }
2923 return flags;
2924 }
2925
2926 /**
2927 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2928 * The attribute is only the last component of the original filename, so is unlikely
2929 * to be valid as is, so operations other than those to access the name throw
2930 * UnsupportedOperationException
2931 */
2932 private static class SourceFileObject implements JavaFileObject {
2933
2934 /** The file's name.
2935 */
2936 private final Name name;
2937
2938 public SourceFileObject(Name name) {
2939 this.name = name;
2940 }
2941
2942 @Override @DefinedBy(Api.COMPILER)
2943 public URI toUri() {
|