1 /* 2 * Copyright (c) 2022, 2024, 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.constant.ClassDesc; 29 import java.nio.file.Files; 30 import java.nio.file.Path; 31 import java.util.function.Consumer; 32 import java.util.function.Function; 33 34 import java.lang.classfile.attribute.ModuleAttribute; 35 import java.lang.classfile.constantpool.ClassEntry; 36 import java.lang.classfile.constantpool.ConstantPoolBuilder; 37 import java.lang.classfile.constantpool.Utf8Entry; 38 import jdk.internal.classfile.impl.ClassFileImpl; 39 import jdk.internal.classfile.impl.TemporaryConstantPool; 40 import java.lang.reflect.AccessFlag; 41 import java.lang.classfile.attribute.CharacterRangeInfo; 42 import java.lang.classfile.attribute.LocalVariableInfo; 43 import java.lang.classfile.attribute.LocalVariableTypeInfo; 44 import java.lang.classfile.instruction.ExceptionCatch; 45 import java.util.List; 46 import static java.util.Objects.requireNonNull; 47 import static jdk.internal.constant.ConstantUtils.CD_module_info; 48 import jdk.internal.javac.PreviewFeature; 49 50 /** 51 * Represents a context for parsing, transforming, and generating classfiles. 52 * A {@code ClassFile} has a set of options that condition how parsing and 53 * generation is done. 54 * 55 * @since 22 56 */ 57 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 58 public sealed interface ClassFile 59 permits ClassFileImpl { 60 61 /** 62 * {@return a context with default options} 63 */ 64 static ClassFile of() { 65 return ClassFileImpl.DEFAULT_CONTEXT; 66 } 67 68 /** 69 * {@return a new context with options altered from the default} 70 * @param options the desired processing options 71 */ 72 static ClassFile of(Option... options) { 73 return of().withOptions(options); 74 } 75 76 /** 77 * {@return a copy of the context with altered options} 78 * @param options the desired processing options 79 */ 80 ClassFile withOptions(Option... options); 81 82 /** 83 * An option that affects the parsing and writing of classfiles. 84 * 85 * @sealedGraph 86 * @since 22 87 */ 88 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 89 sealed interface Option { 90 } 91 92 /** 93 * Option describing attribute mappers for custom attributes. 94 * Default is only to process standard attributes. 95 * 96 * @since 22 97 */ 98 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 99 sealed interface AttributeMapperOption extends Option 100 permits ClassFileImpl.AttributeMapperOptionImpl { 101 102 /** 103 * {@return an option describing attribute mappers for custom attributes} 104 * @param attributeMapper a function mapping attribute names to attribute mappers 105 */ 106 static AttributeMapperOption of(Function<Utf8Entry, AttributeMapper<?>> attributeMapper) { 107 requireNonNull(attributeMapper); 108 return new ClassFileImpl.AttributeMapperOptionImpl(attributeMapper); 109 } 110 111 /** 112 * {@return the function mapping attribute names to attribute mappers} 113 */ 114 Function<Utf8Entry, AttributeMapper<?>> attributeMapper(); 115 } 116 117 /** 118 * Option describing the class hierarchy resolver to use when generating 119 * stack maps. 120 * 121 * @since 22 122 */ 123 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 124 sealed interface ClassHierarchyResolverOption extends Option 125 permits ClassFileImpl.ClassHierarchyResolverOptionImpl { 126 127 /** 128 * {@return an option describing the class hierarchy resolver to use when 129 * generating stack maps} 130 * @param classHierarchyResolver the resolver 131 */ 132 static ClassHierarchyResolverOption of(ClassHierarchyResolver classHierarchyResolver) { 133 requireNonNull(classHierarchyResolver); 134 return new ClassFileImpl.ClassHierarchyResolverOptionImpl(classHierarchyResolver); 135 } 136 137 /** 138 * {@return the class hierarchy resolver} 139 */ 140 ClassHierarchyResolver classHierarchyResolver(); 141 } 142 143 /** 144 * Option describing whether to preserve the original constant pool when 145 * transforming a classfile. Reusing the constant pool enables significant 146 * optimizations in processing time and minimizes differences between the 147 * original and transformed classfile, but may result in a bigger classfile 148 * when a classfile is significantly transformed. 149 * Default is {@code SHARED_POOL} to preserve the original constant 150 * pool. 151 * 152 * @since 22 153 */ 154 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 155 enum ConstantPoolSharingOption implements Option { 156 157 /** Preserves the original constant pool when transforming classfile */ 158 SHARED_POOL, 159 160 /** Creates a new constant pool when transforming classfile */ 161 NEW_POOL 162 } 163 164 /** 165 * Option describing whether to patch out unreachable code. 166 * Default is {@code PATCH_DEAD_CODE} to automatically patch out unreachable 167 * code with NOPs. 168 * 169 * @since 22 170 */ 171 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 172 enum DeadCodeOption implements Option { 173 174 /** Patch unreachable code */ 175 PATCH_DEAD_CODE, 176 177 /** Keep the unreachable code */ 178 KEEP_DEAD_CODE 179 } 180 181 /** 182 * Option describing whether to filter unresolved labels. 183 * Default is {@code FAIL_ON_DEAD_LABELS} to throw IllegalArgumentException 184 * when any {@link ExceptionCatch}, {@link LocalVariableInfo}, 185 * {@link LocalVariableTypeInfo}, or {@link CharacterRangeInfo} 186 * reference to unresolved {@link Label} during bytecode serialization. 187 * Setting this option to {@code DROP_DEAD_LABELS} filters the above 188 * elements instead. 189 * 190 * @since 22 191 */ 192 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 193 enum DeadLabelsOption implements Option { 194 195 /** Fail on unresolved labels */ 196 FAIL_ON_DEAD_LABELS, 197 198 /** Filter unresolved labels */ 199 DROP_DEAD_LABELS 200 } 201 202 /** 203 * Option describing whether to process or discard debug elements. 204 * Debug elements include the local variable table, local variable type 205 * table, and character range table. Discarding debug elements may 206 * reduce the overhead of parsing or transforming classfiles. 207 * Default is {@code PASS_DEBUG} to process debug elements. 208 * 209 * @since 22 210 */ 211 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 212 enum DebugElementsOption implements Option { 213 214 /** Process debug elements */ 215 PASS_DEBUG, 216 217 /** Drop debug elements */ 218 DROP_DEBUG 219 } 220 221 /** 222 * Option describing whether to process or discard line numbers. 223 * Discarding line numbers may reduce the overhead of parsing or transforming 224 * classfiles. 225 * Default is {@code PASS_LINE_NUMBERS} to process line numbers. 226 * 227 * @since 22 228 */ 229 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 230 enum LineNumbersOption implements Option { 231 232 /** Process line numbers */ 233 PASS_LINE_NUMBERS, 234 235 /** Drop line numbers */ 236 DROP_LINE_NUMBERS; 237 } 238 239 /** 240 * Option describing whether to automatically rewrite short jumps to 241 * long when necessary. 242 * Default is {@code FIX_SHORT_JUMPS} to automatically rewrite jump 243 * instructions. 244 * 245 * @since 22 246 */ 247 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 248 enum ShortJumpsOption implements Option { 249 250 /** Automatically convert short jumps to long when necessary */ 251 FIX_SHORT_JUMPS, 252 253 /** Fail if short jump overflows */ 254 FAIL_ON_SHORT_JUMPS 255 } 256 257 /** 258 * Option describing whether to generate stackmaps. 259 * Default is {@code STACK_MAPS_WHEN_REQUIRED} to generate stack 260 * maps for {@link #JAVA_6_VERSION} or above, where specifically for 261 * {@link #JAVA_6_VERSION} the stack maps may not be generated. 262 * @jvms 4.10.1 Verification by Type Checking 263 * 264 * @since 22 265 */ 266 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 267 enum StackMapsOption implements Option { 268 269 /** Generate stack maps when required */ 270 STACK_MAPS_WHEN_REQUIRED, 271 272 /** Always generate stack maps */ 273 GENERATE_STACK_MAPS, 274 275 /** Drop stack maps from code */ 276 DROP_STACK_MAPS 277 } 278 279 /** 280 * Option describing whether to process or discard unrecognized or problematic 281 * original attributes when a class, record component, field, method or code is 282 * transformed in its exploded form. 283 * Default is {@code PASS_ALL_ATTRIBUTES} to process all original attributes. 284 * @see AttributeMapper.AttributeStability 285 * 286 * @since 22 287 */ 288 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) 289 enum AttributesProcessingOption implements Option { 290 291 /** Process all original attributes during transformation */ 292 PASS_ALL_ATTRIBUTES, 293 294 /** Drop unknown attributes during transformation */ 295 DROP_UNKNOWN_ATTRIBUTES, 296 297 /** Drop unknown and unstable original attributes during transformation */ 298 DROP_UNSTABLE_ATTRIBUTES 299 } 300 301 /** 302 * Parse a classfile into a {@link ClassModel}. 303 * @param bytes the bytes of the classfile 304 * @return the class model 305 * @throws IllegalArgumentException or its subclass if the classfile format is 306 * not supported or an incompatibility prevents parsing of the classfile 307 */ 308 ClassModel parse(byte[] bytes); 309 310 /** 311 * Parse a classfile into a {@link ClassModel}. 312 * @param path the path to the classfile 313 * @return the class model 314 * @throws java.io.IOException if an I/O error occurs 315 * @throws IllegalArgumentException or its subclass if the classfile format is 316 * not supported or an incompatibility prevents parsing of the classfile 317 */ 318 default ClassModel parse(Path path) throws IOException { 319 return parse(Files.readAllBytes(path)); 320 } 321 322 /** 323 * Build a classfile into a byte array. 324 * @param thisClass the name of the class to build 325 * @param handler a handler that receives a {@link ClassBuilder} 326 * @return the classfile bytes 327 * @throws IllegalArgumentException if {@code thisClass} represents a primitive type 328 */ 329 default byte[] build(ClassDesc thisClass, 330 Consumer<? super ClassBuilder> handler) { 331 ConstantPoolBuilder pool = ConstantPoolBuilder.of(); 332 return build(pool.classEntry(thisClass), pool, handler); 333 } 334 335 /** 336 * Build a classfile into a byte array using the provided constant pool 337 * builder. 338 * 339 * @param thisClassEntry the name of the class to build 340 * @param constantPool the constant pool builder 341 * @param handler a handler that receives a {@link ClassBuilder} 342 * @return the classfile bytes 343 */ 344 byte[] build(ClassEntry thisClassEntry, 345 ConstantPoolBuilder constantPool, 346 Consumer<? super ClassBuilder> handler); 347 348 /** 349 * Build a classfile into a file. 350 * @param path the path to the file to write 351 * @param thisClass the name of the class to build 352 * @param handler a handler that receives a {@link ClassBuilder} 353 * @throws java.io.IOException if an I/O error occurs 354 */ 355 default void buildTo(Path path, 356 ClassDesc thisClass, 357 Consumer<ClassBuilder> handler) throws IOException { 358 Files.write(path, build(thisClass, handler)); 359 } 360 361 /** 362 * Build a classfile into a file using the provided constant pool 363 * builder. 364 * 365 * @param path the path to the file to write 366 * @param thisClassEntry the name of the class to build 367 * @param constantPool the constant pool builder 368 * @param handler a handler that receives a {@link ClassBuilder} 369 * @throws java.io.IOException if an I/O error occurs 370 */ 371 default void buildTo(Path path, 372 ClassEntry thisClassEntry, 373 ConstantPoolBuilder constantPool, 374 Consumer<? super ClassBuilder> handler) throws IOException { 375 Files.write(path, build(thisClassEntry, constantPool, handler)); 376 } 377 378 /** 379 * Build a module descriptor into a byte array. 380 * @param moduleAttribute the {@code Module} attribute 381 * @return the classfile bytes 382 */ 383 default byte[] buildModule(ModuleAttribute moduleAttribute) { 384 return buildModule(moduleAttribute, clb -> {}); 385 } 386 387 /** 388 * Build a module descriptor into a byte array. 389 * @param moduleAttribute the {@code Module} attribute 390 * @param handler a handler that receives a {@link ClassBuilder} 391 * @return the classfile bytes 392 */ 393 default byte[] buildModule(ModuleAttribute moduleAttribute, 394 Consumer<? super ClassBuilder> handler) { 395 return build(CD_module_info, clb -> { 396 clb.withFlags(AccessFlag.MODULE); 397 clb.with(moduleAttribute); 398 handler.accept(clb); 399 }); 400 } 401 402 /** 403 * Build a module descriptor into a file. 404 * @param path the file to write 405 * @param moduleAttribute the {@code Module} attribute 406 * @throws java.io.IOException if an I/O error occurs 407 */ 408 default void buildModuleTo(Path path, 409 ModuleAttribute moduleAttribute) throws IOException { 410 buildModuleTo(path, moduleAttribute, clb -> {}); 411 } 412 413 /** 414 * Build a module descriptor into a file. 415 * @param path the file to write 416 * @param moduleAttribute the {@code Module} attribute 417 * @param handler a handler that receives a {@link ClassBuilder} 418 * @throws java.io.IOException if an I/O error occurs 419 */ 420 default void buildModuleTo(Path path, 421 ModuleAttribute moduleAttribute, 422 Consumer<? super ClassBuilder> handler) throws IOException { 423 Files.write(path, buildModule(moduleAttribute, handler)); 424 } 425 426 /** 427 * Transform one classfile into a new classfile with the aid of a 428 * {@link ClassTransform}. The transform will receive each element of 429 * this class, as well as a {@link ClassBuilder} for building the new class. 430 * The transform is free to preserve, remove, or replace elements as it 431 * sees fit. 432 * 433 * @implNote 434 * This method behaves as if: 435 * {@snippet lang=java : 436 * this.build(model.thisClass(), ConstantPoolBuilder.of(model), 437 * clb -> clb.transform(model, transform)); 438 * } 439 * 440 * @param model the class model to transform 441 * @param transform the transform 442 * @return the bytes of the new class 443 */ 444 default byte[] transformClass(ClassModel model, ClassTransform transform) { 445 return transformClass(model, model.thisClass(), transform); 446 } 447 448 /** 449 * Transform one classfile into a new classfile with the aid of a 450 * {@link ClassTransform}. The transform will receive each element of 451 * this class, as well as a {@link ClassBuilder} for building the new class. 452 * The transform is free to preserve, remove, or replace elements as it 453 * sees fit. 454 * 455 * @param model the class model to transform 456 * @param newClassName new class name 457 * @param transform the transform 458 * @return the bytes of the new class 459 */ 460 default byte[] transformClass(ClassModel model, ClassDesc newClassName, ClassTransform transform) { 461 return transformClass(model, TemporaryConstantPool.INSTANCE.classEntry(newClassName), transform); 462 } 463 464 /** 465 * Transform one classfile into a new classfile with the aid of a 466 * {@link ClassTransform}. The transform will receive each element of 467 * this class, as well as a {@link ClassBuilder} for building the new class. 468 * The transform is free to preserve, remove, or replace elements as it 469 * sees fit. 470 * 471 * @implNote 472 * This method behaves as if: 473 * {@snippet lang=java : 474 * this.build(newClassName, ConstantPoolBuilder.of(model), 475 * clb -> clb.transform(model, transform)); 476 * } 477 * 478 * @param model the class model to transform 479 * @param newClassName new class name 480 * @param transform the transform 481 * @return the bytes of the new class 482 */ 483 byte[] transformClass(ClassModel model, ClassEntry newClassName, ClassTransform transform); 484 485 /** 486 * Verify a classfile. Any verification errors found will be returned. 487 * @param model the class model to verify 488 * @return a list of verification errors, or an empty list if no errors are 489 * found 490 */ 491 List<VerifyError> verify(ClassModel model); 492 493 /** 494 * Verify a classfile. Any verification errors found will be returned. 495 * @param bytes the classfile bytes to verify 496 * @return a list of verification errors, or an empty list if no errors are 497 * found 498 */ 499 List<VerifyError> verify(byte[] bytes); 500 501 /** 502 * Verify a classfile. Any verification errors found will be returned. 503 * @param path the classfile path to verify 504 * @return a list of verification errors, or an empty list if no errors are 505 * found 506 * @throws java.io.IOException if an I/O error occurs 507 */ 508 default List<VerifyError> verify(Path path) throws IOException { 509 return verify(Files.readAllBytes(path)); 510 } 511 512 /** 0xCAFEBABE */ 513 int MAGIC_NUMBER = 0xCAFEBABE; 514 515 /** The bit mask of PUBLIC access and property modifier. */ 516 int ACC_PUBLIC = 0x0001; 517 518 /** The bit mask of PROTECTED access and property modifier. */ 519 int ACC_PROTECTED = 0x0004; 520 521 /** The bit mask of PRIVATE access and property modifier. */ 522 int ACC_PRIVATE = 0x0002; 523 524 /** The bit mask of INTERFACE access and property modifier. */ 525 int ACC_INTERFACE = 0x0200; 526 527 /** The bit mask of ENUM access and property modifier. */ 528 int ACC_ENUM = 0x4000; 529 530 /** The bit mask of ANNOTATION access and property modifier. */ 531 int ACC_ANNOTATION = 0x2000; 532 533 /** The bit mask of SUPER access and property modifier. */ 534 int ACC_SUPER = 0x0020; 535 536 /** The bit mask of IDENTITY access and property modifier. */ 537 int ACC_IDENTITY = 0x0020; 538 539 /** The bit mask of ABSTRACT access and property modifier. */ 540 int ACC_ABSTRACT = 0x0400; 541 542 /** The bit mask of VOLATILE access and property modifier. */ 543 int ACC_VOLATILE = 0x0040; 544 545 /** The bit mask of TRANSIENT access and property modifier. */ 546 int ACC_TRANSIENT = 0x0080; 547 548 /** The bit mask of SYNTHETIC access and property modifier. */ 549 int ACC_SYNTHETIC = 0x1000; 550 551 /** The bit mask of STATIC access and property modifier. */ 552 int ACC_STATIC = 0x0008; 553 554 /** The bit mask of FINAL access and property modifier. */ 555 int ACC_FINAL = 0x0010; 556 557 /** The bit mask of SYNCHRONIZED access and property modifier. */ 558 int ACC_SYNCHRONIZED = 0x0020; 559 560 /** The bit mask of BRIDGE access and property modifier. */ 561 int ACC_BRIDGE = 0x0040; 562 563 /** The bit mask of VARARGS access and property modifier. */ 564 int ACC_VARARGS = 0x0080; 565 566 /** The bit mask of NATIVE access and property modifier. */ 567 int ACC_NATIVE = 0x0100; 568 569 /** The bit mask of STRICT access and property modifier. */ 570 int ACC_STRICT = 0x0800; 571 572 /** The bit mask of MODULE access and property modifier. */ 573 int ACC_MODULE = 0x8000; 574 575 /** The bit mask of OPEN access and property modifier. */ 576 int ACC_OPEN = 0x20; 577 578 /** The bit mask of MANDATED access and property modifier. */ 579 int ACC_MANDATED = 0x8000; 580 581 /** The bit mask of TRANSITIVE access and property modifier. */ 582 int ACC_TRANSITIVE = 0x20; 583 584 /** The bit mask of STATIC_PHASE access and property modifier. */ 585 int ACC_STATIC_PHASE = 0x40; 586 587 /** The class major version of JAVA_1. */ 588 int JAVA_1_VERSION = 45; 589 590 /** The class major version of JAVA_2. */ 591 int JAVA_2_VERSION = 46; 592 593 /** The class major version of JAVA_3. */ 594 int JAVA_3_VERSION = 47; 595 596 /** The class major version of JAVA_4. */ 597 int JAVA_4_VERSION = 48; 598 599 /** The class major version of JAVA_5. */ 600 int JAVA_5_VERSION = 49; 601 602 /** The class major version of JAVA_6. */ 603 int JAVA_6_VERSION = 50; 604 605 /** The class major version of JAVA_7. */ 606 int JAVA_7_VERSION = 51; 607 608 /** The class major version of JAVA_8. */ 609 int JAVA_8_VERSION = 52; 610 611 /** The class major version of JAVA_9. */ 612 int JAVA_9_VERSION = 53; 613 614 /** The class major version of JAVA_10. */ 615 int JAVA_10_VERSION = 54; 616 617 /** The class major version of JAVA_11. */ 618 int JAVA_11_VERSION = 55; 619 620 /** The class major version of JAVA_12. */ 621 int JAVA_12_VERSION = 56; 622 623 /** The class major version of JAVA_13. */ 624 int JAVA_13_VERSION = 57; 625 626 /** The class major version of JAVA_14. */ 627 int JAVA_14_VERSION = 58; 628 629 /** The class major version of JAVA_15. */ 630 int JAVA_15_VERSION = 59; 631 632 /** The class major version of JAVA_16. */ 633 int JAVA_16_VERSION = 60; 634 635 /** The class major version of JAVA_17. */ 636 int JAVA_17_VERSION = 61; 637 638 /** The class major version of JAVA_18. */ 639 int JAVA_18_VERSION = 62; 640 641 /** The class major version of JAVA_19. */ 642 int JAVA_19_VERSION = 63; 643 644 /** The class major version of JAVA_20. */ 645 int JAVA_20_VERSION = 64; 646 647 /** The class major version of JAVA_21. */ 648 int JAVA_21_VERSION = 65; 649 650 /** The class major version of JAVA_22. */ 651 int JAVA_22_VERSION = 66; 652 653 /** 654 * The class major version of JAVA_23. 655 * @since 23 656 */ 657 int JAVA_23_VERSION = 67; 658 659 /** 660 * The class major version of JAVA_24. 661 * @since 24 662 */ 663 int JAVA_24_VERSION = 68; 664 665 /** 666 * A minor version number indicating a class uses preview features 667 * of a Java SE version since 12, for major versions {@value 668 * #JAVA_12_VERSION} and above. 669 */ 670 int PREVIEW_MINOR_VERSION = 65535; 671 672 /** 673 * {@return the latest major Java version} 674 */ 675 static int latestMajorVersion() { 676 return JAVA_24_VERSION; 677 } 678 679 /** 680 * {@return the latest minor Java version} 681 */ 682 static int latestMinorVersion() { 683 return 0; 684 } 685 686 }