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