ClassReader.java revision 2721:f7ce2cfa4cdb
1172009Simp/* 2172009Simp * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. 3172009Simp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4172009Simp * 5172009Simp * This code is free software; you can redistribute it and/or modify it 6172009Simp * under the terms of the GNU General Public License version 2 only, as 7172009Simp * published by the Free Software Foundation. Oracle designates this 8172009Simp * particular file as subject to the "Classpath" exception as provided 9172009Simp * by Oracle in the LICENSE file that accompanied this code. 10172009Simp * 11172009Simp * This code is distributed in the hope that it will be useful, but WITHOUT 12172009Simp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13172009Simp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14172009Simp * version 2 for more details (a copy is included in the LICENSE file that 15172009Simp * accompanied this code). 16172009Simp * 17172009Simp * You should have received a copy of the GNU General Public License version 18172009Simp * 2 along with this work; if not, write to the Free Software Foundation, 19172009Simp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20172009Simp * 21172009Simp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22172009Simp * or visit www.oracle.com if you need additional information or have any 23172009Simp * questions. 24172009Simp */ 25172009Simp 26172009Simppackage com.sun.tools.javac.jvm; 27172009Simp 28172009Simpimport java.io.*; 29172009Simpimport java.net.URI; 30172009Simpimport java.net.URISyntaxException; 31172009Simpimport java.nio.CharBuffer; 32172009Simpimport java.util.Arrays; 33172009Simpimport java.util.EnumSet; 34172009Simpimport java.util.HashMap; 35247915Sgavinimport java.util.HashSet; 36172009Simpimport java.util.Map; 37172009Simpimport java.util.Set; 38172009Simpimport javax.tools.JavaFileObject; 39172009Simpimport javax.tools.JavaFileManager; 40172009Simp 41172009Simpimport com.sun.tools.javac.comp.Annotate; 42172068Sbruefferimport com.sun.tools.javac.code.*; 43172068Sbruefferimport com.sun.tools.javac.code.Lint.LintCategory; 44172068Sbruefferimport com.sun.tools.javac.code.Type.*; 45172068Sbruefferimport com.sun.tools.javac.code.Scope.WriteableScope; 46172068Sbruefferimport com.sun.tools.javac.code.Symbol.*; 47172068Sbruefferimport com.sun.tools.javac.code.Symtab; 48172068Sbruefferimport com.sun.tools.javac.file.BaseFileObject; 49172068Sbruefferimport com.sun.tools.javac.util.*; 50172068Sbruefferimport com.sun.tools.javac.util.DefinedBy.Api; 51172068Sbruefferimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 52172068Sbrueffer 53172068Sbruefferimport static com.sun.tools.javac.code.Flags.*; 54172068Sbruefferimport static com.sun.tools.javac.code.Kinds.Kind.*; 55172068Sbruefferimport static com.sun.tools.javac.code.TypeTag.CLASS; 56172068Sbruefferimport static com.sun.tools.javac.code.TypeTag.TYPEVAR; 57172068Sbruefferimport static com.sun.tools.javac.jvm.ClassFile.*; 58172068Sbruefferimport static com.sun.tools.javac.jvm.ClassFile.Version.*; 59172068Sbrueffer 60172068Sbruefferimport static com.sun.tools.javac.main.Option.*; 61172009Simp 62172009Simp/** This class provides operations to read a classfile into an internal 63172009Simp * representation. The internal representation is anchored in a 64172009Simp * ClassSymbol which contains in its scope symbol representations 65172009Simp * for all other definitions in the classfile. Top-level Classes themselves 66172009Simp * appear as members of the scopes of PackageSymbols. 67172009Simp * 68178354Ssam * <p><b>This is NOT part of any supported API. 69180419Sweongyo * If you write code that depends on this, you do so at your own risk. 70178354Ssam * This code and its internal interfaces are subject to change or 71178354Ssam * deletion without notice.</b> 72178354Ssam */ 73178354Ssampublic class ClassReader { 74178354Ssam /** The context key for the class reader. */ 75178354Ssam protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>(); 76172009Simp 77172009Simp public static final int INITIAL_BUFFER_SIZE = 0x0fff0; 78172009Simp 79172009Simp Annotate annotate; 80172009Simp 81172009Simp /** Switch: verbose output. 82172009Simp */ 83172009Simp boolean verbose; 84172009Simp 85172009Simp /** Switch: check class file for correct minor version, unrecognized 86172009Simp * attributes. 87184523Sbrueffer */ 88172009Simp boolean checkClassFile; 89172009Simp 90172009Simp /** Switch: read constant pool and code sections. This switch is initially 91172009Simp * set to false but can be turned on from outside. 92172009Simp */ 93172009Simp public boolean readAllOfClassFile = false; 94172009Simp 95172009Simp /** Switch: allow simplified varargs. 96172009Simp */ 97172009Simp boolean allowSimplifiedVarargs; 98172009Simp 99172009Simp /** Lint option: warn about classfile issues 100172009Simp */ 101184523Sbrueffer boolean lintClassfile; 102172009Simp 103172009Simp /** Switch: preserve parameter names from the variable table. 104172009Simp */ 105172009Simp public boolean saveParameterNames; 106172009Simp 107172009Simp /** 108172009Simp * The currently selected profile. 109172009Simp */ 110172009Simp public final Profile profile; 111172009Simp 112172009Simp /** The log to use for verbose output 113172009Simp */ 114172009Simp final Log log; 115172009Simp 116197724Sweongyo /** The symbol table. */ 117172009Simp Symtab syms; 118172009Simp 119172009Simp Types types; 120172009Simp 121172009Simp /** The name table. */ 122172009Simp final Names names; 123172009Simp 124247915Sgavin /** Access to files 125172009Simp */ 126172009Simp private final JavaFileManager fileManager; 127172009Simp 128172009Simp /** Factory for diagnostics 129184523Sbrueffer */ 130172009Simp JCDiagnostic.Factory diagFactory; 131172009Simp 132172009Simp /** The current scope where type variables are entered. 133178354Ssam */ 134178354Ssam protected WriteableScope typevars; 135178354Ssam 136172009Simp /** The path name of the class file currently being read. 137172009Simp */ 138172009Simp protected JavaFileObject currentClassFile = null; 139172009Simp 140172009Simp /** The class or method currently being read. 141178354Ssam */ 142178354Ssam protected Symbol currentOwner = null; 143172009Simp 144172009Simp /** The buffer containing the currently read class file. 145172009Simp */ 146172009Simp byte[] buf = new byte[INITIAL_BUFFER_SIZE]; 147172009Simp 148172009Simp /** The current input pointer. 149172009Simp */ 150172009Simp protected int bp; 151172009Simp 152172009Simp /** The objects of the constant pool. 153172009Simp */ 154172009Simp Object[] poolObj; 155172009Simp 156172009Simp /** For every constant pool entry, an index into buf where the 157172009Simp * defining section of the entry is found. 158172009Simp */ 159172009Simp int[] poolIdx; 160172009Simp 161172009Simp /** The major version number of the class file being read. */ 162172009Simp int majorVersion; 163172009Simp /** The minor version number of the class file being read. */ 164172009Simp int minorVersion; 165172009Simp 166172009Simp /** A table to hold the constant pool indices for method parameter 167172009Simp * names, as given in LocalVariableTable attributes. 168178354Ssam */ 169178354Ssam int[] parameterNameIndices; 170178354Ssam 171178354Ssam /** 172184523Sbrueffer * Whether or not any parameter names have been found. 173172009Simp */ 174172009Simp boolean haveParameterNameIndices; 175178354Ssam 176172009Simp /** Set this to false every time we start reading a method 177172009Simp * and are saving parameter names. Set it to true when we see 178172009Simp * MethodParameters, if it's set when we see a LocalVariableTable, 179172009Simp * then we ignore the parameter names from the LVT. 180172009Simp */ 181172009Simp boolean sawMethodParameters; 182172009Simp 183172009Simp /** 184172009Simp * The set of attribute names for which warnings have been generated for the current class 185172009Simp */ 186172009Simp Set<Name> warnedAttrs = new HashSet<>(); 187172009Simp 188 /** Get the ClassReader instance for this invocation. */ 189 public static ClassReader instance(Context context) { 190 ClassReader instance = context.get(classReaderKey); 191 if (instance == null) 192 instance = new ClassReader(context); 193 return instance; 194 } 195 196 /** Construct a new class reader. */ 197 protected ClassReader(Context context) { 198 context.put(classReaderKey, this); 199 names = Names.instance(context); 200 syms = Symtab.instance(context); 201 types = Types.instance(context); 202 fileManager = context.get(JavaFileManager.class); 203 if (fileManager == null) 204 throw new AssertionError("FileManager initialization error"); 205 diagFactory = JCDiagnostic.Factory.instance(context); 206 207 log = Log.instance(context); 208 209 Options options = Options.instance(context); 210 annotate = Annotate.instance(context); 211 verbose = options.isSet(VERBOSE); 212 checkClassFile = options.isSet("-checkclassfile"); 213 214 Source source = Source.instance(context); 215 allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 216 217 saveParameterNames = options.isSet("save-parameter-names"); 218 219 profile = Profile.instance(context); 220 221 typevars = WriteableScope.create(syms.noSymbol); 222 223 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE); 224 225 initAttributeReaders(); 226 } 227 228 /** Add member to class unless it is synthetic. 229 */ 230 private void enterMember(ClassSymbol c, Symbol sym) { 231 // Synthetic members are not entered -- reason lost to history (optimization?). 232 // Lambda methods must be entered because they may have inner classes (which reference them) 233 if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) 234 c.members_field.enter(sym); 235 } 236 237/************************************************************************ 238 * Error Diagnoses 239 ***********************************************************************/ 240 241 public ClassFinder.BadClassFile badClassFile(String key, Object... args) { 242 return new ClassFinder.BadClassFile ( 243 currentOwner.enclClass(), 244 currentClassFile, 245 diagFactory.fragment(key, args), 246 diagFactory); 247 } 248 249/************************************************************************ 250 * Buffer Access 251 ***********************************************************************/ 252 253 /** Read a character. 254 */ 255 char nextChar() { 256 return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF)); 257 } 258 259 /** Read a byte. 260 */ 261 int nextByte() { 262 return buf[bp++] & 0xFF; 263 } 264 265 /** Read an integer. 266 */ 267 int nextInt() { 268 return 269 ((buf[bp++] & 0xFF) << 24) + 270 ((buf[bp++] & 0xFF) << 16) + 271 ((buf[bp++] & 0xFF) << 8) + 272 (buf[bp++] & 0xFF); 273 } 274 275 /** Extract a character at position bp from buf. 276 */ 277 char getChar(int bp) { 278 return 279 (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF)); 280 } 281 282 /** Extract an integer at position bp from buf. 283 */ 284 int getInt(int bp) { 285 return 286 ((buf[bp] & 0xFF) << 24) + 287 ((buf[bp+1] & 0xFF) << 16) + 288 ((buf[bp+2] & 0xFF) << 8) + 289 (buf[bp+3] & 0xFF); 290 } 291 292 293 /** Extract a long integer at position bp from buf. 294 */ 295 long getLong(int bp) { 296 DataInputStream bufin = 297 new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 298 try { 299 return bufin.readLong(); 300 } catch (IOException e) { 301 throw new AssertionError(e); 302 } 303 } 304 305 /** Extract a float at position bp from buf. 306 */ 307 float getFloat(int bp) { 308 DataInputStream bufin = 309 new DataInputStream(new ByteArrayInputStream(buf, bp, 4)); 310 try { 311 return bufin.readFloat(); 312 } catch (IOException e) { 313 throw new AssertionError(e); 314 } 315 } 316 317 /** Extract a double at position bp from buf. 318 */ 319 double getDouble(int bp) { 320 DataInputStream bufin = 321 new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 322 try { 323 return bufin.readDouble(); 324 } catch (IOException e) { 325 throw new AssertionError(e); 326 } 327 } 328 329/************************************************************************ 330 * Constant Pool Access 331 ***********************************************************************/ 332 333 /** Index all constant pool entries, writing their start addresses into 334 * poolIdx. 335 */ 336 void indexPool() { 337 poolIdx = new int[nextChar()]; 338 poolObj = new Object[poolIdx.length]; 339 int i = 1; 340 while (i < poolIdx.length) { 341 poolIdx[i++] = bp; 342 byte tag = buf[bp++]; 343 switch (tag) { 344 case CONSTANT_Utf8: case CONSTANT_Unicode: { 345 int len = nextChar(); 346 bp = bp + len; 347 break; 348 } 349 case CONSTANT_Class: 350 case CONSTANT_String: 351 case CONSTANT_MethodType: 352 bp = bp + 2; 353 break; 354 case CONSTANT_MethodHandle: 355 bp = bp + 3; 356 break; 357 case CONSTANT_Fieldref: 358 case CONSTANT_Methodref: 359 case CONSTANT_InterfaceMethodref: 360 case CONSTANT_NameandType: 361 case CONSTANT_Integer: 362 case CONSTANT_Float: 363 case CONSTANT_InvokeDynamic: 364 bp = bp + 4; 365 break; 366 case CONSTANT_Long: 367 case CONSTANT_Double: 368 bp = bp + 8; 369 i++; 370 break; 371 default: 372 throw badClassFile("bad.const.pool.tag.at", 373 Byte.toString(tag), 374 Integer.toString(bp -1)); 375 } 376 } 377 } 378 379 /** Read constant pool entry at start address i, use pool as a cache. 380 */ 381 Object readPool(int i) { 382 Object result = poolObj[i]; 383 if (result != null) return result; 384 385 int index = poolIdx[i]; 386 if (index == 0) return null; 387 388 byte tag = buf[index]; 389 switch (tag) { 390 case CONSTANT_Utf8: 391 poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1)); 392 break; 393 case CONSTANT_Unicode: 394 throw badClassFile("unicode.str.not.supported"); 395 case CONSTANT_Class: 396 poolObj[i] = readClassOrType(getChar(index + 1)); 397 break; 398 case CONSTANT_String: 399 // FIXME: (footprint) do not use toString here 400 poolObj[i] = readName(getChar(index + 1)).toString(); 401 break; 402 case CONSTANT_Fieldref: { 403 ClassSymbol owner = readClassSymbol(getChar(index + 1)); 404 NameAndType nt = readNameAndType(getChar(index + 3)); 405 poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner); 406 break; 407 } 408 case CONSTANT_Methodref: 409 case CONSTANT_InterfaceMethodref: { 410 ClassSymbol owner = readClassSymbol(getChar(index + 1)); 411 NameAndType nt = readNameAndType(getChar(index + 3)); 412 poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner); 413 break; 414 } 415 case CONSTANT_NameandType: 416 poolObj[i] = new NameAndType( 417 readName(getChar(index + 1)), 418 readType(getChar(index + 3)), types); 419 break; 420 case CONSTANT_Integer: 421 poolObj[i] = getInt(index + 1); 422 break; 423 case CONSTANT_Float: 424 poolObj[i] = new Float(getFloat(index + 1)); 425 break; 426 case CONSTANT_Long: 427 poolObj[i] = new Long(getLong(index + 1)); 428 break; 429 case CONSTANT_Double: 430 poolObj[i] = new Double(getDouble(index + 1)); 431 break; 432 case CONSTANT_MethodHandle: 433 skipBytes(4); 434 break; 435 case CONSTANT_MethodType: 436 skipBytes(3); 437 break; 438 case CONSTANT_InvokeDynamic: 439 skipBytes(5); 440 break; 441 default: 442 throw badClassFile("bad.const.pool.tag", Byte.toString(tag)); 443 } 444 return poolObj[i]; 445 } 446 447 /** Read signature and convert to type. 448 */ 449 Type readType(int i) { 450 int index = poolIdx[i]; 451 return sigToType(buf, index + 3, getChar(index + 1)); 452 } 453 454 /** If name is an array type or class signature, return the 455 * corresponding type; otherwise return a ClassSymbol with given name. 456 */ 457 Object readClassOrType(int i) { 458 int index = poolIdx[i]; 459 int len = getChar(index + 1); 460 int start = index + 3; 461 Assert.check(buf[start] == '[' || buf[start + len - 1] != ';'); 462 // by the above assertion, the following test can be 463 // simplified to (buf[start] == '[') 464 return (buf[start] == '[' || buf[start + len - 1] == ';') 465 ? (Object)sigToType(buf, start, len) 466 : (Object)syms.enterClass(names.fromUtf(internalize(buf, start, 467 len))); 468 } 469 470 /** Read signature and convert to type parameters. 471 */ 472 List<Type> readTypeParams(int i) { 473 int index = poolIdx[i]; 474 return sigToTypeParams(buf, index + 3, getChar(index + 1)); 475 } 476 477 /** Read class entry. 478 */ 479 ClassSymbol readClassSymbol(int i) { 480 Object obj = readPool(i); 481 if (obj != null && !(obj instanceof ClassSymbol)) 482 throw badClassFile("bad.const.pool.entry", 483 currentClassFile.toString(), 484 "CONSTANT_Class_info", i); 485 return (ClassSymbol)obj; 486 } 487 488 /** Read name. 489 */ 490 Name readName(int i) { 491 Object obj = readPool(i); 492 if (obj != null && !(obj instanceof Name)) 493 throw badClassFile("bad.const.pool.entry", 494 currentClassFile.toString(), 495 "CONSTANT_Utf8_info or CONSTANT_String_info", i); 496 return (Name)obj; 497 } 498 499 /** Read name and type. 500 */ 501 NameAndType readNameAndType(int i) { 502 Object obj = readPool(i); 503 if (obj != null && !(obj instanceof NameAndType)) 504 throw badClassFile("bad.const.pool.entry", 505 currentClassFile.toString(), 506 "CONSTANT_NameAndType_info", i); 507 return (NameAndType)obj; 508 } 509 510/************************************************************************ 511 * Reading Types 512 ***********************************************************************/ 513 514 /** The unread portion of the currently read type is 515 * signature[sigp..siglimit-1]. 516 */ 517 byte[] signature; 518 int sigp; 519 int siglimit; 520 boolean sigEnterPhase = false; 521 522 /** Convert signature to type, where signature is a byte array segment. 523 */ 524 Type sigToType(byte[] sig, int offset, int len) { 525 signature = sig; 526 sigp = offset; 527 siglimit = offset + len; 528 return sigToType(); 529 } 530 531 /** Convert signature to type, where signature is implicit. 532 */ 533 Type sigToType() { 534 switch ((char) signature[sigp]) { 535 case 'T': 536 sigp++; 537 int start = sigp; 538 while (signature[sigp] != ';') sigp++; 539 sigp++; 540 return sigEnterPhase 541 ? Type.noType 542 : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start)); 543 case '+': { 544 sigp++; 545 Type t = sigToType(); 546 return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass); 547 } 548 case '*': 549 sigp++; 550 return new WildcardType(syms.objectType, BoundKind.UNBOUND, 551 syms.boundClass); 552 case '-': { 553 sigp++; 554 Type t = sigToType(); 555 return new WildcardType(t, BoundKind.SUPER, syms.boundClass); 556 } 557 case 'B': 558 sigp++; 559 return syms.byteType; 560 case 'C': 561 sigp++; 562 return syms.charType; 563 case 'D': 564 sigp++; 565 return syms.doubleType; 566 case 'F': 567 sigp++; 568 return syms.floatType; 569 case 'I': 570 sigp++; 571 return syms.intType; 572 case 'J': 573 sigp++; 574 return syms.longType; 575 case 'L': 576 { 577 // int oldsigp = sigp; 578 Type t = classSigToType(); 579 if (sigp < siglimit && signature[sigp] == '.') 580 throw badClassFile("deprecated inner class signature syntax " + 581 "(please recompile from source)"); 582 /* 583 System.err.println(" decoded " + 584 new String(signature, oldsigp, sigp-oldsigp) + 585 " => " + t + " outer " + t.outer()); 586 */ 587 return t; 588 } 589 case 'S': 590 sigp++; 591 return syms.shortType; 592 case 'V': 593 sigp++; 594 return syms.voidType; 595 case 'Z': 596 sigp++; 597 return syms.booleanType; 598 case '[': 599 sigp++; 600 return new ArrayType(sigToType(), syms.arrayClass); 601 case '(': 602 sigp++; 603 List<Type> argtypes = sigToTypes(')'); 604 Type restype = sigToType(); 605 List<Type> thrown = List.nil(); 606 while (signature[sigp] == '^') { 607 sigp++; 608 thrown = thrown.prepend(sigToType()); 609 } 610 // if there is a typevar in the throws clause we should state it. 611 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) { 612 if (l.head.hasTag(TYPEVAR)) { 613 l.head.tsym.flags_field |= THROWS; 614 } 615 } 616 return new MethodType(argtypes, 617 restype, 618 thrown.reverse(), 619 syms.methodClass); 620 case '<': 621 typevars = typevars.dup(currentOwner); 622 Type poly = new ForAll(sigToTypeParams(), sigToType()); 623 typevars = typevars.leave(); 624 return poly; 625 default: 626 throw badClassFile("bad.signature", 627 Convert.utf2string(signature, sigp, 10)); 628 } 629 } 630 631 byte[] signatureBuffer = new byte[0]; 632 int sbp = 0; 633 /** Convert class signature to type, where signature is implicit. 634 */ 635 Type classSigToType() { 636 if (signature[sigp] != 'L') 637 throw badClassFile("bad.class.signature", 638 Convert.utf2string(signature, sigp, 10)); 639 sigp++; 640 Type outer = Type.noType; 641 int startSbp = sbp; 642 643 while (true) { 644 final byte c = signature[sigp++]; 645 switch (c) { 646 647 case ';': { // end 648 ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer, 649 startSbp, 650 sbp - startSbp)); 651 652 try { 653 return (outer == Type.noType) ? 654 t.erasure(types) : 655 new ClassType(outer, List.<Type>nil(), t); 656 } finally { 657 sbp = startSbp; 658 } 659 } 660 661 case '<': // generic arguments 662 ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer, 663 startSbp, 664 sbp - startSbp)); 665 outer = new ClassType(outer, sigToTypes('>'), t) { 666 boolean completed = false; 667 @Override @DefinedBy(Api.LANGUAGE_MODEL) 668 public Type getEnclosingType() { 669 if (!completed) { 670 completed = true; 671 tsym.complete(); 672 Type enclosingType = tsym.type.getEnclosingType(); 673 if (enclosingType != Type.noType) { 674 List<Type> typeArgs = 675 super.getEnclosingType().allparams(); 676 List<Type> typeParams = 677 enclosingType.allparams(); 678 if (typeParams.length() != typeArgs.length()) { 679 // no "rare" types 680 super.setEnclosingType(types.erasure(enclosingType)); 681 } else { 682 super.setEnclosingType(types.subst(enclosingType, 683 typeParams, 684 typeArgs)); 685 } 686 } else { 687 super.setEnclosingType(Type.noType); 688 } 689 } 690 return super.getEnclosingType(); 691 } 692 @Override 693 public void setEnclosingType(Type outer) { 694 throw new UnsupportedOperationException(); 695 } 696 }; 697 switch (signature[sigp++]) { 698 case ';': 699 if (sigp < signature.length && signature[sigp] == '.') { 700 // support old-style GJC signatures 701 // The signature produced was 702 // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>; 703 // rather than say 704 // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>; 705 // so we skip past ".Lfoo/Outer$" 706 sigp += (sbp - startSbp) + // "foo/Outer" 707 3; // ".L" and "$" 708 signatureBuffer[sbp++] = (byte)'$'; 709 break; 710 } else { 711 sbp = startSbp; 712 return outer; 713 } 714 case '.': 715 signatureBuffer[sbp++] = (byte)'$'; 716 break; 717 default: 718 throw new AssertionError(signature[sigp-1]); 719 } 720 continue; 721 722 case '.': 723 //we have seen an enclosing non-generic class 724 if (outer != Type.noType) { 725 t = syms.enterClass(names.fromUtf(signatureBuffer, 726 startSbp, 727 sbp - startSbp)); 728 outer = new ClassType(outer, List.<Type>nil(), t); 729 } 730 signatureBuffer[sbp++] = (byte)'$'; 731 continue; 732 case '/': 733 signatureBuffer[sbp++] = (byte)'.'; 734 continue; 735 default: 736 signatureBuffer[sbp++] = c; 737 continue; 738 } 739 } 740 } 741 742 /** Convert (implicit) signature to list of types 743 * until `terminator' is encountered. 744 */ 745 List<Type> sigToTypes(char terminator) { 746 List<Type> head = List.of(null); 747 List<Type> tail = head; 748 while (signature[sigp] != terminator) 749 tail = tail.setTail(List.of(sigToType())); 750 sigp++; 751 return head.tail; 752 } 753 754 /** Convert signature to type parameters, where signature is a byte 755 * array segment. 756 */ 757 List<Type> sigToTypeParams(byte[] sig, int offset, int len) { 758 signature = sig; 759 sigp = offset; 760 siglimit = offset + len; 761 return sigToTypeParams(); 762 } 763 764 /** Convert signature to type parameters, where signature is implicit. 765 */ 766 List<Type> sigToTypeParams() { 767 List<Type> tvars = List.nil(); 768 if (signature[sigp] == '<') { 769 sigp++; 770 int start = sigp; 771 sigEnterPhase = true; 772 while (signature[sigp] != '>') 773 tvars = tvars.prepend(sigToTypeParam()); 774 sigEnterPhase = false; 775 sigp = start; 776 while (signature[sigp] != '>') 777 sigToTypeParam(); 778 sigp++; 779 } 780 return tvars.reverse(); 781 } 782 783 /** Convert (implicit) signature to type parameter. 784 */ 785 Type sigToTypeParam() { 786 int start = sigp; 787 while (signature[sigp] != ':') sigp++; 788 Name name = names.fromUtf(signature, start, sigp - start); 789 TypeVar tvar; 790 if (sigEnterPhase) { 791 tvar = new TypeVar(name, currentOwner, syms.botType); 792 typevars.enter(tvar.tsym); 793 } else { 794 tvar = (TypeVar)findTypeVar(name); 795 } 796 List<Type> bounds = List.nil(); 797 boolean allInterfaces = false; 798 if (signature[sigp] == ':' && signature[sigp+1] == ':') { 799 sigp++; 800 allInterfaces = true; 801 } 802 while (signature[sigp] == ':') { 803 sigp++; 804 bounds = bounds.prepend(sigToType()); 805 } 806 if (!sigEnterPhase) { 807 types.setBounds(tvar, bounds.reverse(), allInterfaces); 808 } 809 return tvar; 810 } 811 812 /** Find type variable with given name in `typevars' scope. 813 */ 814 Type findTypeVar(Name name) { 815 Symbol s = typevars.findFirst(name); 816 if (s != null) { 817 return s.type; 818 } else { 819 if (readingClassAttr) { 820 // While reading the class attribute, the supertypes 821 // might refer to a type variable from an enclosing element 822 // (method or class). 823 // If the type variable is defined in the enclosing class, 824 // we can actually find it in 825 // currentOwner.owner.type.getTypeArguments() 826 // However, until we have read the enclosing method attribute 827 // we don't know for sure if this owner is correct. It could 828 // be a method and there is no way to tell before reading the 829 // enclosing method attribute. 830 TypeVar t = new TypeVar(name, currentOwner, syms.botType); 831 missingTypeVariables = missingTypeVariables.prepend(t); 832 // System.err.println("Missing type var " + name); 833 return t; 834 } 835 throw badClassFile("undecl.type.var", name); 836 } 837 } 838 839/************************************************************************ 840 * Reading Attributes 841 ***********************************************************************/ 842 843 protected enum AttributeKind { CLASS, MEMBER } 844 845 protected abstract class AttributeReader { 846 protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) { 847 this.name = name; 848 this.version = version; 849 this.kinds = kinds; 850 } 851 852 protected boolean accepts(AttributeKind kind) { 853 if (kinds.contains(kind)) { 854 if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor)) 855 return true; 856 857 if (lintClassfile && !warnedAttrs.contains(name)) { 858 JavaFileObject prev = log.useSource(currentClassFile); 859 try { 860 log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr", 861 name, version.major, version.minor, majorVersion, minorVersion); 862 } finally { 863 log.useSource(prev); 864 } 865 warnedAttrs.add(name); 866 } 867 } 868 return false; 869 } 870 871 protected abstract void read(Symbol sym, int attrLen); 872 873 protected final Name name; 874 protected final ClassFile.Version version; 875 protected final Set<AttributeKind> kinds; 876 } 877 878 protected Set<AttributeKind> CLASS_ATTRIBUTE = 879 EnumSet.of(AttributeKind.CLASS); 880 protected Set<AttributeKind> MEMBER_ATTRIBUTE = 881 EnumSet.of(AttributeKind.MEMBER); 882 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE = 883 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER); 884 885 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>(); 886 887 private void initAttributeReaders() { 888 AttributeReader[] readers = { 889 // v45.3 attributes 890 891 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) { 892 protected void read(Symbol sym, int attrLen) { 893 if (readAllOfClassFile || saveParameterNames) 894 ((MethodSymbol)sym).code = readCode(sym); 895 else 896 bp = bp + attrLen; 897 } 898 }, 899 900 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) { 901 protected void read(Symbol sym, int attrLen) { 902 Object v = readPool(nextChar()); 903 // Ignore ConstantValue attribute if field not final. 904 if ((sym.flags() & FINAL) != 0) 905 ((VarSymbol) sym).setData(v); 906 } 907 }, 908 909 new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 910 protected void read(Symbol sym, int attrLen) { 911 sym.flags_field |= DEPRECATED; 912 } 913 }, 914 915 new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 916 protected void read(Symbol sym, int attrLen) { 917 int nexceptions = nextChar(); 918 List<Type> thrown = List.nil(); 919 for (int j = 0; j < nexceptions; j++) 920 thrown = thrown.prepend(readClassSymbol(nextChar()).type); 921 if (sym.type.getThrownTypes().isEmpty()) 922 sym.type.asMethodType().thrown = thrown.reverse(); 923 } 924 }, 925 926 new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) { 927 protected void read(Symbol sym, int attrLen) { 928 ClassSymbol c = (ClassSymbol) sym; 929 readInnerClasses(c); 930 } 931 }, 932 933 new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 934 protected void read(Symbol sym, int attrLen) { 935 int newbp = bp + attrLen; 936 if (saveParameterNames && !sawMethodParameters) { 937 // Pick up parameter names from the variable table. 938 // Parameter names are not explicitly identified as such, 939 // but all parameter name entries in the LocalVariableTable 940 // have a start_pc of 0. Therefore, we record the name 941 // indicies of all slots with a start_pc of zero in the 942 // parameterNameIndicies array. 943 // Note that this implicitly honors the JVMS spec that 944 // there may be more than one LocalVariableTable, and that 945 // there is no specified ordering for the entries. 946 int numEntries = nextChar(); 947 for (int i = 0; i < numEntries; i++) { 948 int start_pc = nextChar(); 949 int length = nextChar(); 950 int nameIndex = nextChar(); 951 int sigIndex = nextChar(); 952 int register = nextChar(); 953 if (start_pc == 0) { 954 // ensure array large enough 955 if (register >= parameterNameIndices.length) { 956 int newSize = Math.max(register, parameterNameIndices.length + 8); 957 parameterNameIndices = 958 Arrays.copyOf(parameterNameIndices, newSize); 959 } 960 parameterNameIndices[register] = nameIndex; 961 haveParameterNameIndices = true; 962 } 963 } 964 } 965 bp = newbp; 966 } 967 }, 968 969 new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) { 970 protected void read(Symbol sym, int attrlen) { 971 int newbp = bp + attrlen; 972 if (saveParameterNames) { 973 sawMethodParameters = true; 974 int numEntries = nextByte(); 975 parameterNameIndices = new int[numEntries]; 976 haveParameterNameIndices = true; 977 for (int i = 0; i < numEntries; i++) { 978 int nameIndex = nextChar(); 979 int flags = nextChar(); 980 parameterNameIndices[i] = nameIndex; 981 } 982 } 983 bp = newbp; 984 } 985 }, 986 987 988 new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) { 989 protected void read(Symbol sym, int attrLen) { 990 ClassSymbol c = (ClassSymbol) sym; 991 Name n = readName(nextChar()); 992 c.sourcefile = new SourceFileObject(n, c.flatname); 993 // If the class is a toplevel class, originating from a Java source file, 994 // but the class name does not match the file name, then it is 995 // an auxiliary class. 996 String sn = n.toString(); 997 if (c.owner.kind == PCK && 998 sn.endsWith(".java") && 999 !sn.equals(c.name.toString()+".java")) { 1000 c.flags_field |= AUXILIARY; 1001 } 1002 } 1003 }, 1004 1005 new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1006 protected void read(Symbol sym, int attrLen) { 1007 sym.flags_field |= SYNTHETIC; 1008 } 1009 }, 1010 1011 // standard v49 attributes 1012 1013 new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) { 1014 protected void read(Symbol sym, int attrLen) { 1015 int newbp = bp + attrLen; 1016 readEnclosingMethodAttr(sym); 1017 bp = newbp; 1018 } 1019 }, 1020 1021 new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1022 protected void read(Symbol sym, int attrLen) { 1023 if (sym.kind == TYP) { 1024 ClassSymbol c = (ClassSymbol) sym; 1025 readingClassAttr = true; 1026 try { 1027 ClassType ct1 = (ClassType)c.type; 1028 Assert.check(c == currentOwner); 1029 ct1.typarams_field = readTypeParams(nextChar()); 1030 ct1.supertype_field = sigToType(); 1031 ListBuffer<Type> is = new ListBuffer<>(); 1032 while (sigp != siglimit) is.append(sigToType()); 1033 ct1.interfaces_field = is.toList(); 1034 } finally { 1035 readingClassAttr = false; 1036 } 1037 } else { 1038 List<Type> thrown = sym.type.getThrownTypes(); 1039 sym.type = readType(nextChar()); 1040 //- System.err.println(" # " + sym.type); 1041 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty()) 1042 sym.type.asMethodType().thrown = thrown; 1043 1044 } 1045 } 1046 }, 1047 1048 // v49 annotation attributes 1049 1050 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1051 protected void read(Symbol sym, int attrLen) { 1052 attachAnnotationDefault(sym); 1053 } 1054 }, 1055 1056 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1057 protected void read(Symbol sym, int attrLen) { 1058 attachAnnotations(sym); 1059 } 1060 }, 1061 1062 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1063 protected void read(Symbol sym, int attrLen) { 1064 attachParameterAnnotations(sym); 1065 } 1066 }, 1067 1068 new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1069 protected void read(Symbol sym, int attrLen) { 1070 attachAnnotations(sym); 1071 } 1072 }, 1073 1074 new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1075 protected void read(Symbol sym, int attrLen) { 1076 attachParameterAnnotations(sym); 1077 } 1078 }, 1079 1080 // additional "legacy" v49 attributes, superceded by flags 1081 1082 new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1083 protected void read(Symbol sym, int attrLen) { 1084 sym.flags_field |= ANNOTATION; 1085 } 1086 }, 1087 1088 new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) { 1089 protected void read(Symbol sym, int attrLen) { 1090 sym.flags_field |= BRIDGE; 1091 } 1092 }, 1093 1094 new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1095 protected void read(Symbol sym, int attrLen) { 1096 sym.flags_field |= ENUM; 1097 } 1098 }, 1099 1100 new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1101 protected void read(Symbol sym, int attrLen) { 1102 sym.flags_field |= VARARGS; 1103 } 1104 }, 1105 1106 new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1107 protected void read(Symbol sym, int attrLen) { 1108 attachTypeAnnotations(sym); 1109 } 1110 }, 1111 1112 new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1113 protected void read(Symbol sym, int attrLen) { 1114 attachTypeAnnotations(sym); 1115 } 1116 }, 1117 1118 1119 // The following attributes for a Code attribute are not currently handled 1120 // StackMapTable 1121 // SourceDebugExtension 1122 // LineNumberTable 1123 // LocalVariableTypeTable 1124 }; 1125 1126 for (AttributeReader r: readers) 1127 attributeReaders.put(r.name, r); 1128 } 1129 1130 /** Report unrecognized attribute. 1131 */ 1132 void unrecognized(Name attrName) { 1133 if (checkClassFile) 1134 printCCF("ccf.unrecognized.attribute", attrName); 1135 } 1136 1137 1138 1139 protected void readEnclosingMethodAttr(Symbol sym) { 1140 // sym is a nested class with an "Enclosing Method" attribute 1141 // remove sym from it's current owners scope and place it in 1142 // the scope specified by the attribute 1143 sym.owner.members().remove(sym); 1144 ClassSymbol self = (ClassSymbol)sym; 1145 ClassSymbol c = readClassSymbol(nextChar()); 1146 NameAndType nt = readNameAndType(nextChar()); 1147 1148 if (c.members_field == null) 1149 throw badClassFile("bad.enclosing.class", self, c); 1150 1151 MethodSymbol m = findMethod(nt, c.members_field, self.flags()); 1152 if (nt != null && m == null) 1153 throw badClassFile("bad.enclosing.method", self); 1154 1155 self.name = simpleBinaryName(self.flatname, c.flatname) ; 1156 self.owner = m != null ? m : c; 1157 if (self.name.isEmpty()) 1158 self.fullname = names.empty; 1159 else 1160 self.fullname = ClassSymbol.formFullName(self.name, self.owner); 1161 1162 if (m != null) { 1163 ((ClassType)sym.type).setEnclosingType(m.type); 1164 } else if ((self.flags_field & STATIC) == 0) { 1165 ((ClassType)sym.type).setEnclosingType(c.type); 1166 } else { 1167 ((ClassType)sym.type).setEnclosingType(Type.noType); 1168 } 1169 enterTypevars(self); 1170 if (!missingTypeVariables.isEmpty()) { 1171 ListBuffer<Type> typeVars = new ListBuffer<>(); 1172 for (Type typevar : missingTypeVariables) { 1173 typeVars.append(findTypeVar(typevar.tsym.name)); 1174 } 1175 foundTypeVariables = typeVars.toList(); 1176 } else { 1177 foundTypeVariables = List.nil(); 1178 } 1179 } 1180 1181 // See java.lang.Class 1182 private Name simpleBinaryName(Name self, Name enclosing) { 1183 String simpleBinaryName = self.toString().substring(enclosing.toString().length()); 1184 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$') 1185 throw badClassFile("bad.enclosing.method", self); 1186 int index = 1; 1187 while (index < simpleBinaryName.length() && 1188 isAsciiDigit(simpleBinaryName.charAt(index))) 1189 index++; 1190 return names.fromString(simpleBinaryName.substring(index)); 1191 } 1192 1193 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) { 1194 if (nt == null) 1195 return null; 1196 1197 MethodType type = nt.uniqueType.type.asMethodType(); 1198 1199 for (Symbol sym : scope.getSymbolsByName(nt.name)) { 1200 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type)) 1201 return (MethodSymbol)sym; 1202 } 1203 1204 if (nt.name != names.init) 1205 // not a constructor 1206 return null; 1207 if ((flags & INTERFACE) != 0) 1208 // no enclosing instance 1209 return null; 1210 if (nt.uniqueType.type.getParameterTypes().isEmpty()) 1211 // no parameters 1212 return null; 1213 1214 // A constructor of an inner class. 1215 // Remove the first argument (the enclosing instance) 1216 nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail, 1217 nt.uniqueType.type.getReturnType(), 1218 nt.uniqueType.type.getThrownTypes(), 1219 syms.methodClass)); 1220 // Try searching again 1221 return findMethod(nt, scope, flags); 1222 } 1223 1224 /** Similar to Types.isSameType but avoids completion */ 1225 private boolean isSameBinaryType(MethodType mt1, MethodType mt2) { 1226 List<Type> types1 = types.erasure(mt1.getParameterTypes()) 1227 .prepend(types.erasure(mt1.getReturnType())); 1228 List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType()); 1229 while (!types1.isEmpty() && !types2.isEmpty()) { 1230 if (types1.head.tsym != types2.head.tsym) 1231 return false; 1232 types1 = types1.tail; 1233 types2 = types2.tail; 1234 } 1235 return types1.isEmpty() && types2.isEmpty(); 1236 } 1237 1238 /** 1239 * Character.isDigit answers <tt>true</tt> to some non-ascii 1240 * digits. This one does not. <b>copied from java.lang.Class</b> 1241 */ 1242 private static boolean isAsciiDigit(char c) { 1243 return '0' <= c && c <= '9'; 1244 } 1245 1246 /** Read member attributes. 1247 */ 1248 void readMemberAttrs(Symbol sym) { 1249 readAttrs(sym, AttributeKind.MEMBER); 1250 } 1251 1252 void readAttrs(Symbol sym, AttributeKind kind) { 1253 char ac = nextChar(); 1254 for (int i = 0; i < ac; i++) { 1255 Name attrName = readName(nextChar()); 1256 int attrLen = nextInt(); 1257 AttributeReader r = attributeReaders.get(attrName); 1258 if (r != null && r.accepts(kind)) 1259 r.read(sym, attrLen); 1260 else { 1261 unrecognized(attrName); 1262 bp = bp + attrLen; 1263 } 1264 } 1265 } 1266 1267 private boolean readingClassAttr = false; 1268 private List<Type> missingTypeVariables = List.nil(); 1269 private List<Type> foundTypeVariables = List.nil(); 1270 1271 /** Read class attributes. 1272 */ 1273 void readClassAttrs(ClassSymbol c) { 1274 readAttrs(c, AttributeKind.CLASS); 1275 } 1276 1277 /** Read code block. 1278 */ 1279 Code readCode(Symbol owner) { 1280 nextChar(); // max_stack 1281 nextChar(); // max_locals 1282 final int code_length = nextInt(); 1283 bp += code_length; 1284 final char exception_table_length = nextChar(); 1285 bp += exception_table_length * 8; 1286 readMemberAttrs(owner); 1287 return null; 1288 } 1289 1290/************************************************************************ 1291 * Reading Java-language annotations 1292 ***********************************************************************/ 1293 1294 /** Attach annotations. 1295 */ 1296 void attachAnnotations(final Symbol sym) { 1297 int numAttributes = nextChar(); 1298 if (numAttributes != 0) { 1299 ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>(); 1300 for (int i = 0; i<numAttributes; i++) { 1301 CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1302 proxies.append(proxy); 1303 } 1304 annotate.normal(new AnnotationCompleter(sym, proxies.toList())); 1305 } 1306 } 1307 1308 /** Attach parameter annotations. 1309 */ 1310 void attachParameterAnnotations(final Symbol method) { 1311 final MethodSymbol meth = (MethodSymbol)method; 1312 int numParameters = buf[bp++] & 0xFF; 1313 List<VarSymbol> parameters = meth.params(); 1314 int pnum = 0; 1315 while (parameters.tail != null) { 1316 attachAnnotations(parameters.head); 1317 parameters = parameters.tail; 1318 pnum++; 1319 } 1320 if (pnum != numParameters) { 1321 throw badClassFile("bad.runtime.invisible.param.annotations", meth); 1322 } 1323 } 1324 1325 void attachTypeAnnotations(final Symbol sym) { 1326 int numAttributes = nextChar(); 1327 if (numAttributes != 0) { 1328 ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>(); 1329 for (int i = 0; i < numAttributes; i++) 1330 proxies.append(readTypeAnnotation()); 1331 annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); 1332 } 1333 } 1334 1335 /** Attach the default value for an annotation element. 1336 */ 1337 void attachAnnotationDefault(final Symbol sym) { 1338 final MethodSymbol meth = (MethodSymbol)sym; // only on methods 1339 final Attribute value = readAttributeValue(); 1340 1341 // The default value is set later during annotation. It might 1342 // be the case that the Symbol sym is annotated _after_ the 1343 // repeating instances that depend on this default value, 1344 // because of this we set an interim value that tells us this 1345 // element (most likely) has a default. 1346 // 1347 // Set interim value for now, reset just before we do this 1348 // properly at annotate time. 1349 meth.defaultValue = value; 1350 annotate.normal(new AnnotationDefaultCompleter(meth, value)); 1351 } 1352 1353 Type readTypeOrClassSymbol(int i) { 1354 // support preliminary jsr175-format class files 1355 if (buf[poolIdx[i]] == CONSTANT_Class) 1356 return readClassSymbol(i).type; 1357 return readType(i); 1358 } 1359 Type readEnumType(int i) { 1360 // support preliminary jsr175-format class files 1361 int index = poolIdx[i]; 1362 int length = getChar(index + 1); 1363 if (buf[index + length + 2] != ';') 1364 return syms.enterClass(readName(i)).type; 1365 return readType(i); 1366 } 1367 1368 CompoundAnnotationProxy readCompoundAnnotation() { 1369 Type t = readTypeOrClassSymbol(nextChar()); 1370 int numFields = nextChar(); 1371 ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>(); 1372 for (int i=0; i<numFields; i++) { 1373 Name name = readName(nextChar()); 1374 Attribute value = readAttributeValue(); 1375 pairs.append(new Pair<>(name, value)); 1376 } 1377 return new CompoundAnnotationProxy(t, pairs.toList()); 1378 } 1379 1380 TypeAnnotationProxy readTypeAnnotation() { 1381 TypeAnnotationPosition position = readPosition(); 1382 CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1383 1384 return new TypeAnnotationProxy(proxy, position); 1385 } 1386 1387 TypeAnnotationPosition readPosition() { 1388 int tag = nextByte(); // TargetType tag is a byte 1389 1390 if (!TargetType.isValidTargetTypeValue(tag)) 1391 throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); 1392 1393 TargetType type = TargetType.fromTargetTypeValue(tag); 1394 1395 switch (type) { 1396 // instanceof 1397 case INSTANCEOF: { 1398 final int offset = nextChar(); 1399 final TypeAnnotationPosition position = 1400 TypeAnnotationPosition.instanceOf(readTypePath()); 1401 position.offset = offset; 1402 return position; 1403 } 1404 // new expression 1405 case NEW: { 1406 final int offset = nextChar(); 1407 final TypeAnnotationPosition position = 1408 TypeAnnotationPosition.newObj(readTypePath()); 1409 position.offset = offset; 1410 return position; 1411 } 1412 // constructor/method reference receiver 1413 case CONSTRUCTOR_REFERENCE: { 1414 final int offset = nextChar(); 1415 final TypeAnnotationPosition position = 1416 TypeAnnotationPosition.constructorRef(readTypePath()); 1417 position.offset = offset; 1418 return position; 1419 } 1420 case METHOD_REFERENCE: { 1421 final int offset = nextChar(); 1422 final TypeAnnotationPosition position = 1423 TypeAnnotationPosition.methodRef(readTypePath()); 1424 position.offset = offset; 1425 return position; 1426 } 1427 // local variable 1428 case LOCAL_VARIABLE: { 1429 final int table_length = nextChar(); 1430 final int[] newLvarOffset = new int[table_length]; 1431 final int[] newLvarLength = new int[table_length]; 1432 final int[] newLvarIndex = new int[table_length]; 1433 1434 for (int i = 0; i < table_length; ++i) { 1435 newLvarOffset[i] = nextChar(); 1436 newLvarLength[i] = nextChar(); 1437 newLvarIndex[i] = nextChar(); 1438 } 1439 1440 final TypeAnnotationPosition position = 1441 TypeAnnotationPosition.localVariable(readTypePath()); 1442 position.lvarOffset = newLvarOffset; 1443 position.lvarLength = newLvarLength; 1444 position.lvarIndex = newLvarIndex; 1445 return position; 1446 } 1447 // resource variable 1448 case RESOURCE_VARIABLE: { 1449 final int table_length = nextChar(); 1450 final int[] newLvarOffset = new int[table_length]; 1451 final int[] newLvarLength = new int[table_length]; 1452 final int[] newLvarIndex = new int[table_length]; 1453 1454 for (int i = 0; i < table_length; ++i) { 1455 newLvarOffset[i] = nextChar(); 1456 newLvarLength[i] = nextChar(); 1457 newLvarIndex[i] = nextChar(); 1458 } 1459 1460 final TypeAnnotationPosition position = 1461 TypeAnnotationPosition.resourceVariable(readTypePath()); 1462 position.lvarOffset = newLvarOffset; 1463 position.lvarLength = newLvarLength; 1464 position.lvarIndex = newLvarIndex; 1465 return position; 1466 } 1467 // exception parameter 1468 case EXCEPTION_PARAMETER: { 1469 final int exception_index = nextChar(); 1470 final TypeAnnotationPosition position = 1471 TypeAnnotationPosition.exceptionParameter(readTypePath()); 1472 position.setExceptionIndex(exception_index); 1473 return position; 1474 } 1475 // method receiver 1476 case METHOD_RECEIVER: 1477 return TypeAnnotationPosition.methodReceiver(readTypePath()); 1478 // type parameter 1479 case CLASS_TYPE_PARAMETER: { 1480 final int parameter_index = nextByte(); 1481 return TypeAnnotationPosition 1482 .typeParameter(readTypePath(), parameter_index); 1483 } 1484 case METHOD_TYPE_PARAMETER: { 1485 final int parameter_index = nextByte(); 1486 return TypeAnnotationPosition 1487 .methodTypeParameter(readTypePath(), parameter_index); 1488 } 1489 // type parameter bound 1490 case CLASS_TYPE_PARAMETER_BOUND: { 1491 final int parameter_index = nextByte(); 1492 final int bound_index = nextByte(); 1493 return TypeAnnotationPosition 1494 .typeParameterBound(readTypePath(), parameter_index, 1495 bound_index); 1496 } 1497 case METHOD_TYPE_PARAMETER_BOUND: { 1498 final int parameter_index = nextByte(); 1499 final int bound_index = nextByte(); 1500 return TypeAnnotationPosition 1501 .methodTypeParameterBound(readTypePath(), parameter_index, 1502 bound_index); 1503 } 1504 // class extends or implements clause 1505 case CLASS_EXTENDS: { 1506 final int type_index = nextChar(); 1507 return TypeAnnotationPosition.classExtends(readTypePath(), 1508 type_index); 1509 } 1510 // throws 1511 case THROWS: { 1512 final int type_index = nextChar(); 1513 return TypeAnnotationPosition.methodThrows(readTypePath(), 1514 type_index); 1515 } 1516 // method parameter 1517 case METHOD_FORMAL_PARAMETER: { 1518 final int parameter_index = nextByte(); 1519 return TypeAnnotationPosition.methodParameter(readTypePath(), 1520 parameter_index); 1521 } 1522 // type cast 1523 case CAST: { 1524 final int offset = nextChar(); 1525 final int type_index = nextByte(); 1526 final TypeAnnotationPosition position = 1527 TypeAnnotationPosition.typeCast(readTypePath(), type_index); 1528 position.offset = offset; 1529 return position; 1530 } 1531 // method/constructor/reference type argument 1532 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: { 1533 final int offset = nextChar(); 1534 final int type_index = nextByte(); 1535 final TypeAnnotationPosition position = TypeAnnotationPosition 1536 .constructorInvocationTypeArg(readTypePath(), type_index); 1537 position.offset = offset; 1538 return position; 1539 } 1540 case METHOD_INVOCATION_TYPE_ARGUMENT: { 1541 final int offset = nextChar(); 1542 final int type_index = nextByte(); 1543 final TypeAnnotationPosition position = TypeAnnotationPosition 1544 .methodInvocationTypeArg(readTypePath(), type_index); 1545 position.offset = offset; 1546 return position; 1547 } 1548 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: { 1549 final int offset = nextChar(); 1550 final int type_index = nextByte(); 1551 final TypeAnnotationPosition position = TypeAnnotationPosition 1552 .constructorRefTypeArg(readTypePath(), type_index); 1553 position.offset = offset; 1554 return position; 1555 } 1556 case METHOD_REFERENCE_TYPE_ARGUMENT: { 1557 final int offset = nextChar(); 1558 final int type_index = nextByte(); 1559 final TypeAnnotationPosition position = TypeAnnotationPosition 1560 .methodRefTypeArg(readTypePath(), type_index); 1561 position.offset = offset; 1562 return position; 1563 } 1564 // We don't need to worry about these 1565 case METHOD_RETURN: 1566 return TypeAnnotationPosition.methodReturn(readTypePath()); 1567 case FIELD: 1568 return TypeAnnotationPosition.field(readTypePath()); 1569 case UNKNOWN: 1570 throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); 1571 default: 1572 throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type); 1573 } 1574 } 1575 1576 List<TypeAnnotationPosition.TypePathEntry> readTypePath() { 1577 int len = nextByte(); 1578 ListBuffer<Integer> loc = new ListBuffer<>(); 1579 for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) 1580 loc = loc.append(nextByte()); 1581 1582 return TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); 1583 1584 } 1585 1586 Attribute readAttributeValue() { 1587 char c = (char) buf[bp++]; 1588 switch (c) { 1589 case 'B': 1590 return new Attribute.Constant(syms.byteType, readPool(nextChar())); 1591 case 'C': 1592 return new Attribute.Constant(syms.charType, readPool(nextChar())); 1593 case 'D': 1594 return new Attribute.Constant(syms.doubleType, readPool(nextChar())); 1595 case 'F': 1596 return new Attribute.Constant(syms.floatType, readPool(nextChar())); 1597 case 'I': 1598 return new Attribute.Constant(syms.intType, readPool(nextChar())); 1599 case 'J': 1600 return new Attribute.Constant(syms.longType, readPool(nextChar())); 1601 case 'S': 1602 return new Attribute.Constant(syms.shortType, readPool(nextChar())); 1603 case 'Z': 1604 return new Attribute.Constant(syms.booleanType, readPool(nextChar())); 1605 case 's': 1606 return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString()); 1607 case 'e': 1608 return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar())); 1609 case 'c': 1610 return new Attribute.Class(types, readTypeOrClassSymbol(nextChar())); 1611 case '[': { 1612 int n = nextChar(); 1613 ListBuffer<Attribute> l = new ListBuffer<>(); 1614 for (int i=0; i<n; i++) 1615 l.append(readAttributeValue()); 1616 return new ArrayAttributeProxy(l.toList()); 1617 } 1618 case '@': 1619 return readCompoundAnnotation(); 1620 default: 1621 throw new AssertionError("unknown annotation tag '" + c + "'"); 1622 } 1623 } 1624 1625 interface ProxyVisitor extends Attribute.Visitor { 1626 void visitEnumAttributeProxy(EnumAttributeProxy proxy); 1627 void visitArrayAttributeProxy(ArrayAttributeProxy proxy); 1628 void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy); 1629 } 1630 1631 static class EnumAttributeProxy extends Attribute { 1632 Type enumType; 1633 Name enumerator; 1634 public EnumAttributeProxy(Type enumType, Name enumerator) { 1635 super(null); 1636 this.enumType = enumType; 1637 this.enumerator = enumerator; 1638 } 1639 public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); } 1640 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1641 public String toString() { 1642 return "/*proxy enum*/" + enumType + "." + enumerator; 1643 } 1644 } 1645 1646 static class ArrayAttributeProxy extends Attribute { 1647 List<Attribute> values; 1648 ArrayAttributeProxy(List<Attribute> values) { 1649 super(null); 1650 this.values = values; 1651 } 1652 public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); } 1653 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1654 public String toString() { 1655 return "{" + values + "}"; 1656 } 1657 } 1658 1659 /** A temporary proxy representing a compound attribute. 1660 */ 1661 static class CompoundAnnotationProxy extends Attribute { 1662 final List<Pair<Name,Attribute>> values; 1663 public CompoundAnnotationProxy(Type type, 1664 List<Pair<Name,Attribute>> values) { 1665 super(type); 1666 this.values = values; 1667 } 1668 public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); } 1669 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1670 public String toString() { 1671 StringBuilder buf = new StringBuilder(); 1672 buf.append("@"); 1673 buf.append(type.tsym.getQualifiedName()); 1674 buf.append("/*proxy*/{"); 1675 boolean first = true; 1676 for (List<Pair<Name,Attribute>> v = values; 1677 v.nonEmpty(); v = v.tail) { 1678 Pair<Name,Attribute> value = v.head; 1679 if (!first) buf.append(","); 1680 first = false; 1681 buf.append(value.fst); 1682 buf.append("="); 1683 buf.append(value.snd); 1684 } 1685 buf.append("}"); 1686 return buf.toString(); 1687 } 1688 } 1689 1690 /** A temporary proxy representing a type annotation. 1691 */ 1692 static class TypeAnnotationProxy { 1693 final CompoundAnnotationProxy compound; 1694 final TypeAnnotationPosition position; 1695 public TypeAnnotationProxy(CompoundAnnotationProxy compound, 1696 TypeAnnotationPosition position) { 1697 this.compound = compound; 1698 this.position = position; 1699 } 1700 } 1701 1702 class AnnotationDeproxy implements ProxyVisitor { 1703 private ClassSymbol requestingOwner = currentOwner.kind == MTH 1704 ? currentOwner.enclClass() : (ClassSymbol)currentOwner; 1705 1706 List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) { 1707 // also must fill in types!!!! 1708 ListBuffer<Attribute.Compound> buf = new ListBuffer<>(); 1709 for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) { 1710 buf.append(deproxyCompound(l.head)); 1711 } 1712 return buf.toList(); 1713 } 1714 1715 Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) { 1716 ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>(); 1717 for (List<Pair<Name,Attribute>> l = a.values; 1718 l.nonEmpty(); 1719 l = l.tail) { 1720 MethodSymbol meth = findAccessMethod(a.type, l.head.fst); 1721 buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd))); 1722 } 1723 return new Attribute.Compound(a.type, buf.toList()); 1724 } 1725 1726 MethodSymbol findAccessMethod(Type container, Name name) { 1727 CompletionFailure failure = null; 1728 try { 1729 for (Symbol sym : container.tsym.members().getSymbolsByName(name)) { 1730 if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0) 1731 return (MethodSymbol) sym; 1732 } 1733 } catch (CompletionFailure ex) { 1734 failure = ex; 1735 } 1736 // The method wasn't found: emit a warning and recover 1737 JavaFileObject prevSource = log.useSource(requestingOwner.classfile); 1738 try { 1739 if (failure == null) { 1740 log.warning("annotation.method.not.found", 1741 container, 1742 name); 1743 } else { 1744 log.warning("annotation.method.not.found.reason", 1745 container, 1746 name, 1747 failure.getDetailValue());//diagnostic, if present 1748 } 1749 } finally { 1750 log.useSource(prevSource); 1751 } 1752 // Construct a new method type and symbol. Use bottom 1753 // type (typeof null) as return type because this type is 1754 // a subtype of all reference types and can be converted 1755 // to primitive types by unboxing. 1756 MethodType mt = new MethodType(List.<Type>nil(), 1757 syms.botType, 1758 List.<Type>nil(), 1759 syms.methodClass); 1760 return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym); 1761 } 1762 1763 Attribute result; 1764 Type type; 1765 Attribute deproxy(Type t, Attribute a) { 1766 Type oldType = type; 1767 try { 1768 type = t; 1769 a.accept(this); 1770 return result; 1771 } finally { 1772 type = oldType; 1773 } 1774 } 1775 1776 // implement Attribute.Visitor below 1777 1778 public void visitConstant(Attribute.Constant value) { 1779 // assert value.type == type; 1780 result = value; 1781 } 1782 1783 public void visitClass(Attribute.Class clazz) { 1784 result = clazz; 1785 } 1786 1787 public void visitEnum(Attribute.Enum e) { 1788 throw new AssertionError(); // shouldn't happen 1789 } 1790 1791 public void visitCompound(Attribute.Compound compound) { 1792 throw new AssertionError(); // shouldn't happen 1793 } 1794 1795 public void visitArray(Attribute.Array array) { 1796 throw new AssertionError(); // shouldn't happen 1797 } 1798 1799 public void visitError(Attribute.Error e) { 1800 throw new AssertionError(); // shouldn't happen 1801 } 1802 1803 public void visitEnumAttributeProxy(EnumAttributeProxy proxy) { 1804 // type.tsym.flatName() should == proxy.enumFlatName 1805 TypeSymbol enumTypeSym = proxy.enumType.tsym; 1806 VarSymbol enumerator = null; 1807 CompletionFailure failure = null; 1808 try { 1809 for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) { 1810 if (sym.kind == VAR) { 1811 enumerator = (VarSymbol)sym; 1812 break; 1813 } 1814 } 1815 } 1816 catch (CompletionFailure ex) { 1817 failure = ex; 1818 } 1819 if (enumerator == null) { 1820 if (failure != null) { 1821 log.warning("unknown.enum.constant.reason", 1822 currentClassFile, enumTypeSym, proxy.enumerator, 1823 failure.getDiagnostic()); 1824 } else { 1825 log.warning("unknown.enum.constant", 1826 currentClassFile, enumTypeSym, proxy.enumerator); 1827 } 1828 result = new Attribute.Enum(enumTypeSym.type, 1829 new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym)); 1830 } else { 1831 result = new Attribute.Enum(enumTypeSym.type, enumerator); 1832 } 1833 } 1834 1835 public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) { 1836 int length = proxy.values.length(); 1837 Attribute[] ats = new Attribute[length]; 1838 Type elemtype = types.elemtype(type); 1839 int i = 0; 1840 for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) { 1841 ats[i++] = deproxy(elemtype, p.head); 1842 } 1843 result = new Attribute.Array(type, ats); 1844 } 1845 1846 public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) { 1847 result = deproxyCompound(proxy); 1848 } 1849 } 1850 1851 class AnnotationDefaultCompleter extends AnnotationDeproxy implements Annotate.Worker { 1852 final MethodSymbol sym; 1853 final Attribute value; 1854 final JavaFileObject classFile = currentClassFile; 1855 @Override 1856 public String toString() { 1857 return " ClassReader store default for " + sym.owner + "." + sym + " is " + value; 1858 } 1859 AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) { 1860 this.sym = sym; 1861 this.value = value; 1862 } 1863 // implement Annotate.Worker.run() 1864 public void run() { 1865 JavaFileObject previousClassFile = currentClassFile; 1866 try { 1867 // Reset the interim value set earlier in 1868 // attachAnnotationDefault(). 1869 sym.defaultValue = null; 1870 currentClassFile = classFile; 1871 sym.defaultValue = deproxy(sym.type.getReturnType(), value); 1872 } finally { 1873 currentClassFile = previousClassFile; 1874 } 1875 } 1876 } 1877 1878 class AnnotationCompleter extends AnnotationDeproxy implements Annotate.Worker { 1879 final Symbol sym; 1880 final List<CompoundAnnotationProxy> l; 1881 final JavaFileObject classFile; 1882 @Override 1883 public String toString() { 1884 return " ClassReader annotate " + sym.owner + "." + sym + " with " + l; 1885 } 1886 AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) { 1887 this.sym = sym; 1888 this.l = l; 1889 this.classFile = currentClassFile; 1890 } 1891 // implement Annotate.Worker.run() 1892 public void run() { 1893 JavaFileObject previousClassFile = currentClassFile; 1894 try { 1895 currentClassFile = classFile; 1896 List<Attribute.Compound> newList = deproxyCompoundList(l); 1897 if (sym.annotationsPendingCompletion()) { 1898 sym.setDeclarationAttributes(newList); 1899 } else { 1900 sym.appendAttributes(newList); 1901 } 1902 } finally { 1903 currentClassFile = previousClassFile; 1904 } 1905 } 1906 } 1907 1908 class TypeAnnotationCompleter extends AnnotationCompleter { 1909 1910 List<TypeAnnotationProxy> proxies; 1911 1912 TypeAnnotationCompleter(Symbol sym, 1913 List<TypeAnnotationProxy> proxies) { 1914 super(sym, List.<CompoundAnnotationProxy>nil()); 1915 this.proxies = proxies; 1916 } 1917 1918 List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) { 1919 ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>(); 1920 for (TypeAnnotationProxy proxy: proxies) { 1921 Attribute.Compound compound = deproxyCompound(proxy.compound); 1922 Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); 1923 buf.add(typeCompound); 1924 } 1925 return buf.toList(); 1926 } 1927 1928 @Override 1929 public void run() { 1930 JavaFileObject previousClassFile = currentClassFile; 1931 try { 1932 currentClassFile = classFile; 1933 List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies); 1934 sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes())); 1935 } finally { 1936 currentClassFile = previousClassFile; 1937 } 1938 } 1939 } 1940 1941 1942/************************************************************************ 1943 * Reading Symbols 1944 ***********************************************************************/ 1945 1946 /** Read a field. 1947 */ 1948 VarSymbol readField() { 1949 long flags = adjustFieldFlags(nextChar()); 1950 Name name = readName(nextChar()); 1951 Type type = readType(nextChar()); 1952 VarSymbol v = new VarSymbol(flags, name, type, currentOwner); 1953 readMemberAttrs(v); 1954 return v; 1955 } 1956 1957 /** Read a method. 1958 */ 1959 MethodSymbol readMethod() { 1960 long flags = adjustMethodFlags(nextChar()); 1961 Name name = readName(nextChar()); 1962 Type type = readType(nextChar()); 1963 if (currentOwner.isInterface() && 1964 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) { 1965 if (majorVersion > Version.V52.major || 1966 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) { 1967 if ((flags & STATIC) == 0) { 1968 currentOwner.flags_field |= DEFAULT; 1969 flags |= DEFAULT | ABSTRACT; 1970 } 1971 } else { 1972 //protect against ill-formed classfiles 1973 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface", 1974 Integer.toString(majorVersion), 1975 Integer.toString(minorVersion)); 1976 } 1977 } 1978 if (name == names.init && currentOwner.hasOuterInstance()) { 1979 // Sometimes anonymous classes don't have an outer 1980 // instance, however, there is no reliable way to tell so 1981 // we never strip this$n 1982 if (!currentOwner.name.isEmpty()) 1983 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()), 1984 type.getReturnType(), 1985 type.getThrownTypes(), 1986 syms.methodClass); 1987 } 1988 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); 1989 if (types.isSignaturePolymorphic(m)) { 1990 m.flags_field |= SIGNATURE_POLYMORPHIC; 1991 } 1992 if (saveParameterNames) 1993 initParameterNames(m); 1994 Symbol prevOwner = currentOwner; 1995 currentOwner = m; 1996 try { 1997 readMemberAttrs(m); 1998 } finally { 1999 currentOwner = prevOwner; 2000 } 2001 if (saveParameterNames) 2002 setParameterNames(m, type); 2003 return m; 2004 } 2005 2006 private List<Type> adjustMethodParams(long flags, List<Type> args) { 2007 boolean isVarargs = (flags & VARARGS) != 0; 2008 if (isVarargs) { 2009 Type varargsElem = args.last(); 2010 ListBuffer<Type> adjustedArgs = new ListBuffer<>(); 2011 for (Type t : args) { 2012 adjustedArgs.append(t != varargsElem ? 2013 t : 2014 ((ArrayType)t).makeVarargs()); 2015 } 2016 args = adjustedArgs.toList(); 2017 } 2018 return args.tail; 2019 } 2020 2021 /** 2022 * Init the parameter names array. 2023 * Parameter names are currently inferred from the names in the 2024 * LocalVariableTable attributes of a Code attribute. 2025 * (Note: this means parameter names are currently not available for 2026 * methods without a Code attribute.) 2027 * This method initializes an array in which to store the name indexes 2028 * of parameter names found in LocalVariableTable attributes. It is 2029 * slightly supersized to allow for additional slots with a start_pc of 0. 2030 */ 2031 void initParameterNames(MethodSymbol sym) { 2032 // make allowance for synthetic parameters. 2033 final int excessSlots = 4; 2034 int expectedParameterSlots = 2035 Code.width(sym.type.getParameterTypes()) + excessSlots; 2036 if (parameterNameIndices == null 2037 || parameterNameIndices.length < expectedParameterSlots) { 2038 parameterNameIndices = new int[expectedParameterSlots]; 2039 } else 2040 Arrays.fill(parameterNameIndices, 0); 2041 haveParameterNameIndices = false; 2042 sawMethodParameters = false; 2043 } 2044 2045 /** 2046 * Set the parameter names for a symbol from the name index in the 2047 * parameterNameIndicies array. The type of the symbol may have changed 2048 * while reading the method attributes (see the Signature attribute). 2049 * This may be because of generic information or because anonymous 2050 * synthetic parameters were added. The original type (as read from 2051 * the method descriptor) is used to help guess the existence of 2052 * anonymous synthetic parameters. 2053 * On completion, sym.savedParameter names will either be null (if 2054 * no parameter names were found in the class file) or will be set to a 2055 * list of names, one per entry in sym.type.getParameterTypes, with 2056 * any missing names represented by the empty name. 2057 */ 2058 void setParameterNames(MethodSymbol sym, Type jvmType) { 2059 // if no names were found in the class file, there's nothing more to do 2060 if (!haveParameterNameIndices) 2061 return; 2062 // If we get parameter names from MethodParameters, then we 2063 // don't need to skip. 2064 int firstParam = 0; 2065 if (!sawMethodParameters) { 2066 firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; 2067 // the code in readMethod may have skipped the first 2068 // parameter when setting up the MethodType. If so, we 2069 // make a corresponding allowance here for the position of 2070 // the first parameter. Note that this assumes the 2071 // skipped parameter has a width of 1 -- i.e. it is not 2072 // a double width type (long or double.) 2073 if (sym.name == names.init && currentOwner.hasOuterInstance()) { 2074 // Sometimes anonymous classes don't have an outer 2075 // instance, however, there is no reliable way to tell so 2076 // we never strip this$n 2077 if (!currentOwner.name.isEmpty()) 2078 firstParam += 1; 2079 } 2080 2081 if (sym.type != jvmType) { 2082 // reading the method attributes has caused the 2083 // symbol's type to be changed. (i.e. the Signature 2084 // attribute.) This may happen if there are hidden 2085 // (synthetic) parameters in the descriptor, but not 2086 // in the Signature. The position of these hidden 2087 // parameters is unspecified; for now, assume they are 2088 // at the beginning, and so skip over them. The 2089 // primary case for this is two hidden parameters 2090 // passed into Enum constructors. 2091 int skip = Code.width(jvmType.getParameterTypes()) 2092 - Code.width(sym.type.getParameterTypes()); 2093 firstParam += skip; 2094 } 2095 } 2096 List<Name> paramNames = List.nil(); 2097 int index = firstParam; 2098 for (Type t: sym.type.getParameterTypes()) { 2099 int nameIdx = (index < parameterNameIndices.length 2100 ? parameterNameIndices[index] : 0); 2101 Name name = nameIdx == 0 ? names.empty : readName(nameIdx); 2102 paramNames = paramNames.prepend(name); 2103 index += Code.width(t); 2104 } 2105 sym.savedParameterNames = paramNames.reverse(); 2106 } 2107 2108 /** 2109 * skip n bytes 2110 */ 2111 void skipBytes(int n) { 2112 bp = bp + n; 2113 } 2114 2115 /** Skip a field or method 2116 */ 2117 void skipMember() { 2118 bp = bp + 6; 2119 char ac = nextChar(); 2120 for (int i = 0; i < ac; i++) { 2121 bp = bp + 2; 2122 int attrLen = nextInt(); 2123 bp = bp + attrLen; 2124 } 2125 } 2126 2127 /** Enter type variables of this classtype and all enclosing ones in 2128 * `typevars'. 2129 */ 2130 protected void enterTypevars(Type t) { 2131 if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS)) 2132 enterTypevars(t.getEnclosingType()); 2133 for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) 2134 typevars.enter(xs.head.tsym); 2135 } 2136 2137 protected void enterTypevars(Symbol sym) { 2138 if (sym.owner.kind == MTH) { 2139 enterTypevars(sym.owner); 2140 enterTypevars(sym.owner.owner); 2141 } 2142 enterTypevars(sym.type); 2143 } 2144 2145 /** Read contents of a given class symbol `c'. Both external and internal 2146 * versions of an inner class are read. 2147 */ 2148 void readClass(ClassSymbol c) { 2149 ClassType ct = (ClassType)c.type; 2150 2151 // allocate scope for members 2152 c.members_field = WriteableScope.create(c); 2153 2154 // prepare type variable table 2155 typevars = typevars.dup(currentOwner); 2156 if (ct.getEnclosingType().hasTag(CLASS)) 2157 enterTypevars(ct.getEnclosingType()); 2158 2159 // read flags, or skip if this is an inner class 2160 long flags = adjustClassFlags(nextChar()); 2161 if (c.owner.kind == PCK) c.flags_field = flags; 2162 2163 // read own class name and check that it matches 2164 ClassSymbol self = readClassSymbol(nextChar()); 2165 if (c != self) 2166 throw badClassFile("class.file.wrong.class", 2167 self.flatname); 2168 2169 // class attributes must be read before class 2170 // skip ahead to read class attributes 2171 int startbp = bp; 2172 nextChar(); 2173 char interfaceCount = nextChar(); 2174 bp += interfaceCount * 2; 2175 char fieldCount = nextChar(); 2176 for (int i = 0; i < fieldCount; i++) skipMember(); 2177 char methodCount = nextChar(); 2178 for (int i = 0; i < methodCount; i++) skipMember(); 2179 readClassAttrs(c); 2180 2181 if (readAllOfClassFile) { 2182 for (int i = 1; i < poolObj.length; i++) readPool(i); 2183 c.pool = new Pool(poolObj.length, poolObj, types); 2184 } 2185 2186 // reset and read rest of classinfo 2187 bp = startbp; 2188 int n = nextChar(); 2189 if (ct.supertype_field == null) 2190 ct.supertype_field = (n == 0) 2191 ? Type.noType 2192 : readClassSymbol(n).erasure(types); 2193 n = nextChar(); 2194 List<Type> is = List.nil(); 2195 for (int i = 0; i < n; i++) { 2196 Type _inter = readClassSymbol(nextChar()).erasure(types); 2197 is = is.prepend(_inter); 2198 } 2199 if (ct.interfaces_field == null) 2200 ct.interfaces_field = is.reverse(); 2201 2202 Assert.check(fieldCount == nextChar()); 2203 for (int i = 0; i < fieldCount; i++) enterMember(c, readField()); 2204 Assert.check(methodCount == nextChar()); 2205 for (int i = 0; i < methodCount; i++) enterMember(c, readMethod()); 2206 2207 typevars = typevars.leave(); 2208 } 2209 2210 /** Read inner class info. For each inner/outer pair allocate a 2211 * member class. 2212 */ 2213 void readInnerClasses(ClassSymbol c) { 2214 int n = nextChar(); 2215 for (int i = 0; i < n; i++) { 2216 nextChar(); // skip inner class symbol 2217 ClassSymbol outer = readClassSymbol(nextChar()); 2218 Name name = readName(nextChar()); 2219 if (name == null) name = names.empty; 2220 long flags = adjustClassFlags(nextChar()); 2221 if (outer != null) { // we have a member class 2222 if (name == names.empty) 2223 name = names.one; 2224 ClassSymbol member = syms.enterClass(name, outer); 2225 if ((flags & STATIC) == 0) { 2226 ((ClassType)member.type).setEnclosingType(outer.type); 2227 if (member.erasure_field != null) 2228 ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type)); 2229 } 2230 if (c == outer) { 2231 member.flags_field = flags; 2232 enterMember(c, member); 2233 } 2234 } 2235 } 2236 } 2237 2238 /** Read a class definition from the bytes in buf. 2239 */ 2240 private void readClassBuffer(ClassSymbol c) throws IOException { 2241 int magic = nextInt(); 2242 if (magic != JAVA_MAGIC) 2243 throw badClassFile("illegal.start.of.class.file"); 2244 2245 minorVersion = nextChar(); 2246 majorVersion = nextChar(); 2247 int maxMajor = Version.MAX().major; 2248 int maxMinor = Version.MAX().minor; 2249 if (majorVersion > maxMajor || 2250 majorVersion * 1000 + minorVersion < 2251 Version.MIN().major * 1000 + Version.MIN().minor) 2252 { 2253 if (majorVersion == (maxMajor + 1)) 2254 log.warning("big.major.version", 2255 currentClassFile, 2256 majorVersion, 2257 maxMajor); 2258 else 2259 throw badClassFile("wrong.version", 2260 Integer.toString(majorVersion), 2261 Integer.toString(minorVersion), 2262 Integer.toString(maxMajor), 2263 Integer.toString(maxMinor)); 2264 } 2265 else if (checkClassFile && 2266 majorVersion == maxMajor && 2267 minorVersion > maxMinor) 2268 { 2269 printCCF("found.later.version", 2270 Integer.toString(minorVersion)); 2271 } 2272 indexPool(); 2273 if (signatureBuffer.length < bp) { 2274 int ns = Integer.highestOneBit(bp) << 1; 2275 signatureBuffer = new byte[ns]; 2276 } 2277 readClass(c); 2278 } 2279 2280 public void readClassFile(ClassSymbol c) { 2281 currentOwner = c; 2282 currentClassFile = c.classfile; 2283 warnedAttrs.clear(); 2284 filling = true; 2285 try { 2286 bp = 0; 2287 buf = readInputStream(buf, c.classfile.openInputStream()); 2288 readClassBuffer(c); 2289 if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) { 2290 List<Type> missing = missingTypeVariables; 2291 List<Type> found = foundTypeVariables; 2292 missingTypeVariables = List.nil(); 2293 foundTypeVariables = List.nil(); 2294 filling = false; 2295 ClassType ct = (ClassType)currentOwner.type; 2296 ct.supertype_field = 2297 types.subst(ct.supertype_field, missing, found); 2298 ct.interfaces_field = 2299 types.subst(ct.interfaces_field, missing, found); 2300 } else if (missingTypeVariables.isEmpty() != 2301 foundTypeVariables.isEmpty()) { 2302 Name name = missingTypeVariables.head.tsym.name; 2303 throw badClassFile("undecl.type.var", name); 2304 } 2305 } catch (IOException ex) { 2306 throw badClassFile("unable.to.access.file", ex.getMessage()); 2307 } catch (ArrayIndexOutOfBoundsException ex) { 2308 throw badClassFile("bad.class.file", c.flatname); 2309 } finally { 2310 missingTypeVariables = List.nil(); 2311 foundTypeVariables = List.nil(); 2312 filling = false; 2313 } 2314 } 2315 // where 2316 private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException { 2317 try { 2318 buf = ensureCapacity(buf, s.available()); 2319 int r = s.read(buf); 2320 int bp = 0; 2321 while (r != -1) { 2322 bp += r; 2323 buf = ensureCapacity(buf, bp); 2324 r = s.read(buf, bp, buf.length - bp); 2325 } 2326 return buf; 2327 } finally { 2328 try { 2329 s.close(); 2330 } catch (IOException e) { 2331 /* Ignore any errors, as this stream may have already 2332 * thrown a related exception which is the one that 2333 * should be reported. 2334 */ 2335 } 2336 } 2337 } 2338 /* 2339 * ensureCapacity will increase the buffer as needed, taking note that 2340 * the new buffer will always be greater than the needed and never 2341 * exactly equal to the needed size or bp. If equal then the read (above) 2342 * will infinitely loop as buf.length - bp == 0. 2343 */ 2344 private static byte[] ensureCapacity(byte[] buf, int needed) { 2345 if (buf.length <= needed) { 2346 byte[] old = buf; 2347 buf = new byte[Integer.highestOneBit(needed) << 1]; 2348 System.arraycopy(old, 0, buf, 0, old.length); 2349 } 2350 return buf; 2351 } 2352 2353 /** We can only read a single class file at a time; this 2354 * flag keeps track of when we are currently reading a class 2355 * file. 2356 */ 2357 public boolean filling = false; 2358 2359/************************************************************************ 2360 * Adjusting flags 2361 ***********************************************************************/ 2362 2363 long adjustFieldFlags(long flags) { 2364 return flags; 2365 } 2366 2367 long adjustMethodFlags(long flags) { 2368 if ((flags & ACC_BRIDGE) != 0) { 2369 flags &= ~ACC_BRIDGE; 2370 flags |= BRIDGE; 2371 } 2372 if ((flags & ACC_VARARGS) != 0) { 2373 flags &= ~ACC_VARARGS; 2374 flags |= VARARGS; 2375 } 2376 return flags; 2377 } 2378 2379 long adjustClassFlags(long flags) { 2380 return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded 2381 } 2382 2383 /** Output for "-checkclassfile" option. 2384 * @param key The key to look up the correct internationalized string. 2385 * @param arg An argument for substitution into the output string. 2386 */ 2387 private void printCCF(String key, Object arg) { 2388 log.printLines(key, arg); 2389 } 2390 2391 /** 2392 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile. 2393 * The attribute is only the last component of the original filename, so is unlikely 2394 * to be valid as is, so operations other than those to access the name throw 2395 * UnsupportedOperationException 2396 */ 2397 private static class SourceFileObject extends BaseFileObject { 2398 2399 /** The file's name. 2400 */ 2401 private Name name; 2402 private Name flatname; 2403 2404 public SourceFileObject(Name name, Name flatname) { 2405 super(null); // no file manager; never referenced for this file object 2406 this.name = name; 2407 this.flatname = flatname; 2408 } 2409 2410 @Override @DefinedBy(Api.COMPILER) 2411 public URI toUri() { 2412 try { 2413 return new URI(null, name.toString(), null); 2414 } catch (URISyntaxException e) { 2415 throw new CannotCreateUriError(name.toString(), e); 2416 } 2417 } 2418 2419 @Override @DefinedBy(Api.COMPILER) 2420 public String getName() { 2421 return name.toString(); 2422 } 2423 2424 @Override 2425 public String getShortName() { 2426 return getName(); 2427 } 2428 2429 @Override @DefinedBy(Api.COMPILER) 2430 public JavaFileObject.Kind getKind() { 2431 return getKind(getName()); 2432 } 2433 2434 @Override @DefinedBy(Api.COMPILER) 2435 public InputStream openInputStream() { 2436 throw new UnsupportedOperationException(); 2437 } 2438 2439 @Override @DefinedBy(Api.COMPILER) 2440 public OutputStream openOutputStream() { 2441 throw new UnsupportedOperationException(); 2442 } 2443 2444 @Override @DefinedBy(Api.COMPILER) 2445 public CharBuffer getCharContent(boolean ignoreEncodingErrors) { 2446 throw new UnsupportedOperationException(); 2447 } 2448 2449 @Override @DefinedBy(Api.COMPILER) 2450 public Reader openReader(boolean ignoreEncodingErrors) { 2451 throw new UnsupportedOperationException(); 2452 } 2453 2454 @Override @DefinedBy(Api.COMPILER) 2455 public Writer openWriter() { 2456 throw new UnsupportedOperationException(); 2457 } 2458 2459 @Override @DefinedBy(Api.COMPILER) 2460 public long getLastModified() { 2461 throw new UnsupportedOperationException(); 2462 } 2463 2464 @Override @DefinedBy(Api.COMPILER) 2465 public boolean delete() { 2466 throw new UnsupportedOperationException(); 2467 } 2468 2469 @Override 2470 protected String inferBinaryName(Iterable<? extends File> path) { 2471 return flatname.toString(); 2472 } 2473 2474 @Override @DefinedBy(Api.COMPILER) 2475 public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { 2476 return true; // fail-safe mode 2477 } 2478 2479 /** 2480 * Check if two file objects are equal. 2481 * SourceFileObjects are just placeholder objects for the value of a 2482 * SourceFile attribute, and do not directly represent specific files. 2483 * Two SourceFileObjects are equal if their names are equal. 2484 */ 2485 @Override 2486 public boolean equals(Object other) { 2487 if (this == other) 2488 return true; 2489 2490 if (!(other instanceof SourceFileObject)) 2491 return false; 2492 2493 SourceFileObject o = (SourceFileObject) other; 2494 return name.equals(o.name); 2495 } 2496 2497 @Override 2498 public int hashCode() { 2499 return name.hashCode(); 2500 } 2501 } 2502} 2503