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#IDENTITY} access and property modifier. */ 809 int ACC_IDENTITY = 0x0020; 810 811 /** The bit mask of {@link AccessFlag#ABSTRACT} access and property modifier. */ 812 int ACC_ABSTRACT = 0x0400; 813 814 /** The bit mask of {@link AccessFlag#VOLATILE} access and property modifier. */ 815 int ACC_VOLATILE = 0x0040; 816 817 /** The bit mask of {@link AccessFlag#TRANSIENT} access and property modifier. */ 818 int ACC_TRANSIENT = 0x0080; 819 820 /** The bit mask of {@link AccessFlag#SYNTHETIC} access and property modifier. */ 821 int ACC_SYNTHETIC = 0x1000; 822 823 /** The bit mask of {@link AccessFlag#STATIC} access and property modifier. */ 824 int ACC_STATIC = 0x0008; 825 826 /** The bit mask of {@link AccessFlag#FINAL} access and property modifier. */ 827 int ACC_FINAL = 0x0010; 828 829 /** The bit mask of {@link AccessFlag#SYNCHRONIZED} access and property modifier. */ 830 int ACC_SYNCHRONIZED = 0x0020; 831 832 /** The bit mask of {@link AccessFlag#BRIDGE} access and property modifier. */ 833 int ACC_BRIDGE = 0x0040; 834 835 /** The bit mask of {@link AccessFlag#VARARGS} access and property modifier. */ 836 int ACC_VARARGS = 0x0080; 837 838 /** The bit mask of {@link AccessFlag#NATIVE} access and property modifier. */ 839 int ACC_NATIVE = 0x0100; 840 841 /** The bit mask of {@link AccessFlag#STRICT} access and property modifier. */ 842 int ACC_STRICT = 0x0800; 843 844 /** The bit mask of {@link AccessFlag#MODULE} access and property modifier. */ 845 int ACC_MODULE = 0x8000; 846 847 /** The bit mask of {@link AccessFlag#OPEN} access and property modifier. */ 848 int ACC_OPEN = 0x20; 849 850 /** The bit mask of {@link AccessFlag#MANDATED} access and property modifier. */ 851 int ACC_MANDATED = 0x8000; 852 853 /** The bit mask of {@link AccessFlag#TRANSITIVE} access and property modifier. */ 854 int ACC_TRANSITIVE = 0x20; 855 856 /** The bit mask of {@link AccessFlag#STATIC_PHASE} access and property modifier. */ 857 int ACC_STATIC_PHASE = 0x40; 858 859 /** 860 * The class major version of the initial version of Java, {@value}. 861 * 862 * @see ClassFileFormatVersion#RELEASE_0 863 * @see ClassFileFormatVersion#RELEASE_1 864 */ 865 int JAVA_1_VERSION = 45; 866 867 /** 868 * The class major version introduced by Java 2 SE 1.2, {@value}. 869 * 870 * @see ClassFileFormatVersion#RELEASE_2 871 */ 872 int JAVA_2_VERSION = 46; 873 874 /** 875 * The class major version introduced by Java 2 SE 1.3, {@value}. 876 * 877 * @see ClassFileFormatVersion#RELEASE_3 878 */ 879 int JAVA_3_VERSION = 47; 880 881 /** 882 * The class major version introduced by Java 2 SE 1.4, {@value}. 883 * 884 * @see ClassFileFormatVersion#RELEASE_4 885 */ 886 int JAVA_4_VERSION = 48; 887 888 /** 889 * The class major version introduced by Java 2 SE 5.0, {@value}. 890 * 891 * @see ClassFileFormatVersion#RELEASE_5 892 */ 893 int JAVA_5_VERSION = 49; 894 895 /** 896 * The class major version introduced by Java SE 6, {@value}. 897 * 898 * @see ClassFileFormatVersion#RELEASE_6 899 */ 900 int JAVA_6_VERSION = 50; 901 902 /** 903 * The class major version introduced by Java SE 7, {@value}. 904 * 905 * @see ClassFileFormatVersion#RELEASE_7 906 */ 907 int JAVA_7_VERSION = 51; 908 909 /** 910 * The class major version introduced by Java SE 8, {@value}. 911 * 912 * @see ClassFileFormatVersion#RELEASE_8 913 */ 914 int JAVA_8_VERSION = 52; 915 916 /** 917 * The class major version introduced by Java SE 9, {@value}. 918 * 919 * @see ClassFileFormatVersion#RELEASE_9 920 */ 921 int JAVA_9_VERSION = 53; 922 923 /** 924 * The class major version introduced by Java SE 10, {@value}. 925 * 926 * @see ClassFileFormatVersion#RELEASE_10 927 */ 928 int JAVA_10_VERSION = 54; 929 930 /** 931 * The class major version introduced by Java SE 11, {@value}. 932 * 933 * @see ClassFileFormatVersion#RELEASE_11 934 */ 935 int JAVA_11_VERSION = 55; 936 937 /** 938 * The class major version introduced by Java SE 12, {@value}. 939 * 940 * @see ClassFileFormatVersion#RELEASE_12 941 */ 942 int JAVA_12_VERSION = 56; 943 944 /** 945 * The class major version introduced by Java SE 13, {@value}. 946 * 947 * @see ClassFileFormatVersion#RELEASE_13 948 */ 949 int JAVA_13_VERSION = 57; 950 951 /** 952 * The class major version introduced by Java SE 14, {@value}. 953 * 954 * @see ClassFileFormatVersion#RELEASE_14 955 */ 956 int JAVA_14_VERSION = 58; 957 958 /** 959 * The class major version introduced by Java SE 15, {@value}. 960 * 961 * @see ClassFileFormatVersion#RELEASE_15 962 */ 963 int JAVA_15_VERSION = 59; 964 965 /** 966 * The class major version introduced by Java SE 16, {@value}. 967 * 968 * @see ClassFileFormatVersion#RELEASE_16 969 */ 970 int JAVA_16_VERSION = 60; 971 972 /** 973 * The class major version introduced by Java SE 17, {@value}. 974 * 975 * @see ClassFileFormatVersion#RELEASE_17 976 */ 977 int JAVA_17_VERSION = 61; 978 979 /** 980 * The class major version introduced by Java SE 18, {@value}. 981 * 982 * @see ClassFileFormatVersion#RELEASE_18 983 */ 984 int JAVA_18_VERSION = 62; 985 986 /** 987 * The class major version introduced by Java SE 19, {@value}. 988 * 989 * @see ClassFileFormatVersion#RELEASE_19 990 */ 991 int JAVA_19_VERSION = 63; 992 993 /** 994 * The class major version introduced by Java SE 20, {@value}. 995 * 996 * @see ClassFileFormatVersion#RELEASE_20 997 */ 998 int JAVA_20_VERSION = 64; 999 1000 /** 1001 * The class major version introduced by Java SE 21, {@value}. 1002 * 1003 * @see ClassFileFormatVersion#RELEASE_21 1004 */ 1005 int JAVA_21_VERSION = 65; 1006 1007 /** 1008 * The class major version introduced by Java SE 22, {@value}. 1009 * 1010 * @see ClassFileFormatVersion#RELEASE_22 1011 */ 1012 int JAVA_22_VERSION = 66; 1013 1014 /** 1015 * The class major version introduced by Java SE 23, {@value}. 1016 * 1017 * @see ClassFileFormatVersion#RELEASE_23 1018 */ 1019 int JAVA_23_VERSION = 67; 1020 1021 /** 1022 * The class major version introduced by Java SE 24, {@value}. 1023 * 1024 * @see ClassFileFormatVersion#RELEASE_24 1025 */ 1026 int JAVA_24_VERSION = 68; 1027 1028 /** 1029 * The class major version introduced by Java SE 25, {@value}. 1030 * 1031 * @see ClassFileFormatVersion#RELEASE_25 1032 * @since 25 1033 */ 1034 int JAVA_25_VERSION = 69; 1035 1036 /** 1037 * A minor version number {@value} indicating a class uses preview features 1038 * of a Java SE release since 12, for major versions {@value 1039 * #JAVA_12_VERSION} and above. 1040 */ 1041 int PREVIEW_MINOR_VERSION = 65535; 1042 1043 /** 1044 * {@return the latest class major version supported by the current runtime} 1045 */ 1046 static int latestMajorVersion() { 1047 return JAVA_25_VERSION; 1048 } 1049 1050 /** 1051 * {@return the latest class minor version supported by the current runtime} 1052 * 1053 * @apiNote 1054 * This does not report the {@link #PREVIEW_MINOR_VERSION} when the current 1055 * runtime has preview feature enabled, as {@code class} files with a major 1056 * version other than {@link #latestMajorVersion()} and the preview minor 1057 * version are not supported. 1058 */ 1059 static int latestMinorVersion() { 1060 return 0; 1061 } 1062 1063 }