ClassReader.java revision 3348:080e6e093a70
11592Srgrimes/* 21592Srgrimes * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 31592Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41592Srgrimes * 51592Srgrimes * This code is free software; you can redistribute it and/or modify it 61592Srgrimes * under the terms of the GNU General Public License version 2 only, as 71592Srgrimes * published by the Free Software Foundation. Oracle designates this 81592Srgrimes * particular file as subject to the "Classpath" exception as provided 91592Srgrimes * by Oracle in the LICENSE file that accompanied this code. 101592Srgrimes * 111592Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT 121592Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131592Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 141592Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 151592Srgrimes * accompanied this code). 161592Srgrimes * 171592Srgrimes * You should have received a copy of the GNU General Public License version 181592Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 191592Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 201592Srgrimes * 211592Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 221592Srgrimes * or visit www.oracle.com if you need additional information or have any 231592Srgrimes * questions. 241592Srgrimes */ 251592Srgrimes 261592Srgrimespackage com.sun.tools.javac.jvm; 271592Srgrimes 281592Srgrimesimport java.io.*; 291592Srgrimesimport java.net.URI; 301592Srgrimesimport java.net.URISyntaxException; 311592Srgrimesimport java.nio.CharBuffer; 321592Srgrimesimport java.util.Arrays; 331592Srgrimesimport java.util.EnumSet; 341592Srgrimesimport java.util.HashMap; 3529917Smarkmimport java.util.HashSet; 361592Srgrimesimport java.util.Map; 371592Srgrimesimport java.util.Set; 381592Srgrimes 391592Srgrimesimport javax.lang.model.element.Modifier; 401592Srgrimesimport javax.lang.model.element.NestingKind; 4131490Scharnierimport javax.tools.JavaFileManager; 4229917Smarkmimport javax.tools.JavaFileObject; 4331490Scharnier 4431490Scharnierimport com.sun.tools.javac.comp.Annotate; 4550476Speterimport com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter; 461592Srgrimesimport com.sun.tools.javac.code.*; 471592Srgrimesimport com.sun.tools.javac.code.Directive.*; 481592Srgrimesimport com.sun.tools.javac.code.Lint.LintCategory; 491592Srgrimesimport com.sun.tools.javac.code.Scope.WriteableScope; 501592Srgrimesimport com.sun.tools.javac.code.Symbol.*; 511592Srgrimesimport com.sun.tools.javac.code.Symtab; 521592Srgrimesimport com.sun.tools.javac.code.Type.*; 531592Srgrimesimport com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; 541592Srgrimesimport com.sun.tools.javac.file.BaseFileManager; 551592Srgrimesimport com.sun.tools.javac.file.PathFileObject; 561592Srgrimesimport com.sun.tools.javac.jvm.ClassFile.NameAndType; 571592Srgrimesimport com.sun.tools.javac.jvm.ClassFile.Version; 581592Srgrimesimport com.sun.tools.javac.util.*; 591592Srgrimesimport com.sun.tools.javac.util.DefinedBy.Api; 601592Srgrimesimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 6122454Simp 621592Srgrimesimport static com.sun.tools.javac.code.Flags.*; 6322454Simpimport static com.sun.tools.javac.code.Kinds.Kind.*; 6441445Sdgimport static com.sun.tools.javac.code.TypeTag.ARRAY; 651592Srgrimesimport static com.sun.tools.javac.code.TypeTag.CLASS; 661592Srgrimesimport static com.sun.tools.javac.code.TypeTag.TYPEVAR; 671592Srgrimesimport static com.sun.tools.javac.jvm.ClassFile.*; 681592Srgrimesimport static com.sun.tools.javac.jvm.ClassFile.Version.*; 691592Srgrimes 7045393Sbrianimport static com.sun.tools.javac.main.Option.*; 711592Srgrimes 721592Srgrimes/** This class provides operations to read a classfile into an internal 731592Srgrimes * representation. The internal representation is anchored in a 741592Srgrimes * ClassSymbol which contains in its scope symbol representations 751592Srgrimes * for all other definitions in the classfile. Top-level Classes themselves 761592Srgrimes * appear as members of the scopes of PackageSymbols. 771592Srgrimes * 781592Srgrimes * <p><b>This is NOT part of any supported API. 7925099Sdavidn * If you write code that depends on this, you do so at your own risk. 8025099Sdavidn * This code and its internal interfaces are subject to change or 8125099Sdavidn * deletion without notice.</b> 821592Srgrimes */ 8356590Sshinpublic class ClassReader { 8456590Sshin /** The context key for the class reader. */ 8556590Sshin protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>(); 8656590Sshin 8756590Sshin public static final int INITIAL_BUFFER_SIZE = 0x0fff0; 881592Srgrimes 891592Srgrimes private final Annotate annotate; 901592Srgrimes 9141445Sdg /** Switch: verbose output. 9251433Smarkm */ 9351433Smarkm boolean verbose; 9451433Smarkm 951592Srgrimes /** Switch: read constant pool and code sections. This switch is initially 9656590Sshin * set to false but can be turned on from outside. 9756590Sshin */ 9856590Sshin public boolean readAllOfClassFile = false; 9956590Sshin 10056590Sshin /** Switch: allow simplified varargs. 10156590Sshin */ 10256590Sshin boolean allowSimplifiedVarargs; 10356590Sshin 10456590Sshin /** Switch: allow modules. 10556590Sshin */ 10656590Sshin boolean allowModules; 10756590Sshin 10856590Sshin /** Lint option: warn about classfile issues 10956590Sshin */ 1101592Srgrimes boolean lintClassfile; 1111592Srgrimes 1121592Srgrimes /** Switch: preserve parameter names from the variable table. 1131592Srgrimes */ 1141592Srgrimes public boolean saveParameterNames; 1151592Srgrimes 11651433Smarkm /** 11751433Smarkm * The currently selected profile. 1181592Srgrimes */ 1191592Srgrimes public final Profile profile; 12051433Smarkm 12151433Smarkm /** The log to use for verbose output 1221592Srgrimes */ 1231592Srgrimes final Log log; 1241592Srgrimes 1251592Srgrimes /** The symbol table. */ 1261592Srgrimes Symtab syms; 1271592Srgrimes 1281592Srgrimes Types types; 1291592Srgrimes 13056590Sshin /** The name table. */ 1311592Srgrimes final Names names; 1321592Srgrimes 1331592Srgrimes /** Access to files 1341592Srgrimes */ 13524349Simp private final JavaFileManager fileManager; 1361592Srgrimes 1371592Srgrimes /** Factory for diagnostics 13841860Speter */ 1391592Srgrimes JCDiagnostic.Factory diagFactory; 1401592Srgrimes 1411592Srgrimes /** The current scope where type variables are entered. 1421592Srgrimes */ 1431592Srgrimes protected WriteableScope typevars; 1441592Srgrimes 1451592Srgrimes private List<InterimUsesDirective> interimUses = List.nil(); 1461592Srgrimes private List<InterimProvidesDirective> interimProvides = List.nil(); 1471592Srgrimes 1481592Srgrimes /** The path name of the class file currently being read. 1491592Srgrimes */ 1501592Srgrimes protected JavaFileObject currentClassFile = null; 15141445Sdg 15241445Sdg /** The class or method currently being read. 15341445Sdg */ 1541592Srgrimes protected Symbol currentOwner = null; 1551592Srgrimes 1561592Srgrimes /** The module containing the class currently being read. 1571592Srgrimes */ 1581592Srgrimes protected ModuleSymbol currentModule = null; 1591592Srgrimes 1601592Srgrimes /** The buffer containing the currently read class file. 1611592Srgrimes */ 1621592Srgrimes byte[] buf = new byte[INITIAL_BUFFER_SIZE]; 1631592Srgrimes 1641592Srgrimes /** The current input pointer. 1651592Srgrimes */ 1661592Srgrimes protected int bp; 16751433Smarkm 1681592Srgrimes /** The objects of the constant pool. 1691592Srgrimes */ 1701592Srgrimes Object[] poolObj; 1711592Srgrimes 1721592Srgrimes /** For every constant pool entry, an index into buf where the 1731592Srgrimes * defining section of the entry is found. 1741592Srgrimes */ 1751592Srgrimes int[] poolIdx; 17635728Srnordier 1771592Srgrimes /** The major version number of the class file being read. */ 1781592Srgrimes int majorVersion; 1791592Srgrimes /** The minor version number of the class file being read. */ 1801592Srgrimes int minorVersion; 1811592Srgrimes 1821592Srgrimes /** A table to hold the constant pool indices for method parameter 1831592Srgrimes * names, as given in LocalVariableTable attributes. 1841592Srgrimes */ 1851592Srgrimes int[] parameterNameIndices; 1861592Srgrimes 18741445Sdg /** 18841445Sdg * Whether or not any parameter names have been found. 18941445Sdg */ 19056590Sshin boolean haveParameterNameIndices; 1911592Srgrimes 19229917Smarkm /** Set this to false every time we start reading a method 1931592Srgrimes * and are saving parameter names. Set it to true when we see 1941592Srgrimes * MethodParameters, if it's set when we see a LocalVariableTable, 1951592Srgrimes * then we ignore the parameter names from the LVT. 1961592Srgrimes */ 1971592Srgrimes boolean sawMethodParameters; 1981592Srgrimes 1991592Srgrimes /** 2001592Srgrimes * The set of attribute names for which warnings have been generated for the current class 2011592Srgrimes */ 2021592Srgrimes Set<Name> warnedAttrs = new HashSet<>(); 2031592Srgrimes 2041592Srgrimes /** 20556590Sshin * The prototype @Target Attribute.Compound if this class is an annotation annotated with 2061592Srgrimes * @Target 2071592Srgrimes */ 2081592Srgrimes CompoundAnnotationProxy target; 2091592Srgrimes 2101592Srgrimes /** 2111592Srgrimes * The prototype @Repetable Attribute.Compound if this class is an annotation annotated with 2121592Srgrimes * @Repeatable 21345393Sbrian */ 2141592Srgrimes CompoundAnnotationProxy repeatable; 2151592Srgrimes 21656590Sshin /** Get the ClassReader instance for this invocation. */ 21756590Sshin public static ClassReader instance(Context context) { 21856590Sshin ClassReader instance = context.get(classReaderKey); 21951433Smarkm if (instance == null) 22051433Smarkm instance = new ClassReader(context); 22151433Smarkm return instance; 22251433Smarkm } 22351433Smarkm 22425099Sdavidn /** Construct a new class reader. */ 22525099Sdavidn protected ClassReader(Context context) { 22625099Sdavidn context.put(classReaderKey, this); 2271592Srgrimes annotate = Annotate.instance(context); 2281592Srgrimes names = Names.instance(context); 2291592Srgrimes syms = Symtab.instance(context); 2301592Srgrimes types = Types.instance(context); 23156590Sshin fileManager = context.get(JavaFileManager.class); 23256590Sshin if (fileManager == null) 23356590Sshin throw new AssertionError("FileManager initialization error"); 23456590Sshin diagFactory = JCDiagnostic.Factory.instance(context); 23556590Sshin 23656590Sshin log = Log.instance(context); 23756590Sshin 2381592Srgrimes Options options = Options.instance(context); 2391592Srgrimes verbose = options.isSet(VERBOSE); 24056590Sshin 24156590Sshin Source source = Source.instance(context); 24256590Sshin allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 24356590Sshin allowModules = source.allowModules(); 2441592Srgrimes 24556590Sshin saveParameterNames = options.isSet("save-parameter-names"); 24622454Simp 24722454Simp profile = Profile.instance(context); 2481592Srgrimes 2491592Srgrimes typevars = WriteableScope.create(syms.noSymbol); 2501592Srgrimes 2511592Srgrimes lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE); 2521592Srgrimes 2531592Srgrimes initAttributeReaders(); 2541592Srgrimes } 2551592Srgrimes 25622454Simp /** Add member to class unless it is synthetic. 25722454Simp */ 25822454Simp private void enterMember(ClassSymbol c, Symbol sym) { 25922454Simp // Synthetic members are not entered -- reason lost to history (optimization?). 26031490Scharnier // Lambda methods must be entered because they may have inner classes (which reference them) 26156590Sshin if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) 26222454Simp c.members_field.enter(sym); 26322454Simp } 26422454Simp 26522454Simp/************************************************************************ 26622454Simp * Error Diagnoses 26722454Simp ***********************************************************************/ 2681592Srgrimes 2691592Srgrimes public ClassFinder.BadClassFile badClassFile(String key, Object... args) { 2701592Srgrimes return new ClassFinder.BadClassFile ( 2711592Srgrimes currentOwner.enclClass(), 2721592Srgrimes currentClassFile, 27356590Sshin diagFactory.fragment(key, args), 27456590Sshin diagFactory); 27551433Smarkm } 27651433Smarkm 27756590Sshin public ClassFinder.BadEnclosingMethodAttr badEnclosingMethod(Object... args) { 27856590Sshin return new ClassFinder.BadEnclosingMethodAttr ( 27951433Smarkm currentOwner.enclClass(), 28051433Smarkm currentClassFile, 2811592Srgrimes diagFactory.fragment("bad.enclosing.method", args), 2821592Srgrimes diagFactory); 2831592Srgrimes } 28441860Speter 2851592Srgrimes/************************************************************************ 2861592Srgrimes * Buffer Access 2871592Srgrimes ***********************************************************************/ 2881592Srgrimes 2891592Srgrimes /** Read a character. 2901592Srgrimes */ 2911592Srgrimes char nextChar() { 2921592Srgrimes return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF)); 29341860Speter } 2941592Srgrimes 2951592Srgrimes /** Read a byte. 2961592Srgrimes */ 2971592Srgrimes int nextByte() { 2981592Srgrimes return buf[bp++] & 0xFF; 2991592Srgrimes } 3001592Srgrimes 30156590Sshin /** Read an integer. 3021592Srgrimes */ 3031592Srgrimes int nextInt() { 3041592Srgrimes return 3051592Srgrimes ((buf[bp++] & 0xFF) << 24) + 30651433Smarkm ((buf[bp++] & 0xFF) << 16) + 30751433Smarkm ((buf[bp++] & 0xFF) << 8) + 30851433Smarkm (buf[bp++] & 0xFF); 30951433Smarkm } 31056590Sshin 31151433Smarkm /** Extract a character at position bp from buf. 31251433Smarkm */ 31351433Smarkm char getChar(int bp) { 31456590Sshin return 31556758Sshin (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF)); 3161592Srgrimes } 3171592Srgrimes 3181592Srgrimes /** Extract an integer at position bp from buf. 3191592Srgrimes */ 3201592Srgrimes int getInt(int bp) { 3211592Srgrimes return 32256590Sshin ((buf[bp] & 0xFF) << 24) + 32356590Sshin ((buf[bp+1] & 0xFF) << 16) + 32456590Sshin ((buf[bp+2] & 0xFF) << 8) + 32545393Sbrian (buf[bp+3] & 0xFF); 3261592Srgrimes } 3271592Srgrimes 32856590Sshin 32951433Smarkm /** Extract a long integer at position bp from buf. 33051433Smarkm */ 33151433Smarkm long getLong(int bp) { 33251433Smarkm DataInputStream bufin = 33351433Smarkm new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 33451433Smarkm try { 3351592Srgrimes return bufin.readLong(); 3361592Srgrimes } catch (IOException e) { 33751433Smarkm throw new AssertionError(e); 33851433Smarkm } 33951433Smarkm } 34051433Smarkm 34151433Smarkm /** Extract a float at position bp from buf. 34251433Smarkm */ 34351433Smarkm float getFloat(int bp) { 3441592Srgrimes DataInputStream bufin = 34551433Smarkm new DataInputStream(new ByteArrayInputStream(buf, bp, 4)); 3461592Srgrimes try { 3471592Srgrimes return bufin.readFloat(); 3481592Srgrimes } catch (IOException e) { 3491592Srgrimes throw new AssertionError(e); 3501592Srgrimes } 3511592Srgrimes } 3521592Srgrimes 3531592Srgrimes /** Extract a double at position bp from buf. 35445393Sbrian */ 3551592Srgrimes double getDouble(int bp) { 3561592Srgrimes DataInputStream bufin = 3571592Srgrimes new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 3581592Srgrimes try { 35925099Sdavidn return bufin.readDouble(); 36025674Sdavidn } catch (IOException e) { 36125099Sdavidn throw new AssertionError(e); 3621592Srgrimes } 36325099Sdavidn } 36425099Sdavidn 36525099Sdavidn/************************************************************************ 36625099Sdavidn * Constant Pool Access 36725099Sdavidn ***********************************************************************/ 36845393Sbrian 36925099Sdavidn /** Index all constant pool entries, writing their start addresses into 37025099Sdavidn * poolIdx. 37125099Sdavidn */ 37225099Sdavidn void indexPool() { 3731592Srgrimes poolIdx = new int[nextChar()]; 3741592Srgrimes poolObj = new Object[poolIdx.length]; 3751592Srgrimes int i = 1; 3761592Srgrimes while (i < poolIdx.length) { 37745393Sbrian poolIdx[i++] = bp; 3781592Srgrimes byte tag = buf[bp++]; 3791592Srgrimes switch (tag) { 3801592Srgrimes case CONSTANT_Utf8: case CONSTANT_Unicode: { 38125099Sdavidn int len = nextChar(); 38225099Sdavidn bp = bp + len; 3831592Srgrimes break; 3841592Srgrimes } 38551433Smarkm case CONSTANT_Class: 38651433Smarkm case CONSTANT_String: 38751433Smarkm case CONSTANT_MethodType: 38851433Smarkm bp = bp + 2; 38951433Smarkm break; 39051433Smarkm case CONSTANT_MethodHandle: 3911592Srgrimes bp = bp + 3; 39251433Smarkm break; 39351433Smarkm case CONSTANT_Fieldref: 39451433Smarkm case CONSTANT_Methodref: 39551433Smarkm case CONSTANT_InterfaceMethodref: 39651433Smarkm case CONSTANT_NameandType: 39751433Smarkm case CONSTANT_Integer: 39851433Smarkm case CONSTANT_Float: 3991592Srgrimes case CONSTANT_InvokeDynamic: 4001592Srgrimes bp = bp + 4; 40110401Smpp break; 40262643Sbsd case CONSTANT_Long: 40362643Sbsd case CONSTANT_Double: 4041592Srgrimes bp = bp + 8; 4051592Srgrimes i++; 4061592Srgrimes break; 40745393Sbrian default: 4081592Srgrimes throw badClassFile("bad.const.pool.tag.at", 4091592Srgrimes Byte.toString(tag), 4101592Srgrimes Integer.toString(bp -1)); 4111592Srgrimes } 41245393Sbrian } 4131592Srgrimes } 4141592Srgrimes 41527516Swosch /** Read constant pool entry at start address i, use pool as a cache. 41645393Sbrian */ 4171592Srgrimes Object readPool(int i) { 4181592Srgrimes Object result = poolObj[i]; 4191592Srgrimes if (result != null) return result; 4201592Srgrimes 4211592Srgrimes int index = poolIdx[i]; 4221592Srgrimes if (index == 0) return null; 4231592Srgrimes 42425099Sdavidn byte tag = buf[index]; 42556590Sshin switch (tag) { 42625099Sdavidn case CONSTANT_Utf8: 42725099Sdavidn poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1)); 42856590Sshin break; 42925099Sdavidn case CONSTANT_Unicode: 43025099Sdavidn throw badClassFile("unicode.str.not.supported"); 43125099Sdavidn case CONSTANT_Class: 43225099Sdavidn poolObj[i] = readClassOrType(getChar(index + 1)); 43325099Sdavidn break; 43445393Sbrian case CONSTANT_String: 43525099Sdavidn // FIXME: (footprint) do not use toString here 43627516Swosch poolObj[i] = readName(getChar(index + 1)).toString(); 43725099Sdavidn break; 43825099Sdavidn case CONSTANT_Fieldref: { 43925099Sdavidn ClassSymbol owner = readClassSymbol(getChar(index + 1)); 44025099Sdavidn NameAndType nt = readNameAndType(getChar(index + 3)); 44125099Sdavidn poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner); 44225099Sdavidn break; 44325099Sdavidn } 44425099Sdavidn case CONSTANT_Methodref: 44512240Speter case CONSTANT_InterfaceMethodref: { 44612240Speter ClassSymbol owner = readClassSymbol(getChar(index + 1)); 44712240Speter NameAndType nt = readNameAndType(getChar(index + 3)); 44812240Speter poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner); 44912240Speter break; 4501592Srgrimes } 4511592Srgrimes case CONSTANT_NameandType: 4521592Srgrimes poolObj[i] = new NameAndType( 4531592Srgrimes readName(getChar(index + 1)), 4541592Srgrimes readType(getChar(index + 3)), types); 4551592Srgrimes break; 4561592Srgrimes case CONSTANT_Integer: 4571592Srgrimes poolObj[i] = getInt(index + 1); 4581592Srgrimes break; 4591592Srgrimes case CONSTANT_Float: 4601592Srgrimes poolObj[i] = Float.valueOf(getFloat(index + 1)); 4611592Srgrimes break; 4621592Srgrimes case CONSTANT_Long: 4631592Srgrimes poolObj[i] = Long.valueOf(getLong(index + 1)); 4641592Srgrimes break; 4651592Srgrimes case CONSTANT_Double: 4661592Srgrimes poolObj[i] = Double.valueOf(getDouble(index + 1)); 4671592Srgrimes break; 4681592Srgrimes case CONSTANT_MethodHandle: 4691592Srgrimes skipBytes(4); 4701592Srgrimes break; 4711592Srgrimes case CONSTANT_MethodType: 4721592Srgrimes skipBytes(3); 4731592Srgrimes break; 4741592Srgrimes case CONSTANT_InvokeDynamic: 4751592Srgrimes skipBytes(5); 4761592Srgrimes break; 4771592Srgrimes default: 4781592Srgrimes throw badClassFile("bad.const.pool.tag", Byte.toString(tag)); 4791592Srgrimes } 4801592Srgrimes return poolObj[i]; 4811592Srgrimes } 48229917Smarkm 48329917Smarkm /** Read signature and convert to type. 4841592Srgrimes */ 4851592Srgrimes Type readType(int i) { 4861592Srgrimes int index = poolIdx[i]; 4871592Srgrimes return sigToType(buf, index + 3, getChar(index + 1)); 4881592Srgrimes } 4891592Srgrimes 4901592Srgrimes /** If name is an array type or class signature, return the 4911592Srgrimes * corresponding type; otherwise return a ClassSymbol with given name. 4921592Srgrimes */ 4931592Srgrimes Object readClassOrType(int i) { 4941592Srgrimes int index = poolIdx[i]; 4951592Srgrimes int len = getChar(index + 1); 4961592Srgrimes int start = index + 3; 4971592Srgrimes Assert.check(buf[start] == '[' || buf[start + len - 1] != ';'); 4981592Srgrimes // by the above assertion, the following test can be 4991592Srgrimes // simplified to (buf[start] == '[') 5001592Srgrimes return (buf[start] == '[' || buf[start + len - 1] == ';') 5011592Srgrimes ? (Object)sigToType(buf, start, len) 5021592Srgrimes : (Object)enterClass(names.fromUtf(internalize(buf, start, 5031592Srgrimes len))); 5041592Srgrimes } 5051592Srgrimes 5061592Srgrimes /** Read signature and convert to type parameters. 5071592Srgrimes */ 5081592Srgrimes List<Type> readTypeParams(int i) { 5091592Srgrimes int index = poolIdx[i]; 5101592Srgrimes return sigToTypeParams(buf, index + 3, getChar(index + 1)); 5111592Srgrimes } 5121592Srgrimes 5131592Srgrimes /** Read class entry. 5141592Srgrimes */ 5151592Srgrimes ClassSymbol readClassSymbol(int i) { 5161592Srgrimes Object obj = readPool(i); 5171592Srgrimes if (obj != null && !(obj instanceof ClassSymbol)) 5181592Srgrimes throw badClassFile("bad.const.pool.entry", 5191592Srgrimes currentClassFile.toString(), 5201592Srgrimes "CONSTANT_Class_info", i); 5211592Srgrimes return (ClassSymbol)obj; 5221592Srgrimes } 5231592Srgrimes 5241592Srgrimes Name readClassName(int i) { 5251592Srgrimes int index = poolIdx[i]; 5261592Srgrimes if (index == 0) return null; 5271592Srgrimes byte tag = buf[index]; 5281592Srgrimes if (tag != CONSTANT_Class) { 5291592Srgrimes throw badClassFile("bad.const.pool.entry", 5301592Srgrimes currentClassFile.toString(), 5311592Srgrimes "CONSTANT_Class_info", i); 5321592Srgrimes } 53329917Smarkm int nameIndex = poolIdx[getChar(index + 1)]; 53429917Smarkm int len = getChar(nameIndex + 1); 5351592Srgrimes int start = nameIndex + 3; 5361592Srgrimes if (buf[start] == '[' || buf[start + len - 1] == ';') 5371592Srgrimes throw badClassFile("wrong class name"); //TODO: proper diagnostics 5381592Srgrimes return names.fromUtf(internalize(buf, start, len)); 5391592Srgrimes } 5401592Srgrimes 5411592Srgrimes /** Read name. 5421592Srgrimes */ 5431592Srgrimes Name readName(int i) { 5441592Srgrimes Object obj = readPool(i); 5451592Srgrimes if (obj != null && !(obj instanceof Name)) 5461592Srgrimes throw badClassFile("bad.const.pool.entry", 5471592Srgrimes currentClassFile.toString(), 5481592Srgrimes "CONSTANT_Utf8_info or CONSTANT_String_info", i); 5491592Srgrimes return (Name)obj; 5501592Srgrimes } 5511592Srgrimes 5521592Srgrimes /** Read name and type. 55329917Smarkm */ 55429917Smarkm NameAndType readNameAndType(int i) { 5551592Srgrimes Object obj = readPool(i); 5561592Srgrimes if (obj != null && !(obj instanceof NameAndType)) 5571592Srgrimes throw badClassFile("bad.const.pool.entry", 5581592Srgrimes currentClassFile.toString(), 5591592Srgrimes "CONSTANT_NameAndType_info", i); 5601592Srgrimes return (NameAndType)obj; 5611592Srgrimes } 5621592Srgrimes 5631592Srgrimes /** Read the class name of a module-info.class file. 5641592Srgrimes * The name is stored in a CONSTANT_Class entry, where the 5651592Srgrimes * class name is of the form module-name.module-info. 5661592Srgrimes */ 5671592Srgrimes Name readModuleInfoName(int i) { 5681592Srgrimes int classIndex = poolIdx[i]; 56929917Smarkm if (buf[classIndex] == CONSTANT_Class) { 57029917Smarkm int utf8Index = poolIdx[getChar(classIndex + 1)]; 57129917Smarkm if (buf[utf8Index] == CONSTANT_Utf8) { 5721592Srgrimes int len = getChar(utf8Index + 1); 5731592Srgrimes int start = utf8Index + 3; 5741592Srgrimes return names.fromUtf(internalize(buf, start, len)); 5751592Srgrimes } 57629917Smarkm } 57729917Smarkm throw badClassFile("bad.module-info.name"); 57829917Smarkm } 5791592Srgrimes 5801592Srgrimes /** Read requires_flags. 5811592Srgrimes */ 5821592Srgrimes Set<RequiresFlag> readRequiresFlags(int flags) { 5831592Srgrimes Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class); 5841592Srgrimes for (RequiresFlag f: RequiresFlag.values()) { 5851592Srgrimes if ((flags & f.value) != 0) 5861592Srgrimes set.add(f); 5871592Srgrimes } 5881592Srgrimes return set; 5891592Srgrimes } 5901592Srgrimes 5911592Srgrimes/************************************************************************ 5921592Srgrimes * Reading Types 5931592Srgrimes ***********************************************************************/ 5941592Srgrimes 5951592Srgrimes /** The unread portion of the currently read type is 5961592Srgrimes * signature[sigp..siglimit-1]. 5971592Srgrimes */ 5981592Srgrimes byte[] signature; 5991592Srgrimes int sigp; 6001592Srgrimes int siglimit; 6011592Srgrimes boolean sigEnterPhase = false; 6021592Srgrimes 6031592Srgrimes /** Convert signature to type, where signature is a byte array segment. 6041592Srgrimes */ 6051592Srgrimes Type sigToType(byte[] sig, int offset, int len) { 6061592Srgrimes signature = sig; 6071592Srgrimes sigp = offset; 6081592Srgrimes siglimit = offset + len; 6091592Srgrimes return sigToType(); 6101592Srgrimes } 6111592Srgrimes 6121592Srgrimes /** Convert signature to type, where signature is implicit. 6131592Srgrimes */ 6141592Srgrimes Type sigToType() { 6151592Srgrimes switch ((char) signature[sigp]) { 6161592Srgrimes case 'T': 6171592Srgrimes sigp++; 6181592Srgrimes int start = sigp; 6191592Srgrimes while (signature[sigp] != ';') sigp++; 6201592Srgrimes sigp++; 62125099Sdavidn return sigEnterPhase 62225099Sdavidn ? Type.noType 62325099Sdavidn : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start)); 62425099Sdavidn case '+': { 62525099Sdavidn sigp++; 62625099Sdavidn Type t = sigToType(); 62725099Sdavidn return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass); 62825099Sdavidn } 62925099Sdavidn case '*': 63025099Sdavidn sigp++; 63125099Sdavidn return new WildcardType(syms.objectType, BoundKind.UNBOUND, 6321592Srgrimes syms.boundClass); 6331592Srgrimes case '-': { 6341592Srgrimes sigp++; 63545393Sbrian Type t = sigToType(); 6361592Srgrimes return new WildcardType(t, BoundKind.SUPER, syms.boundClass); 6371592Srgrimes } 6381592Srgrimes case 'B': 6391592Srgrimes sigp++; 6401592Srgrimes return syms.byteType; 6411592Srgrimes case 'C': 6421592Srgrimes sigp++; 6431592Srgrimes return syms.charType; 6441592Srgrimes case 'D': 6451592Srgrimes sigp++; 6461592Srgrimes return syms.doubleType; 6471592Srgrimes case 'F': 6481592Srgrimes sigp++; 6491592Srgrimes return syms.floatType; 6501592Srgrimes case 'I': 6511592Srgrimes sigp++; 6521592Srgrimes return syms.intType; 6531592Srgrimes case 'J': 6541592Srgrimes sigp++; 6551592Srgrimes return syms.longType; 6561592Srgrimes case 'L': 6571592Srgrimes { 6581592Srgrimes // int oldsigp = sigp; 6591592Srgrimes Type t = classSigToType(); 6601592Srgrimes if (sigp < siglimit && signature[sigp] == '.') 6611592Srgrimes throw badClassFile("deprecated inner class signature syntax " + 6621592Srgrimes "(please recompile from source)"); 6631592Srgrimes /* 6641592Srgrimes System.err.println(" decoded " + 6651592Srgrimes new String(signature, oldsigp, sigp-oldsigp) + 6661592Srgrimes " => " + t + " outer " + t.outer()); 6671592Srgrimes */ 6681592Srgrimes return t; 6691592Srgrimes } 6701592Srgrimes case 'S': 6711592Srgrimes sigp++; 6721592Srgrimes return syms.shortType; 6731592Srgrimes case 'V': 6741592Srgrimes sigp++; 6751592Srgrimes return syms.voidType; 6761592Srgrimes case 'Z': 6771592Srgrimes sigp++; 6781592Srgrimes return syms.booleanType; 6791592Srgrimes case '[': 6801592Srgrimes sigp++; 6811592Srgrimes return new ArrayType(sigToType(), syms.arrayClass); 6821592Srgrimes case '(': 6831592Srgrimes sigp++; 6841592Srgrimes List<Type> argtypes = sigToTypes(')'); 6851592Srgrimes Type restype = sigToType(); 6861592Srgrimes List<Type> thrown = List.nil(); 6871592Srgrimes while (signature[sigp] == '^') { 6881592Srgrimes sigp++; 6891592Srgrimes thrown = thrown.prepend(sigToType()); 6901592Srgrimes } 6911592Srgrimes // if there is a typevar in the throws clause we should state it. 6921592Srgrimes for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) { 6931592Srgrimes if (l.head.hasTag(TYPEVAR)) { 6941592Srgrimes l.head.tsym.flags_field |= THROWS; 6951592Srgrimes } 6961592Srgrimes } 6971592Srgrimes return new MethodType(argtypes, 6981592Srgrimes restype, 6991592Srgrimes thrown.reverse(), 7001592Srgrimes syms.methodClass); 7011592Srgrimes case '<': 7021592Srgrimes typevars = typevars.dup(currentOwner); 7031592Srgrimes Type poly = new ForAll(sigToTypeParams(), sigToType()); 7041592Srgrimes typevars = typevars.leave(); 7051592Srgrimes return poly; 7061592Srgrimes default: 7071592Srgrimes throw badClassFile("bad.signature", 7081592Srgrimes Convert.utf2string(signature, sigp, 10)); 7091592Srgrimes } 7101592Srgrimes } 7111592Srgrimes 7121592Srgrimes byte[] signatureBuffer = new byte[0]; 7131592Srgrimes int sbp = 0; 71445422Sbrian /** Convert class signature to type, where signature is implicit. 71545422Sbrian */ 7161592Srgrimes Type classSigToType() { 7171592Srgrimes if (signature[sigp] != 'L') 7181592Srgrimes throw badClassFile("bad.class.signature", 7191592Srgrimes Convert.utf2string(signature, sigp, 10)); 7201592Srgrimes sigp++; 7211592Srgrimes Type outer = Type.noType; 7221592Srgrimes int startSbp = sbp; 7231592Srgrimes 7241592Srgrimes while (true) { 7251592Srgrimes final byte c = signature[sigp++]; 7261592Srgrimes switch (c) { 7271592Srgrimes 7281592Srgrimes case ';': { // end 7291592Srgrimes ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, 7301592Srgrimes startSbp, 7311592Srgrimes sbp - startSbp)); 7321592Srgrimes 7331592Srgrimes try { 7341592Srgrimes return (outer == Type.noType) ? 7351592Srgrimes t.erasure(types) : 7361592Srgrimes new ClassType(outer, List.<Type>nil(), t); 7371592Srgrimes } finally { 7381592Srgrimes sbp = startSbp; 7391592Srgrimes } 7401592Srgrimes } 7411592Srgrimes 7421592Srgrimes case '<': // generic arguments 7431592Srgrimes ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, 7441592Srgrimes startSbp, 7451592Srgrimes sbp - startSbp)); 7461592Srgrimes outer = new ClassType(outer, sigToTypes('>'), t) { 747 boolean completed = false; 748 @Override @DefinedBy(Api.LANGUAGE_MODEL) 749 public Type getEnclosingType() { 750 if (!completed) { 751 completed = true; 752 tsym.complete(); 753 Type enclosingType = tsym.type.getEnclosingType(); 754 if (enclosingType != Type.noType) { 755 List<Type> typeArgs = 756 super.getEnclosingType().allparams(); 757 List<Type> typeParams = 758 enclosingType.allparams(); 759 if (typeParams.length() != typeArgs.length()) { 760 // no "rare" types 761 super.setEnclosingType(types.erasure(enclosingType)); 762 } else { 763 super.setEnclosingType(types.subst(enclosingType, 764 typeParams, 765 typeArgs)); 766 } 767 } else { 768 super.setEnclosingType(Type.noType); 769 } 770 } 771 return super.getEnclosingType(); 772 } 773 @Override 774 public void setEnclosingType(Type outer) { 775 throw new UnsupportedOperationException(); 776 } 777 }; 778 switch (signature[sigp++]) { 779 case ';': 780 if (sigp < signature.length && signature[sigp] == '.') { 781 // support old-style GJC signatures 782 // The signature produced was 783 // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>; 784 // rather than say 785 // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>; 786 // so we skip past ".Lfoo/Outer$" 787 sigp += (sbp - startSbp) + // "foo/Outer" 788 3; // ".L" and "$" 789 signatureBuffer[sbp++] = (byte)'$'; 790 break; 791 } else { 792 sbp = startSbp; 793 return outer; 794 } 795 case '.': 796 signatureBuffer[sbp++] = (byte)'$'; 797 break; 798 default: 799 throw new AssertionError(signature[sigp-1]); 800 } 801 continue; 802 803 case '.': 804 //we have seen an enclosing non-generic class 805 if (outer != Type.noType) { 806 t = enterClass(names.fromUtf(signatureBuffer, 807 startSbp, 808 sbp - startSbp)); 809 outer = new ClassType(outer, List.<Type>nil(), t); 810 } 811 signatureBuffer[sbp++] = (byte)'$'; 812 continue; 813 case '/': 814 signatureBuffer[sbp++] = (byte)'.'; 815 continue; 816 default: 817 signatureBuffer[sbp++] = c; 818 continue; 819 } 820 } 821 } 822 823 /** Convert (implicit) signature to list of types 824 * until `terminator' is encountered. 825 */ 826 List<Type> sigToTypes(char terminator) { 827 List<Type> head = List.of(null); 828 List<Type> tail = head; 829 while (signature[sigp] != terminator) 830 tail = tail.setTail(List.of(sigToType())); 831 sigp++; 832 return head.tail; 833 } 834 835 /** Convert signature to type parameters, where signature is a byte 836 * array segment. 837 */ 838 List<Type> sigToTypeParams(byte[] sig, int offset, int len) { 839 signature = sig; 840 sigp = offset; 841 siglimit = offset + len; 842 return sigToTypeParams(); 843 } 844 845 /** Convert signature to type parameters, where signature is implicit. 846 */ 847 List<Type> sigToTypeParams() { 848 List<Type> tvars = List.nil(); 849 if (signature[sigp] == '<') { 850 sigp++; 851 int start = sigp; 852 sigEnterPhase = true; 853 while (signature[sigp] != '>') 854 tvars = tvars.prepend(sigToTypeParam()); 855 sigEnterPhase = false; 856 sigp = start; 857 while (signature[sigp] != '>') 858 sigToTypeParam(); 859 sigp++; 860 } 861 return tvars.reverse(); 862 } 863 864 /** Convert (implicit) signature to type parameter. 865 */ 866 Type sigToTypeParam() { 867 int start = sigp; 868 while (signature[sigp] != ':') sigp++; 869 Name name = names.fromUtf(signature, start, sigp - start); 870 TypeVar tvar; 871 if (sigEnterPhase) { 872 tvar = new TypeVar(name, currentOwner, syms.botType); 873 typevars.enter(tvar.tsym); 874 } else { 875 tvar = (TypeVar)findTypeVar(name); 876 } 877 List<Type> bounds = List.nil(); 878 boolean allInterfaces = false; 879 if (signature[sigp] == ':' && signature[sigp+1] == ':') { 880 sigp++; 881 allInterfaces = true; 882 } 883 while (signature[sigp] == ':') { 884 sigp++; 885 bounds = bounds.prepend(sigToType()); 886 } 887 if (!sigEnterPhase) { 888 types.setBounds(tvar, bounds.reverse(), allInterfaces); 889 } 890 return tvar; 891 } 892 893 /** Find type variable with given name in `typevars' scope. 894 */ 895 Type findTypeVar(Name name) { 896 Symbol s = typevars.findFirst(name); 897 if (s != null) { 898 return s.type; 899 } else { 900 if (readingClassAttr) { 901 // While reading the class attribute, the supertypes 902 // might refer to a type variable from an enclosing element 903 // (method or class). 904 // If the type variable is defined in the enclosing class, 905 // we can actually find it in 906 // currentOwner.owner.type.getTypeArguments() 907 // However, until we have read the enclosing method attribute 908 // we don't know for sure if this owner is correct. It could 909 // be a method and there is no way to tell before reading the 910 // enclosing method attribute. 911 TypeVar t = new TypeVar(name, currentOwner, syms.botType); 912 missingTypeVariables = missingTypeVariables.prepend(t); 913 // System.err.println("Missing type var " + name); 914 return t; 915 } 916 throw badClassFile("undecl.type.var", name); 917 } 918 } 919 920/************************************************************************ 921 * Reading Attributes 922 ***********************************************************************/ 923 924 protected enum AttributeKind { CLASS, MEMBER } 925 926 protected abstract class AttributeReader { 927 protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) { 928 this.name = name; 929 this.version = version; 930 this.kinds = kinds; 931 } 932 933 protected boolean accepts(AttributeKind kind) { 934 if (kinds.contains(kind)) { 935 if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor)) 936 return true; 937 938 if (lintClassfile && !warnedAttrs.contains(name)) { 939 JavaFileObject prev = log.useSource(currentClassFile); 940 try { 941 log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr", 942 name, version.major, version.minor, majorVersion, minorVersion); 943 } finally { 944 log.useSource(prev); 945 } 946 warnedAttrs.add(name); 947 } 948 } 949 return false; 950 } 951 952 protected abstract void read(Symbol sym, int attrLen); 953 954 protected final Name name; 955 protected final ClassFile.Version version; 956 protected final Set<AttributeKind> kinds; 957 } 958 959 protected Set<AttributeKind> CLASS_ATTRIBUTE = 960 EnumSet.of(AttributeKind.CLASS); 961 protected Set<AttributeKind> MEMBER_ATTRIBUTE = 962 EnumSet.of(AttributeKind.MEMBER); 963 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE = 964 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER); 965 966 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>(); 967 968 private void initAttributeReaders() { 969 AttributeReader[] readers = { 970 // v45.3 attributes 971 972 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) { 973 protected void read(Symbol sym, int attrLen) { 974 if (readAllOfClassFile || saveParameterNames) 975 ((MethodSymbol)sym).code = readCode(sym); 976 else 977 bp = bp + attrLen; 978 } 979 }, 980 981 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) { 982 protected void read(Symbol sym, int attrLen) { 983 Object v = readPool(nextChar()); 984 // Ignore ConstantValue attribute if field not final. 985 if ((sym.flags() & FINAL) != 0) 986 ((VarSymbol) sym).setData(v); 987 } 988 }, 989 990 new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 991 protected void read(Symbol sym, int attrLen) { 992 sym.flags_field |= DEPRECATED; 993 } 994 }, 995 996 new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 997 protected void read(Symbol sym, int attrLen) { 998 int nexceptions = nextChar(); 999 List<Type> thrown = List.nil(); 1000 for (int j = 0; j < nexceptions; j++) 1001 thrown = thrown.prepend(readClassSymbol(nextChar()).type); 1002 if (sym.type.getThrownTypes().isEmpty()) 1003 sym.type.asMethodType().thrown = thrown.reverse(); 1004 } 1005 }, 1006 1007 new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) { 1008 protected void read(Symbol sym, int attrLen) { 1009 ClassSymbol c = (ClassSymbol) sym; 1010 if (currentModule.module_info == c) { 1011 //prevent entering the classes too soon: 1012 skipInnerClasses(); 1013 } else { 1014 readInnerClasses(c); 1015 } 1016 } 1017 }, 1018 1019 new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1020 protected void read(Symbol sym, int attrLen) { 1021 int newbp = bp + attrLen; 1022 if (saveParameterNames && !sawMethodParameters) { 1023 // Pick up parameter names from the variable table. 1024 // Parameter names are not explicitly identified as such, 1025 // but all parameter name entries in the LocalVariableTable 1026 // have a start_pc of 0. Therefore, we record the name 1027 // indicies of all slots with a start_pc of zero in the 1028 // parameterNameIndicies array. 1029 // Note that this implicitly honors the JVMS spec that 1030 // there may be more than one LocalVariableTable, and that 1031 // there is no specified ordering for the entries. 1032 int numEntries = nextChar(); 1033 for (int i = 0; i < numEntries; i++) { 1034 int start_pc = nextChar(); 1035 int length = nextChar(); 1036 int nameIndex = nextChar(); 1037 int sigIndex = nextChar(); 1038 int register = nextChar(); 1039 if (start_pc == 0) { 1040 // ensure array large enough 1041 if (register >= parameterNameIndices.length) { 1042 int newSize = Math.max(register, parameterNameIndices.length + 8); 1043 parameterNameIndices = 1044 Arrays.copyOf(parameterNameIndices, newSize); 1045 } 1046 parameterNameIndices[register] = nameIndex; 1047 haveParameterNameIndices = true; 1048 } 1049 } 1050 } 1051 bp = newbp; 1052 } 1053 }, 1054 1055 new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) { 1056 protected void read(Symbol sym, int attrLen) { 1057 ClassSymbol c = (ClassSymbol) sym; 1058 Name n = readName(nextChar()); 1059 c.sourcefile = new SourceFileObject(n, c.flatname); 1060 // If the class is a toplevel class, originating from a Java source file, 1061 // but the class name does not match the file name, then it is 1062 // an auxiliary class. 1063 String sn = n.toString(); 1064 if (c.owner.kind == PCK && 1065 sn.endsWith(".java") && 1066 !sn.equals(c.name.toString()+".java")) { 1067 c.flags_field |= AUXILIARY; 1068 } 1069 } 1070 }, 1071 1072 new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1073 protected void read(Symbol sym, int attrLen) { 1074 sym.flags_field |= SYNTHETIC; 1075 } 1076 }, 1077 1078 // standard v49 attributes 1079 1080 new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) { 1081 protected void read(Symbol sym, int attrLen) { 1082 int newbp = bp + attrLen; 1083 readEnclosingMethodAttr(sym); 1084 bp = newbp; 1085 } 1086 }, 1087 1088 new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1089 protected void read(Symbol sym, int attrLen) { 1090 if (sym.kind == TYP) { 1091 ClassSymbol c = (ClassSymbol) sym; 1092 readingClassAttr = true; 1093 try { 1094 ClassType ct1 = (ClassType)c.type; 1095 Assert.check(c == currentOwner); 1096 ct1.typarams_field = readTypeParams(nextChar()); 1097 ct1.supertype_field = sigToType(); 1098 ListBuffer<Type> is = new ListBuffer<>(); 1099 while (sigp != siglimit) is.append(sigToType()); 1100 ct1.interfaces_field = is.toList(); 1101 } finally { 1102 readingClassAttr = false; 1103 } 1104 } else { 1105 List<Type> thrown = sym.type.getThrownTypes(); 1106 sym.type = readType(nextChar()); 1107 //- System.err.println(" # " + sym.type); 1108 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty()) 1109 sym.type.asMethodType().thrown = thrown; 1110 1111 } 1112 } 1113 }, 1114 1115 // v49 annotation attributes 1116 1117 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1118 protected void read(Symbol sym, int attrLen) { 1119 attachAnnotationDefault(sym); 1120 } 1121 }, 1122 1123 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1124 protected void read(Symbol sym, int attrLen) { 1125 attachAnnotations(sym); 1126 } 1127 }, 1128 1129 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1130 protected void read(Symbol sym, int attrLen) { 1131 attachParameterAnnotations(sym); 1132 } 1133 }, 1134 1135 new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1136 protected void read(Symbol sym, int attrLen) { 1137 attachAnnotations(sym); 1138 } 1139 }, 1140 1141 new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1142 protected void read(Symbol sym, int attrLen) { 1143 attachParameterAnnotations(sym); 1144 } 1145 }, 1146 1147 // additional "legacy" v49 attributes, superceded by flags 1148 1149 new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1150 protected void read(Symbol sym, int attrLen) { 1151 sym.flags_field |= ANNOTATION; 1152 } 1153 }, 1154 1155 new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) { 1156 protected void read(Symbol sym, int attrLen) { 1157 sym.flags_field |= BRIDGE; 1158 } 1159 }, 1160 1161 new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1162 protected void read(Symbol sym, int attrLen) { 1163 sym.flags_field |= ENUM; 1164 } 1165 }, 1166 1167 new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1168 protected void read(Symbol sym, int attrLen) { 1169 sym.flags_field |= VARARGS; 1170 } 1171 }, 1172 1173 new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1174 protected void read(Symbol sym, int attrLen) { 1175 attachTypeAnnotations(sym); 1176 } 1177 }, 1178 1179 new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1180 protected void read(Symbol sym, int attrLen) { 1181 attachTypeAnnotations(sym); 1182 } 1183 }, 1184 1185 // The following attributes for a Code attribute are not currently handled 1186 // StackMapTable 1187 // SourceDebugExtension 1188 // LineNumberTable 1189 // LocalVariableTypeTable 1190 1191 // standard v52 attributes 1192 1193 new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) { 1194 protected void read(Symbol sym, int attrlen) { 1195 int newbp = bp + attrlen; 1196 if (saveParameterNames) { 1197 sawMethodParameters = true; 1198 int numEntries = nextByte(); 1199 parameterNameIndices = new int[numEntries]; 1200 haveParameterNameIndices = true; 1201 for (int i = 0; i < numEntries; i++) { 1202 int nameIndex = nextChar(); 1203 int flags = nextChar(); 1204 parameterNameIndices[i] = nameIndex; 1205 } 1206 } 1207 bp = newbp; 1208 } 1209 }, 1210 1211 // standard v53 attributes 1212 1213 new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) { 1214 @Override 1215 protected boolean accepts(AttributeKind kind) { 1216 return super.accepts(kind) && allowModules; 1217 } 1218 protected void read(Symbol sym, int attrLen) { 1219 if (sym.kind == TYP && sym.owner.kind == MDL) { 1220 ModuleSymbol msym = (ModuleSymbol) sym.owner; 1221 ListBuffer<Directive> directives = new ListBuffer<>(); 1222 1223 ListBuffer<RequiresDirective> requires = new ListBuffer<>(); 1224 int nrequires = nextChar(); 1225 for (int i = 0; i < nrequires; i++) { 1226 Name name = readName(nextChar()); 1227 ModuleSymbol rsym = syms.enterModule(name); 1228 Set<RequiresFlag> flags = readRequiresFlags(nextChar()); 1229 requires.add(new RequiresDirective(rsym, flags)); 1230 } 1231 msym.requires = requires.toList(); 1232 directives.addAll(msym.requires); 1233 1234 ListBuffer<ExportsDirective> exports = new ListBuffer<>(); 1235 int nexports = nextChar(); 1236 for (int i = 0; i < nexports; i++) { 1237 Name n = readName(nextChar()); 1238 PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n))); 1239 int nto = nextChar(); 1240 List<ModuleSymbol> to; 1241 if (nto == 0) { 1242 to = null; 1243 } else { 1244 ListBuffer<ModuleSymbol> lb = new ListBuffer<>(); 1245 for (int t = 0; t < nto; t++) 1246 lb.append(syms.enterModule(readName(nextChar()))); 1247 to = lb.toList(); 1248 } 1249 exports.add(new ExportsDirective(p, to)); 1250 } 1251 msym.exports = exports.toList(); 1252 directives.addAll(msym.exports); 1253 1254 msym.directives = directives.toList(); 1255 1256 ListBuffer<InterimUsesDirective> uses = new ListBuffer<>(); 1257 int nuses = nextChar(); 1258 for (int i = 0; i < nuses; i++) { 1259 Name srvc = readClassName(nextChar()); 1260 uses.add(new InterimUsesDirective(srvc)); 1261 } 1262 interimUses = uses.toList(); 1263 1264 ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>(); 1265 int nprovides = nextChar(); 1266 for (int i = 0; i < nprovides; i++) { 1267 Name srvc = readClassName(nextChar()); 1268 Name impl = readClassName(nextChar()); 1269 provides.add(new InterimProvidesDirective(srvc, impl)); 1270 } 1271 interimProvides = provides.toList(); 1272 } 1273 } 1274 }, 1275 1276 new AttributeReader(names.Version, V53, CLASS_ATTRIBUTE) { 1277 @Override 1278 protected boolean accepts(AttributeKind kind) { 1279 return super.accepts(kind) && allowModules; 1280 } 1281 protected void read(Symbol sym, int attrLen) { 1282 if (sym.kind == TYP && sym.owner.kind == MDL) { 1283 ModuleSymbol msym = (ModuleSymbol) sym.owner; 1284 msym.version = readName(nextChar()); 1285 } 1286 } 1287 }, 1288 }; 1289 1290 for (AttributeReader r: readers) 1291 attributeReaders.put(r.name, r); 1292 } 1293 1294 protected void readEnclosingMethodAttr(Symbol sym) { 1295 // sym is a nested class with an "Enclosing Method" attribute 1296 // remove sym from it's current owners scope and place it in 1297 // the scope specified by the attribute 1298 sym.owner.members().remove(sym); 1299 ClassSymbol self = (ClassSymbol)sym; 1300 ClassSymbol c = readClassSymbol(nextChar()); 1301 NameAndType nt = readNameAndType(nextChar()); 1302 1303 if (c.members_field == null) 1304 throw badClassFile("bad.enclosing.class", self, c); 1305 1306 MethodSymbol m = findMethod(nt, c.members_field, self.flags()); 1307 if (nt != null && m == null) 1308 throw badEnclosingMethod(self); 1309 1310 self.name = simpleBinaryName(self.flatname, c.flatname) ; 1311 self.owner = m != null ? m : c; 1312 if (self.name.isEmpty()) 1313 self.fullname = names.empty; 1314 else 1315 self.fullname = ClassSymbol.formFullName(self.name, self.owner); 1316 1317 if (m != null) { 1318 ((ClassType)sym.type).setEnclosingType(m.type); 1319 } else if ((self.flags_field & STATIC) == 0) { 1320 ((ClassType)sym.type).setEnclosingType(c.type); 1321 } else { 1322 ((ClassType)sym.type).setEnclosingType(Type.noType); 1323 } 1324 enterTypevars(self); 1325 if (!missingTypeVariables.isEmpty()) { 1326 ListBuffer<Type> typeVars = new ListBuffer<>(); 1327 for (Type typevar : missingTypeVariables) { 1328 typeVars.append(findTypeVar(typevar.tsym.name)); 1329 } 1330 foundTypeVariables = typeVars.toList(); 1331 } else { 1332 foundTypeVariables = List.nil(); 1333 } 1334 } 1335 1336 // See java.lang.Class 1337 private Name simpleBinaryName(Name self, Name enclosing) { 1338 String simpleBinaryName = self.toString().substring(enclosing.toString().length()); 1339 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$') 1340 throw badClassFile("bad.enclosing.method", self); 1341 int index = 1; 1342 while (index < simpleBinaryName.length() && 1343 isAsciiDigit(simpleBinaryName.charAt(index))) 1344 index++; 1345 return names.fromString(simpleBinaryName.substring(index)); 1346 } 1347 1348 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) { 1349 if (nt == null) 1350 return null; 1351 1352 MethodType type = nt.uniqueType.type.asMethodType(); 1353 1354 for (Symbol sym : scope.getSymbolsByName(nt.name)) { 1355 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type)) 1356 return (MethodSymbol)sym; 1357 } 1358 1359 if (nt.name != names.init) 1360 // not a constructor 1361 return null; 1362 if ((flags & INTERFACE) != 0) 1363 // no enclosing instance 1364 return null; 1365 if (nt.uniqueType.type.getParameterTypes().isEmpty()) 1366 // no parameters 1367 return null; 1368 1369 // A constructor of an inner class. 1370 // Remove the first argument (the enclosing instance) 1371 nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail, 1372 nt.uniqueType.type.getReturnType(), 1373 nt.uniqueType.type.getThrownTypes(), 1374 syms.methodClass)); 1375 // Try searching again 1376 return findMethod(nt, scope, flags); 1377 } 1378 1379 /** Similar to Types.isSameType but avoids completion */ 1380 private boolean isSameBinaryType(MethodType mt1, MethodType mt2) { 1381 List<Type> types1 = types.erasure(mt1.getParameterTypes()) 1382 .prepend(types.erasure(mt1.getReturnType())); 1383 List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType()); 1384 while (!types1.isEmpty() && !types2.isEmpty()) { 1385 if (types1.head.tsym != types2.head.tsym) 1386 return false; 1387 types1 = types1.tail; 1388 types2 = types2.tail; 1389 } 1390 return types1.isEmpty() && types2.isEmpty(); 1391 } 1392 1393 /** 1394 * Character.isDigit answers <tt>true</tt> to some non-ascii 1395 * digits. This one does not. <b>copied from java.lang.Class</b> 1396 */ 1397 private static boolean isAsciiDigit(char c) { 1398 return '0' <= c && c <= '9'; 1399 } 1400 1401 /** Read member attributes. 1402 */ 1403 void readMemberAttrs(Symbol sym) { 1404 readAttrs(sym, AttributeKind.MEMBER); 1405 } 1406 1407 void readAttrs(Symbol sym, AttributeKind kind) { 1408 char ac = nextChar(); 1409 for (int i = 0; i < ac; i++) { 1410 Name attrName = readName(nextChar()); 1411 int attrLen = nextInt(); 1412 AttributeReader r = attributeReaders.get(attrName); 1413 if (r != null && r.accepts(kind)) 1414 r.read(sym, attrLen); 1415 else { 1416 bp = bp + attrLen; 1417 } 1418 } 1419 } 1420 1421 private boolean readingClassAttr = false; 1422 private List<Type> missingTypeVariables = List.nil(); 1423 private List<Type> foundTypeVariables = List.nil(); 1424 1425 /** Read class attributes. 1426 */ 1427 void readClassAttrs(ClassSymbol c) { 1428 readAttrs(c, AttributeKind.CLASS); 1429 } 1430 1431 /** Read code block. 1432 */ 1433 Code readCode(Symbol owner) { 1434 nextChar(); // max_stack 1435 nextChar(); // max_locals 1436 final int code_length = nextInt(); 1437 bp += code_length; 1438 final char exception_table_length = nextChar(); 1439 bp += exception_table_length * 8; 1440 readMemberAttrs(owner); 1441 return null; 1442 } 1443 1444/************************************************************************ 1445 * Reading Java-language annotations 1446 ***********************************************************************/ 1447 1448 /** Attach annotations. 1449 */ 1450 void attachAnnotations(final Symbol sym) { 1451 int numAttributes = nextChar(); 1452 if (numAttributes != 0) { 1453 ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>(); 1454 for (int i = 0; i<numAttributes; i++) { 1455 CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1456 1457 if (proxy.type.tsym == syms.proprietaryType.tsym) 1458 sym.flags_field |= PROPRIETARY; 1459 else if (proxy.type.tsym == syms.profileType.tsym) { 1460 if (profile != Profile.DEFAULT) { 1461 for (Pair<Name,Attribute> v: proxy.values) { 1462 if (v.fst == names.value && v.snd instanceof Attribute.Constant) { 1463 Attribute.Constant c = (Attribute.Constant) v.snd; 1464 if (c.type == syms.intType && ((Integer) c.value) > profile.value) { 1465 sym.flags_field |= NOT_IN_PROFILE; 1466 } 1467 } 1468 } 1469 } 1470 } else { 1471 if (proxy.type.tsym == syms.annotationTargetType.tsym) { 1472 target = proxy; 1473 } else if (proxy.type.tsym == syms.repeatableType.tsym) { 1474 repeatable = proxy; 1475 } 1476 1477 proxies.append(proxy); 1478 } 1479 } 1480 annotate.normal(new AnnotationCompleter(sym, proxies.toList())); 1481 } 1482 } 1483 1484 /** Attach parameter annotations. 1485 */ 1486 void attachParameterAnnotations(final Symbol method) { 1487 final MethodSymbol meth = (MethodSymbol)method; 1488 int numParameters = buf[bp++] & 0xFF; 1489 List<VarSymbol> parameters = meth.params(); 1490 int pnum = 0; 1491 while (parameters.tail != null) { 1492 attachAnnotations(parameters.head); 1493 parameters = parameters.tail; 1494 pnum++; 1495 } 1496 if (pnum != numParameters) { 1497 throw badClassFile("bad.runtime.invisible.param.annotations", meth); 1498 } 1499 } 1500 1501 void attachTypeAnnotations(final Symbol sym) { 1502 int numAttributes = nextChar(); 1503 if (numAttributes != 0) { 1504 ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>(); 1505 for (int i = 0; i < numAttributes; i++) 1506 proxies.append(readTypeAnnotation()); 1507 annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); 1508 } 1509 } 1510 1511 /** Attach the default value for an annotation element. 1512 */ 1513 void attachAnnotationDefault(final Symbol sym) { 1514 final MethodSymbol meth = (MethodSymbol)sym; // only on methods 1515 final Attribute value = readAttributeValue(); 1516 1517 // The default value is set later during annotation. It might 1518 // be the case that the Symbol sym is annotated _after_ the 1519 // repeating instances that depend on this default value, 1520 // because of this we set an interim value that tells us this 1521 // element (most likely) has a default. 1522 // 1523 // Set interim value for now, reset just before we do this 1524 // properly at annotate time. 1525 meth.defaultValue = value; 1526 annotate.normal(new AnnotationDefaultCompleter(meth, value)); 1527 } 1528 1529 Type readTypeOrClassSymbol(int i) { 1530 // support preliminary jsr175-format class files 1531 if (buf[poolIdx[i]] == CONSTANT_Class) 1532 return readClassSymbol(i).type; 1533 return readType(i); 1534 } 1535 Type readEnumType(int i) { 1536 // support preliminary jsr175-format class files 1537 int index = poolIdx[i]; 1538 int length = getChar(index + 1); 1539 if (buf[index + length + 2] != ';') 1540 return enterClass(readName(i)).type; 1541 return readType(i); 1542 } 1543 1544 CompoundAnnotationProxy readCompoundAnnotation() { 1545 Type t = readTypeOrClassSymbol(nextChar()); 1546 int numFields = nextChar(); 1547 ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>(); 1548 for (int i=0; i<numFields; i++) { 1549 Name name = readName(nextChar()); 1550 Attribute value = readAttributeValue(); 1551 pairs.append(new Pair<>(name, value)); 1552 } 1553 return new CompoundAnnotationProxy(t, pairs.toList()); 1554 } 1555 1556 TypeAnnotationProxy readTypeAnnotation() { 1557 TypeAnnotationPosition position = readPosition(); 1558 CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1559 1560 return new TypeAnnotationProxy(proxy, position); 1561 } 1562 1563 TypeAnnotationPosition readPosition() { 1564 int tag = nextByte(); // TargetType tag is a byte 1565 1566 if (!TargetType.isValidTargetTypeValue(tag)) 1567 throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); 1568 1569 TargetType type = TargetType.fromTargetTypeValue(tag); 1570 1571 switch (type) { 1572 // instanceof 1573 case INSTANCEOF: { 1574 final int offset = nextChar(); 1575 final TypeAnnotationPosition position = 1576 TypeAnnotationPosition.instanceOf(readTypePath()); 1577 position.offset = offset; 1578 return position; 1579 } 1580 // new expression 1581 case NEW: { 1582 final int offset = nextChar(); 1583 final TypeAnnotationPosition position = 1584 TypeAnnotationPosition.newObj(readTypePath()); 1585 position.offset = offset; 1586 return position; 1587 } 1588 // constructor/method reference receiver 1589 case CONSTRUCTOR_REFERENCE: { 1590 final int offset = nextChar(); 1591 final TypeAnnotationPosition position = 1592 TypeAnnotationPosition.constructorRef(readTypePath()); 1593 position.offset = offset; 1594 return position; 1595 } 1596 case METHOD_REFERENCE: { 1597 final int offset = nextChar(); 1598 final TypeAnnotationPosition position = 1599 TypeAnnotationPosition.methodRef(readTypePath()); 1600 position.offset = offset; 1601 return position; 1602 } 1603 // local variable 1604 case LOCAL_VARIABLE: { 1605 final int table_length = nextChar(); 1606 final int[] newLvarOffset = new int[table_length]; 1607 final int[] newLvarLength = new int[table_length]; 1608 final int[] newLvarIndex = new int[table_length]; 1609 1610 for (int i = 0; i < table_length; ++i) { 1611 newLvarOffset[i] = nextChar(); 1612 newLvarLength[i] = nextChar(); 1613 newLvarIndex[i] = nextChar(); 1614 } 1615 1616 final TypeAnnotationPosition position = 1617 TypeAnnotationPosition.localVariable(readTypePath()); 1618 position.lvarOffset = newLvarOffset; 1619 position.lvarLength = newLvarLength; 1620 position.lvarIndex = newLvarIndex; 1621 return position; 1622 } 1623 // resource variable 1624 case RESOURCE_VARIABLE: { 1625 final int table_length = nextChar(); 1626 final int[] newLvarOffset = new int[table_length]; 1627 final int[] newLvarLength = new int[table_length]; 1628 final int[] newLvarIndex = new int[table_length]; 1629 1630 for (int i = 0; i < table_length; ++i) { 1631 newLvarOffset[i] = nextChar(); 1632 newLvarLength[i] = nextChar(); 1633 newLvarIndex[i] = nextChar(); 1634 } 1635 1636 final TypeAnnotationPosition position = 1637 TypeAnnotationPosition.resourceVariable(readTypePath()); 1638 position.lvarOffset = newLvarOffset; 1639 position.lvarLength = newLvarLength; 1640 position.lvarIndex = newLvarIndex; 1641 return position; 1642 } 1643 // exception parameter 1644 case EXCEPTION_PARAMETER: { 1645 final int exception_index = nextChar(); 1646 final TypeAnnotationPosition position = 1647 TypeAnnotationPosition.exceptionParameter(readTypePath()); 1648 position.setExceptionIndex(exception_index); 1649 return position; 1650 } 1651 // method receiver 1652 case METHOD_RECEIVER: 1653 return TypeAnnotationPosition.methodReceiver(readTypePath()); 1654 // type parameter 1655 case CLASS_TYPE_PARAMETER: { 1656 final int parameter_index = nextByte(); 1657 return TypeAnnotationPosition 1658 .typeParameter(readTypePath(), parameter_index); 1659 } 1660 case METHOD_TYPE_PARAMETER: { 1661 final int parameter_index = nextByte(); 1662 return TypeAnnotationPosition 1663 .methodTypeParameter(readTypePath(), parameter_index); 1664 } 1665 // type parameter bound 1666 case CLASS_TYPE_PARAMETER_BOUND: { 1667 final int parameter_index = nextByte(); 1668 final int bound_index = nextByte(); 1669 return TypeAnnotationPosition 1670 .typeParameterBound(readTypePath(), parameter_index, 1671 bound_index); 1672 } 1673 case METHOD_TYPE_PARAMETER_BOUND: { 1674 final int parameter_index = nextByte(); 1675 final int bound_index = nextByte(); 1676 return TypeAnnotationPosition 1677 .methodTypeParameterBound(readTypePath(), parameter_index, 1678 bound_index); 1679 } 1680 // class extends or implements clause 1681 case CLASS_EXTENDS: { 1682 final int type_index = nextChar(); 1683 return TypeAnnotationPosition.classExtends(readTypePath(), 1684 type_index); 1685 } 1686 // throws 1687 case THROWS: { 1688 final int type_index = nextChar(); 1689 return TypeAnnotationPosition.methodThrows(readTypePath(), 1690 type_index); 1691 } 1692 // method parameter 1693 case METHOD_FORMAL_PARAMETER: { 1694 final int parameter_index = nextByte(); 1695 return TypeAnnotationPosition.methodParameter(readTypePath(), 1696 parameter_index); 1697 } 1698 // type cast 1699 case CAST: { 1700 final int offset = nextChar(); 1701 final int type_index = nextByte(); 1702 final TypeAnnotationPosition position = 1703 TypeAnnotationPosition.typeCast(readTypePath(), type_index); 1704 position.offset = offset; 1705 return position; 1706 } 1707 // method/constructor/reference type argument 1708 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: { 1709 final int offset = nextChar(); 1710 final int type_index = nextByte(); 1711 final TypeAnnotationPosition position = TypeAnnotationPosition 1712 .constructorInvocationTypeArg(readTypePath(), type_index); 1713 position.offset = offset; 1714 return position; 1715 } 1716 case METHOD_INVOCATION_TYPE_ARGUMENT: { 1717 final int offset = nextChar(); 1718 final int type_index = nextByte(); 1719 final TypeAnnotationPosition position = TypeAnnotationPosition 1720 .methodInvocationTypeArg(readTypePath(), type_index); 1721 position.offset = offset; 1722 return position; 1723 } 1724 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: { 1725 final int offset = nextChar(); 1726 final int type_index = nextByte(); 1727 final TypeAnnotationPosition position = TypeAnnotationPosition 1728 .constructorRefTypeArg(readTypePath(), type_index); 1729 position.offset = offset; 1730 return position; 1731 } 1732 case METHOD_REFERENCE_TYPE_ARGUMENT: { 1733 final int offset = nextChar(); 1734 final int type_index = nextByte(); 1735 final TypeAnnotationPosition position = TypeAnnotationPosition 1736 .methodRefTypeArg(readTypePath(), type_index); 1737 position.offset = offset; 1738 return position; 1739 } 1740 // We don't need to worry about these 1741 case METHOD_RETURN: 1742 return TypeAnnotationPosition.methodReturn(readTypePath()); 1743 case FIELD: 1744 return TypeAnnotationPosition.field(readTypePath()); 1745 case UNKNOWN: 1746 throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); 1747 default: 1748 throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type); 1749 } 1750 } 1751 1752 List<TypeAnnotationPosition.TypePathEntry> readTypePath() { 1753 int len = nextByte(); 1754 ListBuffer<Integer> loc = new ListBuffer<>(); 1755 for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) 1756 loc = loc.append(nextByte()); 1757 1758 return TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); 1759 1760 } 1761 1762 Attribute readAttributeValue() { 1763 char c = (char) buf[bp++]; 1764 switch (c) { 1765 case 'B': 1766 return new Attribute.Constant(syms.byteType, readPool(nextChar())); 1767 case 'C': 1768 return new Attribute.Constant(syms.charType, readPool(nextChar())); 1769 case 'D': 1770 return new Attribute.Constant(syms.doubleType, readPool(nextChar())); 1771 case 'F': 1772 return new Attribute.Constant(syms.floatType, readPool(nextChar())); 1773 case 'I': 1774 return new Attribute.Constant(syms.intType, readPool(nextChar())); 1775 case 'J': 1776 return new Attribute.Constant(syms.longType, readPool(nextChar())); 1777 case 'S': 1778 return new Attribute.Constant(syms.shortType, readPool(nextChar())); 1779 case 'Z': 1780 return new Attribute.Constant(syms.booleanType, readPool(nextChar())); 1781 case 's': 1782 return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString()); 1783 case 'e': 1784 return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar())); 1785 case 'c': 1786 return new Attribute.Class(types, readTypeOrClassSymbol(nextChar())); 1787 case '[': { 1788 int n = nextChar(); 1789 ListBuffer<Attribute> l = new ListBuffer<>(); 1790 for (int i=0; i<n; i++) 1791 l.append(readAttributeValue()); 1792 return new ArrayAttributeProxy(l.toList()); 1793 } 1794 case '@': 1795 return readCompoundAnnotation(); 1796 default: 1797 throw new AssertionError("unknown annotation tag '" + c + "'"); 1798 } 1799 } 1800 1801 interface ProxyVisitor extends Attribute.Visitor { 1802 void visitEnumAttributeProxy(EnumAttributeProxy proxy); 1803 void visitArrayAttributeProxy(ArrayAttributeProxy proxy); 1804 void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy); 1805 } 1806 1807 static class EnumAttributeProxy extends Attribute { 1808 Type enumType; 1809 Name enumerator; 1810 public EnumAttributeProxy(Type enumType, Name enumerator) { 1811 super(null); 1812 this.enumType = enumType; 1813 this.enumerator = enumerator; 1814 } 1815 public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); } 1816 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1817 public String toString() { 1818 return "/*proxy enum*/" + enumType + "." + enumerator; 1819 } 1820 } 1821 1822 static class ArrayAttributeProxy extends Attribute { 1823 List<Attribute> values; 1824 ArrayAttributeProxy(List<Attribute> values) { 1825 super(null); 1826 this.values = values; 1827 } 1828 public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); } 1829 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1830 public String toString() { 1831 return "{" + values + "}"; 1832 } 1833 } 1834 1835 /** A temporary proxy representing a compound attribute. 1836 */ 1837 static class CompoundAnnotationProxy extends Attribute { 1838 final List<Pair<Name,Attribute>> values; 1839 public CompoundAnnotationProxy(Type type, 1840 List<Pair<Name,Attribute>> values) { 1841 super(type); 1842 this.values = values; 1843 } 1844 public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); } 1845 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1846 public String toString() { 1847 StringBuilder buf = new StringBuilder(); 1848 buf.append("@"); 1849 buf.append(type.tsym.getQualifiedName()); 1850 buf.append("/*proxy*/{"); 1851 boolean first = true; 1852 for (List<Pair<Name,Attribute>> v = values; 1853 v.nonEmpty(); v = v.tail) { 1854 Pair<Name,Attribute> value = v.head; 1855 if (!first) buf.append(","); 1856 first = false; 1857 buf.append(value.fst); 1858 buf.append("="); 1859 buf.append(value.snd); 1860 } 1861 buf.append("}"); 1862 return buf.toString(); 1863 } 1864 } 1865 1866 /** A temporary proxy representing a type annotation. 1867 */ 1868 static class TypeAnnotationProxy { 1869 final CompoundAnnotationProxy compound; 1870 final TypeAnnotationPosition position; 1871 public TypeAnnotationProxy(CompoundAnnotationProxy compound, 1872 TypeAnnotationPosition position) { 1873 this.compound = compound; 1874 this.position = position; 1875 } 1876 } 1877 1878 class AnnotationDeproxy implements ProxyVisitor { 1879 private ClassSymbol requestingOwner; 1880 1881 AnnotationDeproxy(ClassSymbol owner) { 1882 this.requestingOwner = owner; 1883 } 1884 1885 List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) { 1886 // also must fill in types!!!! 1887 ListBuffer<Attribute.Compound> buf = new ListBuffer<>(); 1888 for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) { 1889 buf.append(deproxyCompound(l.head)); 1890 } 1891 return buf.toList(); 1892 } 1893 1894 Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) { 1895 ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>(); 1896 for (List<Pair<Name,Attribute>> l = a.values; 1897 l.nonEmpty(); 1898 l = l.tail) { 1899 MethodSymbol meth = findAccessMethod(a.type, l.head.fst); 1900 buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd))); 1901 } 1902 return new Attribute.Compound(a.type, buf.toList()); 1903 } 1904 1905 MethodSymbol findAccessMethod(Type container, Name name) { 1906 CompletionFailure failure = null; 1907 try { 1908 for (Symbol sym : container.tsym.members().getSymbolsByName(name)) { 1909 if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0) 1910 return (MethodSymbol) sym; 1911 } 1912 } catch (CompletionFailure ex) { 1913 failure = ex; 1914 } 1915 // The method wasn't found: emit a warning and recover 1916 JavaFileObject prevSource = log.useSource(requestingOwner.classfile); 1917 try { 1918 if (lintClassfile) { 1919 if (failure == null) { 1920 log.warning("annotation.method.not.found", 1921 container, 1922 name); 1923 } else { 1924 log.warning("annotation.method.not.found.reason", 1925 container, 1926 name, 1927 failure.getDetailValue());//diagnostic, if present 1928 } 1929 } 1930 } finally { 1931 log.useSource(prevSource); 1932 } 1933 // Construct a new method type and symbol. Use bottom 1934 // type (typeof null) as return type because this type is 1935 // a subtype of all reference types and can be converted 1936 // to primitive types by unboxing. 1937 MethodType mt = new MethodType(List.<Type>nil(), 1938 syms.botType, 1939 List.<Type>nil(), 1940 syms.methodClass); 1941 return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym); 1942 } 1943 1944 Attribute result; 1945 Type type; 1946 Attribute deproxy(Type t, Attribute a) { 1947 Type oldType = type; 1948 try { 1949 type = t; 1950 a.accept(this); 1951 return result; 1952 } finally { 1953 type = oldType; 1954 } 1955 } 1956 1957 // implement Attribute.Visitor below 1958 1959 public void visitConstant(Attribute.Constant value) { 1960 // assert value.type == type; 1961 result = value; 1962 } 1963 1964 public void visitClass(Attribute.Class clazz) { 1965 result = clazz; 1966 } 1967 1968 public void visitEnum(Attribute.Enum e) { 1969 throw new AssertionError(); // shouldn't happen 1970 } 1971 1972 public void visitCompound(Attribute.Compound compound) { 1973 throw new AssertionError(); // shouldn't happen 1974 } 1975 1976 public void visitArray(Attribute.Array array) { 1977 throw new AssertionError(); // shouldn't happen 1978 } 1979 1980 public void visitError(Attribute.Error e) { 1981 throw new AssertionError(); // shouldn't happen 1982 } 1983 1984 public void visitEnumAttributeProxy(EnumAttributeProxy proxy) { 1985 // type.tsym.flatName() should == proxy.enumFlatName 1986 TypeSymbol enumTypeSym = proxy.enumType.tsym; 1987 VarSymbol enumerator = null; 1988 CompletionFailure failure = null; 1989 try { 1990 for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) { 1991 if (sym.kind == VAR) { 1992 enumerator = (VarSymbol)sym; 1993 break; 1994 } 1995 } 1996 } 1997 catch (CompletionFailure ex) { 1998 failure = ex; 1999 } 2000 if (enumerator == null) { 2001 if (failure != null) { 2002 log.warning("unknown.enum.constant.reason", 2003 currentClassFile, enumTypeSym, proxy.enumerator, 2004 failure.getDiagnostic()); 2005 } else { 2006 log.warning("unknown.enum.constant", 2007 currentClassFile, enumTypeSym, proxy.enumerator); 2008 } 2009 result = new Attribute.Enum(enumTypeSym.type, 2010 new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym)); 2011 } else { 2012 result = new Attribute.Enum(enumTypeSym.type, enumerator); 2013 } 2014 } 2015 2016 public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) { 2017 int length = proxy.values.length(); 2018 Attribute[] ats = new Attribute[length]; 2019 Type elemtype = types.elemtype(type); 2020 int i = 0; 2021 for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) { 2022 ats[i++] = deproxy(elemtype, p.head); 2023 } 2024 result = new Attribute.Array(type, ats); 2025 } 2026 2027 public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) { 2028 result = deproxyCompound(proxy); 2029 } 2030 } 2031 2032 class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable { 2033 final MethodSymbol sym; 2034 final Attribute value; 2035 final JavaFileObject classFile = currentClassFile; 2036 2037 AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) { 2038 super(currentOwner.kind == MTH 2039 ? currentOwner.enclClass() : (ClassSymbol)currentOwner); 2040 this.sym = sym; 2041 this.value = value; 2042 } 2043 2044 @Override 2045 public void run() { 2046 JavaFileObject previousClassFile = currentClassFile; 2047 try { 2048 // Reset the interim value set earlier in 2049 // attachAnnotationDefault(). 2050 sym.defaultValue = null; 2051 currentClassFile = classFile; 2052 sym.defaultValue = deproxy(sym.type.getReturnType(), value); 2053 } finally { 2054 currentClassFile = previousClassFile; 2055 } 2056 } 2057 2058 @Override 2059 public String toString() { 2060 return " ClassReader store default for " + sym.owner + "." + sym + " is " + value; 2061 } 2062 } 2063 2064 class AnnotationCompleter extends AnnotationDeproxy implements Runnable { 2065 final Symbol sym; 2066 final List<CompoundAnnotationProxy> l; 2067 final JavaFileObject classFile; 2068 2069 AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) { 2070 super(currentOwner.kind == MTH 2071 ? currentOwner.enclClass() : (ClassSymbol)currentOwner); 2072 this.sym = sym; 2073 this.l = l; 2074 this.classFile = currentClassFile; 2075 } 2076 2077 @Override 2078 public void run() { 2079 JavaFileObject previousClassFile = currentClassFile; 2080 try { 2081 currentClassFile = classFile; 2082 List<Attribute.Compound> newList = deproxyCompoundList(l); 2083 if (sym.annotationsPendingCompletion()) { 2084 sym.setDeclarationAttributes(newList); 2085 } else { 2086 sym.appendAttributes(newList); 2087 } 2088 } finally { 2089 currentClassFile = previousClassFile; 2090 } 2091 } 2092 2093 @Override 2094 public String toString() { 2095 return " ClassReader annotate " + sym.owner + "." + sym + " with " + l; 2096 } 2097 } 2098 2099 class TypeAnnotationCompleter extends AnnotationCompleter { 2100 2101 List<TypeAnnotationProxy> proxies; 2102 2103 TypeAnnotationCompleter(Symbol sym, 2104 List<TypeAnnotationProxy> proxies) { 2105 super(sym, List.<CompoundAnnotationProxy>nil()); 2106 this.proxies = proxies; 2107 } 2108 2109 List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) { 2110 ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>(); 2111 for (TypeAnnotationProxy proxy: proxies) { 2112 Attribute.Compound compound = deproxyCompound(proxy.compound); 2113 Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); 2114 buf.add(typeCompound); 2115 } 2116 return buf.toList(); 2117 } 2118 2119 @Override 2120 public void run() { 2121 JavaFileObject previousClassFile = currentClassFile; 2122 try { 2123 currentClassFile = classFile; 2124 List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies); 2125 sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes())); 2126 } finally { 2127 currentClassFile = previousClassFile; 2128 } 2129 } 2130 } 2131 2132 2133/************************************************************************ 2134 * Reading Symbols 2135 ***********************************************************************/ 2136 2137 /** Read a field. 2138 */ 2139 VarSymbol readField() { 2140 long flags = adjustFieldFlags(nextChar()); 2141 Name name = readName(nextChar()); 2142 Type type = readType(nextChar()); 2143 VarSymbol v = new VarSymbol(flags, name, type, currentOwner); 2144 readMemberAttrs(v); 2145 return v; 2146 } 2147 2148 /** Read a method. 2149 */ 2150 MethodSymbol readMethod() { 2151 long flags = adjustMethodFlags(nextChar()); 2152 Name name = readName(nextChar()); 2153 Type type = readType(nextChar()); 2154 if (currentOwner.isInterface() && 2155 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) { 2156 if (majorVersion > Version.V52.major || 2157 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) { 2158 if ((flags & STATIC) == 0) { 2159 currentOwner.flags_field |= DEFAULT; 2160 flags |= DEFAULT | ABSTRACT; 2161 } 2162 } else { 2163 //protect against ill-formed classfiles 2164 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface", 2165 Integer.toString(majorVersion), 2166 Integer.toString(minorVersion)); 2167 } 2168 } 2169 if (name == names.init && currentOwner.hasOuterInstance()) { 2170 // Sometimes anonymous classes don't have an outer 2171 // instance, however, there is no reliable way to tell so 2172 // we never strip this$n 2173 if (!currentOwner.name.isEmpty()) 2174 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()), 2175 type.getReturnType(), 2176 type.getThrownTypes(), 2177 syms.methodClass); 2178 } 2179 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); 2180 if (types.isSignaturePolymorphic(m)) { 2181 m.flags_field |= SIGNATURE_POLYMORPHIC; 2182 } 2183 if (saveParameterNames) 2184 initParameterNames(m); 2185 Symbol prevOwner = currentOwner; 2186 currentOwner = m; 2187 try { 2188 readMemberAttrs(m); 2189 } finally { 2190 currentOwner = prevOwner; 2191 } 2192 if (saveParameterNames) 2193 setParameterNames(m, type); 2194 2195 if ((flags & VARARGS) != 0) { 2196 final Type last = type.getParameterTypes().last(); 2197 if (last == null || !last.hasTag(ARRAY)) { 2198 m.flags_field &= ~VARARGS; 2199 throw badClassFile("malformed.vararg.method", m); 2200 } 2201 } 2202 2203 return m; 2204 } 2205 2206 private List<Type> adjustMethodParams(long flags, List<Type> args) { 2207 boolean isVarargs = (flags & VARARGS) != 0; 2208 if (isVarargs) { 2209 Type varargsElem = args.last(); 2210 ListBuffer<Type> adjustedArgs = new ListBuffer<>(); 2211 for (Type t : args) { 2212 adjustedArgs.append(t != varargsElem ? 2213 t : 2214 ((ArrayType)t).makeVarargs()); 2215 } 2216 args = adjustedArgs.toList(); 2217 } 2218 return args.tail; 2219 } 2220 2221 /** 2222 * Init the parameter names array. 2223 * Parameter names are currently inferred from the names in the 2224 * LocalVariableTable attributes of a Code attribute. 2225 * (Note: this means parameter names are currently not available for 2226 * methods without a Code attribute.) 2227 * This method initializes an array in which to store the name indexes 2228 * of parameter names found in LocalVariableTable attributes. It is 2229 * slightly supersized to allow for additional slots with a start_pc of 0. 2230 */ 2231 void initParameterNames(MethodSymbol sym) { 2232 // make allowance for synthetic parameters. 2233 final int excessSlots = 4; 2234 int expectedParameterSlots = 2235 Code.width(sym.type.getParameterTypes()) + excessSlots; 2236 if (parameterNameIndices == null 2237 || parameterNameIndices.length < expectedParameterSlots) { 2238 parameterNameIndices = new int[expectedParameterSlots]; 2239 } else 2240 Arrays.fill(parameterNameIndices, 0); 2241 haveParameterNameIndices = false; 2242 sawMethodParameters = false; 2243 } 2244 2245 /** 2246 * Set the parameter names for a symbol from the name index in the 2247 * parameterNameIndicies array. The type of the symbol may have changed 2248 * while reading the method attributes (see the Signature attribute). 2249 * This may be because of generic information or because anonymous 2250 * synthetic parameters were added. The original type (as read from 2251 * the method descriptor) is used to help guess the existence of 2252 * anonymous synthetic parameters. 2253 * On completion, sym.savedParameter names will either be null (if 2254 * no parameter names were found in the class file) or will be set to a 2255 * list of names, one per entry in sym.type.getParameterTypes, with 2256 * any missing names represented by the empty name. 2257 */ 2258 void setParameterNames(MethodSymbol sym, Type jvmType) { 2259 // if no names were found in the class file, there's nothing more to do 2260 if (!haveParameterNameIndices) 2261 return; 2262 // If we get parameter names from MethodParameters, then we 2263 // don't need to skip. 2264 int firstParam = 0; 2265 if (!sawMethodParameters) { 2266 firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; 2267 // the code in readMethod may have skipped the first 2268 // parameter when setting up the MethodType. If so, we 2269 // make a corresponding allowance here for the position of 2270 // the first parameter. Note that this assumes the 2271 // skipped parameter has a width of 1 -- i.e. it is not 2272 // a double width type (long or double.) 2273 if (sym.name == names.init && currentOwner.hasOuterInstance()) { 2274 // Sometimes anonymous classes don't have an outer 2275 // instance, however, there is no reliable way to tell so 2276 // we never strip this$n 2277 if (!currentOwner.name.isEmpty()) 2278 firstParam += 1; 2279 } 2280 2281 if (sym.type != jvmType) { 2282 // reading the method attributes has caused the 2283 // symbol's type to be changed. (i.e. the Signature 2284 // attribute.) This may happen if there are hidden 2285 // (synthetic) parameters in the descriptor, but not 2286 // in the Signature. The position of these hidden 2287 // parameters is unspecified; for now, assume they are 2288 // at the beginning, and so skip over them. The 2289 // primary case for this is two hidden parameters 2290 // passed into Enum constructors. 2291 int skip = Code.width(jvmType.getParameterTypes()) 2292 - Code.width(sym.type.getParameterTypes()); 2293 firstParam += skip; 2294 } 2295 } 2296 List<Name> paramNames = List.nil(); 2297 int index = firstParam; 2298 for (Type t: sym.type.getParameterTypes()) { 2299 int nameIdx = (index < parameterNameIndices.length 2300 ? parameterNameIndices[index] : 0); 2301 Name name = nameIdx == 0 ? names.empty : readName(nameIdx); 2302 paramNames = paramNames.prepend(name); 2303 index += Code.width(t); 2304 } 2305 sym.savedParameterNames = paramNames.reverse(); 2306 } 2307 2308 /** 2309 * skip n bytes 2310 */ 2311 void skipBytes(int n) { 2312 bp = bp + n; 2313 } 2314 2315 /** Skip a field or method 2316 */ 2317 void skipMember() { 2318 bp = bp + 6; 2319 char ac = nextChar(); 2320 for (int i = 0; i < ac; i++) { 2321 bp = bp + 2; 2322 int attrLen = nextInt(); 2323 bp = bp + attrLen; 2324 } 2325 } 2326 2327 void skipInnerClasses() { 2328 int n = nextChar(); 2329 for (int i = 0; i < n; i++) { 2330 nextChar(); 2331 nextChar(); 2332 nextChar(); 2333 nextChar(); 2334 } 2335 } 2336 2337 /** Enter type variables of this classtype and all enclosing ones in 2338 * `typevars'. 2339 */ 2340 protected void enterTypevars(Type t) { 2341 if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS)) 2342 enterTypevars(t.getEnclosingType()); 2343 for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) 2344 typevars.enter(xs.head.tsym); 2345 } 2346 2347 protected void enterTypevars(Symbol sym) { 2348 if (sym.owner.kind == MTH) { 2349 enterTypevars(sym.owner); 2350 enterTypevars(sym.owner.owner); 2351 } 2352 enterTypevars(sym.type); 2353 } 2354 2355 protected ClassSymbol enterClass(Name name) { 2356 return syms.enterClass(currentModule, name); 2357 } 2358 2359 protected ClassSymbol enterClass(Name name, TypeSymbol owner) { 2360 return syms.enterClass(currentModule, name, owner); 2361 } 2362 2363 /** Read contents of a given class symbol `c'. Both external and internal 2364 * versions of an inner class are read. 2365 */ 2366 void readClass(ClassSymbol c) { 2367 ClassType ct = (ClassType)c.type; 2368 2369 // allocate scope for members 2370 c.members_field = WriteableScope.create(c); 2371 2372 // prepare type variable table 2373 typevars = typevars.dup(currentOwner); 2374 if (ct.getEnclosingType().hasTag(CLASS)) 2375 enterTypevars(ct.getEnclosingType()); 2376 2377 // read flags, or skip if this is an inner class 2378 long f = nextChar(); 2379 long flags = adjustClassFlags(f); 2380 if ((flags & MODULE) == 0) { 2381 if (c.owner.kind == PCK) c.flags_field = flags; 2382 // read own class name and check that it matches 2383 currentModule = c.packge().modle; 2384 ClassSymbol self = readClassSymbol(nextChar()); 2385 if (c != self) { 2386 throw badClassFile("class.file.wrong.class", 2387 self.flatname); 2388 } 2389 } else { 2390 c.flags_field = flags; 2391 Name modInfoName = readModuleInfoName(nextChar()); 2392 if (c.owner.name == null) { 2393 syms.enterModule((ModuleSymbol) c.owner, Convert.packagePart(modInfoName)); 2394 } else { 2395 // TODO: validate name 2396 } 2397 currentModule = (ModuleSymbol) c.owner; 2398 } 2399 2400 // class attributes must be read before class 2401 // skip ahead to read class attributes 2402 int startbp = bp; 2403 nextChar(); 2404 char interfaceCount = nextChar(); 2405 bp += interfaceCount * 2; 2406 char fieldCount = nextChar(); 2407 for (int i = 0; i < fieldCount; i++) skipMember(); 2408 char methodCount = nextChar(); 2409 for (int i = 0; i < methodCount; i++) skipMember(); 2410 readClassAttrs(c); 2411 2412 if (readAllOfClassFile) { 2413 for (int i = 1; i < poolObj.length; i++) readPool(i); 2414 c.pool = new Pool(poolObj.length, poolObj, types); 2415 } 2416 2417 // reset and read rest of classinfo 2418 bp = startbp; 2419 int n = nextChar(); 2420 if (ct.supertype_field == null) 2421 ct.supertype_field = (n == 0) 2422 ? Type.noType 2423 : readClassSymbol(n).erasure(types); 2424 n = nextChar(); 2425 List<Type> is = List.nil(); 2426 for (int i = 0; i < n; i++) { 2427 Type _inter = readClassSymbol(nextChar()).erasure(types); 2428 is = is.prepend(_inter); 2429 } 2430 if (ct.interfaces_field == null) 2431 ct.interfaces_field = is.reverse(); 2432 2433 Assert.check(fieldCount == nextChar()); 2434 for (int i = 0; i < fieldCount; i++) enterMember(c, readField()); 2435 Assert.check(methodCount == nextChar()); 2436 for (int i = 0; i < methodCount; i++) enterMember(c, readMethod()); 2437 2438 typevars = typevars.leave(); 2439 } 2440 2441 /** Read inner class info. For each inner/outer pair allocate a 2442 * member class. 2443 */ 2444 void readInnerClasses(ClassSymbol c) { 2445 int n = nextChar(); 2446 for (int i = 0; i < n; i++) { 2447 nextChar(); // skip inner class symbol 2448 ClassSymbol outer = readClassSymbol(nextChar()); 2449 Name name = readName(nextChar()); 2450 if (name == null) name = names.empty; 2451 long flags = adjustClassFlags(nextChar()); 2452 if (outer != null) { // we have a member class 2453 if (name == names.empty) 2454 name = names.one; 2455 ClassSymbol member = enterClass(name, outer); 2456 if ((flags & STATIC) == 0) { 2457 ((ClassType)member.type).setEnclosingType(outer.type); 2458 if (member.erasure_field != null) 2459 ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type)); 2460 } 2461 if (c == outer) { 2462 member.flags_field = flags; 2463 enterMember(c, member); 2464 } 2465 } 2466 } 2467 } 2468 2469 /** Read a class definition from the bytes in buf. 2470 */ 2471 private void readClassBuffer(ClassSymbol c) throws IOException { 2472 int magic = nextInt(); 2473 if (magic != JAVA_MAGIC) 2474 throw badClassFile("illegal.start.of.class.file"); 2475 2476 minorVersion = nextChar(); 2477 majorVersion = nextChar(); 2478 int maxMajor = Version.MAX().major; 2479 int maxMinor = Version.MAX().minor; 2480 if (majorVersion > maxMajor || 2481 majorVersion * 1000 + minorVersion < 2482 Version.MIN().major * 1000 + Version.MIN().minor) { 2483 if (majorVersion == (maxMajor + 1)) 2484 log.warning("big.major.version", 2485 currentClassFile, 2486 majorVersion, 2487 maxMajor); 2488 else 2489 throw badClassFile("wrong.version", 2490 Integer.toString(majorVersion), 2491 Integer.toString(minorVersion), 2492 Integer.toString(maxMajor), 2493 Integer.toString(maxMinor)); 2494 } 2495 2496 indexPool(); 2497 if (signatureBuffer.length < bp) { 2498 int ns = Integer.highestOneBit(bp) << 1; 2499 signatureBuffer = new byte[ns]; 2500 } 2501 readClass(c); 2502 } 2503 2504 public void readClassFile(ClassSymbol c) { 2505 currentOwner = c; 2506 currentClassFile = c.classfile; 2507 warnedAttrs.clear(); 2508 filling = true; 2509 target = null; 2510 repeatable = null; 2511 try { 2512 bp = 0; 2513 buf = readInputStream(buf, c.classfile.openInputStream()); 2514 readClassBuffer(c); 2515 if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) { 2516 List<Type> missing = missingTypeVariables; 2517 List<Type> found = foundTypeVariables; 2518 missingTypeVariables = List.nil(); 2519 foundTypeVariables = List.nil(); 2520 filling = false; 2521 ClassType ct = (ClassType)currentOwner.type; 2522 ct.supertype_field = 2523 types.subst(ct.supertype_field, missing, found); 2524 ct.interfaces_field = 2525 types.subst(ct.interfaces_field, missing, found); 2526 } else if (missingTypeVariables.isEmpty() != 2527 foundTypeVariables.isEmpty()) { 2528 Name name = missingTypeVariables.head.tsym.name; 2529 throw badClassFile("undecl.type.var", name); 2530 } 2531 2532 if ((c.flags_field & Flags.ANNOTATION) != 0) { 2533 c.setAnnotationTypeMetadata(new AnnotationTypeMetadata(c, new CompleterDeproxy(c, target, repeatable))); 2534 } else { 2535 c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType()); 2536 } 2537 2538 if (c == currentModule.module_info) { 2539 if (interimUses.nonEmpty() || interimProvides.nonEmpty()) { 2540 Assert.check(currentModule.isCompleted()); 2541 currentModule.usesProvidesCompleter = 2542 new UsesProvidesCompleter(currentModule, interimUses, interimProvides); 2543 } else { 2544 currentModule.uses = List.nil(); 2545 currentModule.provides = List.nil(); 2546 } 2547 } 2548 } catch (IOException ex) { 2549 throw badClassFile("unable.to.access.file", ex.getMessage()); 2550 } catch (ArrayIndexOutOfBoundsException ex) { 2551 throw badClassFile("bad.class.file", c.flatname); 2552 } finally { 2553 interimUses = List.nil(); 2554 interimProvides = List.nil(); 2555 missingTypeVariables = List.nil(); 2556 foundTypeVariables = List.nil(); 2557 filling = false; 2558 } 2559 } 2560 // where 2561 private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException { 2562 try { 2563 buf = ensureCapacity(buf, s.available()); 2564 int r = s.read(buf); 2565 int bp = 0; 2566 while (r != -1) { 2567 bp += r; 2568 buf = ensureCapacity(buf, bp); 2569 r = s.read(buf, bp, buf.length - bp); 2570 } 2571 return buf; 2572 } finally { 2573 try { 2574 s.close(); 2575 } catch (IOException e) { 2576 /* Ignore any errors, as this stream may have already 2577 * thrown a related exception which is the one that 2578 * should be reported. 2579 */ 2580 } 2581 } 2582 } 2583 /* 2584 * ensureCapacity will increase the buffer as needed, taking note that 2585 * the new buffer will always be greater than the needed and never 2586 * exactly equal to the needed size or bp. If equal then the read (above) 2587 * will infinitely loop as buf.length - bp == 0. 2588 */ 2589 private static byte[] ensureCapacity(byte[] buf, int needed) { 2590 if (buf.length <= needed) { 2591 byte[] old = buf; 2592 buf = new byte[Integer.highestOneBit(needed) << 1]; 2593 System.arraycopy(old, 0, buf, 0, old.length); 2594 } 2595 return buf; 2596 } 2597 2598 /** We can only read a single class file at a time; this 2599 * flag keeps track of when we are currently reading a class 2600 * file. 2601 */ 2602 public boolean filling = false; 2603 2604/************************************************************************ 2605 * Adjusting flags 2606 ***********************************************************************/ 2607 2608 long adjustFieldFlags(long flags) { 2609 return flags; 2610 } 2611 2612 long adjustMethodFlags(long flags) { 2613 if ((flags & ACC_BRIDGE) != 0) { 2614 flags &= ~ACC_BRIDGE; 2615 flags |= BRIDGE; 2616 } 2617 if ((flags & ACC_VARARGS) != 0) { 2618 flags &= ~ACC_VARARGS; 2619 flags |= VARARGS; 2620 } 2621 return flags; 2622 } 2623 2624 long adjustClassFlags(long flags) { 2625 if ((flags & ACC_MODULE) != 0) { 2626 flags &= ~ACC_MODULE; 2627 flags |= MODULE; 2628 } 2629 return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded 2630 } 2631 2632 /** 2633 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile. 2634 * The attribute is only the last component of the original filename, so is unlikely 2635 * to be valid as is, so operations other than those to access the name throw 2636 * UnsupportedOperationException 2637 */ 2638 private static class SourceFileObject implements JavaFileObject { 2639 2640 /** The file's name. 2641 */ 2642 private final Name name; 2643 private final Name flatname; 2644 2645 public SourceFileObject(Name name, Name flatname) { 2646 this.name = name; 2647 this.flatname = flatname; 2648 } 2649 2650 @Override @DefinedBy(Api.COMPILER) 2651 public URI toUri() { 2652 try { 2653 return new URI(null, name.toString(), null); 2654 } catch (URISyntaxException e) { 2655 throw new PathFileObject.CannotCreateUriError(name.toString(), e); 2656 } 2657 } 2658 2659 @Override @DefinedBy(Api.COMPILER) 2660 public String getName() { 2661 return name.toString(); 2662 } 2663 2664 @Override @DefinedBy(Api.COMPILER) 2665 public JavaFileObject.Kind getKind() { 2666 return BaseFileManager.getKind(getName()); 2667 } 2668 2669 @Override @DefinedBy(Api.COMPILER) 2670 public InputStream openInputStream() { 2671 throw new UnsupportedOperationException(); 2672 } 2673 2674 @Override @DefinedBy(Api.COMPILER) 2675 public OutputStream openOutputStream() { 2676 throw new UnsupportedOperationException(); 2677 } 2678 2679 @Override @DefinedBy(Api.COMPILER) 2680 public CharBuffer getCharContent(boolean ignoreEncodingErrors) { 2681 throw new UnsupportedOperationException(); 2682 } 2683 2684 @Override @DefinedBy(Api.COMPILER) 2685 public Reader openReader(boolean ignoreEncodingErrors) { 2686 throw new UnsupportedOperationException(); 2687 } 2688 2689 @Override @DefinedBy(Api.COMPILER) 2690 public Writer openWriter() { 2691 throw new UnsupportedOperationException(); 2692 } 2693 2694 @Override @DefinedBy(Api.COMPILER) 2695 public long getLastModified() { 2696 throw new UnsupportedOperationException(); 2697 } 2698 2699 @Override @DefinedBy(Api.COMPILER) 2700 public boolean delete() { 2701 throw new UnsupportedOperationException(); 2702 } 2703 2704 @Override @DefinedBy(Api.COMPILER) 2705 public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { 2706 return true; // fail-safe mode 2707 } 2708 2709 @Override @DefinedBy(Api.COMPILER) 2710 public NestingKind getNestingKind() { 2711 return null; 2712 } 2713 2714 @Override @DefinedBy(Api.COMPILER) 2715 public Modifier getAccessLevel() { 2716 return null; 2717 } 2718 2719 /** 2720 * Check if two file objects are equal. 2721 * SourceFileObjects are just placeholder objects for the value of a 2722 * SourceFile attribute, and do not directly represent specific files. 2723 * Two SourceFileObjects are equal if their names are equal. 2724 */ 2725 @Override 2726 public boolean equals(Object other) { 2727 if (this == other) 2728 return true; 2729 2730 if (!(other instanceof SourceFileObject)) 2731 return false; 2732 2733 SourceFileObject o = (SourceFileObject) other; 2734 return name.equals(o.name); 2735 } 2736 2737 @Override 2738 public int hashCode() { 2739 return name.hashCode(); 2740 } 2741 } 2742 2743 private class CompleterDeproxy implements AnnotationTypeCompleter { 2744 ClassSymbol proxyOn; 2745 CompoundAnnotationProxy target; 2746 CompoundAnnotationProxy repeatable; 2747 2748 public CompleterDeproxy(ClassSymbol c, CompoundAnnotationProxy target, 2749 CompoundAnnotationProxy repeatable) 2750 { 2751 this.proxyOn = c; 2752 this.target = target; 2753 this.repeatable = repeatable; 2754 } 2755 2756 @Override 2757 public void complete(ClassSymbol sym) { 2758 Assert.check(proxyOn == sym); 2759 Attribute.Compound theTarget = null, theRepeatable = null; 2760 AnnotationDeproxy deproxy; 2761 2762 try { 2763 if (target != null) { 2764 deproxy = new AnnotationDeproxy(proxyOn); 2765 theTarget = deproxy.deproxyCompound(target); 2766 } 2767 2768 if (repeatable != null) { 2769 deproxy = new AnnotationDeproxy(proxyOn); 2770 theRepeatable = deproxy.deproxyCompound(repeatable); 2771 } 2772 } catch (Exception e) { 2773 throw new CompletionFailure(sym, e.getMessage()); 2774 } 2775 2776 sym.getAnnotationTypeMetadata().setTarget(theTarget); 2777 sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable); 2778 } 2779 } 2780 2781 private static final class InterimUsesDirective { 2782 public final Name service; 2783 2784 public InterimUsesDirective(Name service) { 2785 this.service = service; 2786 } 2787 2788 } 2789 2790 private static final class InterimProvidesDirective { 2791 public final Name service; 2792 public final Name impl; 2793 2794 public InterimProvidesDirective(Name service, Name impl) { 2795 this.service = service; 2796 this.impl = impl; 2797 } 2798 2799 } 2800 2801 private final class UsesProvidesCompleter implements Completer { 2802 private final ModuleSymbol currentModule; 2803 private final List<InterimUsesDirective> interimUsesCopy; 2804 private final List<InterimProvidesDirective> interimProvidesCopy; 2805 2806 public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) { 2807 this.currentModule = currentModule; 2808 this.interimUsesCopy = interimUsesCopy; 2809 this.interimProvidesCopy = interimProvidesCopy; 2810 } 2811 2812 @Override 2813 public void complete(Symbol sym) throws CompletionFailure { 2814 ListBuffer<Directive> directives = new ListBuffer<>(); 2815 directives.addAll(currentModule.directives); 2816 ListBuffer<UsesDirective> uses = new ListBuffer<>(); 2817 for (InterimUsesDirective interim : interimUsesCopy) { 2818 UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service)); 2819 uses.add(d); 2820 directives.add(d); 2821 } 2822 currentModule.uses = uses.toList(); 2823 ListBuffer<ProvidesDirective> provides = new ListBuffer<>(); 2824 for (InterimProvidesDirective interim : interimProvidesCopy) { 2825 ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service), 2826 syms.enterClass(currentModule, interim.impl)); 2827 provides.add(d); 2828 directives.add(d); 2829 } 2830 currentModule.provides = provides.toList(); 2831 currentModule.directives = directives.toList(); 2832 } 2833 } 2834} 2835