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