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 UnboundLoadableDescriptorsAttribute
516 extends UnboundAttribute<LoadableDescriptorsAttribute>
517 implements LoadableDescriptorsAttribute {
518
519 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOADABLE_DESCRIPTORS);
520
521 private final List<Utf8Entry> loadableDescriptors;
522
523 public UnboundLoadableDescriptorsAttribute(List<Utf8Entry> loadableDescriptors) {
524 super(Attributes.loadableDescriptors());
525 this.loadableDescriptors = List.copyOf(loadableDescriptors);
526 }
527
528 @Override
529 public List<Utf8Entry> loadableDescriptors() {
530 return loadableDescriptors;
531 }
532
533 @Override
534 public Utf8Entry attributeName() {
535 return NAME;
536 }
537 }
538
539 public static final class UnboundNestMembersAttribute
540 extends UnboundAttribute<NestMembersAttribute>
541 implements NestMembersAttribute {
542
543 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_MEMBERS);
544
545 private final List<ClassEntry> memberEntries;
546
547 public UnboundNestMembersAttribute(List<ClassEntry> memberEntries) {
548 super(Attributes.nestMembers());
549 this.memberEntries = Util.sanitizeU2List(memberEntries);
550 }
551
552 @Override
553 public List<ClassEntry> nestMembers() {
554 return memberEntries;
555 }
556
557 @Override
558 public Utf8Entry attributeName() {
559 return NAME;
560 }
561 }
562
563 public static final class UnboundNestHostAttribute
564 extends UnboundAttribute<NestHostAttribute>
565 implements NestHostAttribute {
566
567 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_HOST);
568
569 private final ClassEntry hostEntry;
570
571 public UnboundNestHostAttribute(ClassEntry hostEntry) {
572 super(Attributes.nestHost());
573 this.hostEntry = requireNonNull(hostEntry);
574 }
575
576 @Override
577 public ClassEntry nestHost() {
578 return hostEntry;
579 }
580
581 @Override
582 public Utf8Entry attributeName() {
583 return NAME;
584 }
585 }
586
587 public static final class UnboundCompilationIDAttribute
588 extends UnboundAttribute<CompilationIDAttribute>
589 implements CompilationIDAttribute {
590
591 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_COMPILATION_ID);
592
593 private final Utf8Entry idEntry;
594
595 public UnboundCompilationIDAttribute(Utf8Entry idEntry) {
596 super(Attributes.compilationId());
597 this.idEntry = requireNonNull(idEntry);
598 }
599
600 @Override
601 public Utf8Entry compilationId() {
602 return idEntry;
603 }
604
605 @Override
606 public Utf8Entry attributeName() {
607 return NAME;
608 }
609 }
610
611 public static final class UnboundSourceIDAttribute
612 extends UnboundAttribute<SourceIDAttribute>
613 implements SourceIDAttribute {
614
615 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_ID);
616
617 private final Utf8Entry idEntry;
618
619 public UnboundSourceIDAttribute(Utf8Entry idEntry) {
620 super(Attributes.sourceId());
621 this.idEntry = requireNonNull(idEntry);
622 }
623
624 @Override
625 public Utf8Entry sourceId() {
626 return idEntry;
627 }
628
629 @Override
630 public Utf8Entry attributeName() {
631 return NAME;
632 }
633 }
634
635 public static final class UnboundSourceDebugExtensionAttribute
636 extends UnboundAttribute<SourceDebugExtensionAttribute>
637 implements SourceDebugExtensionAttribute {
638
639 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_DEBUG_EXTENSION);
640
641 private final byte[] contents;
642
643 public UnboundSourceDebugExtensionAttribute(byte[] contents) {
644 super(Attributes.sourceDebugExtension());
645 this.contents = requireNonNull(contents);
646 }
647
648 @Override
649 public byte[] contents() {
650 return contents;
651 }
652
653 @Override
654 public Utf8Entry attributeName() {
655 return NAME;
656 }
657 }
658
659 public static final class UnboundCharacterRangeTableAttribute
660 extends UnboundAttribute<CharacterRangeTableAttribute>
661 implements CharacterRangeTableAttribute {
662
663 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_CHARACTER_RANGE_TABLE);
664
665 private final List<CharacterRangeInfo> ranges;
666
667 public UnboundCharacterRangeTableAttribute(List<CharacterRangeInfo> ranges) {
668 super(Attributes.characterRangeTable());
669 this.ranges = Util.sanitizeU2List(ranges);
670 }
671
672 @Override
673 public List<CharacterRangeInfo> characterRangeTable() {
674 return ranges;
675 }
676
677 @Override
678 public Utf8Entry attributeName() {
679 return NAME;
680 }
681 }
682
683 public static final class UnboundLineNumberTableAttribute
684 extends UnboundAttribute<LineNumberTableAttribute>
685 implements LineNumberTableAttribute {
686
687 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE);
688
689 private final List<LineNumberInfo> lines;
690
691 public UnboundLineNumberTableAttribute(List<LineNumberInfo> lines) {
692 super(Attributes.lineNumberTable());
693 this.lines = Util.sanitizeU2List(lines);
694 }
695
696 @Override
697 public List<LineNumberInfo> lineNumbers() {
698 return lines;
699 }
700
701 @Override
702 public Utf8Entry attributeName() {
703 return NAME;
704 }
705 }
706
707 public static final class UnboundLocalVariableTableAttribute
708 extends UnboundAttribute<LocalVariableTableAttribute>
709 implements LocalVariableTableAttribute {
710
711 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE);
712
713 private final List<LocalVariableInfo> locals;
714
715 public UnboundLocalVariableTableAttribute(List<LocalVariableInfo> locals) {
716 super(Attributes.localVariableTable());
717 this.locals = Util.sanitizeU2List(locals);
718 }
719
720 @Override
721 public List<LocalVariableInfo> localVariables() {
722 return locals;
723 }
724
725 @Override
726 public Utf8Entry attributeName() {
727 return NAME;
728 }
729 }
730
731 public static final class UnboundLocalVariableTypeTableAttribute
732 extends UnboundAttribute<LocalVariableTypeTableAttribute>
733 implements LocalVariableTypeTableAttribute {
734
735 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE);
736
737 private final List<LocalVariableTypeInfo> locals;
738
739 public UnboundLocalVariableTypeTableAttribute(List<LocalVariableTypeInfo> locals) {
740 super(Attributes.localVariableTypeTable());
741 this.locals = Util.sanitizeU2List(locals);
742 }
743
744 @Override
745 public List<LocalVariableTypeInfo> localVariableTypes() {
746 return locals;
747 }
748
749 @Override
750 public Utf8Entry attributeName() {
751 return NAME;
752 }
753 }
754
755 public static final class UnboundRuntimeVisibleAnnotationsAttribute
756 extends UnboundAttribute<RuntimeVisibleAnnotationsAttribute>
757 implements RuntimeVisibleAnnotationsAttribute {
758
759 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_ANNOTATIONS);
760
761 private final List<Annotation> elements;
762
763 public UnboundRuntimeVisibleAnnotationsAttribute(List<Annotation> elements) {
764 super(Attributes.runtimeVisibleAnnotations());
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 UnboundRuntimeInvisibleAnnotationsAttribute
780 extends UnboundAttribute<RuntimeInvisibleAnnotationsAttribute>
781 implements RuntimeInvisibleAnnotationsAttribute {
782
783 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_ANNOTATIONS);
784
785 private final List<Annotation> elements;
786
787 public UnboundRuntimeInvisibleAnnotationsAttribute(List<Annotation> elements) {
788 super(Attributes.runtimeInvisibleAnnotations());
789 this.elements = Util.sanitizeU2List(elements);
790 }
791
792 @Override
793 public List<Annotation> annotations() {
794 return elements;
795 }
796
797 @Override
798 public Utf8Entry attributeName() {
799 return NAME;
800 }
801 }
802
803 public static final class UnboundRuntimeVisibleParameterAnnotationsAttribute
804 extends UnboundAttribute<RuntimeVisibleParameterAnnotationsAttribute>
805 implements RuntimeVisibleParameterAnnotationsAttribute {
806
807 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
808
809 private final List<List<Annotation>> elements;
810
811 public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
812 super(Attributes.runtimeVisibleParameterAnnotations());
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 UnboundRuntimeInvisibleParameterAnnotationsAttribute
828 extends UnboundAttribute<RuntimeInvisibleParameterAnnotationsAttribute>
829 implements RuntimeInvisibleParameterAnnotationsAttribute {
830
831 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
832
833 private final List<List<Annotation>> elements;
834
835 public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
836 super(Attributes.runtimeInvisibleParameterAnnotations());
837 this.elements = Util.sanitizeParameterAnnotations(elements);
838 }
839
840 @Override
841 public List<List<Annotation>> parameterAnnotations() {
842 return elements;
843 }
844
845 @Override
846 public Utf8Entry attributeName() {
847 return NAME;
848 }
849 }
850
851 public static final class UnboundRuntimeVisibleTypeAnnotationsAttribute
852 extends UnboundAttribute<RuntimeVisibleTypeAnnotationsAttribute>
853 implements RuntimeVisibleTypeAnnotationsAttribute {
854
855 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
856
857 private final List<TypeAnnotation> elements;
858
859 public UnboundRuntimeVisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
860 super(Attributes.runtimeVisibleTypeAnnotations());
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 static final class UnboundRuntimeInvisibleTypeAnnotationsAttribute
876 extends UnboundAttribute<RuntimeInvisibleTypeAnnotationsAttribute>
877 implements RuntimeInvisibleTypeAnnotationsAttribute {
878
879 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
880
881 private final List<TypeAnnotation> elements;
882
883 public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
884 super(Attributes.runtimeInvisibleTypeAnnotations());
885 this.elements = Util.sanitizeU2List(elements);
886 }
887
888 @Override
889 public List<TypeAnnotation> annotations() {
890 return elements;
891 }
892
893 @Override
894 public Utf8Entry attributeName() {
895 return NAME;
896 }
897 }
898
899 public record UnboundCharacterRangeInfo(int startPc, int endPc,
900 int characterRangeStart,
901 int characterRangeEnd,
902 int flags)
903 implements CharacterRangeInfo {
904
905 public UnboundCharacterRangeInfo {
906 Util.checkU2(startPc, "start pc");
907 Util.checkU2(endPc, "end pc");
908 Util.checkU2(flags, "flags");
909 }
910 }
911
912 public record UnboundInnerClassInfo(ClassEntry innerClass,
913 Optional<ClassEntry> outerClass,
914 Optional<Utf8Entry> innerName,
915 int flagsMask)
916 implements InnerClassInfo {
917 public UnboundInnerClassInfo {
918 requireNonNull(innerClass);
919 requireNonNull(outerClass);
920 requireNonNull(innerName);
921 Util.checkFlags(flagsMask);
922 }
923 }
924
925 public record UnboundLineNumberInfo(int startPc, int lineNumber)
926 implements LineNumberInfo {
927 public UnboundLineNumberInfo {
928 Util.checkU2(startPc, "start pc");
929 Util.checkU2(lineNumber, "line number");
930 }
931 }
932
933 public record UnboundLocalVariableInfo(int startPc, int length,
934 Utf8Entry name,
935 Utf8Entry type,
936 int slot)
937 implements LocalVariableInfo {
938 public UnboundLocalVariableInfo {
939 requireNonNull(name);
940 requireNonNull(type);
941 }
942 }
943
944 public record UnboundLocalVariableTypeInfo(int startPc, int length,
945 Utf8Entry name,
946 Utf8Entry signature,
947 int slot)
948 implements LocalVariableTypeInfo {
949 public UnboundLocalVariableTypeInfo {
950 requireNonNull(name);
951 requireNonNull(signature);
952 }
953 }
954
955 public record UnboundMethodParameterInfo(Optional<Utf8Entry> name, int flagsMask)
956 implements MethodParameterInfo {
957 public UnboundMethodParameterInfo {
958 requireNonNull(name);
959 Util.checkFlags(flagsMask);
960 }
961 }
962
963 public record UnboundModuleExportInfo(PackageEntry exportedPackage,
964 int exportsFlagsMask,
965 List<ModuleEntry> exportsTo)
966 implements ModuleExportInfo {
967 public UnboundModuleExportInfo {
968 requireNonNull(exportedPackage);
969 Util.checkFlags(exportsFlagsMask);
970 exportsTo = Util.sanitizeU2List(exportsTo);
971 }
972 }
973
974 public record UnboundModuleHashInfo(ModuleEntry moduleName,
975 byte[] hash) implements ModuleHashInfo {
976 public UnboundModuleHashInfo {
977 requireNonNull(moduleName);
978 requireNonNull(hash);
979 }
980 }
981
982 public record UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask,
983 List<ModuleEntry> opensTo)
984 implements ModuleOpenInfo {
985 public UnboundModuleOpenInfo {
986 requireNonNull(openedPackage);
987 Util.checkFlags(opensFlagsMask);
988 opensTo = Util.sanitizeU2List(opensTo);
989 }
990 }
991
992 public record UnboundModuleProvideInfo(ClassEntry provides,
993 List<ClassEntry> providesWith)
994 implements ModuleProvideInfo {
995 public UnboundModuleProvideInfo {
996 requireNonNull(provides);
997 providesWith = Util.sanitizeU2List(providesWith);
998 }
999 }
1000
1001 public record UnboundModuleRequiresInfo(ModuleEntry requires, int requiresFlagsMask,
1002 Optional<Utf8Entry> requiresVersion)
1003 implements ModuleRequireInfo {
1004 public UnboundModuleRequiresInfo {
1005 requireNonNull(requires);
1006 Util.checkFlags(requiresFlagsMask);
1007 requireNonNull(requiresVersion);
1008 }
1009 }
1010
1011 public record UnboundRecordComponentInfo(Utf8Entry name,
1012 Utf8Entry descriptor,
1013 List<Attribute<?>> attributes)
1014 implements RecordComponentInfo {
1015 public UnboundRecordComponentInfo {
1016 requireNonNull(name);
1017 requireNonNull(descriptor);
1018 attributes = Util.sanitizeU2List(attributes);
1019 }
1020 }
1021
1022 public record UnboundTypeAnnotation(TargetInfo targetInfo,
1023 List<TypePathComponent> targetPath,
1024 Annotation annotation) implements TypeAnnotation {
1025
1026 public UnboundTypeAnnotation {
1027 requireNonNull(targetInfo);
1028 targetPath = Util.sanitizeU1List(targetPath);
1029 requireNonNull(annotation);
1030 }
1031 }
1032
1033 public record TypePathComponentImpl(TypeAnnotation.TypePathComponent.Kind typePathKind, int typeArgumentIndex)
1034 implements TypeAnnotation.TypePathComponent {}
1035
1036 public static final class UnboundModuleAttribute extends UnboundAttribute<ModuleAttribute> implements ModuleAttribute {
1037
1038 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE);
1039
1040 private final ModuleEntry moduleName;
1041 private final int moduleFlags;
1042 private final Utf8Entry moduleVersion;
1043 private final List<ModuleRequireInfo> requires;
1044 private final List<ModuleExportInfo> exports;
1045 private final List<ModuleOpenInfo> opens;
1046 private final List<ClassEntry> uses;
1047 private final List<ModuleProvideInfo> provides;
1048
1049 public UnboundModuleAttribute(ModuleEntry moduleName,
1050 int moduleFlags,
1051 Utf8Entry moduleVersion,
1052 Collection<ModuleRequireInfo> requires,
1053 Collection<ModuleExportInfo> exports,
1054 Collection<ModuleOpenInfo> opens,
1055 Collection<ClassEntry> uses,
1056 Collection<ModuleProvideInfo> provides)
1057 {
1058 super(Attributes.module());
1059 this.moduleName = requireNonNull(moduleName);
1060 this.moduleFlags = Util.checkFlags(moduleFlags);
1061 this.moduleVersion = moduleVersion;
1062 this.requires = Util.sanitizeU2List(requires);
1063 this.exports = Util.sanitizeU2List(exports);
1064 this.opens = Util.sanitizeU2List(opens);
1065 this.uses = Util.sanitizeU2List(uses);
1066 this.provides = Util.sanitizeU2List(provides);
1067 }
1068
1069 @Override
1070 public ModuleEntry moduleName() {
1071 return moduleName;
1072 }
1073
1074 @Override
1075 public int moduleFlagsMask() {
1076 return moduleFlags;
1077 }
1078
1079 @Override
1080 public Optional<Utf8Entry> moduleVersion() {
1081 return Optional.ofNullable(moduleVersion);
1082 }
1083
1084 @Override
1085 public List<ModuleRequireInfo> requires() {
1086 return requires;
1087 }
1088
1089 @Override
1090 public List<ModuleExportInfo> exports() {
1091 return exports;
1092 }
1093
1094 @Override
1095 public List<ModuleOpenInfo> opens() {
1096 return opens;
1097 }
1098
1099 @Override
1100 public List<ClassEntry> uses() {
1101 return uses;
1102 }
1103
1104 @Override
1105 public List<ModuleProvideInfo> provides() {
1106 return provides;
1107 }
1108
1109 @Override
1110 public Utf8Entry attributeName() {
1111 return NAME;
1112 }
1113 }
1114
1115 public abstract static non-sealed class AdHocAttribute<T extends Attribute<T>>
1116 extends UnboundAttribute<T> {
1117
1118 public AdHocAttribute(AttributeMapper<T> mapper) {
1119 super(mapper);
1120 }
1121
1122 public abstract void writeBody(BufWriterImpl b);
1123
1124 @Override
1125 public void writeTo(BufWriterImpl b) {
1126 b.writeIndex(b.constantPool().utf8Entry(mapper.name()));
1127 int lengthIndex = b.skip(4);
1128 writeBody(b);
1129 int written = b.size() - lengthIndex - 4;
1130 b.patchInt(lengthIndex, written);
1131 }
1132 }
1133
1134 public static final class EmptyBootstrapAttribute
1135 extends UnboundAttribute<BootstrapMethodsAttribute>
1136 implements BootstrapMethodsAttribute {
1137
1138 private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_BOOTSTRAP_METHODS);
1139
1140 public EmptyBootstrapAttribute() {
1141 super(Attributes.bootstrapMethods());
1142 }
1143
1144 @Override
1145 public int bootstrapMethodsSize() {
1146 return 0;
1147 }
1148
1149 @Override
1150 public List<BootstrapMethodEntry> bootstrapMethods() {
1151 return List.of();
1152 }
1153
1154 @Override
1155 public Utf8Entry attributeName() {
1156 return NAME;
1157 }
1158 }
1159 }