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 }