1 /*
2 * Copyright (c) 2022, 2025, 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 package jdk.internal.classfile.impl;
26
27 import java.lang.classfile.*;
28 import java.lang.classfile.attribute.*;
29 import java.lang.classfile.constantpool.ClassEntry;
30 import java.lang.classfile.constantpool.ConstantValueEntry;
31 import java.lang.classfile.constantpool.ModuleEntry;
32 import java.lang.classfile.constantpool.NameAndTypeEntry;
33 import java.lang.classfile.constantpool.PackageEntry;
34 import java.lang.classfile.constantpool.Utf8Entry;
35 import java.util.Collection;
36 import java.util.List;
37 import java.util.Optional;
38
39 import jdk.internal.access.SharedSecrets;
40
41 import static java.util.Objects.requireNonNull;
42
43 public abstract sealed class UnboundAttribute<T extends Attribute<T>>
44 extends AbstractElement
45 implements Attribute<T>, Util.Writable {
46 protected final AttributeMapper<T> mapper;
47
48 public UnboundAttribute(AttributeMapper<T> mapper) {
49 this.mapper = mapper;
50 }
51
52 @Override
53 public AttributeMapper<T> attributeMapper() {
54 return mapper;
55 }
56
57 @Override
58 @SuppressWarnings("unchecked")
59 public void writeTo(BufWriterImpl buf) {
60 mapper.writeAttribute(buf, (T) this);
61 }
62
63 @Override
64 public void writeTo(DirectClassBuilder builder) {
65 builder.writeAttribute(this);
66 }
67
68 @Override
69 public void writeTo(DirectCodeBuilder builder) {
70 builder.writeAttribute(this);
71 }
72
73 @Override
74 public void writeTo(DirectMethodBuilder builder) {
75 builder.writeAttribute(this);
76 }
77
78 @Override
79 public void writeTo(DirectFieldBuilder builder) {
80 builder.writeAttribute(this);
81 }
82
83 @Override
84 public String toString() {
85 return String.format("Attribute[name=%s]", mapper.name());
86 }
87 public static final class UnboundConstantValueAttribute
88 extends UnboundAttribute<ConstantValueAttribute>
89 implements ConstantValueAttribute {
90
91 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_CONSTANT_VALUE);
92
93 private final ConstantValueEntry entry;
94
95 public UnboundConstantValueAttribute(ConstantValueEntry entry) {
96 super(Attributes.constantValue());
97 this.entry = requireNonNull(entry);
98 }
99
100 @Override
101 public ConstantValueEntry constant() {
102 return entry;
103 }
104
105 @Override
106 public Utf8Entry attributeName() {
107 return NAME;
108 }
109 }
110
111 public static final class UnboundDeprecatedAttribute
112 extends UnboundAttribute<DeprecatedAttribute>
113 implements DeprecatedAttribute {
114
115 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_DEPRECATED);
116
117 public UnboundDeprecatedAttribute() {
118 super(Attributes.deprecated());
119 }
120
121 @Override
122 public Utf8Entry attributeName() {
123 return NAME;
124 }
125 }
126
127 public static final class UnboundSyntheticAttribute
128 extends UnboundAttribute<SyntheticAttribute>
129 implements SyntheticAttribute {
130
131 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SYNTHETIC);
132
133 public UnboundSyntheticAttribute() {
134 super(Attributes.synthetic());
135 }
136
137 @Override
138 public Utf8Entry attributeName() {
139 return NAME;
140 }
141 }
142
143 public static final class UnboundSignatureAttribute
144 extends UnboundAttribute<SignatureAttribute>
145 implements SignatureAttribute {
146
147 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SIGNATURE);
148
149 private final Utf8Entry signature;
150
151 public UnboundSignatureAttribute(Utf8Entry signature) {
152 super(Attributes.signature());
153 this.signature = requireNonNull(signature);
154 }
155
156 @Override
157 public Utf8Entry signature() {
158 return signature;
159 }
160
161 @Override
162 public Utf8Entry attributeName() {
163 return NAME;
164 }
165 }
166
167 public static final class UnboundExceptionsAttribute
168 extends UnboundAttribute<ExceptionsAttribute>
169 implements ExceptionsAttribute {
170
171 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_EXCEPTIONS);
172
173 private final List<ClassEntry> exceptions;
174
175 public UnboundExceptionsAttribute(List<ClassEntry> exceptions) {
176 super(Attributes.exceptions());
177 this.exceptions = Util.sanitizeU2List(exceptions);
178 }
179
180 @Override
181 public List<ClassEntry> exceptions() {
182 return exceptions;
183 }
184
185 @Override
186 public Utf8Entry attributeName() {
187 return NAME;
188 }
189 }
190
191 public static final class UnboundAnnotationDefaultAttribute
192 extends UnboundAttribute<AnnotationDefaultAttribute>
193 implements AnnotationDefaultAttribute {
194
195 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_ANNOTATION_DEFAULT);
196
197 private final AnnotationValue annotationDefault;
198
199 public UnboundAnnotationDefaultAttribute(AnnotationValue annotationDefault) {
200 super(Attributes.annotationDefault());
201 this.annotationDefault = requireNonNull(annotationDefault);
202 }
203
204 @Override
205 public AnnotationValue defaultValue() {
206 return annotationDefault;
207 }
208
209 @Override
210 public Utf8Entry attributeName() {
211 return NAME;
212 }
213 }
214
215 public static final class UnboundSourceFileAttribute extends UnboundAttribute<SourceFileAttribute>
216 implements SourceFileAttribute {
217
218 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_FILE);
219
220 private final Utf8Entry sourceFile;
221
222 public UnboundSourceFileAttribute(Utf8Entry sourceFile) {
223 super(Attributes.sourceFile());
224 this.sourceFile = requireNonNull(sourceFile);
225 }
226
227 @Override
228 public Utf8Entry sourceFile() {
229 return sourceFile;
230 }
231
232 @Override
233 public Utf8Entry attributeName() {
234 return NAME;
235 }
236 }
237
238 public static final class UnboundStackMapTableAttribute extends UnboundAttribute<StackMapTableAttribute>
239 implements StackMapTableAttribute {
240
241 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_STACK_MAP_TABLE);
242
243 private final List<StackMapFrameInfo> entries;
244
245 public UnboundStackMapTableAttribute(List<StackMapFrameInfo> entries) {
246 super(Attributes.stackMapTable());
247 this.entries = Util.sanitizeU2List(entries);
248 }
249
250 @Override
251 public List<StackMapFrameInfo> entries() {
252 return entries;
253 }
254
255 @Override
256 public Utf8Entry attributeName() {
257 return NAME;
258 }
259 }
260
261 public static final class UnboundInnerClassesAttribute
262 extends UnboundAttribute<InnerClassesAttribute>
263 implements InnerClassesAttribute {
264
265 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_INNER_CLASSES);
266
267 private final List<InnerClassInfo> innerClasses;
268
269 public UnboundInnerClassesAttribute(List<InnerClassInfo> innerClasses) {
270 super(Attributes.innerClasses());
271 this.innerClasses = Util.sanitizeU2List(innerClasses);
272 }
273
274 @Override
275 public List<InnerClassInfo> classes() {
276 return innerClasses;
277 }
278
279 @Override
280 public Utf8Entry attributeName() {
281 return NAME;
282 }
283 }
284
285 public static final class UnboundRecordAttribute
286 extends UnboundAttribute<RecordAttribute>
287 implements RecordAttribute {
288
289 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RECORD);
290
291 private final List<RecordComponentInfo> components;
292
293 public UnboundRecordAttribute(List<RecordComponentInfo> components) {
294 super(Attributes.record());
295 this.components = Util.sanitizeU2List(components);
296 }
297
298 @Override
299 public List<RecordComponentInfo> components() {
300 return components;
301 }
302
303 @Override
304 public Utf8Entry attributeName() {
305 return NAME;
306 }
307 }
308
309 public static final class UnboundEnclosingMethodAttribute
310 extends UnboundAttribute<EnclosingMethodAttribute>
311 implements EnclosingMethodAttribute {
312
313 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_ENCLOSING_METHOD);
314
315 private final ClassEntry classEntry;
316 private final NameAndTypeEntry method;
317
318 public UnboundEnclosingMethodAttribute(ClassEntry classEntry, NameAndTypeEntry method) {
319 super(Attributes.enclosingMethod());
320 this.classEntry = requireNonNull(classEntry);
321 this.method = method;
322 }
323
324 @Override
325 public ClassEntry enclosingClass() {
326 return classEntry;
327 }
328
329 @Override
330 public Optional<NameAndTypeEntry> enclosingMethod() {
331 return Optional.ofNullable(method);
332 }
333
334 @Override
335 public Utf8Entry attributeName() {
336 return NAME;
337 }
338 }
339
340 public static final class UnboundMethodParametersAttribute
341 extends UnboundAttribute<MethodParametersAttribute>
342 implements MethodParametersAttribute {
343
344 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_METHOD_PARAMETERS);
345
346 private final List<MethodParameterInfo> parameters;
347
348 public UnboundMethodParametersAttribute(List<MethodParameterInfo> parameters) {
349 super(Attributes.methodParameters());
350 this.parameters = Util.sanitizeU1List(parameters);
351 }
352
353 @Override
354 public List<MethodParameterInfo> parameters() {
355 return parameters;
356 }
357
358 @Override
359 public Utf8Entry attributeName() {
360 return NAME;
361 }
362 }
363
364 public static final class UnboundModuleTargetAttribute
365 extends UnboundAttribute<ModuleTargetAttribute>
366 implements ModuleTargetAttribute {
367
368 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_TARGET);
369
370 final Utf8Entry moduleTarget;
371
372 public UnboundModuleTargetAttribute(Utf8Entry moduleTarget) {
373 super(Attributes.moduleTarget());
374 this.moduleTarget = requireNonNull(moduleTarget);
375 }
376
377 @Override
378 public Utf8Entry targetPlatform() {
379 return moduleTarget;
380 }
381
382 @Override
383 public Utf8Entry attributeName() {
384 return NAME;
385 }
386 }
387
388 public static final class UnboundModuleMainClassAttribute
389 extends UnboundAttribute<ModuleMainClassAttribute>
390 implements ModuleMainClassAttribute {
391
392 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_MAIN_CLASS);
393
394 final ClassEntry mainClass;
395
396 public UnboundModuleMainClassAttribute(ClassEntry mainClass) {
397 super(Attributes.moduleMainClass());
398 this.mainClass = requireNonNull(mainClass);
399 }
400
401 @Override
402 public ClassEntry mainClass() {
403 return mainClass;
404 }
405
406 @Override
407 public Utf8Entry attributeName() {
408 return NAME;
409 }
410 }
411
412 public static final class UnboundModuleHashesAttribute
413 extends UnboundAttribute<ModuleHashesAttribute>
414 implements ModuleHashesAttribute {
415
416 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_HASHES);
417
418 private final Utf8Entry algorithm;
419 private final List<ModuleHashInfo> hashes;
420
421 public UnboundModuleHashesAttribute(Utf8Entry algorithm, List<ModuleHashInfo> hashes) {
422 super(Attributes.moduleHashes());
423 this.algorithm = requireNonNull(algorithm);
424 this.hashes = Util.sanitizeU2List(hashes);
425 }
426
427 @Override
428 public Utf8Entry algorithm() {
429 return algorithm;
430 }
431
432 @Override
433 public List<ModuleHashInfo> hashes() {
434 return hashes;
435 }
436
437 @Override
438 public Utf8Entry attributeName() {
439 return NAME;
440 }
441 }
442
443 public static final class UnboundModulePackagesAttribute
444 extends UnboundAttribute<ModulePackagesAttribute>
445 implements ModulePackagesAttribute {
446
447 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_PACKAGES);
448
449 private final List<PackageEntry> packages;
450
451 public UnboundModulePackagesAttribute(Collection<PackageEntry> packages) {
452 super(Attributes.modulePackages());
453 this.packages = Util.sanitizeU2List(packages);
454 }
455
456 @Override
457 public List<PackageEntry> packages() {
458 return packages;
459 }
460
461 @Override
462 public Utf8Entry attributeName() {
463 return NAME;
464 }
465 }
466
467 public static final class UnboundModuleResolutionAttribute
468 extends UnboundAttribute<ModuleResolutionAttribute>
469 implements ModuleResolutionAttribute {
470
471 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_RESOLUTION);
472
473 private final int resolutionFlags;
474
475 public UnboundModuleResolutionAttribute(int flags) {
476 super(Attributes.moduleResolution());
477 resolutionFlags = Util.checkU2(flags, "resolution flags");
478 }
479
480 @Override
481 public int resolutionFlags() {
482 return resolutionFlags;
483 }
484
485 @Override
486 public Utf8Entry attributeName() {
487 return NAME;
488 }
489 }
490
491 public static final class UnboundPermittedSubclassesAttribute
492 extends UnboundAttribute<PermittedSubclassesAttribute>
493 implements PermittedSubclassesAttribute {
494
495 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_PERMITTED_SUBCLASSES);
496
497 private final List<ClassEntry> permittedSubclasses;
498
499 public UnboundPermittedSubclassesAttribute(List<ClassEntry> permittedSubclasses) {
500 super(Attributes.permittedSubclasses());
501 this.permittedSubclasses = Util.sanitizeU2List(permittedSubclasses);
502 }
503
504 @Override
505 public List<ClassEntry> permittedSubclasses() {
506 return permittedSubclasses;
507 }
508
509 @Override
510 public Utf8Entry attributeName() {
511 return NAME;
512 }
513 }
514
515 public static final class UnboundNestMembersAttribute
516 extends UnboundAttribute<NestMembersAttribute>
517 implements NestMembersAttribute {
518
519 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_MEMBERS);
520
521 private final List<ClassEntry> memberEntries;
522
523 public UnboundNestMembersAttribute(List<ClassEntry> memberEntries) {
524 super(Attributes.nestMembers());
525 this.memberEntries = Util.sanitizeU2List(memberEntries);
526 }
527
528 @Override
529 public List<ClassEntry> nestMembers() {
530 return memberEntries;
531 }
532
533 @Override
534 public Utf8Entry attributeName() {
535 return NAME;
536 }
537 }
538
539 public static final class UnboundNestHostAttribute
540 extends UnboundAttribute<NestHostAttribute>
541 implements NestHostAttribute {
542
543 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_HOST);
544
545 private final ClassEntry hostEntry;
546
547 public UnboundNestHostAttribute(ClassEntry hostEntry) {
548 super(Attributes.nestHost());
549 this.hostEntry = requireNonNull(hostEntry);
550 }
551
552 @Override
553 public ClassEntry nestHost() {
554 return hostEntry;
555 }
556
557 @Override
558 public Utf8Entry attributeName() {
559 return NAME;
560 }
561 }
562
563 public static final class UnboundCompilationIDAttribute
564 extends UnboundAttribute<CompilationIDAttribute>
565 implements CompilationIDAttribute {
566
567 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_COMPILATION_ID);
568
569 private final Utf8Entry idEntry;
570
571 public UnboundCompilationIDAttribute(Utf8Entry idEntry) {
572 super(Attributes.compilationId());
573 this.idEntry = requireNonNull(idEntry);
574 }
575
576 @Override
577 public Utf8Entry compilationId() {
578 return idEntry;
579 }
580
581 @Override
582 public Utf8Entry attributeName() {
583 return NAME;
584 }
585 }
586
587 public static final class UnboundSourceIDAttribute
588 extends UnboundAttribute<SourceIDAttribute>
589 implements SourceIDAttribute {
590
591 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_ID);
592
593 private final Utf8Entry idEntry;
594
595 public UnboundSourceIDAttribute(Utf8Entry idEntry) {
596 super(Attributes.sourceId());
597 this.idEntry = requireNonNull(idEntry);
598 }
599
600 @Override
601 public Utf8Entry sourceId() {
602 return idEntry;
603 }
604
605 @Override
606 public Utf8Entry attributeName() {
607 return NAME;
608 }
609 }
610
611 public static final class UnboundSourceDebugExtensionAttribute
612 extends UnboundAttribute<SourceDebugExtensionAttribute>
613 implements SourceDebugExtensionAttribute {
614
615 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_DEBUG_EXTENSION);
616
617 private final byte[] contents;
618
619 public UnboundSourceDebugExtensionAttribute(byte[] contents) {
620 super(Attributes.sourceDebugExtension());
621 this.contents = requireNonNull(contents);
622 }
623
624 @Override
625 public byte[] contents() {
626 return contents;
627 }
628
629 @Override
630 public Utf8Entry attributeName() {
631 return NAME;
632 }
633 }
634
635 public static final class UnboundCharacterRangeTableAttribute
636 extends UnboundAttribute<CharacterRangeTableAttribute>
637 implements CharacterRangeTableAttribute {
638
639 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_CHARACTER_RANGE_TABLE);
640
641 private final List<CharacterRangeInfo> ranges;
642
643 public UnboundCharacterRangeTableAttribute(List<CharacterRangeInfo> ranges) {
644 super(Attributes.characterRangeTable());
645 this.ranges = Util.sanitizeU2List(ranges);
646 }
647
648 @Override
649 public List<CharacterRangeInfo> characterRangeTable() {
650 return ranges;
651 }
652
653 @Override
654 public Utf8Entry attributeName() {
655 return NAME;
656 }
657 }
658
659 public static final class UnboundLineNumberTableAttribute
660 extends UnboundAttribute<LineNumberTableAttribute>
661 implements LineNumberTableAttribute {
662
663 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE);
664
665 private final List<LineNumberInfo> lines;
666
667 public UnboundLineNumberTableAttribute(List<LineNumberInfo> lines) {
668 super(Attributes.lineNumberTable());
669 this.lines = Util.sanitizeU2List(lines);
670 }
671
672 @Override
673 public List<LineNumberInfo> lineNumbers() {
674 return lines;
675 }
676
677 @Override
678 public Utf8Entry attributeName() {
679 return NAME;
680 }
681 }
682
683 public static final class UnboundLocalVariableTableAttribute
684 extends UnboundAttribute<LocalVariableTableAttribute>
685 implements LocalVariableTableAttribute {
686
687 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE);
688
689 private final List<LocalVariableInfo> locals;
690
691 public UnboundLocalVariableTableAttribute(List<LocalVariableInfo> locals) {
692 super(Attributes.localVariableTable());
693 this.locals = Util.sanitizeU2List(locals);
694 }
695
696 @Override
697 public List<LocalVariableInfo> localVariables() {
698 return locals;
699 }
700
701 @Override
702 public Utf8Entry attributeName() {
703 return NAME;
704 }
705 }
706
707 public static final class UnboundLocalVariableTypeTableAttribute
708 extends UnboundAttribute<LocalVariableTypeTableAttribute>
709 implements LocalVariableTypeTableAttribute {
710
711 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE);
712
713 private final List<LocalVariableTypeInfo> locals;
714
715 public UnboundLocalVariableTypeTableAttribute(List<LocalVariableTypeInfo> locals) {
716 super(Attributes.localVariableTypeTable());
717 this.locals = Util.sanitizeU2List(locals);
718 }
719
720 @Override
721 public List<LocalVariableTypeInfo> localVariableTypes() {
722 return locals;
723 }
724
725 @Override
726 public Utf8Entry attributeName() {
727 return NAME;
728 }
729 }
730
731 public static final class UnboundRuntimeVisibleAnnotationsAttribute
732 extends UnboundAttribute<RuntimeVisibleAnnotationsAttribute>
733 implements RuntimeVisibleAnnotationsAttribute {
734
735 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_ANNOTATIONS);
736
737 private final List<Annotation> elements;
738
739 public UnboundRuntimeVisibleAnnotationsAttribute(List<Annotation> elements) {
740 super(Attributes.runtimeVisibleAnnotations());
741 this.elements = Util.sanitizeU2List(elements);
742 }
743
744 @Override
745 public List<Annotation> annotations() {
746 return elements;
747 }
748
749 @Override
750 public Utf8Entry attributeName() {
751 return NAME;
752 }
753 }
754
755 public static final class UnboundRuntimeInvisibleAnnotationsAttribute
756 extends UnboundAttribute<RuntimeInvisibleAnnotationsAttribute>
757 implements RuntimeInvisibleAnnotationsAttribute {
758
759 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_ANNOTATIONS);
760
761 private final List<Annotation> elements;
762
763 public UnboundRuntimeInvisibleAnnotationsAttribute(List<Annotation> elements) {
764 super(Attributes.runtimeInvisibleAnnotations());
765 this.elements = Util.sanitizeU2List(elements);
766 }
767
768 @Override
769 public List<Annotation> annotations() {
770 return elements;
771 }
772
773 @Override
774 public Utf8Entry attributeName() {
775 return NAME;
776 }
777 }
778
779 public static final class UnboundRuntimeVisibleParameterAnnotationsAttribute
780 extends UnboundAttribute<RuntimeVisibleParameterAnnotationsAttribute>
781 implements RuntimeVisibleParameterAnnotationsAttribute {
782
783 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
784
785 private final List<List<Annotation>> elements;
786
787 public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
788 super(Attributes.runtimeVisibleParameterAnnotations());
789 this.elements = Util.sanitizeParameterAnnotations(elements);
790 }
791
792 @Override
793 public List<List<Annotation>> parameterAnnotations() {
794 return elements;
795 }
796
797 @Override
798 public Utf8Entry attributeName() {
799 return NAME;
800 }
801 }
802
803 public static final class UnboundRuntimeInvisibleParameterAnnotationsAttribute
804 extends UnboundAttribute<RuntimeInvisibleParameterAnnotationsAttribute>
805 implements RuntimeInvisibleParameterAnnotationsAttribute {
806
807 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
808
809 private final List<List<Annotation>> elements;
810
811 public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
812 super(Attributes.runtimeInvisibleParameterAnnotations());
813 this.elements = Util.sanitizeParameterAnnotations(elements);
814 }
815
816 @Override
817 public List<List<Annotation>> parameterAnnotations() {
818 return elements;
819 }
820
821 @Override
822 public Utf8Entry attributeName() {
823 return NAME;
824 }
825 }
826
827 public static final class UnboundRuntimeVisibleTypeAnnotationsAttribute
828 extends UnboundAttribute<RuntimeVisibleTypeAnnotationsAttribute>
829 implements RuntimeVisibleTypeAnnotationsAttribute {
830
831 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
832
833 private final List<TypeAnnotation> elements;
834
835 public UnboundRuntimeVisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
836 super(Attributes.runtimeVisibleTypeAnnotations());
837 this.elements = Util.sanitizeU2List(elements);
838 }
839
840 @Override
841 public List<TypeAnnotation> annotations() {
842 return elements;
843 }
844
845 @Override
846 public Utf8Entry attributeName() {
847 return NAME;
848 }
849 }
850
851 public static final class UnboundRuntimeInvisibleTypeAnnotationsAttribute
852 extends UnboundAttribute<RuntimeInvisibleTypeAnnotationsAttribute>
853 implements RuntimeInvisibleTypeAnnotationsAttribute {
854
855 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
856
857 private final List<TypeAnnotation> elements;
858
859 public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
860 super(Attributes.runtimeInvisibleTypeAnnotations());
861 this.elements = Util.sanitizeU2List(elements);
862 }
863
864 @Override
865 public List<TypeAnnotation> annotations() {
866 return elements;
867 }
868
869 @Override
870 public Utf8Entry attributeName() {
871 return NAME;
872 }
873 }
874
875 public record UnboundCharacterRangeInfo(int startPc, int endPc,
876 int characterRangeStart,
877 int characterRangeEnd,
878 int flags)
879 implements CharacterRangeInfo {
880
881 public UnboundCharacterRangeInfo {
882 Util.checkU2(startPc, "start pc");
883 Util.checkU2(endPc, "end pc");
884 Util.checkU2(flags, "flags");
885 }
886 }
887
888 public record UnboundInnerClassInfo(ClassEntry innerClass,
889 Optional<ClassEntry> outerClass,
890 Optional<Utf8Entry> innerName,
891 int flagsMask)
892 implements InnerClassInfo {
893 public UnboundInnerClassInfo {
894 requireNonNull(innerClass);
895 requireNonNull(outerClass);
896 requireNonNull(innerName);
897 Util.checkFlags(flagsMask);
898 }
899 }
900
901 public record UnboundLineNumberInfo(int startPc, int lineNumber)
902 implements LineNumberInfo {
903 public UnboundLineNumberInfo {
904 Util.checkU2(startPc, "start pc");
905 Util.checkU2(lineNumber, "line number");
906 }
907 }
908
909 public record UnboundLocalVariableInfo(int startPc, int length,
910 Utf8Entry name,
911 Utf8Entry type,
912 int slot)
913 implements LocalVariableInfo {
914 public UnboundLocalVariableInfo {
915 requireNonNull(name);
916 requireNonNull(type);
917 }
918 }
919
920 public record UnboundLocalVariableTypeInfo(int startPc, int length,
921 Utf8Entry name,
922 Utf8Entry signature,
923 int slot)
924 implements LocalVariableTypeInfo {
925 public UnboundLocalVariableTypeInfo {
926 requireNonNull(name);
927 requireNonNull(signature);
928 }
929 }
930
931 public record UnboundMethodParameterInfo(Optional<Utf8Entry> name, int flagsMask)
932 implements MethodParameterInfo {
933 public UnboundMethodParameterInfo {
934 requireNonNull(name);
935 Util.checkFlags(flagsMask);
936 }
937 }
938
939 public record UnboundModuleExportInfo(PackageEntry exportedPackage,
940 int exportsFlagsMask,
941 List<ModuleEntry> exportsTo)
942 implements ModuleExportInfo {
943 public UnboundModuleExportInfo {
944 requireNonNull(exportedPackage);
945 Util.checkFlags(exportsFlagsMask);
946 exportsTo = Util.sanitizeU2List(exportsTo);
947 }
948 }
949
950 public record UnboundModuleHashInfo(ModuleEntry moduleName,
951 byte[] hash) implements ModuleHashInfo {
952 public UnboundModuleHashInfo {
953 requireNonNull(moduleName);
954 requireNonNull(hash);
955 }
956 }
957
958 public record UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask,
959 List<ModuleEntry> opensTo)
960 implements ModuleOpenInfo {
961 public UnboundModuleOpenInfo {
962 requireNonNull(openedPackage);
963 Util.checkFlags(opensFlagsMask);
964 opensTo = Util.sanitizeU2List(opensTo);
965 }
966 }
967
968 public record UnboundModuleProvideInfo(ClassEntry provides,
969 List<ClassEntry> providesWith)
970 implements ModuleProvideInfo {
971 public UnboundModuleProvideInfo {
972 requireNonNull(provides);
973 providesWith = Util.sanitizeU2List(providesWith);
974 }
975 }
976
977 public record UnboundModuleRequiresInfo(ModuleEntry requires, int requiresFlagsMask,
978 Optional<Utf8Entry> requiresVersion)
979 implements ModuleRequireInfo {
980 public UnboundModuleRequiresInfo {
981 requireNonNull(requires);
982 Util.checkFlags(requiresFlagsMask);
983 requireNonNull(requiresVersion);
984 }
985 }
986
987 public record UnboundRecordComponentInfo(Utf8Entry name,
988 Utf8Entry descriptor,
989 List<Attribute<?>> attributes)
990 implements RecordComponentInfo {
991 public UnboundRecordComponentInfo {
992 requireNonNull(name);
993 requireNonNull(descriptor);
994 attributes = Util.sanitizeU2List(attributes);
995 }
996 }
997
998 public record UnboundTypeAnnotation(TargetInfo targetInfo,
999 List<TypePathComponent> targetPath,
1000 Annotation annotation) implements TypeAnnotation {
1001
1002 public UnboundTypeAnnotation {
1003 requireNonNull(targetInfo);
1004 targetPath = Util.sanitizeU1List(targetPath);
1005 requireNonNull(annotation);
1006 }
1007 }
1008
1009 public record TypePathComponentImpl(TypeAnnotation.TypePathComponent.Kind typePathKind, int typeArgumentIndex)
1010 implements TypeAnnotation.TypePathComponent {}
1011
1012 public static final class UnboundModuleAttribute extends UnboundAttribute<ModuleAttribute> implements ModuleAttribute {
1013
1014 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE);
1015
1016 private final ModuleEntry moduleName;
1017 private final int moduleFlags;
1018 private final Utf8Entry moduleVersion;
1019 private final List<ModuleRequireInfo> requires;
1020 private final List<ModuleExportInfo> exports;
1021 private final List<ModuleOpenInfo> opens;
1022 private final List<ClassEntry> uses;
1023 private final List<ModuleProvideInfo> provides;
1024
1025 public UnboundModuleAttribute(ModuleEntry moduleName,
1026 int moduleFlags,
1027 Utf8Entry moduleVersion,
1028 Collection<ModuleRequireInfo> requires,
1029 Collection<ModuleExportInfo> exports,
1030 Collection<ModuleOpenInfo> opens,
1031 Collection<ClassEntry> uses,
1032 Collection<ModuleProvideInfo> provides)
1033 {
1034 super(Attributes.module());
1035 this.moduleName = requireNonNull(moduleName);
1036 this.moduleFlags = Util.checkFlags(moduleFlags);
1037 this.moduleVersion = moduleVersion;
1038 this.requires = Util.sanitizeU2List(requires);
1039 this.exports = Util.sanitizeU2List(exports);
1040 this.opens = Util.sanitizeU2List(opens);
1041 this.uses = Util.sanitizeU2List(uses);
1042 this.provides = Util.sanitizeU2List(provides);
1043 }
1044
1045 @Override
1046 public ModuleEntry moduleName() {
1047 return moduleName;
1048 }
1049
1050 @Override
1051 public int moduleFlagsMask() {
1052 return moduleFlags;
1053 }
1054
1055 @Override
1056 public Optional<Utf8Entry> moduleVersion() {
1057 return Optional.ofNullable(moduleVersion);
1058 }
1059
1060 @Override
1061 public List<ModuleRequireInfo> requires() {
1062 return requires;
1063 }
1064
1065 @Override
1066 public List<ModuleExportInfo> exports() {
1067 return exports;
1068 }
1069
1070 @Override
1071 public List<ModuleOpenInfo> opens() {
1072 return opens;
1073 }
1074
1075 @Override
1076 public List<ClassEntry> uses() {
1077 return uses;
1078 }
1079
1080 @Override
1081 public List<ModuleProvideInfo> provides() {
1082 return provides;
1083 }
1084
1085 @Override
1086 public Utf8Entry attributeName() {
1087 return NAME;
1088 }
1089 }
1090
1091 public abstract static non-sealed class AdHocAttribute<T extends Attribute<T>>
1092 extends UnboundAttribute<T> {
1093
1094 public AdHocAttribute(AttributeMapper<T> mapper) {
1095 super(mapper);
1096 }
1097
1098 public abstract void writeBody(BufWriterImpl b);
1099
1100 @Override
1101 public void writeTo(BufWriterImpl b) {
1102 b.writeIndex(b.constantPool().utf8Entry(mapper.name()));
1103 int lengthIndex = b.skip(4);
1104 writeBody(b);
1105 int written = b.size() - lengthIndex - 4;
1106 b.patchInt(lengthIndex, written);
1107 }
1108 }
1109
1110 public static final class EmptyBootstrapAttribute
1111 extends UnboundAttribute<BootstrapMethodsAttribute>
1112 implements BootstrapMethodsAttribute {
1113
1114 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_BOOTSTRAP_METHODS);
1115
1116 public EmptyBootstrapAttribute() {
1117 super(Attributes.bootstrapMethods());
1118 }
1119
1120 @Override
1121 public int bootstrapMethodsSize() {
1122 return 0;
1123 }
1124
1125 @Override
1126 public List<BootstrapMethodEntry> bootstrapMethods() {
1127 return List.of();
1128 }
1129
1130 @Override
1131 public Utf8Entry attributeName() {
1132 return NAME;
1133 }
1134 }
1135 }