1 /*
2 * Copyright (c) 2022, 2026, 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 java.lang.classfile;
26
27 import java.io.IOException;
28 import java.lang.classfile.AttributeMapper.AttributeStability;
29 import java.lang.classfile.attribute.CharacterRangeInfo;
30 import java.lang.classfile.attribute.CodeAttribute;
31 import java.lang.classfile.attribute.LocalVariableInfo;
32 import java.lang.classfile.attribute.LocalVariableTypeInfo;
33 import java.lang.classfile.attribute.ModuleAttribute;
34 import java.lang.classfile.attribute.StackMapTableAttribute;
35 import java.lang.classfile.attribute.UnknownAttribute;
36 import java.lang.classfile.constantpool.ClassEntry;
37 import java.lang.classfile.constantpool.ConstantPoolBuilder;
38 import java.lang.classfile.constantpool.Utf8Entry;
39 import java.lang.classfile.instruction.BranchInstruction;
40 import java.lang.classfile.instruction.CharacterRange;
41 import java.lang.classfile.instruction.DiscontinuedInstruction;
42 import java.lang.classfile.instruction.ExceptionCatch;
43 import java.lang.classfile.instruction.LineNumber;
44 import java.lang.classfile.instruction.LocalVariable;
45 import java.lang.classfile.instruction.LocalVariableType;
46 import java.lang.constant.ClassDesc;
47 import java.lang.reflect.AccessFlag;
48 import java.lang.reflect.ClassFileFormatVersion;
49 import java.nio.file.Files;
50 import java.nio.file.Path;
51 import java.util.List;
52 import java.util.function.Consumer;
53 import java.util.function.Function;
54
55 import jdk.internal.classfile.impl.ClassFileImpl;
56 import jdk.internal.classfile.impl.TemporaryConstantPool;
57 import jdk.internal.javac.PreviewFeature;
58
59 import static java.util.Objects.requireNonNull;
60 import static jdk.internal.constant.ConstantUtils.CD_module_info;
61
62 /**
63 * Provides ability to parse, transform, and generate {@code class} files.
64 * A {@code ClassFile} is a context with a set of options that condition how
65 * parsing and generation are done.
66 *
67 * @since 24
68 */
69 public sealed interface ClassFile
70 permits ClassFileImpl {
71
72 /**
73 * {@return a context with default options} Each subtype of {@link Option}
74 * specifies its default.
75 * <p>
76 * The default {@link AttributeMapperOption} and {@link
77 * ClassHierarchyResolverOption} may be unsuitable for some {@code class}
78 * files and result in parsing or generation errors.
79 */
80 static ClassFile of() {
81 return ClassFileImpl.DEFAULT_CONTEXT;
82 }
83
84 /**
85 * {@return a context with options altered from the default} Equivalent to
86 * {@link #of() ClassFile.of().withOptions(options)}.
87 * @param options the desired processing options
88 */
89 static ClassFile of(Option... options) {
90 return of().withOptions(options);
91 }
92
93 /**
94 * {@return a context with altered options from this context}
95 * @param options the desired processing options
96 */
97 ClassFile withOptions(Option... options);
98
99 /**
100 * An option that affects the parsing or writing of {@code class} files.
101 *
102 * @see java.lang.classfile##options Options
103 * @sealedGraph
104 * @since 24
105 */
106 sealed interface Option {
107 }
108
109 /**
110 * The option describing user-defined attributes for parsing {@code class}
111 * files. The default does not recognize any user-defined attribute.
112 * <p>
113 * An {@code AttributeMapperOption} contains a function that maps an
114 * attribute name to a user attribute mapper. The function may return {@code
115 * null} if it does not recognize an attribute name. The returned mapper
116 * must ensure its {@link AttributeMapper#name() name()} is equivalent to
117 * the {@link Utf8Entry#stringValue() stringValue()} of the input {@link
118 * Utf8Entry}.
119 * <p>
120 * The mapping function in this attribute has lower priority than mappers in
121 * {@link Attributes}, so it is impossible to override built-in attributes
122 * with this option. If an attribute is not recognized by any mapper in
123 * {@link Attributes} and is not assigned a mapper, or recognized, by this
124 * option, that attribute will be modeled by an {@link UnknownAttribute}.
125 *
126 * @see AttributeMapper
127 * @see CustomAttribute
128 * @since 24
129 */
130 sealed interface AttributeMapperOption extends Option
131 permits ClassFileImpl.AttributeMapperOptionImpl {
132
133 /**
134 * {@return an option describing user-defined attributes for parsing}
135 *
136 * @param attributeMapper a function mapping attribute names to attribute mappers
137 */
138 static AttributeMapperOption of(Function<Utf8Entry, AttributeMapper<?>> attributeMapper) {
139 requireNonNull(attributeMapper);
140 return new ClassFileImpl.AttributeMapperOptionImpl(attributeMapper);
141 }
142
143 /**
144 * {@return the function mapping attribute names to attribute mappers}
145 */
146 Function<Utf8Entry, AttributeMapper<?>> attributeMapper();
147 }
148
149 /**
150 * The option describing the class hierarchy resolver to use when generating
151 * stack maps or verifying classes. The default is {@link
152 * ClassHierarchyResolver#defaultResolver()}, which uses core reflection to
153 * find a class with a given name in {@linkplain ClassLoader#getSystemClassLoader()
154 * system class loader} and inspect it, and is insufficient if a class is
155 * not present in the system class loader as in applications, or if loading
156 * of system classes is not desired as in agents.
157 * <p>
158 * A {@code ClassHierarchyResolverOption} contains a {@link ClassHierarchyResolver}.
159 * The resolver must be able to process all classes and interfaces, including
160 * those appearing as the component types of array types, that appear in the
161 * operand stack of the generated bytecode. If the resolver fails on any
162 * of the classes and interfaces with an {@link IllegalArgumentException},
163 * the {@code class} file generation fails.
164 *
165 * @see ClassHierarchyResolver
166 * @jvms 4.10.1.2 Verification Type System
167 * @since 24
168 */
169 sealed interface ClassHierarchyResolverOption extends Option
170 permits ClassFileImpl.ClassHierarchyResolverOptionImpl {
171
172 /**
173 * {@return an option describing the class hierarchy resolver to use}
174 *
175 * @param classHierarchyResolver the resolver
176 */
177 static ClassHierarchyResolverOption of(ClassHierarchyResolver classHierarchyResolver) {
178 requireNonNull(classHierarchyResolver);
179 return new ClassFileImpl.ClassHierarchyResolverOptionImpl(classHierarchyResolver);
180 }
181
182 /**
183 * {@return the class hierarchy resolver}
184 */
185 ClassHierarchyResolver classHierarchyResolver();
186 }
187
188 /**
189 * Option describing whether to extend from the original constant pool when
190 * transforming a {@code class} file. The default is {@link #SHARED_POOL}
191 * to extend from the original constant pool.
192 * <p>
193 * This option affects all overloads of {@link #transformClass transformClass}.
194 * Extending from the original constant pool keeps the indices into the
195 * constant pool intact, which enables significant optimizations in processing
196 * time and minimizes differences between the original and transformed {@code
197 * class} files, but may result in a bigger transformed {@code class} file
198 * when many elements of the original {@code class} file are dropped and
199 * many original constant pool entries become unused.
200 * <p>
201 * An alternative to this option is to use {@link #build(ClassEntry,
202 * ConstantPoolBuilder, Consumer)} directly. It allows extension from
203 * arbitrary constant pools, and may be useful if a built {@code class} file
204 * reuses structures from multiple original {@code class} files.
205 *
206 * @see ConstantPoolBuilder
207 * @see #build(ClassEntry, ConstantPoolBuilder, Consumer)
208 * @see #transformClass(ClassModel, ClassTransform)
209 * @since 24
210 */
211 enum ConstantPoolSharingOption implements Option {
212
213 /**
214 * Extend the new constant pool from the original constant pool when
215 * transforming the {@code class} file.
216 * <p>
217 * These two transformations below are equivalent:
218 * {@snippet lang=java :
219 * ClassModel originalClass = null; // @replace substring=null; replacement=...
220 * ClassDesc resultClassName = null; // @replace substring=null; replacement=...
221 * ClassTransform classTransform = null; // @replace substring=null; replacement=...
222 * var resultOne = ClassFile.of(ConstantPoolSharingOption.SHARED_POOL)
223 * .transformClass(originalClass, resultClassName, classTransform);
224 * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(originalClass),
225 * clb -> clb.transform(originalClass, classTransform));
226 * }
227 *
228 * @see ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel)
229 */
230 SHARED_POOL,
231
232 /**
233 * Creates a new constant pool when transforming the {@code class} file.
234 * <p>
235 * These two transformations below are equivalent:
236 * {@snippet lang=java :
237 * ClassModel originalClass = null; // @replace substring=null; replacement=...
238 * ClassDesc resultClassName = null; // @replace substring=null; replacement=...
239 * ClassTransform classTransform = null; // @replace substring=null; replacement=...
240 * var resultOne = ClassFile.of(ConstantPoolSharingOption.NEW_POOL)
241 * .transformClass(originalClass, resultClassName, classTransform);
242 * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(),
243 * clb -> clb.transform(originalClass, classTransform));
244 * }
245 *
246 * @see ConstantPoolBuilder#of() ConstantPoolBuilder::of()
247 */
248 NEW_POOL
249 }
250
251 /**
252 * The option describing whether to patch out unreachable code for stack map
253 * generation. The default is {@link #PATCH_DEAD_CODE} to automatically
254 * patch unreachable code and generate a valid stack map entry for the
255 * patched code.
256 * <p>
257 * The stack map generation process may fail when it encounters unreachable
258 * code and {@link #KEEP_DEAD_CODE} is set. In such cases, users should
259 * set {@link StackMapsOption#DROP_STACK_MAPS} and provide their own stack
260 * maps that passes verification (JVMS {@jvms 4.10.1}).
261 *
262 * @see StackMapsOption
263 * @jvms 4.10.1 Verification by Type Checking
264 * @since 24
265 */
266 enum DeadCodeOption implements Option {
267
268 /**
269 * Patch unreachable code with dummy code, and generate valid dummy
270 * stack map entries. This ensures the generated code can pass
271 * verification (JVMS {@jvms 4.10.1}).
272 */
273 PATCH_DEAD_CODE,
274
275 /**
276 * Keep the unreachable code for the accuracy of the generated {@code
277 * class} file. Users should set {@link StackMapsOption#DROP_STACK_MAPS}
278 * to prevent stack map generation from running and provide their own
279 * {@link StackMapTableAttribute} to a {@link CodeBuilder}.
280 */
281 KEEP_DEAD_CODE
282 }
283
284 /**
285 * The option describing whether to filter {@linkplain
286 * CodeBuilder#labelBinding(Label) unbound labels} and drop their
287 * enclosing structures if possible. The default is {@link
288 * #FAIL_ON_DEAD_LABELS} to fail fast with an {@link IllegalArgumentException}
289 * when a {@link PseudoInstruction} refers to an unbound label during
290 * bytecode generation.
291 * <p>
292 * The affected {@link PseudoInstruction}s include {@link ExceptionCatch},
293 * {@link LocalVariable}, {@link LocalVariableType}, and {@link
294 * CharacterRange}. Setting this option to {@link #DROP_DEAD_LABELS}
295 * filters these pseudo-instructions from a {@link CodeBuilder} instead.
296 * Note that instructions, such as {@link BranchInstruction}, with unbound
297 * labels always fail-fast with an {@link IllegalArgumentException}.
298 *
299 * @see DebugElementsOption
300 * @since 24
301 */
302 enum DeadLabelsOption implements Option {
303
304 /**
305 * Fail fast on {@linkplain CodeBuilder#labelBinding(Label) unbound
306 * labels}. This also ensures the accuracy of the generated {@code
307 * class} files.
308 */
309 FAIL_ON_DEAD_LABELS,
310
311 /**
312 * Filter {@link PseudoInstruction}s with {@linkplain
313 * CodeBuilder#labelBinding(Label) unbound labels}. Note that
314 * instructions with unbound labels still cause an {@link
315 * IllegalArgumentException}.
316 */
317 DROP_DEAD_LABELS
318 }
319
320 /**
321 * The option describing whether to process or discard debug {@link
322 * PseudoInstruction}s in the traversal of a {@link CodeModel} or a {@link
323 * CodeBuilder}. The default is {@link #PASS_DEBUG} to process debug
324 * pseudo-instructions as all other {@link CodeElement}.
325 * <p>
326 * Debug pseudo-instructions include {@link LocalVariable}, {@link
327 * LocalVariableType}, and {@link CharacterRange}. Discarding debug
328 * elements may reduce the overhead of parsing or transforming {@code class}
329 * files and has no impact on the run-time behavior.
330 *
331 * @see LineNumbersOption
332 * @since 24
333 */
334 enum DebugElementsOption implements Option {
335
336 /**
337 * Process debug pseudo-instructions like other member elements of a
338 * {@link CodeModel}.
339 */
340 PASS_DEBUG,
341
342 /**
343 * Drop debug pseudo-instructions from traversal and builders.
344 */
345 DROP_DEBUG
346 }
347
348 /**
349 * The option describing whether to process or discard {@link LineNumber}s
350 * in the traversal of a {@link CodeModel} or a {@link CodeBuilder}. The
351 * default is {@link #PASS_LINE_NUMBERS} to process all line number entries
352 * as all other {@link CodeElement}.
353 * <p>
354 * Discarding line numbers may reduce the overhead of parsing or transforming
355 * {@code class} files and has no impact on the run-time behavior.
356 *
357 * @see DebugElementsOption
358 * @since 24
359 */
360 enum LineNumbersOption implements Option {
361
362 /**
363 * Process {@link LineNumber} like other member elements of a {@link
364 * CodeModel}.
365 */
366 PASS_LINE_NUMBERS,
367
368 /**
369 * Drop {@link LineNumber} from traversal and builders.
370 */
371 DROP_LINE_NUMBERS;
372 }
373
374 /**
375 * The option describing whether to automatically rewrite short jumps to
376 * equivalent instructions when necessary. The default is {@link
377 * #FIX_SHORT_JUMPS} to automatically rewrite.
378 * <p>
379 * Due to physical restrictions, some types of instructions cannot encode
380 * certain jump targets with bci offsets less than -32768 or greater than
381 * 32767, as they use a {@code s2} to encode such an offset. (The maximum
382 * length of the {@code code} array is 65535.) These types of instructions
383 * are called "short jumps".
384 * <p>
385 * Disabling rewrite can ensure the physical accuracy of a generated {@code
386 * class} file and avoid the overhead from a failed first attempt for
387 * overflowing forward jumps in some cases, if the generated {@code class}
388 * file is stable.
389 *
390 * @see BranchInstruction
391 * @see DiscontinuedInstruction.JsrInstruction
392 * @since 24
393 */
394 enum ShortJumpsOption implements Option {
395
396 /**
397 * Automatically convert short jumps to long when necessary.
398 * <p>
399 * For an invalid instruction model, a {@link CodeBuilder} may generate
400 * another or a few other instructions to accomplish the same effect.
401 */
402 FIX_SHORT_JUMPS,
403
404 /**
405 * Fail with an {@link IllegalArgumentException} if short jump overflows.
406 * <p>
407 * This is useful to ensure the physical accuracy of a generated {@code
408 * class} file and avoids the overhead from a failed first attempt for
409 * overflowing forward jumps in some cases.
410 */
411 FAIL_ON_SHORT_JUMPS
412 }
413
414 /**
415 * The option describing whether to generate stack maps. The default is
416 * {@link #STACK_MAPS_WHEN_REQUIRED} to generate stack maps or reuse
417 * existing ones if compatible.
418 * <p>
419 * The {@link StackMapTableAttribute} is a derived property from a {@link
420 * CodeAttribute Code} attribute to allow a Java Virtual Machine to perform
421 * verification in one pass. Thus, it is not modeled as part of a {@link
422 * CodeModel}, but computed on-demand instead via stack maps generation.
423 * <p>
424 * Stack map generation may fail with an {@link IllegalArgumentException} if
425 * there is {@linkplain DeadCodeOption unreachable code} or legacy
426 * {@linkplain DiscontinuedInstruction.JsrInstruction jump routine}
427 * instructions. When {@link #DROP_STACK_MAPS} option is used, users can
428 * provide their own stack maps by supplying a {@link StackMapTableAttribute}
429 * to a {@link CodeBuilder}.
430 *
431 * @see StackMapTableAttribute
432 * @see DeadCodeOption
433 * @jvms 4.10.1 Verification by Type Checking
434 * @since 24
435 */
436 enum StackMapsOption implements Option {
437
438 /**
439 * Generate stack maps or reuse existing ones if compatible. Stack maps
440 * are present on major versions {@value #JAVA_6_VERSION} or above. For
441 * these versions, {@link CodeBuilder} tries to reuse compatible stack
442 * maps information if the code array and exception handlers are still
443 * compatible after a transformation; otherwise, it runs stack map
444 * generation. However, it does not fail fast if the major version is
445 * {@value #JAVA_6_VERSION}, which allows jump subroutine instructions
446 * that are incompatible with stack maps to exist in the {@code code}
447 * array.
448 */
449 STACK_MAPS_WHEN_REQUIRED,
450
451 /**
452 * Forces running stack map generation. This runs stack map generation
453 * unconditionally and fails fast if the generation fails due to any
454 * reason.
455 */
456 GENERATE_STACK_MAPS,
457
458 /**
459 * Do not run stack map generation. Users must supply their own
460 * {@link StackMapTableAttribute} to a {@link CodeBuilder} if the code
461 * has branches or exception handlers; otherwise, the generated code
462 * will fail verification (JVMS {@jvms 4.10.1}).
463 * <p>
464 * This option is required for user-supplied {@link StackMapTableAttribute}
465 * to be respected. Stack maps on an existing {@link CodeAttribute Code}
466 * attribute can be reused as below with this option:
467 * {@snippet lang=java file="PackageSnippets.java" region="manual-reuse-stack-maps"}
468 */
469 DROP_STACK_MAPS
470 }
471
472 /**
473 * The option describing whether to retain or discard attributes that cannot
474 * verify their correctness after a transformation. The default is {@link
475 * #PASS_ALL_ATTRIBUTES} to retain all attributes as-is.
476 * <p>
477 * Many attributes only depend on data managed by the Class-File API, such
478 * as constant pool entries or labels into the {@code code} array. If they
479 * change, the Class-File API knows their updated values and can write a
480 * correct version by expanding the structures and recomputing the updated
481 * indexes, known as "explosion". However, some attributes, such as type
482 * annotations, depend on arbitrary data that may be modified during
483 * transformations but the Class-File API does not track, such as index to
484 * an entry in the {@linkplain ClassModel#interfaces() interfaces} of a
485 * {@code ClassFile} structure. As a result, the Class-File API cannot
486 * verify the correctness of such information.
487 *
488 * @see AttributeStability
489 * @since 24
490 */
491 enum AttributesProcessingOption implements Option {
492
493 /**
494 * Retain all original attributes during transformation.
495 */
496 PASS_ALL_ATTRIBUTES,
497
498 /**
499 * Drop attributes with {@link AttributeStability#UNKNOWN} data
500 * dependency during transformation.
501 */
502 DROP_UNKNOWN_ATTRIBUTES,
503
504 /**
505 * Drop attributes with {@link AttributeStability#UNSTABLE} or higher
506 * data dependency during transformation.
507 */
508 DROP_UNSTABLE_ATTRIBUTES
509 }
510
511 /**
512 * Parses a {@code class} file into a {@link ClassModel}.
513 * <p>
514 * Due to the on-demand nature of {@code class} file parsing, an {@link
515 * IllegalArgumentException} may be thrown on any accessor method invocation
516 * on the returned model or any structure returned by the accessors in the
517 * structure hierarchy.
518 *
519 * @param bytes the bytes of the {@code class} file
520 * @return the class model
521 * @throws IllegalArgumentException if the {@code class} file is malformed
522 * or of a version {@linkplain #latestMajorVersion() not supported}
523 * by the current runtime
524 */
525 ClassModel parse(byte[] bytes);
526
527 /**
528 * Parses a {@code class} into a {@link ClassModel}.
529 * <p>
530 * Due to the on-demand nature of {@code class} file parsing, an {@link
531 * IllegalArgumentException} may be thrown on any accessor method invocation
532 * on the returned model or any structure returned by the accessors in the
533 * structure hierarchy.
534 *
535 * @param path the path to the {@code class} file
536 * @return the class model
537 * @throws IOException if an I/O error occurs
538 * @throws IllegalArgumentException if the {@code class} file is malformed
539 * or of a version {@linkplain #latestMajorVersion() not supported}
540 * by the current runtime
541 * @see #parse(byte[])
542 */
543 default ClassModel parse(Path path) throws IOException {
544 return parse(Files.readAllBytes(path));
545 }
546
547 /**
548 * Builds a {@code class} file into a byte array.
549 *
550 * @param thisClass the name of the class to build
551 * @param handler a handler that receives a {@link ClassBuilder}
552 * @return the {@code class} file bytes
553 * @throws IllegalArgumentException if {@code thisClass} represents a
554 * primitive type or building encounters a failure
555 */
556 default byte[] build(ClassDesc thisClass,
557 Consumer<? super ClassBuilder> handler) {
558 ConstantPoolBuilder pool = ConstantPoolBuilder.of();
559 return build(pool.classEntry(thisClass), pool, handler);
560 }
561
562 /**
563 * Builds a {@code class} file into a byte array using the provided constant
564 * pool builder.
565 *
566 * @param thisClassEntry the name of the class to build
567 * @param constantPool the constant pool builder
568 * @param handler a handler that receives a {@link ClassBuilder}
569 * @return the {@code class} file bytes
570 * @throws IllegalArgumentException if building encounters a failure
571 */
572 byte[] build(ClassEntry thisClassEntry,
573 ConstantPoolBuilder constantPool,
574 Consumer<? super ClassBuilder> handler);
575
576 /**
577 * Builds a {@code class} file into a file in a file system.
578 *
579 * @param path the path to the file to write
580 * @param thisClass the name of the class to build
581 * @param handler a handler that receives a {@link ClassBuilder}
582 * @throws IOException if an I/O error occurs
583 * @throws IllegalArgumentException if building encounters a failure
584 */
585 default void buildTo(Path path,
586 ClassDesc thisClass,
587 Consumer<ClassBuilder> handler) throws IOException {
588 Files.write(path, build(thisClass, handler));
589 }
590
591 /**
592 * Builds a {@code class} file into a file in a file system using the
593 * provided constant pool builder.
594 *
595 * @param path the path to the file to write
596 * @param thisClassEntry the name of the class to build
597 * @param constantPool the constant pool builder
598 * @param handler a handler that receives a {@link ClassBuilder}
599 * @throws IOException if an I/O error occurs
600 * @throws IllegalArgumentException if building encounters a failure
601 */
602 default void buildTo(Path path,
603 ClassEntry thisClassEntry,
604 ConstantPoolBuilder constantPool,
605 Consumer<? super ClassBuilder> handler) throws IOException {
606 Files.write(path, build(thisClassEntry, constantPool, handler));
607 }
608
609 /**
610 * Builds a module descriptor into a byte array.
611 *
612 * @param moduleAttribute the {@code Module} attribute
613 * @return the {@code class} file bytes
614 * @throws IllegalArgumentException if building encounters a failure
615 */
616 default byte[] buildModule(ModuleAttribute moduleAttribute) {
617 return buildModule(moduleAttribute, clb -> {});
618 }
619
620 /**
621 * Builds a module descriptor into a byte array.
622 *
623 * @param moduleAttribute the {@code Module} attribute
624 * @param handler a handler that receives a {@link ClassBuilder}
625 * @return the {@code class} file bytes
626 * @throws IllegalArgumentException if building encounters a failure
627 */
628 default byte[] buildModule(ModuleAttribute moduleAttribute,
629 Consumer<? super ClassBuilder> handler) {
630 return build(CD_module_info, clb -> {
631 clb.withFlags(AccessFlag.MODULE);
632 clb.with(moduleAttribute);
633 handler.accept(clb);
634 });
635 }
636
637 /**
638 * Builds a module descriptor into a file in a file system.
639 *
640 * @param path the file to write
641 * @param moduleAttribute the {@code Module} attribute
642 * @throws IOException if an I/O error occurs
643 * @throws IllegalArgumentException if building encounters a failure
644 */
645 default void buildModuleTo(Path path,
646 ModuleAttribute moduleAttribute) throws IOException {
647 buildModuleTo(path, moduleAttribute, clb -> {});
648 }
649
650 /**
651 * Builds a module descriptor into a file in a file system.
652 *
653 * @param path the file to write
654 * @param moduleAttribute the {@code Module} attribute
655 * @param handler a handler that receives a {@link ClassBuilder}
656 * @throws IOException if an I/O error occurs
657 * @throws IllegalArgumentException if building encounters a failure
658 */
659 default void buildModuleTo(Path path,
660 ModuleAttribute moduleAttribute,
661 Consumer<? super ClassBuilder> handler) throws IOException {
662 Files.write(path, buildModule(moduleAttribute, handler));
663 }
664
665 /**
666 * Transform one {@code class} file into a new {@code class} file according
667 * to a {@link ClassTransform}. The transform will receive each element of
668 * this class, as well as a {@link ClassBuilder} for building the new class.
669 * The transform is free to preserve, remove, or replace elements as it
670 * sees fit.
671 * <p>
672 * This method behaves as if:
673 * {@snippet lang=java :
674 * ConstantPoolBuilder cpb = null; // @replace substring=null; replacement=...
675 * this.build(model.thisClass(), cpb,
676 * clb -> clb.transform(model, transform));
677 * }
678 * where {@code cpb} is determined by {@link ConstantPoolSharingOption}.
679 *
680 * @apiNote
681 * This is named {@code transformClass} instead of {@code transform} for
682 * consistency with {@link ClassBuilder#transformField}, {@link
683 * ClassBuilder#transformMethod}, and {@link MethodBuilder#transformCode},
684 * and to distinguish from {@link ClassFileBuilder#transform}, which is
685 * more generic and powerful.
686 *
687 * @param model the class model to transform
688 * @param transform the transform
689 * @return the bytes of the new class
690 * @throws IllegalArgumentException if building encounters a failure
691 * @see ConstantPoolSharingOption
692 */
693 default byte[] transformClass(ClassModel model, ClassTransform transform) {
694 return transformClass(model, model.thisClass(), transform);
695 }
696
697 /**
698 * Transform one {@code class} file into a new {@code class} file according
699 * to a {@link ClassTransform}. The transform will receive each element of
700 * this class, as well as a {@link ClassBuilder} for building the new class.
701 * The transform is free to preserve, remove, or replace elements as it
702 * sees fit.
703 *
704 * @apiNote
705 * This is named {@code transformClass} instead of {@code transform} for
706 * consistency with {@link ClassBuilder#transformField}, {@link
707 * ClassBuilder#transformMethod}, and {@link MethodBuilder#transformCode},
708 * and to distinguish from {@link ClassFileBuilder#transform}, which is
709 * more generic and powerful.
710 *
711 * @param model the class model to transform
712 * @param newClassName new class name
713 * @param transform the transform
714 * @return the bytes of the new class
715 * @throws IllegalArgumentException if building encounters a failure
716 * @see ConstantPoolSharingOption
717 */
718 default byte[] transformClass(ClassModel model, ClassDesc newClassName, ClassTransform transform) {
719 return transformClass(model, TemporaryConstantPool.INSTANCE.classEntry(newClassName), transform);
720 }
721
722 /**
723 * Transform one {@code class} file into a new {@code class} file according
724 * to a {@link ClassTransform}. The transform will receive each element of
725 * this class, as well as a {@link ClassBuilder} for building the new class.
726 * The transform is free to preserve, remove, or replace elements as it
727 * sees fit.
728 * <p>
729 * This method behaves as if:
730 * {@snippet lang=java :
731 * ConstantPoolBuilder cpb = null; // @replace substring=null; replacement=...
732 * this.build(newClassName, cpb, clb -> clb.transform(model, transform));
733 * }
734 * where {@code cpb} is determined by {@link ConstantPoolSharingOption}.
735 *
736 * @apiNote
737 * This is named {@code transformClass} instead of {@code transform} for
738 * consistency with {@link ClassBuilder#transformField}, {@link
739 * ClassBuilder#transformMethod}, and {@link MethodBuilder#transformCode},
740 * and to distinguish from {@link ClassFileBuilder#transform}, which is
741 * more generic and powerful.
742 *
743 * @param model the class model to transform
744 * @param newClassName new class name
745 * @param transform the transform
746 * @return the bytes of the new class
747 * @throws IllegalArgumentException if building encounters a failure
748 * @see ConstantPoolSharingOption
749 */
750 byte[] transformClass(ClassModel model, ClassEntry newClassName, ClassTransform transform);
751
752 /**
753 * Verify a {@code class} file. All verification errors found will be returned.
754 *
755 * @param model the class model to verify
756 * @return a list of verification errors, or an empty list if no error is
757 * found
758 */
759 List<VerifyError> verify(ClassModel model);
760
761 /**
762 * Verify a {@code class} file. All verification errors found will be returned.
763 *
764 * @param bytes the {@code class} file bytes to verify
765 * @return a list of verification errors, or an empty list if no error is
766 * found
767 */
768 List<VerifyError> verify(byte[] bytes);
769
770 /**
771 * Verify a {@code class} file. All verification errors found will be returned.
772 *
773 * @param path the {@code class} file path to verify
774 * @return a list of verification errors, or an empty list if no error is
775 * found
776 * @throws IOException if an I/O error occurs
777 */
778 default List<VerifyError> verify(Path path) throws IOException {
779 return verify(Files.readAllBytes(path));
780 }
781
782 /**
783 * The magic number identifying the {@code class} file format, {@value
784 * "0x%04x" #MAGIC_NUMBER}. It is a big-endian 4-byte value.
785 */
786 int MAGIC_NUMBER = 0xCAFEBABE;
787
788 /** The bit mask of {@link AccessFlag#PUBLIC} access and property modifier. */
789 int ACC_PUBLIC = 0x0001;
790
791 /** The bit mask of {@link AccessFlag#PROTECTED} access and property modifier. */
792 int ACC_PROTECTED = 0x0004;
793
794 /** The bit mask of {@link AccessFlag#PRIVATE} access and property modifier. */
795 int ACC_PRIVATE = 0x0002;
796
797 /** The bit mask of {@link AccessFlag#INTERFACE} access and property modifier. */
798 int ACC_INTERFACE = 0x0200;
799
800 /** The bit mask of {@link AccessFlag#ENUM} access and property modifier. */
801 int ACC_ENUM = 0x4000;
802
803 /** The bit mask of {@link AccessFlag#ANNOTATION} access and property modifier. */
804 int ACC_ANNOTATION = 0x2000;
805
806 /** The bit mask of {@link AccessFlag#SUPER} access and property modifier. */
807 int ACC_SUPER = 0x0020;
808
809 /**
810 * The bit mask of {@link AccessFlag#IDENTITY} access and property modifier.
811 *
812 * @since Valhalla
813 */
814 @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective = true)
815 int ACC_IDENTITY = 0x0020;
816
817 /** The bit mask of {@link AccessFlag#ABSTRACT} access and property modifier. */
818 int ACC_ABSTRACT = 0x0400;
819
820 /** The bit mask of {@link AccessFlag#VOLATILE} access and property modifier. */
821 int ACC_VOLATILE = 0x0040;
822
823 /** The bit mask of {@link AccessFlag#TRANSIENT} access and property modifier. */
824 int ACC_TRANSIENT = 0x0080;
825
826 /** The bit mask of {@link AccessFlag#SYNTHETIC} access and property modifier. */
827 int ACC_SYNTHETIC = 0x1000;
828
829 /** The bit mask of {@link AccessFlag#STATIC} access and property modifier. */
830 int ACC_STATIC = 0x0008;
831
832 /** The bit mask of {@link AccessFlag#FINAL} access and property modifier. */
833 int ACC_FINAL = 0x0010;
834
835 /** The bit mask of {@link AccessFlag#SYNCHRONIZED} access and property modifier. */
836 int ACC_SYNCHRONIZED = 0x0020;
837
838 /** The bit mask of {@link AccessFlag#BRIDGE} access and property modifier. */
839 int ACC_BRIDGE = 0x0040;
840
841 /** The bit mask of {@link AccessFlag#VARARGS} access and property modifier. */
842 int ACC_VARARGS = 0x0080;
843
844 /** The bit mask of {@link AccessFlag#NATIVE} access and property modifier. */
845 int ACC_NATIVE = 0x0100;
846
847 /** The bit mask of {@link AccessFlag#STRICT} access and property modifier. */
848 int ACC_STRICT = 0x0800;
849
850 /**
851 * The bit mask of {@link AccessFlag#STRICT_INIT} access and property modifier.
852 *
853 * @since Valhalla
854 */
855 @PreviewFeature(feature = PreviewFeature.Feature.STRICT_FIELDS, reflective = true)
856 int ACC_STRICT_INIT = 0x0800;
857
858 /** The bit mask of {@link AccessFlag#MODULE} access and property modifier. */
859 int ACC_MODULE = 0x8000;
860
861 /** The bit mask of {@link AccessFlag#OPEN} access and property modifier. */
862 int ACC_OPEN = 0x20;
863
864 /** The bit mask of {@link AccessFlag#MANDATED} access and property modifier. */
865 int ACC_MANDATED = 0x8000;
866
867 /** The bit mask of {@link AccessFlag#TRANSITIVE} access and property modifier. */
868 int ACC_TRANSITIVE = 0x20;
869
870 /** The bit mask of {@link AccessFlag#STATIC_PHASE} access and property modifier. */
871 int ACC_STATIC_PHASE = 0x40;
872
873 /**
874 * The class major version of the initial version of Java, {@value}.
875 *
876 * @see ClassFileFormatVersion#RELEASE_0
877 * @see ClassFileFormatVersion#RELEASE_1
878 */
879 int JAVA_1_VERSION = 45;
880
881 /**
882 * The class major version introduced by Java 2 SE 1.2, {@value}.
883 *
884 * @see ClassFileFormatVersion#RELEASE_2
885 */
886 int JAVA_2_VERSION = 46;
887
888 /**
889 * The class major version introduced by Java 2 SE 1.3, {@value}.
890 *
891 * @see ClassFileFormatVersion#RELEASE_3
892 */
893 int JAVA_3_VERSION = 47;
894
895 /**
896 * The class major version introduced by Java 2 SE 1.4, {@value}.
897 *
898 * @see ClassFileFormatVersion#RELEASE_4
899 */
900 int JAVA_4_VERSION = 48;
901
902 /**
903 * The class major version introduced by Java 2 SE 5.0, {@value}.
904 *
905 * @see ClassFileFormatVersion#RELEASE_5
906 */
907 int JAVA_5_VERSION = 49;
908
909 /**
910 * The class major version introduced by Java SE 6, {@value}.
911 *
912 * @see ClassFileFormatVersion#RELEASE_6
913 */
914 int JAVA_6_VERSION = 50;
915
916 /**
917 * The class major version introduced by Java SE 7, {@value}.
918 *
919 * @see ClassFileFormatVersion#RELEASE_7
920 */
921 int JAVA_7_VERSION = 51;
922
923 /**
924 * The class major version introduced by Java SE 8, {@value}.
925 *
926 * @see ClassFileFormatVersion#RELEASE_8
927 */
928 int JAVA_8_VERSION = 52;
929
930 /**
931 * The class major version introduced by Java SE 9, {@value}.
932 *
933 * @see ClassFileFormatVersion#RELEASE_9
934 */
935 int JAVA_9_VERSION = 53;
936
937 /**
938 * The class major version introduced by Java SE 10, {@value}.
939 *
940 * @see ClassFileFormatVersion#RELEASE_10
941 */
942 int JAVA_10_VERSION = 54;
943
944 /**
945 * The class major version introduced by Java SE 11, {@value}.
946 *
947 * @see ClassFileFormatVersion#RELEASE_11
948 */
949 int JAVA_11_VERSION = 55;
950
951 /**
952 * The class major version introduced by Java SE 12, {@value}.
953 *
954 * @see ClassFileFormatVersion#RELEASE_12
955 */
956 int JAVA_12_VERSION = 56;
957
958 /**
959 * The class major version introduced by Java SE 13, {@value}.
960 *
961 * @see ClassFileFormatVersion#RELEASE_13
962 */
963 int JAVA_13_VERSION = 57;
964
965 /**
966 * The class major version introduced by Java SE 14, {@value}.
967 *
968 * @see ClassFileFormatVersion#RELEASE_14
969 */
970 int JAVA_14_VERSION = 58;
971
972 /**
973 * The class major version introduced by Java SE 15, {@value}.
974 *
975 * @see ClassFileFormatVersion#RELEASE_15
976 */
977 int JAVA_15_VERSION = 59;
978
979 /**
980 * The class major version introduced by Java SE 16, {@value}.
981 *
982 * @see ClassFileFormatVersion#RELEASE_16
983 */
984 int JAVA_16_VERSION = 60;
985
986 /**
987 * The class major version introduced by Java SE 17, {@value}.
988 *
989 * @see ClassFileFormatVersion#RELEASE_17
990 */
991 int JAVA_17_VERSION = 61;
992
993 /**
994 * The class major version introduced by Java SE 18, {@value}.
995 *
996 * @see ClassFileFormatVersion#RELEASE_18
997 */
998 int JAVA_18_VERSION = 62;
999
1000 /**
1001 * The class major version introduced by Java SE 19, {@value}.
1002 *
1003 * @see ClassFileFormatVersion#RELEASE_19
1004 */
1005 int JAVA_19_VERSION = 63;
1006
1007 /**
1008 * The class major version introduced by Java SE 20, {@value}.
1009 *
1010 * @see ClassFileFormatVersion#RELEASE_20
1011 */
1012 int JAVA_20_VERSION = 64;
1013
1014 /**
1015 * The class major version introduced by Java SE 21, {@value}.
1016 *
1017 * @see ClassFileFormatVersion#RELEASE_21
1018 */
1019 int JAVA_21_VERSION = 65;
1020
1021 /**
1022 * The class major version introduced by Java SE 22, {@value}.
1023 *
1024 * @see ClassFileFormatVersion#RELEASE_22
1025 */
1026 int JAVA_22_VERSION = 66;
1027
1028 /**
1029 * The class major version introduced by Java SE 23, {@value}.
1030 *
1031 * @see ClassFileFormatVersion#RELEASE_23
1032 */
1033 int JAVA_23_VERSION = 67;
1034
1035 /**
1036 * The class major version introduced by Java SE 24, {@value}.
1037 *
1038 * @see ClassFileFormatVersion#RELEASE_24
1039 */
1040 int JAVA_24_VERSION = 68;
1041
1042 /**
1043 * The class major version introduced by Java SE 25, {@value}.
1044 *
1045 * @see ClassFileFormatVersion#RELEASE_25
1046 * @since 25
1047 */
1048 int JAVA_25_VERSION = 69;
1049
1050 /**
1051 * The class major version introduced by Java SE 26, {@value}.
1052 *
1053 * @see ClassFileFormatVersion#RELEASE_26
1054 * @since 26
1055 */
1056 int JAVA_26_VERSION = 70;
1057
1058 /**
1059 * The class major version introduced by Java SE 27, {@value}.
1060 *
1061 * @see ClassFileFormatVersion#RELEASE_27
1062 * @since 27
1063 */
1064 int JAVA_27_VERSION = 71;
1065
1066 /**
1067 * A minor version number {@value} indicating a class uses preview features
1068 * of a Java SE release since 12, for major versions {@value
1069 * #JAVA_12_VERSION} and above.
1070 */
1071 int PREVIEW_MINOR_VERSION = 65535;
1072
1073 /**
1074 * {@return the latest class major version supported by the current runtime}
1075 */
1076 static int latestMajorVersion() {
1077 return JAVA_27_VERSION;
1078 }
1079
1080 /**
1081 * {@return the latest class minor version supported by the current runtime}
1082 *
1083 * @apiNote
1084 * This does not report the {@link #PREVIEW_MINOR_VERSION} when the current
1085 * runtime has preview feature enabled, as {@code class} files with a major
1086 * version other than {@link #latestMajorVersion()} and the preview minor
1087 * version are not supported.
1088 */
1089 static int latestMinorVersion() {
1090 return 0;
1091 }
1092
1093 }