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 } --- EOF ---