1 /* 2 * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.classfile.impl; 27 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.List; 31 import java.util.Optional; 32 import java.util.function.Function; 33 34 import java.lang.classfile.*; 35 import java.lang.classfile.attribute.*; 36 import java.lang.classfile.constantpool.ClassEntry; 37 import java.lang.classfile.constantpool.ConstantPool; 38 import java.lang.classfile.constantpool.ConstantValueEntry; 39 import java.lang.classfile.constantpool.LoadableConstantEntry; 40 import java.lang.classfile.constantpool.ModuleEntry; 41 import java.lang.classfile.constantpool.NameAndTypeEntry; 42 import java.lang.classfile.constantpool.PackageEntry; 43 import java.lang.classfile.constantpool.Utf8Entry; 44 import jdk.internal.access.SharedSecrets; 45 46 import static java.lang.classfile.Attributes.*; 47 48 public abstract sealed class BoundAttribute<T extends Attribute<T>> 49 extends AbstractElement 50 implements Attribute<T> { 51 52 static final int NAME_AND_LENGTH_PREFIX = 6; 53 private final AttributeMapper<T> mapper; 54 final ClassReaderImpl classReader; 55 final int payloadStart; 56 57 BoundAttribute(ClassReader classReader, AttributeMapper<T> mapper, int payloadStart) { 58 this.mapper = mapper; 59 this.classReader = (ClassReaderImpl)classReader; 60 this.payloadStart = payloadStart; 61 } 62 63 public int payloadLen() { 64 return classReader.readInt(payloadStart - 4); 65 } 66 67 @Override 68 public String attributeName() { 69 return mapper.name(); 70 } 71 72 @Override 73 public AttributeMapper<T> attributeMapper() { 74 return mapper; 75 } 76 77 public byte[] contents() { 78 return classReader.readBytes(payloadStart, payloadLen()); 79 } 80 81 @Override 82 public void writeTo(DirectClassBuilder builder) { 83 builder.writeAttribute(this); 84 } 85 86 @Override 87 public void writeTo(DirectCodeBuilder builder) { 88 builder.writeAttribute(this); 89 } 90 91 @Override 92 public void writeTo(DirectMethodBuilder builder) { 93 builder.writeAttribute(this); 94 } 95 96 @Override 97 public void writeTo(DirectFieldBuilder builder) { 98 builder.writeAttribute(this); 99 } 100 101 @Override 102 @SuppressWarnings("unchecked") 103 public void writeTo(BufWriter buf) { 104 if (!buf.canWriteDirect(classReader)) 105 attributeMapper().writeAttribute(buf, (T) this); 106 else 107 classReader.copyBytesTo(buf, payloadStart - NAME_AND_LENGTH_PREFIX, payloadLen() + NAME_AND_LENGTH_PREFIX); 108 } 109 110 public ConstantPool constantPool() { 111 return classReader; 112 } 113 114 @Override 115 public String toString() { 116 return String.format("Attribute[name=%s]", mapper.name()); 117 } 118 119 <E> List<E> readEntryList(int p) { 120 int cnt = classReader.readU2(p); 121 p += 2; 122 var entries = new Object[cnt]; 123 int end = p + (cnt * 2); 124 for (int i = 0; p < end; i++, p += 2) { 125 entries[i] = classReader.readEntry(p); 126 } 127 return SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(entries); 128 } 129 130 public static List<Attribute<?>> readAttributes(AttributedElement enclosing, ClassReader reader, int pos, 131 Function<Utf8Entry, AttributeMapper<?>> customAttributes) { 132 int size = reader.readU2(pos); 133 var filled = new ArrayList<Attribute<?>>(size); 134 int p = pos + 2; 135 int cfLen = reader.classfileLength(); 136 var apo = ((ClassReaderImpl)reader).context().attributesProcessingOption(); 137 for (int i = 0; i < size; ++i) { 138 Utf8Entry name = reader.readUtf8Entry(p); 139 int len = reader.readInt(p + 2); 140 p += 6; 141 if (len < 0 || len > cfLen - p) { 142 throw new IllegalArgumentException("attribute " + name.stringValue() + " too big to handle"); 143 } 144 145 var mapper = standardAttribute(name); 146 if (mapper == null) { 147 mapper = customAttributes.apply(name); 148 } 149 if (mapper != null) { 150 filled.add((Attribute)mapper.readAttribute(enclosing, reader, p)); 151 } else { 152 AttributeMapper<UnknownAttribute> fakeMapper = new AttributeMapper<>() { 153 @Override 154 public String name() { 155 return name.stringValue(); 156 } 157 158 @Override 159 public UnknownAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) { 160 // Will never get called 161 throw new UnsupportedOperationException(); 162 } 163 164 @Override 165 public void writeAttribute(BufWriter buf, UnknownAttribute attr) { 166 buf.writeIndex(name); 167 var cont = attr.contents(); 168 buf.writeInt(cont.length); 169 buf.writeBytes(cont); 170 } 171 172 @Override 173 public boolean allowMultiple() { 174 return true; 175 } 176 177 @Override 178 public AttributeMapper.AttributeStability stability() { 179 return AttributeStability.UNKNOWN; 180 } 181 }; 182 filled.add(new BoundUnknownAttribute(reader, fakeMapper, p)); 183 } 184 p += len; 185 } 186 return Collections.unmodifiableList(filled); 187 } 188 189 public static final class BoundUnknownAttribute extends BoundAttribute<UnknownAttribute> 190 implements UnknownAttribute { 191 public BoundUnknownAttribute(ClassReader cf, AttributeMapper<UnknownAttribute> mapper, int pos) { 192 super(cf, mapper, pos); 193 } 194 } 195 196 public static final class BoundStackMapTableAttribute 197 extends BoundAttribute<StackMapTableAttribute> 198 implements StackMapTableAttribute { 199 final MethodModel method; 200 final LabelContext ctx; 201 List<StackMapFrameInfo> entries = null; 202 203 public BoundStackMapTableAttribute(CodeImpl code, ClassReader cf, AttributeMapper<StackMapTableAttribute> mapper, int pos) { 204 super(cf, mapper, pos); 205 method = code.parent().orElseThrow(); 206 ctx = code; 207 } 208 209 @Override 210 public List<StackMapFrameInfo> entries() { 211 if (entries == null) { 212 entries = new StackMapDecoder(classReader, payloadStart, ctx, StackMapDecoder.initFrameLocals(method)).entries(); 213 } 214 return entries; 215 } 216 } 217 218 public static final class BoundSyntheticAttribute extends BoundAttribute<SyntheticAttribute> 219 implements SyntheticAttribute { 220 public BoundSyntheticAttribute(ClassReader cf, AttributeMapper<SyntheticAttribute> mapper, int pos) { 221 super(cf, mapper, pos); 222 } 223 } 224 225 public static final class BoundLineNumberTableAttribute 226 extends BoundAttribute<LineNumberTableAttribute> 227 implements LineNumberTableAttribute { 228 private List<LineNumberInfo> lineNumbers = null; 229 230 public BoundLineNumberTableAttribute(ClassReader cf, AttributeMapper<LineNumberTableAttribute> mapper, int pos) { 231 super(cf, mapper, pos); 232 } 233 234 @Override 235 public List<LineNumberInfo> lineNumbers() { 236 if (lineNumbers == null) { 237 int nLn = classReader.readU2(payloadStart); 238 LineNumberInfo[] elements = new LineNumberInfo[nLn]; 239 int p = payloadStart + 2; 240 int pEnd = p + (nLn * 4); 241 for (int i = 0; p < pEnd; p += 4, i++) { 242 int startPc = classReader.readU2(p); 243 int lineNumber = classReader.readU2(p + 2); 244 elements[i] = LineNumberInfo.of(startPc, lineNumber); 245 } 246 lineNumbers = List.of(elements); 247 } 248 return lineNumbers; 249 } 250 } 251 252 public static final class BoundCharacterRangeTableAttribute extends BoundAttribute<CharacterRangeTableAttribute> implements CharacterRangeTableAttribute { 253 private List<CharacterRangeInfo> characterRangeTable = null; 254 255 public BoundCharacterRangeTableAttribute(ClassReader cf, AttributeMapper<CharacterRangeTableAttribute> mapper, int pos) { 256 super(cf, mapper, pos); 257 } 258 259 @Override 260 public List<CharacterRangeInfo> characterRangeTable() { 261 if (characterRangeTable == null) { 262 int nLn = classReader.readU2(payloadStart); 263 CharacterRangeInfo[] elements = new CharacterRangeInfo[nLn]; 264 int p = payloadStart + 2; 265 int pEnd = p + (nLn * 14); 266 for (int i = 0; p < pEnd; p += 14, i++) { 267 int startPc = classReader.readU2(p); 268 int endPc = classReader.readU2(p + 2); 269 int characterRangeStart = classReader.readInt(p + 4); 270 int characterRangeEnd = classReader.readInt(p + 8); 271 int flags = classReader.readU2(p + 12); 272 elements[i] = CharacterRangeInfo.of(startPc, endPc, characterRangeStart, characterRangeEnd, flags); 273 } 274 characterRangeTable = List.of(elements); 275 } 276 return characterRangeTable; 277 } 278 } 279 280 public static final class BoundLocalVariableTableAttribute 281 extends BoundAttribute<LocalVariableTableAttribute> 282 implements LocalVariableTableAttribute { 283 private final CodeImpl codeAttribute; 284 private List<LocalVariableInfo> localVars = null; 285 286 public BoundLocalVariableTableAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<LocalVariableTableAttribute> mapper, int pos) { 287 super(cf, mapper, pos); 288 codeAttribute = (CodeImpl) enclosing; 289 } 290 291 @Override 292 public List<LocalVariableInfo> localVariables() { 293 if (localVars == null) { 294 int cnt = classReader.readU2(payloadStart); 295 BoundLocalVariable[] elements = new BoundLocalVariable[cnt]; 296 int p = payloadStart + 2; 297 int pEnd = p + (cnt * 10); 298 for (int i = 0; p < pEnd; p += 10, i++) { 299 elements[i] = new BoundLocalVariable(codeAttribute, p); 300 } 301 localVars = List.of(elements); 302 } 303 return localVars; 304 } 305 } 306 307 public static final class BoundLocalVariableTypeTableAttribute 308 extends BoundAttribute<LocalVariableTypeTableAttribute> 309 implements LocalVariableTypeTableAttribute { 310 private final CodeImpl codeAttribute; 311 private List<LocalVariableTypeInfo> localVars = null; 312 313 public BoundLocalVariableTypeTableAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<LocalVariableTypeTableAttribute> mapper, int pos) { 314 super(cf, mapper, pos); 315 this.codeAttribute = (CodeImpl) enclosing; 316 } 317 318 @Override 319 public List<LocalVariableTypeInfo> localVariableTypes() { 320 if (localVars == null) { 321 final int cnt = classReader.readU2(payloadStart); 322 BoundLocalVariableType[] elements = new BoundLocalVariableType[cnt]; 323 int p = payloadStart + 2; 324 int pEnd = p + (cnt * 10); 325 for (int i = 0; p < pEnd; p += 10, i++) { 326 elements[i] = new BoundLocalVariableType(codeAttribute, p); 327 } 328 localVars = List.of(elements); 329 } 330 return localVars; 331 } 332 } 333 334 public static final class BoundMethodParametersAttribute extends BoundAttribute<MethodParametersAttribute> 335 implements MethodParametersAttribute { 336 private List<MethodParameterInfo> parameters = null; 337 338 public BoundMethodParametersAttribute(ClassReader cf, AttributeMapper<MethodParametersAttribute> mapper, int pos) { 339 super(cf, mapper, pos); 340 } 341 342 @Override 343 public List<MethodParameterInfo> parameters() { 344 if (parameters == null) { 345 final int cnt = classReader.readU1(payloadStart); 346 MethodParameterInfo[] elements = new MethodParameterInfo[cnt]; 347 int p = payloadStart + 1; 348 int pEnd = p + (cnt * 4); 349 for (int i = 0; p < pEnd; p += 4, i++) { 350 Utf8Entry name = classReader.readUtf8EntryOrNull(p); 351 int accessFlags = classReader.readU2(p + 2); 352 elements[i] = MethodParameterInfo.of(Optional.ofNullable(name), accessFlags); 353 } 354 parameters = List.of(elements); 355 } 356 return parameters; 357 } 358 } 359 360 public static final class BoundModuleHashesAttribute extends BoundAttribute<ModuleHashesAttribute> 361 implements ModuleHashesAttribute { 362 private List<ModuleHashInfo> hashes = null; 363 364 public BoundModuleHashesAttribute(ClassReader cf, AttributeMapper<ModuleHashesAttribute> mapper, int pos) { 365 super(cf, mapper, pos); 366 } 367 368 @Override 369 public Utf8Entry algorithm() { 370 return classReader.readUtf8Entry(payloadStart); 371 } 372 373 @Override 374 public List<ModuleHashInfo> hashes() { 375 if (hashes == null) { 376 final int cnt = classReader.readU2(payloadStart + 2); 377 ModuleHashInfo[] elements = new ModuleHashInfo[cnt]; 378 int p = payloadStart + 4; 379 //System.err.printf("%5d: ModuleHashesAttr alg = %s, cnt = %d%n", pos, algorithm(), cnt); 380 for (int i = 0; i < cnt; ++i) { 381 ModuleEntry module = classReader.readModuleEntry(p); 382 int hashLength = classReader.readU2(p + 2); 383 //System.err.printf("%5d: [%d] module = %s, hashLength = %d%n", p, i, module, hashLength); 384 p += 4; 385 elements[i] = ModuleHashInfo.of(module, classReader.readBytes(p, hashLength)); 386 p += hashLength; 387 } 388 hashes = List.of(elements); 389 } 390 return hashes; 391 } 392 } 393 394 public static final class BoundRecordAttribute extends BoundAttribute<RecordAttribute> 395 implements RecordAttribute { 396 private List<RecordComponentInfo> components = null; 397 398 public BoundRecordAttribute(ClassReader cf, AttributeMapper<RecordAttribute> mapper, int pos) { 399 super(cf, mapper, pos); 400 } 401 402 @Override 403 public List<RecordComponentInfo> components() { 404 if (components == null) { 405 final int cnt = classReader.readU2(payloadStart); 406 RecordComponentInfo[] elements = new RecordComponentInfo[cnt]; 407 int p = payloadStart + 2; 408 for (int i = 0; i < cnt; i++) { 409 elements[i] = new BoundRecordComponentInfo(classReader, p); 410 p = classReader.skipAttributeHolder(p + 4); 411 } 412 components = List.of(elements); 413 } 414 return components; 415 } 416 } 417 418 public static final class BoundDeprecatedAttribute extends BoundAttribute<DeprecatedAttribute> 419 implements DeprecatedAttribute { 420 public BoundDeprecatedAttribute(ClassReader cf, AttributeMapper<DeprecatedAttribute> mapper, int pos) { 421 super(cf, mapper, pos); 422 } 423 } 424 425 public static final class BoundSignatureAttribute extends BoundAttribute<SignatureAttribute> 426 implements SignatureAttribute { 427 public BoundSignatureAttribute(ClassReader cf, AttributeMapper<SignatureAttribute> mapper, int pos) { 428 super(cf, mapper, pos); 429 } 430 431 @Override 432 public Utf8Entry signature() { 433 return classReader.readUtf8Entry(payloadStart); 434 } 435 } 436 437 public static final class BoundSourceFileAttribute extends BoundAttribute<SourceFileAttribute> 438 implements SourceFileAttribute { 439 public BoundSourceFileAttribute(ClassReader cf, AttributeMapper<SourceFileAttribute> mapper, int pos) { 440 super(cf, mapper, pos); 441 } 442 443 @Override 444 public Utf8Entry sourceFile() { 445 return classReader.readUtf8Entry(payloadStart); 446 } 447 448 } 449 450 public static final class BoundModuleMainClassAttribute extends BoundAttribute<ModuleMainClassAttribute> implements ModuleMainClassAttribute { 451 public BoundModuleMainClassAttribute(ClassReader cf, AttributeMapper<ModuleMainClassAttribute> mapper, int pos) { 452 super(cf, mapper, pos); 453 } 454 455 @Override 456 public ClassEntry mainClass() { 457 return classReader.readClassEntry(payloadStart); 458 } 459 } 460 461 public static final class BoundNestHostAttribute extends BoundAttribute<NestHostAttribute> 462 implements NestHostAttribute { 463 public BoundNestHostAttribute(ClassReader cf, AttributeMapper<NestHostAttribute> mapper, int pos) { 464 super(cf, mapper, pos); 465 } 466 467 @Override 468 public ClassEntry nestHost() { 469 return classReader.readClassEntry(payloadStart); 470 } 471 } 472 473 public static final class BoundSourceDebugExtensionAttribute extends BoundAttribute<SourceDebugExtensionAttribute> 474 implements SourceDebugExtensionAttribute { 475 public BoundSourceDebugExtensionAttribute(ClassReader cf, AttributeMapper<SourceDebugExtensionAttribute> mapper, int pos) { 476 super(cf, mapper, pos); 477 } 478 } 479 480 public static final class BoundConstantValueAttribute extends BoundAttribute<ConstantValueAttribute> 481 implements ConstantValueAttribute { 482 public BoundConstantValueAttribute(ClassReader cf, AttributeMapper<ConstantValueAttribute> mapper, int pos) { 483 super(cf, mapper, pos); 484 } 485 486 @Override 487 public ConstantValueEntry constant() { 488 return classReader.readEntry(payloadStart, ConstantValueEntry.class); 489 } 490 491 } 492 493 public static final class BoundModuleTargetAttribute extends BoundAttribute<ModuleTargetAttribute> 494 implements ModuleTargetAttribute { 495 public BoundModuleTargetAttribute(ClassReader cf, AttributeMapper<ModuleTargetAttribute> mapper, int pos) { 496 super(cf, mapper, pos); 497 } 498 499 @Override 500 public Utf8Entry targetPlatform() { 501 return classReader.readUtf8Entry(payloadStart); 502 } 503 } 504 505 public static final class BoundCompilationIDAttribute extends BoundAttribute<CompilationIDAttribute> 506 implements CompilationIDAttribute { 507 public BoundCompilationIDAttribute(ClassReader cf, AttributeMapper<CompilationIDAttribute> mapper, int pos) { 508 super(cf, mapper, pos); 509 } 510 511 @Override 512 public Utf8Entry compilationId() { 513 return classReader.readUtf8Entry(payloadStart); 514 } 515 } 516 517 public static final class BoundSourceIDAttribute extends BoundAttribute<SourceIDAttribute> 518 implements SourceIDAttribute { 519 public BoundSourceIDAttribute(ClassReader cf, AttributeMapper<SourceIDAttribute> mapper, int pos) { 520 super(cf, mapper, pos); 521 } 522 523 @Override 524 public Utf8Entry sourceId() { 525 return classReader.readUtf8Entry(payloadStart); 526 } 527 } 528 529 public static final class BoundModuleResolutionAttribute extends BoundAttribute<ModuleResolutionAttribute> 530 implements ModuleResolutionAttribute { 531 public BoundModuleResolutionAttribute(ClassReader cf, AttributeMapper<ModuleResolutionAttribute> mapper, int pos) { 532 super(cf, mapper, pos); 533 } 534 535 @Override 536 public int resolutionFlags() { 537 return classReader.readU2(payloadStart); 538 } 539 } 540 541 public static final class BoundExceptionsAttribute extends BoundAttribute<ExceptionsAttribute> 542 implements ExceptionsAttribute { 543 private List<ClassEntry> exceptions = null; 544 545 public BoundExceptionsAttribute(ClassReader cf, AttributeMapper<ExceptionsAttribute> mapper, int pos) { 546 super(cf, mapper, pos); 547 } 548 549 @Override 550 public List<ClassEntry> exceptions() { 551 if (exceptions == null) { 552 exceptions = readEntryList(payloadStart); 553 } 554 return exceptions; 555 } 556 } 557 558 public static final class BoundModuleAttribute extends BoundAttribute<ModuleAttribute> 559 implements ModuleAttribute { 560 private List<ModuleRequireInfo> requires = null; 561 private List<ModuleExportInfo> exports = null; 562 private List<ModuleOpenInfo> opens = null; 563 private List<ClassEntry> uses = null; 564 private List<ModuleProvideInfo> provides = null; 565 566 public BoundModuleAttribute(ClassReader cf, AttributeMapper<ModuleAttribute> mapper, int pos) { 567 super(cf, mapper, pos); 568 } 569 570 @Override 571 public ModuleEntry moduleName() { 572 return classReader.readModuleEntry(payloadStart); 573 } 574 575 @Override 576 public int moduleFlagsMask() { 577 return classReader.readU2(payloadStart + 2); 578 } 579 580 @Override 581 public Optional<Utf8Entry> moduleVersion() { 582 return Optional.ofNullable(classReader.readUtf8EntryOrNull(payloadStart + 4)); 583 } 584 585 @Override 586 public List<ModuleRequireInfo> requires() { 587 if (requires == null) { 588 structure(); 589 } 590 return requires; 591 } 592 593 @Override 594 public List<ModuleExportInfo> exports() { 595 if (exports == null) { 596 structure(); 597 } 598 return exports; 599 } 600 601 @Override 602 public List<ModuleOpenInfo> opens() { 603 if (opens == null) { 604 structure(); 605 } 606 return opens; 607 } 608 609 @Override 610 public List<ClassEntry> uses() { 611 if (uses == null) { 612 structure(); 613 } 614 return uses; 615 } 616 617 @Override 618 public List<ModuleProvideInfo> provides() { 619 if (provides == null) { 620 structure(); 621 } 622 return provides; 623 } 624 625 private void structure() { 626 int p = payloadStart + 8; 627 628 { 629 int cnt = classReader.readU2(payloadStart + 6); 630 ModuleRequireInfo[] elements = new ModuleRequireInfo[cnt]; 631 int end = p + (cnt * 6); 632 for (int i = 0; p < end; p += 6, i++) { 633 elements[i] = ModuleRequireInfo.of(classReader.readModuleEntry(p), 634 classReader.readU2(p + 2), 635 classReader.readEntryOrNull(p + 4, Utf8Entry.class)); 636 } 637 requires = List.of(elements); 638 } 639 640 { 641 int cnt = classReader.readU2(p); 642 p += 2; 643 ModuleExportInfo[] elements = new ModuleExportInfo[cnt]; 644 for (int i = 0; i < cnt; i++) { 645 PackageEntry pe = classReader.readPackageEntry(p); 646 int exportFlags = classReader.readU2(p + 2); 647 p += 4; 648 List<ModuleEntry> exportsTo = readEntryList(p); 649 p += 2 + exportsTo.size() * 2; 650 elements[i] = ModuleExportInfo.of(pe, exportFlags, exportsTo); 651 } 652 exports = List.of(elements); 653 } 654 655 { 656 int cnt = classReader.readU2(p); 657 p += 2; 658 ModuleOpenInfo[] elements = new ModuleOpenInfo[cnt]; 659 for (int i = 0; i < cnt; i++) { 660 PackageEntry po = classReader.readPackageEntry(p); 661 int opensFlags = classReader.readU2(p + 2); 662 p += 4; 663 List<ModuleEntry> opensTo = readEntryList(p); 664 p += 2 + opensTo.size() * 2; 665 elements[i] = ModuleOpenInfo.of(po, opensFlags, opensTo); 666 } 667 opens = List.of(elements); 668 } 669 670 { 671 uses = readEntryList(p); 672 p += 2 + uses.size() * 2; 673 int cnt = classReader.readU2(p); 674 p += 2; 675 ModuleProvideInfo[] elements = new ModuleProvideInfo[cnt]; 676 provides = new ArrayList<>(cnt); 677 for (int i = 0; i < cnt; i++) { 678 ClassEntry c = classReader.readClassEntry(p); 679 p += 2; 680 List<ClassEntry> providesWith = readEntryList(p); 681 p += 2 + providesWith.size() * 2; 682 elements[i] = ModuleProvideInfo.of(c, providesWith); 683 } 684 provides = List.of(elements); 685 } 686 } 687 } 688 689 public static final class BoundModulePackagesAttribute extends BoundAttribute<ModulePackagesAttribute> 690 implements ModulePackagesAttribute { 691 private List<PackageEntry> packages = null; 692 693 public BoundModulePackagesAttribute(ClassReader cf, AttributeMapper<ModulePackagesAttribute> mapper, int pos) { 694 super(cf, mapper, pos); 695 } 696 697 @Override 698 public List<PackageEntry> packages() { 699 if (packages == null) { 700 packages = readEntryList(payloadStart); 701 } 702 return packages; 703 } 704 } 705 706 public static final class BoundNestMembersAttribute extends BoundAttribute<NestMembersAttribute> 707 implements NestMembersAttribute { 708 709 private List<ClassEntry> members = null; 710 711 public BoundNestMembersAttribute(ClassReader cf, AttributeMapper<NestMembersAttribute> mapper, int pos) { 712 super(cf, mapper, pos); 713 } 714 715 @Override 716 public List<ClassEntry> nestMembers() { 717 if (members == null) { 718 members = readEntryList(payloadStart); 719 } 720 return members; 721 } 722 } 723 724 public static final class BoundBootstrapMethodsAttribute extends BoundAttribute<BootstrapMethodsAttribute> 725 implements BootstrapMethodsAttribute { 726 727 private List<BootstrapMethodEntry> bootstraps = null; 728 private final int size; 729 730 public BoundBootstrapMethodsAttribute(ClassReader reader, AttributeMapper<BootstrapMethodsAttribute> mapper, int pos) { 731 super(reader, mapper, pos); 732 size = classReader.readU2(pos); 733 } 734 735 @Override 736 public int bootstrapMethodsSize() { 737 return size; 738 } 739 740 @Override 741 public List<BootstrapMethodEntry> bootstrapMethods() { 742 if (bootstraps == null) { 743 BootstrapMethodEntry[] bs = new BootstrapMethodEntry[size]; 744 int p = payloadStart + 2; 745 for (int i = 0; i < size; ++i) { 746 final AbstractPoolEntry.MethodHandleEntryImpl handle 747 = (AbstractPoolEntry.MethodHandleEntryImpl) classReader.readMethodHandleEntry(p); 748 final List<LoadableConstantEntry> args = readEntryList(p + 2); 749 p += 4 + args.size() * 2; 750 int hash = BootstrapMethodEntryImpl.computeHashCode(handle, args); 751 bs[i] = new BootstrapMethodEntryImpl(classReader, i, hash, handle, args); 752 } 753 bootstraps = List.of(bs); 754 } 755 return bootstraps; 756 } 757 } 758 759 public static final class BoundInnerClassesAttribute extends BoundAttribute<InnerClassesAttribute> 760 implements InnerClassesAttribute { 761 private List<InnerClassInfo> classes; 762 763 public BoundInnerClassesAttribute(ClassReader cf, AttributeMapper<InnerClassesAttribute> mapper, int pos) { 764 super(cf, mapper, pos); 765 } 766 767 @Override 768 public List<InnerClassInfo> classes() { 769 if (classes == null) { 770 final int cnt = classReader.readU2(payloadStart); 771 int p = payloadStart + 2; 772 InnerClassInfo[] elements = new InnerClassInfo[cnt]; 773 for (int i = 0; i < cnt; i++) { 774 ClassEntry innerClass = classReader.readClassEntry(p); 775 var outerClass = classReader.readEntryOrNull(p + 2, ClassEntry.class); 776 var innerName = classReader.readEntryOrNull(p + 4, Utf8Entry.class); 777 int flags = classReader.readU2(p + 6); 778 p += 8; 779 elements[i] = InnerClassInfo.of(innerClass, Optional.ofNullable(outerClass), Optional.ofNullable(innerName), flags); 780 } 781 classes = List.of(elements); 782 } 783 return classes; 784 } 785 } 786 787 public static final class BoundEnclosingMethodAttribute extends BoundAttribute<EnclosingMethodAttribute> 788 implements EnclosingMethodAttribute { 789 public BoundEnclosingMethodAttribute(ClassReader cf, AttributeMapper<EnclosingMethodAttribute> mapper, int pos) { 790 super(cf, mapper, pos); 791 } 792 793 @Override 794 public ClassEntry enclosingClass() { 795 return classReader.readClassEntry(payloadStart); 796 } 797 798 @Override 799 public Optional<NameAndTypeEntry> enclosingMethod() { 800 return Optional.ofNullable(classReader.readEntryOrNull(payloadStart + 2, NameAndTypeEntry.class)); 801 } 802 } 803 804 public static final class BoundAnnotationDefaultAttr 805 extends BoundAttribute<AnnotationDefaultAttribute> 806 implements AnnotationDefaultAttribute { 807 private AnnotationValue annotationValue; 808 809 public BoundAnnotationDefaultAttr(ClassReader cf, AttributeMapper<AnnotationDefaultAttribute> mapper, int pos) { 810 super(cf, mapper, pos); 811 } 812 813 @Override 814 public AnnotationValue defaultValue() { 815 if (annotationValue == null) 816 annotationValue = AnnotationReader.readElementValue(classReader, payloadStart); 817 return annotationValue; 818 } 819 } 820 821 public static final class BoundRuntimeVisibleTypeAnnotationsAttribute extends BoundAttribute<RuntimeVisibleTypeAnnotationsAttribute> 822 implements RuntimeVisibleTypeAnnotationsAttribute { 823 824 private final LabelContext labelContext; 825 826 public BoundRuntimeVisibleTypeAnnotationsAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<RuntimeVisibleTypeAnnotationsAttribute> mapper, int pos) { 827 super(cf, mapper, pos); 828 this.labelContext = (enclosing instanceof LabelContext lc) ? lc : null; 829 } 830 831 @Override 832 public List<TypeAnnotation> annotations() { 833 return AnnotationReader.readTypeAnnotations(classReader, payloadStart, labelContext); 834 } 835 } 836 837 public static final class BoundRuntimeInvisibleTypeAnnotationsAttribute 838 extends BoundAttribute<RuntimeInvisibleTypeAnnotationsAttribute> 839 implements RuntimeInvisibleTypeAnnotationsAttribute { 840 public BoundRuntimeInvisibleTypeAnnotationsAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute> mapper, int pos) { 841 super(cf, mapper, pos); 842 this.labelContext = (enclosing instanceof LabelContext lc) ? lc : null; 843 } 844 845 private final LabelContext labelContext; 846 847 @Override 848 public List<TypeAnnotation> annotations() { 849 return AnnotationReader.readTypeAnnotations(classReader, payloadStart, labelContext); 850 } 851 } 852 853 public static final class BoundRuntimeVisibleParameterAnnotationsAttribute 854 extends BoundAttribute<RuntimeVisibleParameterAnnotationsAttribute> 855 implements RuntimeVisibleParameterAnnotationsAttribute { 856 857 public BoundRuntimeVisibleParameterAnnotationsAttribute(ClassReader cf, AttributeMapper<RuntimeVisibleParameterAnnotationsAttribute> mapper, int pos) { 858 super(cf, mapper, pos); 859 } 860 861 @Override 862 public List<List<Annotation>> parameterAnnotations() { 863 return AnnotationReader.readParameterAnnotations(classReader, payloadStart); 864 } 865 } 866 867 public static final class BoundRuntimeInvisibleParameterAnnotationsAttribute 868 extends BoundAttribute<RuntimeInvisibleParameterAnnotationsAttribute> 869 implements RuntimeInvisibleParameterAnnotationsAttribute { 870 871 public BoundRuntimeInvisibleParameterAnnotationsAttribute(ClassReader cf, AttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute> mapper, int pos) { 872 super(cf, mapper, pos); 873 } 874 875 @Override 876 public List<List<Annotation>> parameterAnnotations() { 877 return AnnotationReader.readParameterAnnotations(classReader, payloadStart); 878 } 879 } 880 881 public static final class BoundRuntimeInvisibleAnnotationsAttribute 882 extends BoundAttribute<RuntimeInvisibleAnnotationsAttribute> 883 implements RuntimeInvisibleAnnotationsAttribute { 884 private List<Annotation> inflated; 885 886 public BoundRuntimeInvisibleAnnotationsAttribute(ClassReader cf, 887 int payloadStart) { 888 super(cf, Attributes.runtimeInvisibleAnnotations(), payloadStart); 889 } 890 891 @Override 892 public List<Annotation> annotations() { 893 if (inflated == null) 894 inflated = AnnotationReader.readAnnotations(classReader, payloadStart); 895 return inflated; 896 } 897 } 898 899 public static final class BoundRuntimeVisibleAnnotationsAttribute 900 extends BoundAttribute<RuntimeVisibleAnnotationsAttribute> 901 implements RuntimeVisibleAnnotationsAttribute { 902 private List<Annotation> inflated; 903 904 public BoundRuntimeVisibleAnnotationsAttribute(ClassReader cf, 905 int payloadStart) { 906 super(cf, Attributes.runtimeVisibleAnnotations(), payloadStart); 907 } 908 909 @Override 910 public List<Annotation> annotations() { 911 if (inflated == null) 912 inflated = AnnotationReader.readAnnotations(classReader, payloadStart); 913 return inflated; 914 } 915 } 916 917 public static final class BoundPermittedSubclassesAttribute extends BoundAttribute<PermittedSubclassesAttribute> 918 implements PermittedSubclassesAttribute { 919 private List<ClassEntry> permittedSubclasses = null; 920 921 public BoundPermittedSubclassesAttribute(ClassReader cf, AttributeMapper<PermittedSubclassesAttribute> mapper, int pos) { 922 super(cf, mapper, pos); 923 } 924 925 @Override 926 public List<ClassEntry> permittedSubclasses() { 927 if (permittedSubclasses == null) { 928 permittedSubclasses = readEntryList(payloadStart); 929 } 930 return permittedSubclasses; 931 } 932 } 933 934 public abstract static sealed class BoundCodeAttribute 935 extends BoundAttribute<CodeAttribute> 936 implements CodeAttribute 937 permits CodeImpl { 938 protected final int codeStart; 939 protected final int codeLength; 940 protected final int codeEnd; 941 protected final int attributePos; 942 protected final int exceptionHandlerPos; 943 protected final int exceptionHandlerCnt; 944 protected final MethodModel enclosingMethod; 945 946 public BoundCodeAttribute(AttributedElement enclosing, 947 ClassReader reader, 948 AttributeMapper<CodeAttribute> mapper, 949 int payloadStart) { 950 super(reader, mapper, payloadStart); 951 this.codeLength = classReader.readInt(payloadStart + 4); 952 this.enclosingMethod = (MethodModel) enclosing; 953 this.codeStart = payloadStart + 8; 954 this.codeEnd = codeStart + codeLength; 955 this.exceptionHandlerPos = codeEnd; 956 this.exceptionHandlerCnt = classReader.readU2(exceptionHandlerPos); 957 this.attributePos = exceptionHandlerPos + 2 + exceptionHandlerCnt * 8; 958 } 959 960 // CodeAttribute 961 962 @Override 963 public int maxStack() { 964 return classReader.readU2(payloadStart); 965 } 966 967 @Override 968 public int maxLocals() { 969 return classReader.readU2(payloadStart + 2); 970 } 971 972 @Override 973 public int codeLength() { 974 return codeLength; 975 } 976 977 @Override 978 public byte[] codeArray() { 979 return classReader.readBytes(payloadStart + 8, codeLength()); 980 } 981 } 982 983 /** 984 * {@return the attribute mapper for a standard attribute} 985 * 986 * @param name the name of the attribute to find 987 */ 988 public static AttributeMapper<?> standardAttribute(Utf8Entry name) { 989 // critical bootstrap path, so no lambdas nor method handles here 990 return switch (name.hashCode()) { 991 case 0x78147009 -> 992 name.equalsString(NAME_ANNOTATION_DEFAULT) ? annotationDefault() : null; 993 case 0x665e3a3a -> 994 name.equalsString(NAME_BOOTSTRAP_METHODS) ? bootstrapMethods() : null; 995 case 0xcb7e162 -> 996 name.equalsString(NAME_CHARACTER_RANGE_TABLE) ? characterRangeTable() : null; 997 case 0x21e41e7e -> 998 name.equalsString(NAME_CODE) ? code() : null; 999 case 0x5a306b41 -> 1000 name.equalsString(NAME_COMPILATION_ID) ? compilationId() : null; 1001 case 0x3e191c7c -> 1002 name.equalsString(NAME_CONSTANT_VALUE) ? constantValue() : null; 1003 case 0x5e88ed0c -> 1004 name.equalsString(NAME_DEPRECATED) ? deprecated() : null; 1005 case 0x7284695e -> 1006 name.equalsString(NAME_ENCLOSING_METHOD) ? enclosingMethod() : null; 1007 case 0x21df25db -> 1008 name.equalsString(NAME_EXCEPTIONS) ? exceptions() : null; 1009 case 0x11392da9 -> 1010 name.equalsString(NAME_INNER_CLASSES) ? innerClasses() : null; 1011 case 0x167536fc -> 1012 name.equalsString(NAME_LINE_NUMBER_TABLE) ? lineNumberTable() : null; 1013 case 0x46939abc -> 1014 name.equalsString(NAME_LOCAL_VARIABLE_TABLE) ? localVariableTable() : null; 1015 case 0x63ee67f4 -> 1016 name.equalsString(NAME_LOCAL_VARIABLE_TYPE_TABLE) ? localVariableTypeTable() : null; 1017 case 0x2b597e15 -> 1018 name.equalsString(NAME_METHOD_PARAMETERS) ? methodParameters() : null; 1019 case 0x19f20ade -> 1020 name.equalsString(NAME_MODULE) ? module() : null; 1021 case 0x47f6395e -> 1022 name.equalsString(NAME_MODULE_HASHES) ? moduleHashes() : null; 1023 case 0x54db809 -> 1024 name.equalsString(NAME_MODULE_MAIN_CLASS) ? moduleMainClass() : null; 1025 case 0x1abd1c2c -> 1026 name.equalsString(NAME_MODULE_PACKAGES) ? modulePackages() : null; 1027 case 0x6ba46dd -> 1028 name.equalsString(NAME_MODULE_RESOLUTION) ? moduleResolution() : null; 1029 case 0x46f7d91d -> 1030 name.equalsString(NAME_MODULE_TARGET) ? moduleTarget() : null; 1031 case 0x5137f53 -> 1032 name.equalsString(NAME_NEST_HOST) ? nestHost() : null; 1033 case 0x4a8fa3b6 -> 1034 name.equalsString(NAME_NEST_MEMBERS) ? nestMembers() : null; 1035 case 0x55c73cb6 -> 1036 name.equalsString(NAME_PERMITTED_SUBCLASSES) ? permittedSubclasses() : null; 1037 case 0x3fe76d4e -> 1038 name.equalsString(NAME_RECORD) ? record() : null; 1039 case 0x180d6925 -> 1040 name.equalsString(NAME_RUNTIME_INVISIBLE_ANNOTATIONS) ? runtimeInvisibleAnnotations() : null; 1041 case 0x7be22752 -> 1042 name.equalsString(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS) ? runtimeInvisibleParameterAnnotations() : null; 1043 case 0x5299824 -> 1044 name.equalsString(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS) ? runtimeInvisibleTypeAnnotations() : null; 1045 case 0x3534786e -> 1046 name.equalsString(NAME_RUNTIME_VISIBLE_ANNOTATIONS) ? runtimeVisibleAnnotations() : null; 1047 case 0xb4b4ac6 -> 1048 name.equalsString(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS) ? runtimeVisibleParameterAnnotations() : null; 1049 case 0x6926482 -> 1050 name.equalsString(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS) ? runtimeVisibleTypeAnnotations() : null; 1051 case 0x16a42b7c -> 1052 name.equalsString(NAME_SIGNATURE) ? signature() : null; 1053 case 0x400ab245 -> 1054 name.equalsString(NAME_SOURCE_DEBUG_EXTENSION) ? sourceDebugExtension() : null; 1055 case 0x2af490d4 -> 1056 name.equalsString(NAME_SOURCE_FILE) ? sourceFile() : null; 1057 case 0x303e0c58 -> 1058 name.equalsString(NAME_SOURCE_ID) ? sourceId() : null; 1059 case 0x19c7d0cd -> 1060 name.equalsString(NAME_STACK_MAP_TABLE) ? stackMapTable() : null; 1061 case 0x3dc79b7a -> 1062 name.equalsString(NAME_SYNTHETIC) ? synthetic() : null; 1063 default -> null; 1064 }; 1065 } 1066 }