1 /* 2 * Copyright (c) 2022, 2023, 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 public abstract sealed class BoundAttribute<T extends Attribute<T>> 47 extends AbstractElement 48 implements Attribute<T> { 49 50 static final int NAME_AND_LENGTH_PREFIX = 6; 51 private final AttributeMapper<T> mapper; 52 final ClassReader classReader; 53 final int payloadStart; 54 55 BoundAttribute(ClassReader classReader, AttributeMapper<T> mapper, int payloadStart) { 56 this.mapper = mapper; 57 this.classReader = classReader; 58 this.payloadStart = payloadStart; 59 } 60 61 public int payloadLen() { 62 return classReader.readInt(payloadStart - 4); 63 } 64 65 @Override 66 public String attributeName() { 67 return mapper.name(); 68 } 69 70 @Override 71 public AttributeMapper<T> attributeMapper() { 72 return mapper; 73 } 74 75 public byte[] contents() { 76 return classReader.readBytes(payloadStart, payloadLen()); 77 } 78 79 @Override 80 public void writeTo(DirectClassBuilder builder) { 81 builder.writeAttribute(this); 82 } 83 84 @Override 85 public void writeTo(DirectCodeBuilder builder) { 86 builder.writeAttribute(this); 87 } 88 89 @Override 90 public void writeTo(DirectMethodBuilder builder) { 91 builder.writeAttribute(this); 92 } 93 94 @Override 95 public void writeTo(DirectFieldBuilder builder) { 96 builder.writeAttribute(this); 97 } 98 99 @Override 100 @SuppressWarnings("unchecked") 101 public void writeTo(BufWriter buf) { 102 if (!buf.canWriteDirect(classReader)) 103 attributeMapper().writeAttribute(buf, (T) this); 104 else 105 classReader.copyBytesTo(buf, payloadStart - NAME_AND_LENGTH_PREFIX, payloadLen() + NAME_AND_LENGTH_PREFIX); 106 } 107 108 public ConstantPool constantPool() { 109 return classReader; 110 } 111 112 @Override 113 public String toString() { 114 return String.format("Attribute[name=%s]", mapper.name()); 115 } 116 117 <E> List<E> readEntryList(int p) { 118 int cnt = classReader.readU2(p); 119 p += 2; 120 var entries = new Object[cnt]; 121 int end = p + (cnt * 2); 122 for (int i = 0; p < end; i++, p += 2) { 123 entries[i] = classReader.readEntry(p); 124 } 125 return SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(entries); 126 } 127 128 public static List<Attribute<?>> readAttributes(AttributedElement enclosing, ClassReader reader, int pos, 129 Function<Utf8Entry, AttributeMapper<?>> customAttributes) { 130 int size = reader.readU2(pos); 131 var filled = new ArrayList<Attribute<?>>(size); 132 int p = pos + 2; 133 int cfLen = reader.classfileLength(); 134 var apo = ((ClassReaderImpl)reader).context().attributesProcessingOption(); 135 for (int i = 0; i < size; ++i) { 136 Utf8Entry name = reader.readUtf8Entry(p); 137 int len = reader.readInt(p + 2); 138 p += 6; 139 if (len < 0 || len > cfLen - p) { 140 throw new IllegalArgumentException("attribute " + name.stringValue() + " too big to handle"); 141 } 142 143 var mapper = Attributes.standardAttribute(name); 144 if (mapper == null) { 145 mapper = customAttributes.apply(name); 146 } 147 if (mapper != null) { 148 filled.add((Attribute)mapper.readAttribute(enclosing, reader, p)); 149 } else { 150 AttributeMapper<UnknownAttribute> fakeMapper = new AttributeMapper<>() { 151 @Override 152 public String name() { 153 return name.stringValue(); 154 } 155 156 @Override 157 public UnknownAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) { 158 // Will never get called 159 throw new UnsupportedOperationException(); 160 } 161 162 @Override 163 public void writeAttribute(BufWriter buf, UnknownAttribute attr) { 164 buf.writeIndex(name); 165 var cont = attr.contents(); 166 buf.writeInt(cont.length); 167 buf.writeBytes(cont); 168 } 169 170 @Override 171 public boolean allowMultiple() { 172 return true; 173 } 174 175 @Override 176 public AttributeMapper.AttributeStability stability() { 177 return AttributeStability.UNKNOWN; 178 } 179 }; 180 filled.add(new BoundUnknownAttribute(reader, fakeMapper, p)); 181 } 182 p += len; 183 } 184 return Collections.unmodifiableList(filled); 185 } 186 187 public static final class BoundUnknownAttribute extends BoundAttribute<UnknownAttribute> 188 implements UnknownAttribute { 189 public BoundUnknownAttribute(ClassReader cf, AttributeMapper<UnknownAttribute> mapper, int pos) { 190 super(cf, mapper, pos); 191 } 192 } 193 194 public static final class BoundStackMapTableAttribute 195 extends BoundAttribute<StackMapTableAttribute> 196 implements StackMapTableAttribute { 197 final MethodModel method; 198 final LabelContext ctx; 199 List<StackMapFrameInfo> entries = null; 200 201 public BoundStackMapTableAttribute(CodeImpl code, ClassReader cf, AttributeMapper<StackMapTableAttribute> mapper, int pos) { 202 super(cf, mapper, pos); 203 method = code.parent().orElseThrow(); 204 ctx = code; 205 } 206 207 @Override 208 public List<StackMapFrameInfo> entries() { 209 if (entries == null) { 210 entries = new StackMapDecoder(classReader, payloadStart, ctx, StackMapDecoder.initFrameLocals(method)).entries(); 211 } 212 return entries; 213 } 214 } 215 216 public static final class BoundSyntheticAttribute extends BoundAttribute<SyntheticAttribute> 217 implements SyntheticAttribute { 218 public BoundSyntheticAttribute(ClassReader cf, AttributeMapper<SyntheticAttribute> mapper, int pos) { 219 super(cf, mapper, pos); 220 } 221 } 222 223 public static final class BoundLineNumberTableAttribute 224 extends BoundAttribute<LineNumberTableAttribute> 225 implements LineNumberTableAttribute { 226 private List<LineNumberInfo> lineNumbers = null; 227 228 public BoundLineNumberTableAttribute(ClassReader cf, AttributeMapper<LineNumberTableAttribute> mapper, int pos) { 229 super(cf, mapper, pos); 230 } 231 232 @Override 233 public List<LineNumberInfo> lineNumbers() { 234 if (lineNumbers == null) { 235 int nLn = classReader.readU2(payloadStart); 236 LineNumberInfo[] elements = new LineNumberInfo[nLn]; 237 int p = payloadStart + 2; 238 int pEnd = p + (nLn * 4); 239 for (int i = 0; p < pEnd; p += 4, i++) { 240 int startPc = classReader.readU2(p); 241 int lineNumber = classReader.readU2(p + 2); 242 elements[i] = LineNumberInfo.of(startPc, lineNumber); 243 } 244 lineNumbers = List.of(elements); 245 } 246 return lineNumbers; 247 } 248 } 249 250 public static final class BoundCharacterRangeTableAttribute extends BoundAttribute<CharacterRangeTableAttribute> implements CharacterRangeTableAttribute { 251 private List<CharacterRangeInfo> characterRangeTable = null; 252 253 public BoundCharacterRangeTableAttribute(ClassReader cf, AttributeMapper<CharacterRangeTableAttribute> mapper, int pos) { 254 super(cf, mapper, pos); 255 } 256 257 @Override 258 public List<CharacterRangeInfo> characterRangeTable() { 259 if (characterRangeTable == null) { 260 int nLn = classReader.readU2(payloadStart); 261 CharacterRangeInfo[] elements = new CharacterRangeInfo[nLn]; 262 int p = payloadStart + 2; 263 int pEnd = p + (nLn * 14); 264 for (int i = 0; p < pEnd; p += 14, i++) { 265 int startPc = classReader.readU2(p); 266 int endPc = classReader.readU2(p + 2); 267 int characterRangeStart = classReader.readInt(p + 4); 268 int characterRangeEnd = classReader.readInt(p + 8); 269 int flags = classReader.readU2(p + 12); 270 elements[i] = CharacterRangeInfo.of(startPc, endPc, characterRangeStart, characterRangeEnd, flags); 271 } 272 characterRangeTable = List.of(elements); 273 } 274 return characterRangeTable; 275 } 276 } 277 278 public static final class BoundLocalVariableTableAttribute 279 extends BoundAttribute<LocalVariableTableAttribute> 280 implements LocalVariableTableAttribute { 281 private final CodeImpl codeAttribute; 282 private List<LocalVariableInfo> localVars = null; 283 284 public BoundLocalVariableTableAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<LocalVariableTableAttribute> mapper, int pos) { 285 super(cf, mapper, pos); 286 codeAttribute = (CodeImpl) enclosing; 287 } 288 289 @Override 290 public List<LocalVariableInfo> localVariables() { 291 if (localVars == null) { 292 int cnt = classReader.readU2(payloadStart); 293 BoundLocalVariable[] elements = new BoundLocalVariable[cnt]; 294 int p = payloadStart + 2; 295 int pEnd = p + (cnt * 10); 296 for (int i = 0; p < pEnd; p += 10, i++) { 297 elements[i] = new BoundLocalVariable(codeAttribute, p); 298 } 299 localVars = List.of(elements); 300 } 301 return localVars; 302 } 303 } 304 305 public static final class BoundLocalVariableTypeTableAttribute 306 extends BoundAttribute<LocalVariableTypeTableAttribute> 307 implements LocalVariableTypeTableAttribute { 308 private final CodeImpl codeAttribute; 309 private List<LocalVariableTypeInfo> localVars = null; 310 311 public BoundLocalVariableTypeTableAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<LocalVariableTypeTableAttribute> mapper, int pos) { 312 super(cf, mapper, pos); 313 this.codeAttribute = (CodeImpl) enclosing; 314 } 315 316 @Override 317 public List<LocalVariableTypeInfo> localVariableTypes() { 318 if (localVars == null) { 319 final int cnt = classReader.readU2(payloadStart); 320 BoundLocalVariableType[] elements = new BoundLocalVariableType[cnt]; 321 int p = payloadStart + 2; 322 int pEnd = p + (cnt * 10); 323 for (int i = 0; p < pEnd; p += 10, i++) { 324 elements[i] = new BoundLocalVariableType(codeAttribute, p); 325 } 326 localVars = List.of(elements); 327 } 328 return localVars; 329 } 330 } 331 332 public static final class BoundMethodParametersAttribute extends BoundAttribute<MethodParametersAttribute> 333 implements MethodParametersAttribute { 334 private List<MethodParameterInfo> parameters = null; 335 336 public BoundMethodParametersAttribute(ClassReader cf, AttributeMapper<MethodParametersAttribute> mapper, int pos) { 337 super(cf, mapper, pos); 338 } 339 340 @Override 341 public List<MethodParameterInfo> parameters() { 342 if (parameters == null) { 343 final int cnt = classReader.readU1(payloadStart); 344 MethodParameterInfo[] elements = new MethodParameterInfo[cnt]; 345 int p = payloadStart + 1; 346 int pEnd = p + (cnt * 4); 347 for (int i = 0; p < pEnd; p += 4, i++) { 348 Utf8Entry name = classReader.readUtf8EntryOrNull(p); 349 int accessFlags = classReader.readU2(p + 2); 350 elements[i] = MethodParameterInfo.of(Optional.ofNullable(name), accessFlags); 351 } 352 parameters = List.of(elements); 353 } 354 return parameters; 355 } 356 } 357 358 public static final class BoundModuleHashesAttribute extends BoundAttribute<ModuleHashesAttribute> 359 implements ModuleHashesAttribute { 360 private List<ModuleHashInfo> hashes = null; 361 362 public BoundModuleHashesAttribute(ClassReader cf, AttributeMapper<ModuleHashesAttribute> mapper, int pos) { 363 super(cf, mapper, pos); 364 } 365 366 @Override 367 public Utf8Entry algorithm() { 368 return classReader.readUtf8Entry(payloadStart); 369 } 370 371 @Override 372 public List<ModuleHashInfo> hashes() { 373 if (hashes == null) { 374 final int cnt = classReader.readU2(payloadStart + 2); 375 ModuleHashInfo[] elements = new ModuleHashInfo[cnt]; 376 int p = payloadStart + 4; 377 //System.err.printf("%5d: ModuleHashesAttr alg = %s, cnt = %d%n", pos, algorithm(), cnt); 378 for (int i = 0; i < cnt; ++i) { 379 ModuleEntry module = classReader.readModuleEntry(p); 380 int hashLength = classReader.readU2(p + 2); 381 //System.err.printf("%5d: [%d] module = %s, hashLength = %d%n", p, i, module, hashLength); 382 p += 4; 383 elements[i] = ModuleHashInfo.of(module, classReader.readBytes(p, hashLength)); 384 p += hashLength; 385 } 386 hashes = List.of(elements); 387 } 388 return hashes; 389 } 390 } 391 392 public static final class BoundRecordAttribute extends BoundAttribute<RecordAttribute> 393 implements RecordAttribute { 394 private List<RecordComponentInfo> components = null; 395 396 public BoundRecordAttribute(ClassReader cf, AttributeMapper<RecordAttribute> mapper, int pos) { 397 super(cf, mapper, pos); 398 } 399 400 @Override 401 public List<RecordComponentInfo> components() { 402 if (components == null) { 403 final int cnt = classReader.readU2(payloadStart); 404 RecordComponentInfo[] elements = new RecordComponentInfo[cnt]; 405 int p = payloadStart + 2; 406 for (int i = 0; i < cnt; i++) { 407 elements[i] = new BoundRecordComponentInfo(classReader, p); 408 p = classReader.skipAttributeHolder(p + 4); 409 } 410 components = List.of(elements); 411 } 412 return components; 413 } 414 } 415 416 public static final class BoundDeprecatedAttribute extends BoundAttribute<DeprecatedAttribute> 417 implements DeprecatedAttribute { 418 public BoundDeprecatedAttribute(ClassReader cf, AttributeMapper<DeprecatedAttribute> mapper, int pos) { 419 super(cf, mapper, pos); 420 } 421 } 422 423 public static final class BoundSignatureAttribute extends BoundAttribute<SignatureAttribute> 424 implements SignatureAttribute { 425 public BoundSignatureAttribute(ClassReader cf, AttributeMapper<SignatureAttribute> mapper, int pos) { 426 super(cf, mapper, pos); 427 } 428 429 @Override 430 public Utf8Entry signature() { 431 return classReader.readUtf8Entry(payloadStart); 432 } 433 } 434 435 public static final class BoundSourceFileAttribute extends BoundAttribute<SourceFileAttribute> 436 implements SourceFileAttribute { 437 public BoundSourceFileAttribute(ClassReader cf, AttributeMapper<SourceFileAttribute> mapper, int pos) { 438 super(cf, mapper, pos); 439 } 440 441 @Override 442 public Utf8Entry sourceFile() { 443 return classReader.readUtf8Entry(payloadStart); 444 } 445 446 } 447 448 public static final class BoundModuleMainClassAttribute extends BoundAttribute<ModuleMainClassAttribute> implements ModuleMainClassAttribute { 449 public BoundModuleMainClassAttribute(ClassReader cf, AttributeMapper<ModuleMainClassAttribute> mapper, int pos) { 450 super(cf, mapper, pos); 451 } 452 453 @Override 454 public ClassEntry mainClass() { 455 return classReader.readClassEntry(payloadStart); 456 } 457 } 458 459 public static final class BoundNestHostAttribute extends BoundAttribute<NestHostAttribute> 460 implements NestHostAttribute { 461 public BoundNestHostAttribute(ClassReader cf, AttributeMapper<NestHostAttribute> mapper, int pos) { 462 super(cf, mapper, pos); 463 } 464 465 @Override 466 public ClassEntry nestHost() { 467 return classReader.readClassEntry(payloadStart); 468 } 469 } 470 471 public static final class BoundSourceDebugExtensionAttribute extends BoundAttribute<SourceDebugExtensionAttribute> 472 implements SourceDebugExtensionAttribute { 473 public BoundSourceDebugExtensionAttribute(ClassReader cf, AttributeMapper<SourceDebugExtensionAttribute> mapper, int pos) { 474 super(cf, mapper, pos); 475 } 476 } 477 478 public static final class BoundConstantValueAttribute extends BoundAttribute<ConstantValueAttribute> 479 implements ConstantValueAttribute { 480 public BoundConstantValueAttribute(ClassReader cf, AttributeMapper<ConstantValueAttribute> mapper, int pos) { 481 super(cf, mapper, pos); 482 } 483 484 @Override 485 public ConstantValueEntry constant() { 486 return classReader.readEntry(payloadStart, ConstantValueEntry.class); 487 } 488 489 } 490 491 public static final class BoundModuleTargetAttribute extends BoundAttribute<ModuleTargetAttribute> 492 implements ModuleTargetAttribute { 493 public BoundModuleTargetAttribute(ClassReader cf, AttributeMapper<ModuleTargetAttribute> mapper, int pos) { 494 super(cf, mapper, pos); 495 } 496 497 @Override 498 public Utf8Entry targetPlatform() { 499 return classReader.readUtf8Entry(payloadStart); 500 } 501 } 502 503 public static final class BoundCompilationIDAttribute extends BoundAttribute<CompilationIDAttribute> 504 implements CompilationIDAttribute { 505 public BoundCompilationIDAttribute(ClassReader cf, AttributeMapper<CompilationIDAttribute> mapper, int pos) { 506 super(cf, mapper, pos); 507 } 508 509 @Override 510 public Utf8Entry compilationId() { 511 return classReader.readUtf8Entry(payloadStart); 512 } 513 } 514 515 public static final class BoundSourceIDAttribute extends BoundAttribute<SourceIDAttribute> 516 implements SourceIDAttribute { 517 public BoundSourceIDAttribute(ClassReader cf, AttributeMapper<SourceIDAttribute> mapper, int pos) { 518 super(cf, mapper, pos); 519 } 520 521 @Override 522 public Utf8Entry sourceId() { 523 return classReader.readUtf8Entry(payloadStart); 524 } 525 } 526 527 public static final class BoundModuleResolutionAttribute extends BoundAttribute<ModuleResolutionAttribute> 528 implements ModuleResolutionAttribute { 529 public BoundModuleResolutionAttribute(ClassReader cf, AttributeMapper<ModuleResolutionAttribute> mapper, int pos) { 530 super(cf, mapper, pos); 531 } 532 533 @Override 534 public int resolutionFlags() { 535 return classReader.readU2(payloadStart); 536 } 537 } 538 539 public static final class BoundExceptionsAttribute extends BoundAttribute<ExceptionsAttribute> 540 implements ExceptionsAttribute { 541 private List<ClassEntry> exceptions = null; 542 543 public BoundExceptionsAttribute(ClassReader cf, AttributeMapper<ExceptionsAttribute> mapper, int pos) { 544 super(cf, mapper, pos); 545 } 546 547 @Override 548 public List<ClassEntry> exceptions() { 549 if (exceptions == null) { 550 exceptions = readEntryList(payloadStart); 551 } 552 return exceptions; 553 } 554 } 555 556 public static final class BoundModuleAttribute extends BoundAttribute<ModuleAttribute> 557 implements ModuleAttribute { 558 private List<ModuleRequireInfo> requires = null; 559 private List<ModuleExportInfo> exports = null; 560 private List<ModuleOpenInfo> opens = null; 561 private List<ClassEntry> uses = null; 562 private List<ModuleProvideInfo> provides = null; 563 564 public BoundModuleAttribute(ClassReader cf, AttributeMapper<ModuleAttribute> mapper, int pos) { 565 super(cf, mapper, pos); 566 } 567 568 @Override 569 public ModuleEntry moduleName() { 570 return classReader.readModuleEntry(payloadStart); 571 } 572 573 @Override 574 public int moduleFlagsMask() { 575 return classReader.readU2(payloadStart + 2); 576 } 577 578 @Override 579 public Optional<Utf8Entry> moduleVersion() { 580 return Optional.ofNullable(classReader.readUtf8EntryOrNull(payloadStart + 4)); 581 } 582 583 @Override 584 public List<ModuleRequireInfo> requires() { 585 if (requires == null) { 586 structure(); 587 } 588 return requires; 589 } 590 591 @Override 592 public List<ModuleExportInfo> exports() { 593 if (exports == null) { 594 structure(); 595 } 596 return exports; 597 } 598 599 @Override 600 public List<ModuleOpenInfo> opens() { 601 if (opens == null) { 602 structure(); 603 } 604 return opens; 605 } 606 607 @Override 608 public List<ClassEntry> uses() { 609 if (uses == null) { 610 structure(); 611 } 612 return uses; 613 } 614 615 @Override 616 public List<ModuleProvideInfo> provides() { 617 if (provides == null) { 618 structure(); 619 } 620 return provides; 621 } 622 623 private void structure() { 624 int p = payloadStart + 8; 625 626 { 627 int cnt = classReader.readU2(payloadStart + 6); 628 ModuleRequireInfo[] elements = new ModuleRequireInfo[cnt]; 629 int end = p + (cnt * 6); 630 for (int i = 0; p < end; p += 6, i++) { 631 elements[i] = ModuleRequireInfo.of(classReader.readModuleEntry(p), 632 classReader.readU2(p + 2), 633 (Utf8Entry) classReader.readEntryOrNull(p + 4)); 634 } 635 requires = List.of(elements); 636 } 637 638 { 639 int cnt = classReader.readU2(p); 640 p += 2; 641 ModuleExportInfo[] elements = new ModuleExportInfo[cnt]; 642 for (int i = 0; i < cnt; i++) { 643 PackageEntry pe = classReader.readPackageEntry(p); 644 int exportFlags = classReader.readU2(p + 2); 645 p += 4; 646 List<ModuleEntry> exportsTo = readEntryList(p); 647 p += 2 + exportsTo.size() * 2; 648 elements[i] = ModuleExportInfo.of(pe, exportFlags, exportsTo); 649 } 650 exports = List.of(elements); 651 } 652 653 { 654 int cnt = classReader.readU2(p); 655 p += 2; 656 ModuleOpenInfo[] elements = new ModuleOpenInfo[cnt]; 657 for (int i = 0; i < cnt; i++) { 658 PackageEntry po = classReader.readPackageEntry(p); 659 int opensFlags = classReader.readU2(p + 2); 660 p += 4; 661 List<ModuleEntry> opensTo = readEntryList(p); 662 p += 2 + opensTo.size() * 2; 663 elements[i] = ModuleOpenInfo.of(po, opensFlags, opensTo); 664 } 665 opens = List.of(elements); 666 } 667 668 { 669 uses = readEntryList(p); 670 p += 2 + uses.size() * 2; 671 int cnt = classReader.readU2(p); 672 p += 2; 673 ModuleProvideInfo[] elements = new ModuleProvideInfo[cnt]; 674 provides = new ArrayList<>(cnt); 675 for (int i = 0; i < cnt; i++) { 676 ClassEntry c = classReader.readClassEntry(p); 677 p += 2; 678 List<ClassEntry> providesWith = readEntryList(p); 679 p += 2 + providesWith.size() * 2; 680 elements[i] = ModuleProvideInfo.of(c, providesWith); 681 } 682 provides = List.of(elements); 683 } 684 } 685 } 686 687 public static final class BoundModulePackagesAttribute extends BoundAttribute<ModulePackagesAttribute> 688 implements ModulePackagesAttribute { 689 private List<PackageEntry> packages = null; 690 691 public BoundModulePackagesAttribute(ClassReader cf, AttributeMapper<ModulePackagesAttribute> mapper, int pos) { 692 super(cf, mapper, pos); 693 } 694 695 @Override 696 public List<PackageEntry> packages() { 697 if (packages == null) { 698 packages = readEntryList(payloadStart); 699 } 700 return packages; 701 } 702 } 703 704 public static final class BoundNestMembersAttribute extends BoundAttribute<NestMembersAttribute> 705 implements NestMembersAttribute { 706 707 private List<ClassEntry> members = null; 708 709 public BoundNestMembersAttribute(ClassReader cf, AttributeMapper<NestMembersAttribute> mapper, int pos) { 710 super(cf, mapper, pos); 711 } 712 713 @Override 714 public List<ClassEntry> nestMembers() { 715 if (members == null) { 716 members = readEntryList(payloadStart); 717 } 718 return members; 719 } 720 } 721 722 public static final class BoundBootstrapMethodsAttribute extends BoundAttribute<BootstrapMethodsAttribute> 723 implements BootstrapMethodsAttribute { 724 725 private List<BootstrapMethodEntry> bootstraps = null; 726 private final int size; 727 728 public BoundBootstrapMethodsAttribute(ClassReader reader, AttributeMapper<BootstrapMethodsAttribute> mapper, int pos) { 729 super(reader, mapper, pos); 730 size = classReader.readU2(pos); 731 } 732 733 @Override 734 public int bootstrapMethodsSize() { 735 return size; 736 } 737 738 @Override 739 public List<BootstrapMethodEntry> bootstrapMethods() { 740 if (bootstraps == null) { 741 BootstrapMethodEntry[] bs = new BootstrapMethodEntry[size]; 742 int p = payloadStart + 2; 743 for (int i = 0; i < size; ++i) { 744 final AbstractPoolEntry.MethodHandleEntryImpl handle 745 = (AbstractPoolEntry.MethodHandleEntryImpl) classReader.readMethodHandleEntry(p); 746 final List<LoadableConstantEntry> args = readEntryList(p + 2); 747 p += 4 + args.size() * 2; 748 int hash = BootstrapMethodEntryImpl.computeHashCode(handle, args); 749 bs[i] = new BootstrapMethodEntryImpl(classReader, i, hash, handle, args); 750 } 751 bootstraps = List.of(bs); 752 } 753 return bootstraps; 754 } 755 } 756 757 public static final class BoundInnerClassesAttribute extends BoundAttribute<InnerClassesAttribute> 758 implements InnerClassesAttribute { 759 private List<InnerClassInfo> classes; 760 761 public BoundInnerClassesAttribute(ClassReader cf, AttributeMapper<InnerClassesAttribute> mapper, int pos) { 762 super(cf, mapper, pos); 763 } 764 765 @Override 766 public List<InnerClassInfo> classes() { 767 if (classes == null) { 768 final int cnt = classReader.readU2(payloadStart); 769 int p = payloadStart + 2; 770 InnerClassInfo[] elements = new InnerClassInfo[cnt]; 771 for (int i = 0; i < cnt; i++) { 772 ClassEntry innerClass = classReader.readClassEntry(p); // TODO FIXME 773 int outerClassIndex = classReader.readU2(p + 2); 774 ClassEntry outerClass = outerClassIndex == 0 775 ? null 776 : (ClassEntry) classReader.entryByIndex(outerClassIndex); 777 int innerNameIndex = classReader.readU2(p + 4); 778 Utf8Entry innerName = innerNameIndex == 0 779 ? null 780 : (Utf8Entry) classReader.entryByIndex(innerNameIndex); 781 int flags = classReader.readU2(p + 6); 782 p += 8; 783 elements[i] = InnerClassInfo.of(innerClass, Optional.ofNullable(outerClass), Optional.ofNullable(innerName), flags); 784 } 785 classes = List.of(elements); 786 } 787 return classes; 788 } 789 } 790 791 public static final class BoundEnclosingMethodAttribute extends BoundAttribute<EnclosingMethodAttribute> 792 implements EnclosingMethodAttribute { 793 public BoundEnclosingMethodAttribute(ClassReader cf, AttributeMapper<EnclosingMethodAttribute> mapper, int pos) { 794 super(cf, mapper, pos); 795 } 796 797 @Override 798 public ClassEntry enclosingClass() { 799 return classReader.readClassEntry(payloadStart); 800 } 801 802 @Override 803 public Optional<NameAndTypeEntry> enclosingMethod() { 804 return Optional.ofNullable((NameAndTypeEntry) classReader.readEntryOrNull(payloadStart + 2)); 805 } 806 } 807 808 public static final class BoundAnnotationDefaultAttr 809 extends BoundAttribute<AnnotationDefaultAttribute> 810 implements AnnotationDefaultAttribute { 811 private AnnotationValue annotationValue; 812 813 public BoundAnnotationDefaultAttr(ClassReader cf, AttributeMapper<AnnotationDefaultAttribute> mapper, int pos) { 814 super(cf, mapper, pos); 815 } 816 817 @Override 818 public AnnotationValue defaultValue() { 819 if (annotationValue == null) 820 annotationValue = AnnotationReader.readElementValue(classReader, payloadStart); 821 return annotationValue; 822 } 823 } 824 825 public static final class BoundRuntimeVisibleTypeAnnotationsAttribute extends BoundAttribute<RuntimeVisibleTypeAnnotationsAttribute> 826 implements RuntimeVisibleTypeAnnotationsAttribute { 827 828 private final LabelContext labelContext; 829 830 public BoundRuntimeVisibleTypeAnnotationsAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<RuntimeVisibleTypeAnnotationsAttribute> mapper, int pos) { 831 super(cf, mapper, pos); 832 this.labelContext = (enclosing instanceof LabelContext lc) ? lc : null; 833 } 834 835 @Override 836 public List<TypeAnnotation> annotations() { 837 return AnnotationReader.readTypeAnnotations(classReader, payloadStart, labelContext); 838 } 839 } 840 841 public static final class BoundRuntimeInvisibleTypeAnnotationsAttribute 842 extends BoundAttribute<RuntimeInvisibleTypeAnnotationsAttribute> 843 implements RuntimeInvisibleTypeAnnotationsAttribute { 844 public BoundRuntimeInvisibleTypeAnnotationsAttribute(AttributedElement enclosing, ClassReader cf, AttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute> mapper, int pos) { 845 super(cf, mapper, pos); 846 this.labelContext = (enclosing instanceof LabelContext lc) ? lc : null; 847 } 848 849 private final LabelContext labelContext; 850 851 @Override 852 public List<TypeAnnotation> annotations() { 853 return AnnotationReader.readTypeAnnotations(classReader, payloadStart, labelContext); 854 } 855 } 856 857 public static final class BoundRuntimeVisibleParameterAnnotationsAttribute 858 extends BoundAttribute<RuntimeVisibleParameterAnnotationsAttribute> 859 implements RuntimeVisibleParameterAnnotationsAttribute { 860 861 public BoundRuntimeVisibleParameterAnnotationsAttribute(ClassReader cf, AttributeMapper<RuntimeVisibleParameterAnnotationsAttribute> mapper, int pos) { 862 super(cf, mapper, pos); 863 } 864 865 @Override 866 public List<List<Annotation>> parameterAnnotations() { 867 return AnnotationReader.readParameterAnnotations(classReader, payloadStart); 868 } 869 } 870 871 public static final class BoundRuntimeInvisibleParameterAnnotationsAttribute 872 extends BoundAttribute<RuntimeInvisibleParameterAnnotationsAttribute> 873 implements RuntimeInvisibleParameterAnnotationsAttribute { 874 875 public BoundRuntimeInvisibleParameterAnnotationsAttribute(ClassReader cf, AttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute> mapper, int pos) { 876 super(cf, mapper, pos); 877 } 878 879 @Override 880 public List<List<Annotation>> parameterAnnotations() { 881 return AnnotationReader.readParameterAnnotations(classReader, payloadStart); 882 } 883 } 884 885 public static final class BoundRuntimeInvisibleAnnotationsAttribute 886 extends BoundAttribute<RuntimeInvisibleAnnotationsAttribute> 887 implements RuntimeInvisibleAnnotationsAttribute { 888 private List<Annotation> inflated; 889 890 public BoundRuntimeInvisibleAnnotationsAttribute(ClassReader cf, 891 int payloadStart) { 892 super(cf, Attributes.RUNTIME_INVISIBLE_ANNOTATIONS, payloadStart); 893 } 894 895 @Override 896 public List<Annotation> annotations() { 897 if (inflated == null) 898 inflated = AnnotationReader.readAnnotations(classReader, payloadStart); 899 return inflated; 900 } 901 } 902 903 public static final class BoundRuntimeVisibleAnnotationsAttribute 904 extends BoundAttribute<RuntimeVisibleAnnotationsAttribute> 905 implements RuntimeVisibleAnnotationsAttribute { 906 private List<Annotation> inflated; 907 908 public BoundRuntimeVisibleAnnotationsAttribute(ClassReader cf, 909 int payloadStart) { 910 super(cf, Attributes.RUNTIME_VISIBLE_ANNOTATIONS, payloadStart); 911 } 912 913 @Override 914 public List<Annotation> annotations() { 915 if (inflated == null) 916 inflated = AnnotationReader.readAnnotations(classReader, payloadStart); 917 return inflated; 918 } 919 } 920 921 public static final class BoundPermittedSubclassesAttribute extends BoundAttribute<PermittedSubclassesAttribute> 922 implements PermittedSubclassesAttribute { 923 private List<ClassEntry> permittedSubclasses = null; 924 925 public BoundPermittedSubclassesAttribute(ClassReader cf, AttributeMapper<PermittedSubclassesAttribute> mapper, int pos) { 926 super(cf, mapper, pos); 927 } 928 929 @Override 930 public List<ClassEntry> permittedSubclasses() { 931 if (permittedSubclasses == null) { 932 permittedSubclasses = readEntryList(payloadStart); 933 } 934 return permittedSubclasses; 935 } 936 } 937 938 public static final class BoundPreloadAttribute extends BoundAttribute<PreloadAttribute> 939 implements PreloadAttribute { 940 private List<ClassEntry> preloads = null; 941 942 public BoundPreloadAttribute(ClassReader cf, AttributeMapper<PreloadAttribute> mapper, int pos) { 943 super(cf, mapper, pos); 944 } 945 946 @Override 947 public List<ClassEntry> preloads() { 948 if (preloads == null) { 949 preloads = readEntryList(payloadStart); 950 } 951 return preloads; 952 } 953 } 954 955 public static abstract sealed class BoundCodeAttribute 956 extends BoundAttribute<CodeAttribute> 957 implements CodeAttribute 958 permits CodeImpl { 959 protected final int codeStart; 960 protected final int codeLength; 961 protected final int codeEnd; 962 protected final int attributePos; 963 protected final int exceptionHandlerPos; 964 protected final int exceptionHandlerCnt; 965 protected final MethodModel enclosingMethod; 966 967 public BoundCodeAttribute(AttributedElement enclosing, 968 ClassReader reader, 969 AttributeMapper<CodeAttribute> mapper, 970 int payloadStart) { 971 super(reader, mapper, payloadStart); 972 this.codeLength = classReader.readInt(payloadStart + 4); 973 this.enclosingMethod = (MethodModel) enclosing; 974 this.codeStart = payloadStart + 8; 975 this.codeEnd = codeStart + codeLength; 976 this.exceptionHandlerPos = codeEnd; 977 this.exceptionHandlerCnt = classReader.readU2(exceptionHandlerPos); 978 this.attributePos = exceptionHandlerPos + 2 + exceptionHandlerCnt * 8; 979 } 980 981 // CodeAttribute 982 983 @Override 984 public int maxStack() { 985 return classReader.readU2(payloadStart); 986 } 987 988 @Override 989 public int maxLocals() { 990 return classReader.readU2(payloadStart + 2); 991 } 992 993 @Override 994 public int codeLength() { 995 return codeLength; 996 } 997 998 @Override 999 public byte[] codeArray() { 1000 return classReader.readBytes(payloadStart + 8, codeLength()); 1001 } 1002 } 1003 }