/* * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /** *
* A {@link ClassModel} is an immutable description of a class * file. It provides accessor methods to get at class metadata (e.g., {@link * ClassModel#thisClass()}, {@link ClassModel#flags()}), * as well as subordinate classfile entities ({@link ClassModel#fields()}, * {@link ClassModel#attributes()}). A {@link * ClassModel} is inflated lazily; most parts of the classfile are * not parsed until they are actually needed. Due to the laziness, these models * may not be thread safe. Additionally, invocations to accessor methods on * models may lead to {@link IllegalArgumentException} due to malformed {@code * class} file format, as parsing happens lazily. *
* We can enumerate the names of the fields and methods in a class by: * {@snippet lang="java" class="PackageSnippets" region="enumerateFieldsMethods1"} *
* When we enumerate the methods, we get a {@link MethodModel} for each method; like a * {@code ClassModel}, it gives us access to method metadata and * the ability to descend into subordinate entities such as the bytecodes of the * method body. In this way, a {@code ClassModel} is the root of a * tree, with children for fields, methods, and attributes, and {@code MethodModel} in * turn has its own children (attributes, {@code CodeModel}, etc.) *
* Methods like {@link ClassModel#methods} allows us to traverse the class structure * explicitly, going straight to the parts we are interested in. This is useful * for certain kinds of analysis, but if we wanted to process the whole * classfile, we may want something more organized. A {@link * ClassModel} also provides us with a view of the classfile as a * series of class elements, which may include methods, fields, attributes, * and more, and which can be distinguished with pattern matching. We could * rewrite the above example as: * {@snippet lang="java" class="PackageSnippets" region="enumerateFieldsMethods2"} *
* The models returned as elements from traversing {@code ClassModel} can in * turn be sources of elements. If we wanted to * traverse a classfile and enumerate all the classes for which we access fields * and methods, we can pick out the class elements that describe methods, then * in turn pick out the method elements that describe the code attribute, and * finally pick out the code elements that describe field access and invocation * instructions: * {@snippet lang="java" class="PackageSnippets" region="gatherDependencies1"} *
* This same query could alternately be processed as a stream pipeline over * class elements: * {@snippet lang="java" class="PackageSnippets" region="gatherDependencies2"} * *
* Constant pool entries are also exposed through models and elements; in the * above traversal example, the {@link InvokeInstruction} * element exposed a method for {@code owner} that corresponds to a {@code * Constant_Class_info} entry in the constant pool. * *
* Some attributes are not surfaced as elements; these are attributes that are * tightly coupled to -- and logically part of -- other parts of the class file. * These include the {@code BootstrapMethods}, {@code LineNumberTable}, {@code * StackMapTable}, {@code LocalVariableTable}, and {@code * LocalVariableTypeTable} attributes. These are processed by the library and * treated as part of the structure they are coupled to (the entries of the * {@code BootstrapMethods} attribute are treated as part of the constant pool; * line numbers and local variable metadata are modeled as elements of {@link * CodeModel}.) *
* The {@code Code} attribute, in addition to being modeled as a {@link * MethodElement}, is also a model in its own right ({@link * CodeModel}) due to its complex structure. *
* Each standard attribute has an interface (in {@code java.lang.classfile.attribute}) * which exposes the contents of the attribute and provides factories to * construct the attribute. For example, the {@code Signature} attribute is * defined by the {@link SignatureAttribute} class, and * provides accessors for {@link SignatureAttribute#signature()} * as well as factories taking {@link Utf8Entry} or * {@link String}. * *
* There are built-in attribute mappers (in {@link Attributes}) for * each of the attribute types defined in section {@jvms 4.7} of The Java Virtual * Machine Specification, as well as several common nonstandard attributes used by the * JDK such as {@code CharacterRangeTable}. *
* Unrecognized attributes are delivered as elements of type {@link * UnknownAttribute}, which provide access only to the * {@code byte[]} contents of the attribute. *
* For nonstandard attributes, user-provided attribute mappers can be specified * through the use of the {@link * ClassFile.AttributeMapperOption#of(Function)}} * classfile option. Implementations of custom attributes should extend {@link * CustomAttribute}. * *
* {@link ClassFile#of(ClassFile.Option[])} * accepts a list of options. {@link ClassFile.Option} is a base interface * for some statically enumerated options, as well as factories for more complex options, * including: *
* {@link ClassFile.AttributeMapperOption} and {@link ClassFile.ClassHierarchyResolverOption} * are critical to the correctness of {@code class} file parsing and generation. * The attribute mapper is required to parse custom attributes. A correct * resolver is required to generate {@code class} files that refer to classes * not available to the system class loader in its bytecode, or in corner cases, * when generation wishes to avoid loading system classes, such as in agents. *
* Most options allow you to request that certain parts of the classfile be * skipped during traversal, such as debug information or unrecognized * attributes. Some options allow you to suppress generation of portions of the * classfile, such as stack maps. Many of these options are to access * performance tradeoffs; processing debug information and line numbers has a * cost (both in writing and reading.) If you don't need this information, you * can suppress it with options to gain some performance. * *
* Rather than creating builders directly, builders are provided as an argument * to a user-provided lambda. To generate the familiar "hello world" program, * we ask for a class builder, and use that class builder to create method * builders for the constructor and {@code main} method, and in turn use the * method builders to create a {@code Code} attribute and use the code builders * to generate the instructions: * {@snippet lang="java" class="PackageSnippets" region="helloWorld1"} *
* The convenience methods {@code ClassBuilder.buildMethodBody} allows us to ask * {@link ClassBuilder} to create code builders to build method bodies directly, * skipping the method builder custom lambda: * {@snippet lang="java" class="PackageSnippets" region="helloWorld2"} *
* Builders often support multiple ways of expressing the same entity at * different levels of abstraction. For example, the {@code invokevirtual} * instruction invoking {@code println} could have been generated with {@link * CodeBuilder#invokevirtual(ClassDesc, * String, MethodTypeDesc) CodeBuilder.invokevirtual}, {@link * CodeBuilder#invoke(Opcode, * ClassDesc, String, MethodTypeDesc, * boolean) CodeBuilder.invoke}, or {@link * CodeBuilder#with(ClassFileElement) * CodeBuilder.with}. *
* The convenience method {@code CodeBuilder.invokevirtual} behaves as if it calls * the convenience method {@code CodeBuilder.invoke}, which in turn behaves * as if it calls method {@code CodeBuilder.with}. This composing of method calls on the * builder enables the composing of transforms (as described later). *
* Unless otherwise noted, passing a {@code null} argument to a constructor * or method of any Class-File API class or interface will cause a {@link * NullPointerException} to be thrown. Additionally, * invoking a method with an array or collection containing a {@code null} element * will cause a {@code NullPointerException}, unless otherwise specified.
* ** If a constant pool entry has a nominal representation then it provides a * method returning the corresponding nominal descriptor type e.g. * method {@link ClassEntry#asSymbol} returns * {@code ClassDesc}. *
* Where appropriate builders provide two methods for building an element with * symbolic information, one accepting nominal descriptors, and the other * accepting constant pool entries. * *
* Using nominal descriptors assures the right serial form is applied by the * ClassFile API library based on the actual context. Also these nominal * descriptors are validated during their construction, so it is not possible to * create them with invalid content by mistake. Following example pass class * name to the {@link ClassDesc#of} method for validation * and the library performs automatic conversion to the right internal form of * the class name when serialized in the constant pool as a class entry. * {@snippet lang=java : * var validClassEntry = constantPoolBuilder.classEntry(ClassDesc.of("mypackage.MyClass")); * } *
* On the other hand it is possible to use builders methods and factories accepting * constant pool entries directly. Constant pool entries can be constructed also * directly from raw values, with no additional conversions or validations. * Following example uses intentionally wrong class name form and it is applied * without any validation or conversion. * {@snippet lang=java : * var invalidClassEntry = constantPoolBuilder.classEntry( * constantPoolBuilder.utf8Entry("mypackage.MyClass")); * } *
* More complex verification of a classfile can be achieved by invocation of * {@link ClassFile#verify}. * *
* If we wanted to strip out methods whose names starts with "debug", we could * get an existing {@link ClassModel}, build a new classfile that * provides a {@link ClassBuilder}, iterate the elements of the * original {@link ClassModel}, and pass through all of them to * the builder except the methods we want to drop: * {@snippet lang="java" class="PackageSnippets" region="stripDebugMethods1"} *
* This hands every class element, except for those corresponding to methods * whose names start with {@code debug}, back to the builder. Transformations * can of course be more complicated, diving into method bodies and instructions * and transforming those as well, but the same structure is repeated at every * level, since every entity has corresponding model, builder, and element * abstractions. *
* Transformation can be viewed as a "flatMap" operation on the sequence of * elements; for every element, we could pass it through unchanged, drop it, or * replace it with one or more elements. Because transformation is such a * common operation on classfiles, each model type has a corresponding {@code * XxxTransform} type (which describes a transform on a sequence of {@code * XxxElement}) and each builder type has {@code transformYyy} methods for transforming * its child models. A transform is simply a functional interface that takes a * builder and an element, and an implementation "flatMap"s elements * into the builder. We could express the above as: * {@snippet lang="java" class="PackageSnippets" region="stripDebugMethods2"} *
* {@code ClassTransform.dropping} convenience method allow us to simplify the same * transformation construction and express the above as: * {@snippet lang="java" class="PackageSnippets" region="stripDebugMethods3"} * *
* We can then lift this transformation on code elements into a * transformation on method elements. This intercepts method elements that * correspond to a {@code Code} attribute, dives into its code elements, and * applies the code transform to them, and passes other method elements through * unchanged: * {@snippet lang=java : * MethodTransform mt = MethodTransform.transformingCode(fooToBar); * } *
* and further lift the transform on method elements into one on class * elements: * {@snippet lang=java : * ClassTransform ct = ClassTransform.transformingMethods(mt); * } *
* or lift the code transform into the class transform directly: * {@snippet lang=java : * ClassTransform ct = ClassTransform.transformingMethodBodiess(fooToBar); * } *
* and then transform the classfile: * {@snippet lang=java : * var cc = ClassFile.of(); * byte[] newBytes = cc.transform(cc.parse(bytes), ct); * } *
* This is much more concise (and less error-prone) than the equivalent * expressed by traversing the classfile structure directly: * {@snippet lang="java" class="PackageSnippets" region="fooToBarUnrolled"} * *
* Then we can compose {@code fooToBar} and {@code instrumentCalls} with {@link * CodeTransform#andThen(CodeTransform)}: * * {@snippet lang=java : * var cc = ClassFile.of(); * byte[] newBytes = cc.transform(cc.parse(bytes), * ClassTransform.transformingMethods( * MethodTransform.transformingCode( * fooToBar.andThen(instrumentCalls)))); * } * * Transform {@code instrumentCalls} will receive all code elements produced by * transform {@code forToBar}, either those code elements from the original classfile * or replacements (replacing static invocations to {@code Foo} with those to {@code Bar}). * *
* Conversely, classfile transforms that are only interested in consuming a portion * of classfile elements do not need to concern with new and unknown classfile * elements and may pass them through. Following example shows such future-proof * code transformation: * {@snippet lang="java" class="PackageSnippets" region="benevolentTransform"} * *
* The API is largely derived from a data model * for the classfile format, which defines each element kind (which includes models and * attributes) and its properties. For each element kind, there is a * corresponding interface to describe that element, and factory methods to * create that element. Some element kinds also have convenience methods on the * corresponding builder (e.g., {@link * CodeBuilder#invokevirtual(ClassDesc, * String, MethodTypeDesc)}). *
* Most symbolic information in elements is represented by constant pool entries * (for example, the owner of a field is represented by a {@link * ClassEntry}.) Factories and builders also * accept nominal descriptors from {@link java.lang.constant} (e.g., {@link * ClassDesc}.) * *