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 IDENTITY access and property modifier. */
538     int ACC_IDENTITY = 0x0020;
539 
540     /** The bit mask of ABSTRACT access and property modifier. */
541     int ACC_ABSTRACT = 0x0400;
542 
543     /** The bit mask of VOLATILE access and property modifier. */
544     int ACC_VOLATILE = 0x0040;
545 
546     /** The bit mask of TRANSIENT access and property modifier. */
547     int ACC_TRANSIENT = 0x0080;
548 
549     /** The bit mask of SYNTHETIC access and property modifier. */
550     int ACC_SYNTHETIC = 0x1000;
551 
552     /** The bit mask of STATIC access and property modifier. */
553     int ACC_STATIC = 0x0008;
554 
555     /** The bit mask of FINAL access and property modifier. */
556     int ACC_FINAL = 0x0010;
557 
558     /** The bit mask of SYNCHRONIZED access and property modifier. */
559     int ACC_SYNCHRONIZED = 0x0020;
560 
561     /** The bit mask of BRIDGE access and property modifier. */
562     int ACC_BRIDGE = 0x0040;
563 
564     /** The bit mask of VARARGS access and property modifier. */
565     int ACC_VARARGS = 0x0080;
566 
567     /** The bit mask of NATIVE access and property modifier. */
568     int ACC_NATIVE = 0x0100;
569 
570     /** The bit mask of STRICT access and property modifier. */
571     int ACC_STRICT = 0x0800;
572 
573     /** The bit mask of MODULE access and property modifier. */
574     int ACC_MODULE = 0x8000;
575 
576     /** The bit mask of OPEN access and property modifier. */
577     int ACC_OPEN = 0x20;
578 
579     /** The bit mask of MANDATED access and property modifier. */
580     int ACC_MANDATED = 0x8000;
581 
582     /** The bit mask of TRANSITIVE access and property modifier. */
583     int ACC_TRANSITIVE = 0x20;
584 
585     /** The bit mask of STATIC_PHASE access and property modifier. */
586     int ACC_STATIC_PHASE = 0x40;
587 
588     /** The class major version of JAVA_1. */
589     int JAVA_1_VERSION = 45;
590 
591     /** The class major version of JAVA_2. */
592     int JAVA_2_VERSION = 46;
593 
594     /** The class major version of JAVA_3. */
595     int JAVA_3_VERSION = 47;
596 
597     /** The class major version of JAVA_4. */
598     int JAVA_4_VERSION = 48;
599 
600     /** The class major version of JAVA_5. */
601     int JAVA_5_VERSION = 49;
602 
603     /** The class major version of JAVA_6. */
604     int JAVA_6_VERSION = 50;
605 
606     /** The class major version of JAVA_7. */
607     int JAVA_7_VERSION = 51;
608 
609     /** The class major version of JAVA_8. */
610     int JAVA_8_VERSION = 52;
611 
612     /** The class major version of JAVA_9. */
613     int JAVA_9_VERSION = 53;
614 
615     /** The class major version of JAVA_10. */
616     int JAVA_10_VERSION = 54;
617 
618     /** The class major version of JAVA_11. */
619     int JAVA_11_VERSION = 55;
620 
621     /** The class major version of JAVA_12. */
622     int JAVA_12_VERSION = 56;
623 
624     /** The class major version of JAVA_13. */
625     int JAVA_13_VERSION = 57;
626 
627     /** The class major version of JAVA_14. */
628     int JAVA_14_VERSION = 58;
629 
630     /** The class major version of JAVA_15. */
631     int JAVA_15_VERSION = 59;
632 
633     /** The class major version of JAVA_16. */
634     int JAVA_16_VERSION = 60;
635 
636     /** The class major version of JAVA_17. */
637     int JAVA_17_VERSION = 61;
638 
639     /** The class major version of JAVA_18. */
640     int JAVA_18_VERSION = 62;
641 
642     /** The class major version of JAVA_19. */
643     int JAVA_19_VERSION = 63;
644 
645     /** The class major version of JAVA_20. */
646     int JAVA_20_VERSION = 64;
647 
648     /** The class major version of JAVA_21. */
649     int JAVA_21_VERSION = 65;
650 
651     /** The class major version of JAVA_22. */
652     int JAVA_22_VERSION = 66;
653 
654     /**
655      * The class major version of JAVA_23.
656      * @since 23
657      */
658     int JAVA_23_VERSION = 67;
659 
660     /**
661      * The class major version of JAVA_24.
662      * @since 24
663      */
664     int JAVA_24_VERSION = 68;
665 
666     /**
667      * A minor version number indicating a class uses preview features
668      * of a Java SE version since 12, for major versions {@value
669      * #JAVA_12_VERSION} and above.
670      */
671     int PREVIEW_MINOR_VERSION = 65535;
672 
673     /**
674      * {@return the latest major Java version}
675      */
676     static int latestMajorVersion() {
677         return JAVA_24_VERSION;
678     }
679 
680     /**
681      * {@return the latest minor Java version}
682      */
683     static int latestMinorVersion() {
684         return 0;
685     }
686 
687 }
--- EOF ---