Module java.base
Package java.lang.classfile

# Interface ClassFileTransform

≠
public abstract sealed interface ClassFileTransform<C, E, B>
permits java.lang.classfile.ClassTransform, java.lang.classfile.CodeTransform, java.lang.classfile.FieldTransform, java.lang.classfile.MethodTransform
Comparing master and cf

Type Parameters:
  `C` - the transform type
  `E` - the member element type
  `B` - the builder type

All Known Subinterfaces:
  `ClassTransform, CodeTransform, FieldTransform, MethodTransform`

public sealed interface ClassFileTransform<C extends ClassFileTransform<C, E, B>, E extends ClassFileElement, B extends ClassFileBuilder<E, B>> permits ClassTransform, FieldTransform, MethodTransform, CodeTransform
A transformation on streams of elements. Transforms are used during transformation of classfile entities; a transform is provided to a method like `ClassFile.transformClass(ClassModel, ClassTransform)` , and the elements of the class, along with a builder, are presented to the transform.

The subtypes of ClassFileTransform (e.g., `ClassTransform` ) are functional interfaces that accept an element and a corresponding builder. Since any element can be reproduced on the builder via `ClassFileBuilder.with(ClassFileElement)` , a transform can easily leave elements in place, remove them, replace them, or augment them with other elements. This enables localized transforms to be represented concisely.

Transforms also have an `atEnd(ClassFileBuilder)` method, for which the default implementation does nothing, so that a transform can perform additional building after the stream of elements is exhausted.

Transforms can be chained together via the `andThen(ClassFileTransform)` method, so that the output of one becomes the input to another. This allows smaller units of transformation to be captured and reused.

Some transforms are stateful; for example, a transform that injects an annotation on a class may watch for the `RuntimeVisibleAnnotationsAttribute` element and transform it if found, but if it is not found, will generate a RuntimeVisibleAnnotationsAttribute element containing the injected annotation from the atEnd(ClassFileBuilder) handler. To do this, the transform must accumulate some state during the traversal so that the end handler knows what to doa `CompoundElement` by processing its individual member elements and sending the results to a `ClassFileBuilder` , through `ClassFileBuilder.transform(CompoundElement, ClassFileTransform)` . A subtype of `ClassFileTransform` is defined for each subtype of `CompoundElement` and `ClassFileBuilder` , as shown in the sealed class hierarchy below.

For example, this is a basic transformation of a `CodeModel` that redirects all calls to static methods in the `Foo` class to the `Bar` class, preserving all other elements:

    CodeTransform fooToBar = (b, e) -> {
        if (e instanceof InvokeInstruction i
                && i.owner().name().equalsString("Foo")
                && i.opcode() == Opcode.INVOKESTATIC) {
            // remove the old element i by doing nothing to the builder
            // add a new invokestatic instruction to the builder
            b.invokestatic(CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface());
        } else {
            b.with(e);  // leaves the element in place
        }
    };

Note that if no transformation of a member element is desired, the element should be presented to `builder::with` . If no action is taken, that member element is dropped.

More advanced usages of transforms include start or end handling, stateful transformation that makes a decision based on previously encountered member elements, and composition of transforms, where one transform processes the results of a previous transform on the input compound structure. All these capabilities are supported by this interface and accessible to user transform implementations.

Users can define custom start and end handling for a transform by overriding `atStart(B)` and `atEnd(B)` . The start handler is called before any member element is processed, and the end handler is called after all member elements are processed. For example, the start handler can be used to inject extra code elements to the beginning of a code array, and the end handler, combined with stateful transformation, can perform cleanup actions, such as determining if an attribute has been merged, or if a new attribute should be defined. Each subtype of `ClassFileTransform` defines a utility method `endHandler` that returns a transform that only has end handling.

Transforms can have states that persist across processing of individual member elements. For example, if a transform injects an annotation, the transform may keep track if it has encountered and presented an updated `RuntimeVisibleAnnotationsAttribute` to the builder; if it has not yet, it can present a new attribute containing only the injected annotation in its end handlerMoved out of a paragraph.Moved to a paragraph with id stateful.. If such a transform is to be shared or Moved out of a paragraph.Moved to a paragraph with id stateful.reused, each returned transform should have Moved out of a paragraph.Moved to a paragraph with id stateful.its own state. Each subtype of `ClassFileTransform` defines a utility method `ofStateful` where a supplier creates the transform at its initial state each time the transform is reused.

Transforms can be composed via `andThen(C)` . When this transform is composed with another transform, it means the output member elements received by the `ClassFileBuilder` become the input elements to that other transform. Composition avoids building intermediate structures for multiple transforms to run on. Each subtype of `ClassFileTransform` implements `andThen(C)` , which generally should not be implemented by users.

Transforms that run on smaller structures can be lifted to its enclosing structures to selectively run on all enclosed smaller structures of the same kind. For example, a `CodeTransform` can be lifted via `ClassTransform.transformingMethodBodies(Predicate, CodeTransform)` to transform the method body of select methods in the class it runs on. This allows users to write small transforms and apply to larger scales.

Besides `ClassFileBuilder.transform(CompoundElement, ClassFileTransform)` , there are other methods that accepts a transform conveniently, such as `ClassFile.transformClass(ClassModel, ClassTransform)` , `ClassBuilder.transformField(FieldModel, FieldTransform)` , `ClassBuilder.transformMethod(MethodModel, MethodTransform)` , or `MethodBuilder.transformCode(CodeModel, CodeTransform)` . They are convenience methods that suit the majority of transformation scenarios. state must be reset for each traversal; this will happen automatically if the transform is created with `ClassTransform.ofStateful(Supplier)` (or corresponding methods for other classfile locations.)

Sealed Class Hierarchy Graph:
Since:
  24

## Methods

- ≠
  public abstract void accept(B arg0, E arg1)
  Comparing master and cf

  ### accept

  void accept (B builder, E element)
  Transform an element by taking the appropriate actions on the builder. Used when transforming a classfile entity (class, method, field, method body.) If no transformation is desired, the element can be presented to `ClassFileBuilder.with(ClassFileElement)` . If the element is to be dropped, no action is required.

  Moved to a paragraph. This method is called by the Class-File API. Users should never call this method.

  Parameters:
    `builder` - the builder for the new entity
    `element` - the element
- ≠
  public abstract C andThen(C arg0)
  Comparing master and cf

  ### andThen

  C andThen (C next)
  Chain this transform with another; elements presented to the builder of this transform will become the input to the next transform.

  Moved to a paragraph. This method is implemented by the Class-File API. Users usually don't have sufficient access to Class-File API functionalities to override this method correctly for generic downstream transforms.

  Parameters:
    `next` - the downstream transform
  Returns:
    the chained transform
- ≠
  public default void atEnd(B arg0)
  Comparing master and cf

  ### atEnd

  default void atEnd (B builder)
  Take any final action during transformation of a classfile entity. Called after all elements of the class are presented to `accept(ClassFileBuilder, ClassFileElement)` .

  Moved to a paragraph. This method is called by the Class-File API. Users should never call this method.

  Implementation Requirements:
    The default implementation does nothing.
  Parameters:
    `builder` - the builder for the new entity
- ≠
  public default void atStart(B arg0)
  Comparing master and cf

  ### atStart

  default void atStart (B builder)
  Take any preliminary action during transformation of a classfile entity. Called before any elements of the class are presented to `accept(ClassFileBuilder, ClassFileElement)` .

  Moved to a paragraph. This method is called by the Class-File API. Users should never call this method.

  Implementation Requirements:
    The default implementation does nothing.
  Parameters:
    `builder` - the builder for the new entity

## Summary

Differences
| Elements | Comments | Descriptions | Total
Added | Changed | Removed | Added | Changed | Removed | Added | Changed | Removed
--- | --- | --- | --- | --- | --- | --- | --- | ---
ClassFileTransform |  |  |  |  |  |  | 37 | 3 | 10 | 50
accept(B,E) |  |  |  |  |  |  |  | 1 |  | 1
andThen(C) |  |  |  |  |  |  |  | 1 |  | 1
atEnd(B) |  |  |  |  |  |  |  | 1 |  | 1
atStart(B) |  |  |  |  |  |  |  | 1 |  | 1
Total |  |  |  |  |  |  | 37 | 7 | 10 | 54