1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy;
17
18 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19 import net.bytebuddy.description.annotation.AnnotationDescription;
20 import net.bytebuddy.description.annotation.AnnotationValue;
21 import net.bytebuddy.description.field.FieldDescription;
22 import net.bytebuddy.description.method.MethodDescription;
23 import net.bytebuddy.description.method.ParameterDescription;
24 import net.bytebuddy.description.modifier.*;
25 import net.bytebuddy.description.type.*;
26 import net.bytebuddy.dynamic.*;
27 import net.bytebuddy.dynamic.scaffold.*;
28 import net.bytebuddy.dynamic.scaffold.inline.DecoratingDynamicTypeBuilder;
29 import net.bytebuddy.dynamic.scaffold.inline.MethodNameTransformer;
30 import net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder;
31 import net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder;
32 import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
33 import net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder;
34 import net.bytebuddy.implementation.Implementation;
35 import net.bytebuddy.implementation.MethodCall;
36 import net.bytebuddy.implementation.SuperMethodCall;
37 import net.bytebuddy.implementation.attribute.AnnotationRetention;
38 import net.bytebuddy.implementation.attribute.AnnotationValueFilter;
39 import net.bytebuddy.implementation.attribute.MethodAttributeAppender;
40 import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
41 import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
42 import net.bytebuddy.implementation.bytecode.Duplication;
43 import net.bytebuddy.implementation.bytecode.StackManipulation;
44 import net.bytebuddy.implementation.bytecode.TypeCreation;
45 import net.bytebuddy.implementation.bytecode.assign.Assigner;
46 import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
47 import net.bytebuddy.implementation.bytecode.collection.ArrayFactory;
48 import net.bytebuddy.implementation.bytecode.constant.IntegerConstant;
49 import net.bytebuddy.implementation.bytecode.constant.TextConstant;
50 import net.bytebuddy.implementation.bytecode.member.FieldAccess;
51 import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
52 import net.bytebuddy.implementation.bytecode.member.MethodReturn;
53 import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
54 import net.bytebuddy.matcher.ElementMatcher;
55 import net.bytebuddy.matcher.LatentMatcher;
56 import net.bytebuddy.utility.CompoundList;
57 import net.bytebuddy.utility.JavaConstant;
58 import net.bytebuddy.utility.JavaType;
59 import net.bytebuddy.jar.asm.MethodVisitor;
60 import net.bytebuddy.jar.asm.Opcodes;
61
62 import java.lang.annotation.Annotation;
63 import java.lang.annotation.ElementType;
64 import java.lang.reflect.Type;
65 import java.util.*;
66
67 import static net.bytebuddy.matcher.ElementMatchers.*;
68
69 /**
70  * Instances of this class serve as a focus point for configuration of the library's behavior and as an entry point
71  * to any form of code generation using the library. For this purpose, Byte Buddy offers a fluent API which allows
72  * for the step-wise generation of a new Java type. A type is generated either by:
73  * <ul>
74  * <li><b>Subclassing</b> some type: A subclass - as the name suggests - extends another, existing Java type. Virtual
75  * members of the generated type's super types can be overridden. Subclasses can also be interface extensions of one
76  * or several interfaces.</li>
77  * <li><b>Redefining</b> a type: By redefining a type, it is not only possible to override virtual methods of the
78  * redefined type but also to redefine existing methods. This way, it is also possible to change the behavior of
79  * non-virtual methods and constructors of the redefined type.</li>
80  * <li><b>Rebasing</b> a type: Rebasing a type works similar to creating a subclass, i.e. any method being overridden
81  * is still capable of invoking any original code of the rebased type. Any rebased method is however inlined into the
82  * rebased type and any original code is preserved automatically. This way, the type's identity does not change.</li>
83  * </ul>
84  * Byte Buddy's API does not change when a type is rebased, redefined or subclassed. All types are created via the
85  * {@link net.bytebuddy.dynamic.DynamicType.Builder} interface. Byte Buddy's API is expressed by fully immutable
86  * components and is therefore thread-safe. As a consequence, method calls must be chained for all of Byte Buddy's
87  * component, e.g. a method call like the following has no effect:
88  * <pre>
89  * ByteBuddy byteBuddy = new ByteBuddy();
90  * byteBuddy.foo()</pre>
91  * Instead, the following method chain is correct use of the API:
92  * <pre>
93  * ByteBuddy byteBuddy = new ByteBuddy().foo();</pre>
94  * <p>
95  * For the creation of Java agents, Byte Buddy offers a convenience API implemented by the
96  * {@link net.bytebuddy.agent.builder.AgentBuilder}. The API wraps a {@link ByteBuddy} instance and offers agent-specific
97  * configuration opportunities by integrating against the {@link java.lang.instrument.Instrumentation} API.
98  * </p>
99  *
100  * @see net.bytebuddy.agent.builder.AgentBuilder
101  */

102 @HashCodeAndEqualsPlugin.Enhance
103 public class ByteBuddy {
104
105     /**
106      * The default prefix for the default {@link net.bytebuddy.NamingStrategy}.
107      */

108     private static final String BYTE_BUDDY_DEFAULT_PREFIX = "ByteBuddy";
109
110     /**
111      * The default suffix when defining a {@link AuxiliaryType.NamingStrategy}.
112      */

113     private static final String BYTE_BUDDY_DEFAULT_SUFFIX = "auxiliary";
114
115     /**
116      * The class file version to use for types that are not based on an existing class file.
117      */

118     protected final ClassFileVersion classFileVersion;
119
120     /**
121      * The naming strategy to use.
122      */

123     protected final NamingStrategy namingStrategy;
124
125     /**
126      * The naming strategy to use for naming auxiliary types.
127      */

128     protected final AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy;
129
130     /**
131      * The annotation value filter factory to use.
132      */

133     protected final AnnotationValueFilter.Factory annotationValueFilterFactory;
134
135     /**
136      * The annotation retention strategy to use.
137      */

138     protected final AnnotationRetention annotationRetention;
139
140     /**
141      * The implementation context factory to use.
142      */

143     protected final Implementation.Context.Factory implementationContextFactory;
144
145     /**
146      * The method graph compiler to use.
147      */

148     protected final MethodGraph.Compiler methodGraphCompiler;
149
150     /**
151      * The instrumented type factory to use.
152      */

153     protected final InstrumentedType.Factory instrumentedTypeFactory;
154
155     /**
156      * A matcher for identifying methods that should be excluded from instrumentation.
157      */

158     protected final LatentMatcher<? super MethodDescription> ignoredMethods;
159
160     /**
161      * Determines if a type should be explicitly validated.
162      */

163     protected final TypeValidation typeValidation;
164
165     /**
166      * The visibility bridge strategy to apply.
167      */

168     protected final VisibilityBridgeStrategy visibilityBridgeStrategy;
169
170     /**
171      * The class writer strategy to use.
172      */

173     protected final ClassWriterStrategy classWriterStrategy;
174
175     /**
176      * <p>
177      * Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
178      * </p>
179      * <p>
180      * When creating this configuration, Byte Buddy attempts to discover the current JVM's version. If this
181      * is not possible, class files are created Java 6-compatible.
182      * </p>
183      *
184      * @see ClassFileVersion#ofThisVm(ClassFileVersion)
185      */

186     public ByteBuddy() {
187         this(ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V6));
188     }
189
190     /**
191      * Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
192      *
193      * @param classFileVersion The class file version to use for types that are not based on an existing class file.
194      */

195     public ByteBuddy(ClassFileVersion classFileVersion) {
196         this(classFileVersion,
197                 new NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_PREFIX),
198                 new AuxiliaryType.NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_SUFFIX),
199                 AnnotationValueFilter.Default.APPEND_DEFAULTS,
200                 AnnotationRetention.ENABLED,
201                 Implementation.Context.Default.Factory.INSTANCE,
202                 MethodGraph.Compiler.DEFAULT,
203                 InstrumentedType.Factory.Default.MODIFIABLE,
204                 TypeValidation.ENABLED,
205                 VisibilityBridgeStrategy.Default.ALWAYS,
206                 ClassWriterStrategy.Default.CONSTANT_POOL_RETAINING,
207                 new LatentMatcher.Resolved<MethodDescription>(isSynthetic().or(isDefaultFinalizer())));
208     }
209
210     /**
211      * Creates a new Byte Buddy instance.
212      *
213      * @param classFileVersion             The class file version to use for types that are not based on an existing class file.
214      * @param namingStrategy               The naming strategy to use.
215      * @param auxiliaryTypeNamingStrategy  The naming strategy to use for naming auxiliary types.
216      * @param annotationValueFilterFactory The annotation value filter factory to use.
217      * @param annotationRetention          The annotation retention strategy to use.
218      * @param implementationContextFactory The implementation context factory to use.
219      * @param methodGraphCompiler          The method graph compiler to use.
220      * @param instrumentedTypeFactory      The instrumented type factory to use.
221      * @param typeValidation               Determines if a type should be explicitly validated.
222      * @param visibilityBridgeStrategy     The visibility bridge strategy to apply.
223      * @param classWriterStrategy          The class writer strategy to use.
224      * @param ignoredMethods               A matcher for identifying methods that should be excluded from instrumentation.
225      */

226     protected ByteBuddy(ClassFileVersion classFileVersion,
227                         NamingStrategy namingStrategy,
228                         AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
229                         AnnotationValueFilter.Factory annotationValueFilterFactory,
230                         AnnotationRetention annotationRetention,
231                         Implementation.Context.Factory implementationContextFactory,
232                         MethodGraph.Compiler methodGraphCompiler,
233                         InstrumentedType.Factory instrumentedTypeFactory,
234                         TypeValidation typeValidation,
235                         VisibilityBridgeStrategy visibilityBridgeStrategy,
236                         ClassWriterStrategy classWriterStrategy,
237                         LatentMatcher<? super MethodDescription> ignoredMethods) {
238         this.classFileVersion = classFileVersion;
239         this.namingStrategy = namingStrategy;
240         this.auxiliaryTypeNamingStrategy = auxiliaryTypeNamingStrategy;
241         this.annotationValueFilterFactory = annotationValueFilterFactory;
242         this.annotationRetention = annotationRetention;
243         this.implementationContextFactory = implementationContextFactory;
244         this.methodGraphCompiler = methodGraphCompiler;
245         this.instrumentedTypeFactory = instrumentedTypeFactory;
246         this.typeValidation = typeValidation;
247         this.visibilityBridgeStrategy = visibilityBridgeStrategy;
248         this.classWriterStrategy = classWriterStrategy;
249         this.ignoredMethods = ignoredMethods;
250     }
251
252     /**
253      * <p>
254      * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
255      * this interface type is created.
256      * </p>
257      * <p>
258      * When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
259      * to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
260      * {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Class, ConstructorStrategy)}.
261      * </p>
262      * <p>
263      * <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
264      * </p>
265      * <p>
266      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
267      * types, a external cache or {@link TypeCache} should be used.
268      * </p>
269      *
270      * @param superType The super class or interface type to extend.
271      * @param <T>       A loaded type that the generated class is guaranteed to inherit.
272      * @return A type builder for creating a new class extending the provided class or interface.
273      */

274     @SuppressWarnings("unchecked")
275     public <T> DynamicType.Builder<T> subclass(Class<T> superType) {
276         return (DynamicType.Builder<T>) subclass(TypeDescription.ForLoadedType.of(superType));
277     }
278
279     /**
280      * <p>
281      * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
282      * this interface type is created.
283      * </p>
284      * <p>
285      * <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
286      * </p>
287      * <p>
288      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
289      * types, a external cache or {@link TypeCache} should be used.
290      * </p>
291      *
292      * @param superType           The super class or interface type to extend.
293      * @param constructorStrategy A constructor strategy that determines the
294      * @param <T>                 A loaded type that the generated class is guaranteed to inherit.
295      * @return A type builder for creating a new class extending the provided class or interface.
296      */

297     @SuppressWarnings("unchecked")
298     public <T> DynamicType.Builder<T> subclass(Class<T> superType, ConstructorStrategy constructorStrategy) {
299         return (DynamicType.Builder<T>) subclass(TypeDescription.ForLoadedType.of(superType), constructorStrategy);
300     }
301
302     /**
303      * <p>
304      * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
305      * this interface type is created.
306      * </p>
307      * <p>
308      * When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
309      * to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
310      * {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Type, ConstructorStrategy)}.
311      * </p>
312      * <p>
313      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
314      * as raw types if they declare type variables.
315      * </p>
316      * <p>
317      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
318      * types, a external cache or {@link TypeCache} should be used.
319      * </p>
320      *
321      * @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
322      *                  variables that are referenced by the generic type must be declared by the generated subclass before creating
323      *                  the type.
324      * @return A type builder for creating a new class extending the provided class or interface.
325      */

326     public DynamicType.Builder<?> subclass(Type superType) {
327         return subclass(TypeDefinition.Sort.describe(superType));
328     }
329
330     /**
331      * <p>
332      * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
333      * this interface type is created.
334      * </p>
335      * <p>
336      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
337      * as raw types if they declare type variables.
338      * </p>
339      * <p>
340      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
341      * types, a external cache or {@link TypeCache} should be used.
342      * </p>
343      *
344      * @param superType           The super class or interface type to extend. The type must be a raw type or parameterized
345      *                            type. All type variables that are referenced by the generic type must be declared by the
346      *                            generated subclass before creating the type.
347      * @param constructorStrategy A constructor strategy that determines the
348      * @return A type builder for creating a new class extending the provided class or interface.
349      */

350     public DynamicType.Builder<?> subclass(Type superType, ConstructorStrategy constructorStrategy) {
351         return subclass(TypeDefinition.Sort.describe(superType), constructorStrategy);
352     }
353
354     /**
355      * <p>
356      * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
357      * this interface type is created.
358      * </p>
359      * <p>
360      * When extending a class, Byte Buddy imitates all visible constructors of the subclassed type and sets them to be {@code public}.
361      * Any constructor is implemented to only invoke its super type constructor of equal signature. Another behavior can be specified by
362      * supplying an explicit {@link ConstructorStrategy} by {@link ByteBuddy#subclass(TypeDefinition, ConstructorStrategy)}.
363      * </p>
364      * <p>
365      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
366      * as raw types if they declare type variables.
367      * </p>
368      * <p>
369      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
370      * types, a external cache or {@link TypeCache} should be used.
371      * </p>
372      *
373      * @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
374      *                  variables that are referenced by the generic type must be declared by the generated subclass before creating
375      *                  the type.
376      * @return A type builder for creating a new class extending the provided class or interface.
377      */

378     public DynamicType.Builder<?> subclass(TypeDefinition superType) {
379         return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING);
380     }
381
382     /**
383      * <p>
384      * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
385      * this interface type is created.
386      * </p>
387      * <p>
388      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
389      * as raw types if they declare type variables.
390      * </p>
391      * <p>
392      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
393      * types, a external cache or {@link TypeCache} should be used.
394      * </p>
395      *
396      * @param superType           The super class or interface type to extend. The type must be a raw type or parameterized
397      *                            type. All type variables that are referenced by the generic type must be declared by the
398      *                            generated subclass before creating the type.
399      * @param constructorStrategy A constructor strategy that determines the
400      * @return A type builder for creating a new class extending the provided class or interface.
401      */

402     public DynamicType.Builder<?> subclass(TypeDefinition superType, ConstructorStrategy constructorStrategy) {
403         TypeDescription.Generic actualSuperType;
404         TypeList.Generic interfaceTypes;
405         if (superType.isPrimitive() || superType.isArray() || superType.isFinal()) {
406             throw new IllegalArgumentException("Cannot subclass primitive, array or final types: " + superType);
407         } else if (superType.isInterface()) {
408             actualSuperType = TypeDescription.Generic.OBJECT;
409             interfaceTypes = new TypeList.Generic.Explicit(superType);
410         } else {
411             actualSuperType = superType.asGenericType();
412             interfaceTypes = new TypeList.Generic.Empty();
413         }
414         return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(namingStrategy.subclass(superType.asGenericType()),
415                 ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.PLAIN).resolve(superType.getModifiers()),
416                 actualSuperType).withInterfaces(interfaceTypes),
417                 classFileVersion,
418                 auxiliaryTypeNamingStrategy,
419                 annotationValueFilterFactory,
420                 annotationRetention,
421                 implementationContextFactory,
422                 methodGraphCompiler,
423                 typeValidation,
424                 visibilityBridgeStrategy,
425                 classWriterStrategy,
426                 ignoredMethods,
427                 constructorStrategy);
428     }
429
430     /**
431      * <p>
432      * Creates a new, plain interface type.
433      * </p>
434      * <p>
435      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
436      * types, a external cache or {@link TypeCache} should be used.
437      * </p>
438      *
439      * @return A type builder that creates a new interface type.
440      */

441     public DynamicType.Builder<?> makeInterface() {
442         return makeInterface(Collections.<TypeDescription>emptyList());
443     }
444
445     /**
446      * <p>
447      * Creates a new interface type that extends the provided interface.
448      * </p>
449      * <p>
450      * <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
451      * </p>
452      * <p>
453      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
454      * types, a external cache or {@link TypeCache} should be used.
455      * </p>
456      *
457      * @param interfaceType An interface type that the generated interface implements.
458      * @param <T>           A loaded type that the generated interface is guaranteed to inherit.
459      * @return A type builder that creates a new interface type.
460      */

461     @SuppressWarnings("unchecked")
462     public <T> DynamicType.Builder<T> makeInterface(Class<T> interfaceType) {
463         return (DynamicType.Builder<T>) makeInterface(Collections.<Type>singletonList(interfaceType));
464     }
465
466     /**
467      * <p>
468      * Creates a new interface type that extends the provided interface.
469      * </p>
470      * <p>
471      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
472      * as raw types if they declare type variables or an owner type.
473      * </p>
474      * <p>
475      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
476      * types, a external cache or {@link TypeCache} should be used.
477      * </p>
478      *
479      * @param interfaceType The interface types to implement. The types must be raw or parameterized types. All type
480      *                      variables that are referenced by a parameterized type must be declared by the generated
481      *                      subclass before creating the type.
482      * @return A type builder that creates a new interface type.
483      */

484     public DynamicType.Builder<?> makeInterface(Type... interfaceType) {
485         return makeInterface(Arrays.asList(interfaceType));
486     }
487
488     /**
489      * <p>
490      * Creates a new interface type that extends the provided interface.
491      * </p>
492      * <p>
493      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
494      * as raw types if they declare type variables or an owner type.
495      * </p>
496      * <p>
497      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
498      * types, a external cache or {@link TypeCache} should be used.
499      * </p>
500      *
501      * @param interfaceTypes The interface types to implement. The types must be raw or parameterized types. All
502      *                       type variables that are referenced by a parameterized type must be declared by the
503      *                       generated subclass before creating the type.
504      * @return A type builder that creates a new interface type.
505      */

506     public DynamicType.Builder<?> makeInterface(List<? extends Type> interfaceTypes) {
507         return makeInterface(new TypeList.Generic.ForLoadedTypes(interfaceTypes));
508     }
509
510     /**
511      * <p>
512      * Creates a new interface type that extends the provided interface.
513      * </p>
514      * <p>
515      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
516      * as raw types if they declare type variables or an owner type.
517      * </p>
518      * <p>
519      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
520      * types, a external cache or {@link TypeCache} should be used.
521      * </p>
522      *
523      * @param interfaceType The interface types to implement. The types must be raw or parameterized types. All
524      *                      type variables that are referenced by a parameterized type must be declared by the
525      *                      generated subclass before creating the type.
526      * @return A type builder that creates a new interface type.
527      */

528     public DynamicType.Builder<?> makeInterface(TypeDefinition... interfaceType) {
529         return makeInterface(Arrays.asList(interfaceType));
530     }
531
532     /**
533      * <p>
534      * Creates a new interface type that extends the provided interface.
535      * </p>
536      * <p>
537      * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
538      * as raw types if they declare type variables or an owner type.
539      * </p>
540      * <p>
541      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
542      * types, a external cache or {@link TypeCache} should be used.
543      * </p>
544      *
545      * @param interfaceTypes The interface types to implement. The types must be raw or parameterized types. All
546      *                       type variables that are referenced by a parameterized type must be declared by the
547      *                       generated subclass before creating the type.
548      * @return A type builder that creates a new interface type.
549      */

550     public DynamicType.Builder<?> makeInterface(Collection<? extends TypeDefinition> interfaceTypes) {
551         return subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS).implement(interfaceTypes).modifiers(TypeManifestation.INTERFACE, Visibility.PUBLIC);
552     }
553
554     /**
555      * <p>
556      * Creates a new package definition. Package definitions are defined by classes named {@code package-info}
557      * without any methods or fields but permit annotations. Any field or method definition will cause an
558      * {@link IllegalStateException} to be thrown when the type is created.
559      * </p>
560      * <p>
561      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
562      * types, a external cache or {@link TypeCache} should be used.
563      * </p>
564      *
565      * @param name The fully qualified name of the package.
566      * @return A type builder that creates a {@code package-info} class file.
567      */

568     public DynamicType.Builder<?> makePackage(String name) {
569         return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(name + "." + PackageDescription.PACKAGE_CLASS_NAME,
570                 PackageDescription.PACKAGE_MODIFIERS,
571                 TypeDescription.Generic.OBJECT),
572                 classFileVersion,
573                 auxiliaryTypeNamingStrategy,
574                 annotationValueFilterFactory,
575                 annotationRetention,
576                 implementationContextFactory,
577                 methodGraphCompiler,
578                 typeValidation,
579                 visibilityBridgeStrategy,
580                 classWriterStrategy,
581                 ignoredMethods,
582                 ConstructorStrategy.Default.NO_CONSTRUCTORS);
583     }
584
585     /**
586      * Creates a new Java record. This builder automatically defines fields for record members, standard accessors and a record constructor for any
587      * defined record component.
588      *
589      * @return A dynamic type builder that creates a record.
590      */

591     public DynamicType.Builder<?> makeRecord() {
592         TypeDescription.Generic record = InstrumentedType.Default.of(JavaType.RECORD.getTypeStub().getName(), TypeDescription.Generic.OBJECT, Visibility.PUBLIC)
593                 .withMethod(new MethodDescription.Token(Opcodes.ACC_PROTECTED))
594                 .withMethod(new MethodDescription.Token("hashCode",
595                         Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
596                         TypeDescription.ForLoadedType.of(int.class).asGenericType()))
597                 .withMethod(new MethodDescription.Token("equals",
598                         Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
599                         TypeDescription.ForLoadedType.of(boolean.class).asGenericType(),
600                         Collections.singletonList(TypeDescription.Generic.OBJECT)))
601                 .withMethod(new MethodDescription.Token("toString",
602                         Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
603                         TypeDescription.ForLoadedType.of(String.class).asGenericType()))
604                 .asGenericType();
605         return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(namingStrategy.subclass(record), Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, record).withRecord(true),
606                 classFileVersion,
607                 auxiliaryTypeNamingStrategy,
608                 annotationValueFilterFactory,
609                 annotationRetention,
610                 implementationContextFactory,
611                 methodGraphCompiler,
612                 typeValidation,
613                 visibilityBridgeStrategy,
614                 classWriterStrategy,
615                 ignoredMethods,
616                 RecordConstructorStrategy.INSTANCE)
617                 .method(isHashCode()).intercept(RecordObjectMethod.HASH_CODE)
618                 .method(isEquals()).intercept(RecordObjectMethod.EQUALS)
619                 .method(isToString()).intercept(RecordObjectMethod.TO_STRING);
620     }
621
622     /**
623      * <p>
624      * Creates a new {@link Annotation} type. Annotation properties are implemented as non-staticpublic methods with the
625      * property type being defined as the return type.
626      * </p>
627      * <p>
628      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
629      * types, a external cache or {@link TypeCache} should be used.
630      * </p>
631      *
632      * @return A type builder that creates a new {@link Annotation} type.
633      */

634     public DynamicType.Builder<? extends Annotation> makeAnnotation() {
635         return new SubclassDynamicTypeBuilder<Annotation>(instrumentedTypeFactory.subclass(namingStrategy.subclass(TypeDescription.Generic.ANNOTATION),
636                 ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.ANNOTATION).resolve(),
637                 TypeDescription.Generic.OBJECT).withInterfaces(new TypeList.Generic.Explicit(TypeDescription.Generic.ANNOTATION)),
638                 classFileVersion,
639                 auxiliaryTypeNamingStrategy,
640                 annotationValueFilterFactory,
641                 annotationRetention,
642                 implementationContextFactory,
643                 methodGraphCompiler,
644                 typeValidation,
645                 visibilityBridgeStrategy,
646                 classWriterStrategy,
647                 ignoredMethods,
648                 ConstructorStrategy.Default.NO_CONSTRUCTORS);
649     }
650
651     /**
652      * <p>
653      * Creates a new {@link Enum} type.
654      * </p>
655      * <p>
656      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
657      * types, a external cache or {@link TypeCache} should be used.
658      * </p>
659      *
660      * @param value The names of the type's enumeration constants
661      * @return A type builder for creating an enumeration type.
662      */

663     public DynamicType.Builder<? extends Enum<?>> makeEnumeration(String... value) {
664         return makeEnumeration(Arrays.asList(value));
665     }
666
667     /**
668      * <p>
669      * Creates a new {@link Enum} type.
670      * </p>
671      * <p>
672      * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
673      * types, a external cache or {@link TypeCache} should be used.
674      * </p>
675      *
676      * @param values The names of the type's enumeration constants
677      * @return A type builder for creating an enumeration type.
678      */

679     public DynamicType.Builder<? extends Enum<?>> makeEnumeration(Collection<? extends String> values) {
680         if (values.isEmpty()) {
681             throw new IllegalArgumentException("Require at least one enumeration constant");
682         }
683         TypeDescription.Generic enumType = TypeDescription.Generic.Builder.parameterizedType(Enum.class, TargetType.class).build();
684         return new SubclassDynamicTypeBuilder<Enum<?>>(instrumentedTypeFactory.subclass(namingStrategy.subclass(enumType),
685                 ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.FINAL, EnumerationState.ENUMERATION).resolve(),
686                 enumType),
687                 classFileVersion,
688                 auxiliaryTypeNamingStrategy,
689                 annotationValueFilterFactory,
690                 annotationRetention,
691                 implementationContextFactory,
692                 methodGraphCompiler,
693                 typeValidation,
694                 visibilityBridgeStrategy,
695                 classWriterStrategy,
696                 ignoredMethods,
697                 ConstructorStrategy.Default.NO_CONSTRUCTORS)
698                 .defineConstructor(Visibility.PRIVATE).withParameters(String.classint.class)
699                 .intercept(SuperMethodCall.INSTANCE)
700                 .defineMethod(EnumerationImplementation.ENUM_VALUE_OF_METHOD_NAME,
701                         TargetType.class,
702                         Visibility.PUBLIC, Ownership.STATIC).withParameters(String.class)
703                 .intercept(MethodCall.invoke(enumType.getDeclaredMethods()
704                         .filter(named(EnumerationImplementation.ENUM_VALUE_OF_METHOD_NAME).and(takesArguments(Class.class, String.class))).getOnly())
705                         .withOwnType().withArgument(0)
706                         .withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC))
707                 .defineMethod(EnumerationImplementation.ENUM_VALUES_METHOD_NAME,
708                         TargetType[].class,
709                         Visibility.PUBLIC, Ownership.STATIC)
710                 .intercept(new EnumerationImplementation(new ArrayList<String>(values)));
711     }
712
713     /**
714      * <p>
715      * Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
716      * by the new implementation.
717      * </p>
718      * <p>
719      * The class file of the redefined type is located by querying the redefined type's class loader by name. For specifying an
720      * alternative {@link ClassFileLocator}, use {@link ByteBuddy#redefine(Class, ClassFileLocator)}.
721      * </p>
722      * <p>
723      * <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link net.bytebuddy.dynamic.loading.ClassReloadingStrategy},
724      * it is important that no fields or methods are added to the redefined class. Note that some {@link Implementation}s implicitly add fields or methods.
725      * Finally, Byte Buddy might be forced to add a method if a redefined class already defines a class initializer. This can be disabled by setting
726      * {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link net.bytebuddy.implementation.Implementation.Context.Disabled.Factory}
727      * where the class initializer is retained <i>as is</i>.
728      * </p>
729      *
730      * @param type The type that is being redefined.
731      * @param <T>  The loaded type of the redefined type.
732      * @return A type builder for redefining the provided type.
733      */

734     public <T> DynamicType.Builder<T> redefine(Class<T> type) {
735         return redefine(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
736     }
737
738     /**
739      * <p>
740      * Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
741      * by the new implementation.
742      * </p>
743      * <p>
744      * <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link net.bytebuddy.dynamic.loading.ClassReloadingStrategy},
745      * it is important that no fields or methods are added to the redefined class. Note that some {@link Implementation}s implicitly add fields or methods.
746      * Finally, Byte Buddy might be forced to add a method if a redefined class already defines a class initializer. This can be disabled by setting
747      * {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link net.bytebuddy.implementation.Implementation.Context.Disabled.Factory}
748      * where the class initializer is retained <i>as is</i>.
749      * </p>
750      *
751      * @param type             The type that is being redefined.
752      * @param classFileLocator The class file locator that is queried for the redefined type's class file.
753      * @param <T>              The loaded type of the redefined type.
754      * @return A type builder for redefining the provided type.
755      */

756     public <T> DynamicType.Builder<T> redefine(Class<T> type, ClassFileLocator classFileLocator) {
757         return redefine(TypeDescription.ForLoadedType.of(type), classFileLocator);
758     }
759
760     /**
761      * <p>
762      * Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
763      * by the new implementation.
764      * </p>
765      * <p>
766      * <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link net.bytebuddy.dynamic.loading.ClassReloadingStrategy},
767      * it is important that no fields or methods are added to the redefined class. Note that some {@link Implementation}s implicitly add fields or methods.
768      * Finally, Byte Buddy might be forced to add a method if a redefined class already defines a class initializer. This can be disabled by setting
769      * {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link net.bytebuddy.implementation.Implementation.Context.Disabled.Factory}
770      * where the class initializer is retained <i>as is</i>.
771      * </p>
772      *
773      * @param type             The type that is being redefined.
774      * @param classFileLocator The class file locator that is queried for the redefined type's class file.
775      * @param <T>              The loaded type of the redefined type.
776      * @return A type builder for redefining the provided type.
777      */

778     public <T> DynamicType.Builder<T> redefine(TypeDescription type, ClassFileLocator classFileLocator) {
779         if (type.isArray() || type.isPrimitive()) {
780             throw new IllegalArgumentException("Cannot redefine array or primitive type: " + type);
781         }
782         return new RedefinitionDynamicTypeBuilder<T>(instrumentedTypeFactory.represent(type),
783                 classFileVersion,
784                 auxiliaryTypeNamingStrategy,
785                 annotationValueFilterFactory,
786                 annotationRetention,
787                 implementationContextFactory,
788                 methodGraphCompiler,
789                 typeValidation,
790                 visibilityBridgeStrategy,
791                 classWriterStrategy,
792                 ignoredMethods,
793                 type,
794                 classFileLocator);
795     }
796
797     /**
798      * <p>
799      * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
800      * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
801      * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
802      * </p>
803      * <p>
804      * The class file of the rebased type is located by querying the rebased type's class loader by name. For specifying an
805      * alternative {@link ClassFileLocator}, use {@link ByteBuddy#redefine(Class, ClassFileLocator)}.
806      * </p>
807      *
808      * @param type The type that is being rebased.
809      * @param <T>  The loaded type of the rebased type.
810      * @return A type builder for rebasing the provided type.
811      */

812     public <T> DynamicType.Builder<T> rebase(Class<T> type) {
813         return rebase(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
814     }
815
816     /**
817      * <p>
818      * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
819      * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
820      * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
821      * </p>
822      * <p>
823      * When a method is rebased, the original method is copied into a new method with a different name. These names are
824      * generated automatically by Byte Buddy unless a {@link MethodNameTransformer} is specified explicitly.
825      * Use {@link ByteBuddy#rebase(Class, ClassFileLocator, MethodNameTransformer)} for doing so.
826      * </p>
827      *
828      * @param type             The type that is being rebased.
829      * @param classFileLocator The class file locator that is queried for the rebased type's class file.
830      * @param <T>              The loaded type of the rebased type.
831      * @return A type builder for rebasing the provided type.
832      */

833     public <T> DynamicType.Builder<T> rebase(Class<T> type, ClassFileLocator classFileLocator) {
834         return rebase(TypeDescription.ForLoadedType.of(type), classFileLocator);
835     }
836
837     /**
838      * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
839      * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
840      * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
841      *
842      * @param type                  The type that is being rebased.
843      * @param classFileLocator      The class file locator that is queried for the rebased type's class file.
844      * @param methodNameTransformer The method name transformer for renaming a method that is rebased.
845      * @param <T>                   The loaded type of the rebased type.
846      * @return A type builder for rebasing the provided type.
847      */

848     public <T> DynamicType.Builder<T> rebase(Class<T> type, ClassFileLocator classFileLocator, MethodNameTransformer methodNameTransformer) {
849         return rebase(TypeDescription.ForLoadedType.of(type), classFileLocator, methodNameTransformer);
850     }
851
852     /**
853      * <p>
854      * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
855      * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
856      * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
857      * </p>
858      * <p>
859      * When a method is rebased, the original method is copied into a new method with a different name. These names are
860      * generated automatically by Byte Buddy unless a {@link MethodNameTransformer} is specified explicitly.
861      * Use {@link ByteBuddy#rebase(TypeDescription, ClassFileLocator, MethodNameTransformer)} for doing so.
862      * </p>
863      *
864      * @param type             The type that is being rebased.
865      * @param classFileLocator The class file locator that is queried for the rebased type's class file.
866      * @param <T>              The loaded type of the rebased type.
867      * @return A type builder for rebasing the provided type.
868      */

869     public <T> DynamicType.Builder<T> rebase(TypeDescription type, ClassFileLocator classFileLocator) {
870         return rebase(type, classFileLocator, MethodNameTransformer.Suffixing.withRandomSuffix());
871     }
872
873     /**
874      * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
875      * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
876      * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
877      *
878      * @param type                  The type that is being rebased.
879      * @param classFileLocator      The class file locator that is queried for the rebased type's class file.
880      * @param methodNameTransformer The method name transformer for renaming a method that is rebased.
881      * @param <T>                   The loaded type of the rebased type.
882      * @return A type builder for rebasing the provided type.
883      */

884     public <T> DynamicType.Builder<T> rebase(TypeDescription type, ClassFileLocator classFileLocator, MethodNameTransformer methodNameTransformer) {
885         if (type.isArray() || type.isPrimitive()) {
886             throw new IllegalArgumentException("Cannot rebase array or primitive type: " + type);
887         }
888         return new RebaseDynamicTypeBuilder<T>(instrumentedTypeFactory.represent(type),
889                 classFileVersion,
890                 auxiliaryTypeNamingStrategy,
891                 annotationValueFilterFactory,
892                 annotationRetention,
893                 implementationContextFactory,
894                 methodGraphCompiler,
895                 typeValidation,
896                 visibilityBridgeStrategy,
897                 classWriterStrategy,
898                 ignoredMethods,
899                 type,
900                 classFileLocator,
901                 methodNameTransformer);
902     }
903
904     /**
905      * Rebases a package. This offers an opportunity to add annotations to the package definition. Packages are defined
906      * by classes named {@code package-info} without any methods or fields but permit annotations. Any field or method
907      * definition will cause an {@link IllegalStateException} to be thrown when the type is created.
908      *
909      * @param aPackage         The package that is being rebased.
910      * @param classFileLocator The class file locator to use for locating the package's class file.
911      * @return A type builder for rebasing the given package.
912      */

913     public DynamicType.Builder<?> rebase(Package aPackage, ClassFileLocator classFileLocator) {
914         return rebase(new PackageDescription.ForLoadedPackage(aPackage), classFileLocator);
915     }
916
917     /**
918      * Rebases a package. This offers an opportunity to add annotations to the package definition. Packages are defined
919      * by classes named {@code package-info} without any methods or fields but permit annotations. Any field or method
920      * definition will cause an {@link IllegalStateException} to be thrown when the type is created.
921      *
922      * @param aPackage         The package that is being rebased.
923      * @param classFileLocator The class file locator to use for locating the package's class file.
924      * @return A type builder for rebasing the given package.
925      */

926     public DynamicType.Builder<?> rebase(PackageDescription aPackage, ClassFileLocator classFileLocator) {
927         return rebase(new TypeDescription.ForPackageDescription(aPackage), classFileLocator);
928     }
929
930     /**
931      * <p>
932      * Decorates a type with {@link net.bytebuddy.asm.AsmVisitorWrapper} and allows adding attributes and annotations. A decoration does
933      * not allow for any standard transformations but can be used as a performance optimization compared to a redefinition, especially
934      * when implementing a Java agent that only applies ASM-based code changes.
935      * </p>
936      * <p>
937      * <b>Important</b>: Only use this mode to improve performance in a narrowly defined transformation. Using other features as those mentioned
938      * might result in an unexpected outcome of the transformation or error. Using decoration also requires the configuration of an
939      * {@link Implementation.Context.Factory} that does not attempt any type transformation.
940      * </p>
941      *
942      * @param type The type to decorate.
943      * @param <T>  The loaded type of the decorated type.
944      * @return A type builder for decorating the provided type.
945      */

946     public <T> DynamicType.Builder<T> decorate(Class<T> type) {
947         return decorate(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
948     }
949
950     /**
951      * <p>
952      * Decorates a type with {@link net.bytebuddy.asm.AsmVisitorWrapper} and allows adding attributes and annotations. A decoration does
953      * not allow for any standard transformations but can be used as a performance optimization compared to a redefinition, especially
954      * when implementing a Java agent that only applies ASM-based code changes.
955      * </p>
956      * <p>
957      * <b>Important</b>: Only use this mode to improve performance in a narrowly defined transformation. Using other features as those mentioned
958      * might result in an unexpected outcome of the transformation or error. Using decoration also requires the configuration of an
959      * {@link Implementation.Context.Factory} that does not attempt any type transformation.
960      * </p>
961      *
962      * @param type             The type to decorate.
963      * @param classFileLocator The class file locator to use.
964      * @param <T>              The loaded type of the decorated type.
965      * @return A type builder for decorating the provided type.
966      */

967     public <T> DynamicType.Builder<T> decorate(Class<T> type, ClassFileLocator classFileLocator) {
968         return decorate(TypeDescription.ForLoadedType.of(type), classFileLocator);
969     }
970
971     /**
972      * <p>
973      * Decorates a type with {@link net.bytebuddy.asm.AsmVisitorWrapper} and allows adding attributes and annotations. A decoration does
974      * not allow for any standard transformations but can be used as a performance optimization compared to a redefinition, especially
975      * when implementing a Java agent that only applies ASM-based code changes.
976      * </p>
977      * <p>
978      * <b>Important</b>: Only use this mode to improve performance in a narrowly defined transformation. Using other features as those mentioned
979      * might result in an unexpected outcome of the transformation or error. Using decoration also requires the configuration of an
980      * {@link Implementation.Context.Factory} that does not attempt any type transformation.
981      * </p>
982      *
983      * @param type             The type to decorate.
984      * @param classFileLocator The class file locator to use.
985      * @param <T>              The loaded type of the decorated type.
986      * @return A type builder for decorating the provided type.
987      */

988     public <T> DynamicType.Builder<T> decorate(TypeDescription type, ClassFileLocator classFileLocator) {
989         if (type.isArray() || type.isPrimitive()) {
990             throw new IllegalArgumentException("Cannot decorate array or primitive type: " + type);
991         }
992         return new DecoratingDynamicTypeBuilder<T>(type,
993                 classFileVersion,
994                 auxiliaryTypeNamingStrategy,
995                 annotationValueFilterFactory,
996                 annotationRetention,
997                 implementationContextFactory,
998                 methodGraphCompiler,
999                 typeValidation,
1000                 classWriterStrategy,
1001                 ignoredMethods,
1002                 classFileLocator);
1003     }
1004
1005     /**
1006      * Creates a new configuration where all class files that are not based on an existing class file are created
1007      * using the supplied class file version. When creating a Byte Buddy instance by {@link ByteBuddy#ByteBuddy()}, the class
1008      * file version is detected automatically. If the class file version is known before creating a Byte Buddy instance, the
1009      * {@link ByteBuddy#ByteBuddy(ClassFileVersion)} constructor should be used.
1010      *
1011      * @param classFileVersion The class file version to use for types that are not based on an existing class file.
1012      * @return A new Byte Buddy instance that uses the supplied class file version.
1013      */

1014     public ByteBuddy with(ClassFileVersion classFileVersion) {
1015         return new ByteBuddy(classFileVersion,
1016                 namingStrategy,
1017                 auxiliaryTypeNamingStrategy,
1018                 annotationValueFilterFactory,
1019                 annotationRetention,
1020                 implementationContextFactory,
1021                 methodGraphCompiler,
1022                 instrumentedTypeFactory,
1023                 typeValidation,
1024                 visibilityBridgeStrategy,
1025                 classWriterStrategy,
1026                 ignoredMethods);
1027     }
1028
1029     /**
1030      * Creates a new configuration where new types are named by applying the given naming strategy. By default, Byte Buddy
1031      * simply retains the name of rebased and redefined types but adds a random suffix to the name of created subclasses or
1032      * -interfaces. If a type is defined within the {@code java.*} namespace, Byte Buddy also adds a suffix to the generated
1033      * class because this namespace is only available for the bootstrap class loader.
1034      *
1035      * @param namingStrategy The naming strategy to apply when creating a new dynamic type.
1036      * @return A new Byte Buddy instance that uses the supplied naming strategy.
1037      */

1038     public ByteBuddy with(NamingStrategy namingStrategy) {
1039         return new ByteBuddy(classFileVersion,
1040                 namingStrategy,
1041                 auxiliaryTypeNamingStrategy,
1042                 annotationValueFilterFactory,
1043                 annotationRetention,
1044                 implementationContextFactory,
1045                 methodGraphCompiler,
1046                 instrumentedTypeFactory,
1047                 typeValidation,
1048                 visibilityBridgeStrategy,
1049                 classWriterStrategy,
1050                 ignoredMethods);
1051     }
1052
1053     /**
1054      * Creates a new configuration where auxiliary types are named by applying the given naming strategy. Auxiliary types
1055      * are helper types that might be required for implementing certain {@link Implementation}s. By default, Byte Buddy
1056      * adds a random suffix to the instrumented type's name when naming its auxiliary types.
1057      *
1058      * @param auxiliaryTypeNamingStrategy The naming strategy to apply when creating a new auxiliary type.
1059      * @return A new Byte Buddy instance that uses the supplied naming strategy for auxiliary types.
1060      */

1061     public ByteBuddy with(AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy) {
1062         return new ByteBuddy(classFileVersion,
1063                 namingStrategy,
1064                 auxiliaryTypeNamingStrategy,
1065                 annotationValueFilterFactory,
1066                 annotationRetention,
1067                 implementationContextFactory,
1068                 methodGraphCompiler,
1069                 instrumentedTypeFactory,
1070                 typeValidation,
1071                 visibilityBridgeStrategy,
1072                 classWriterStrategy,
1073                 ignoredMethods);
1074     }
1075
1076     /**
1077      * Creates a new configuration where annotation values are written according to the given filter factory. Using
1078      * a filter factory, it is for example possible not to include certain values into a class file such that the
1079      * runtime returns an annotation type's default value. By default, Byte Buddy includes all values into a class file,
1080      * also such values for which a default value exists.
1081      *
1082      * @param annotationValueFilterFactory The annotation value filter factory to use.
1083      * @return A new Byte Buddy instance that uses the supplied annotation value filter factory.
1084      */

1085     public ByteBuddy with(AnnotationValueFilter.Factory annotationValueFilterFactory) {
1086         return new ByteBuddy(classFileVersion,
1087                 namingStrategy,
1088                 auxiliaryTypeNamingStrategy,
1089                 annotationValueFilterFactory,
1090                 annotationRetention,
1091                 implementationContextFactory,
1092                 methodGraphCompiler,
1093                 instrumentedTypeFactory,
1094                 typeValidation,
1095                 visibilityBridgeStrategy,
1096                 classWriterStrategy,
1097                 ignoredMethods);
1098     }
1099
1100     /**
1101      * <p>
1102      * Creates a new configuration where annotations that are found in an existing class file are or are not preserved
1103      * in the format they are discovered, i.e. rewritten in the format they were already present in the class file.
1104      * By default, Byte Buddy retains annotations when a class is rebased or redefined.
1105      * </p>
1106      * <p>
1107      * <b>Warning</b>: Retaining annotations can cause problems when annotations of a field or method are added based
1108      * on the annotations of a matched method. Doing so, Byte Buddy might write the annotations of the field or method
1109      * explicitly to a class file while simultaneously retaining the existing annotation what results in duplicates.
1110      * When matching fields or methods while adding annotations, disabling annotation retention might be required.
1111      * </p>
1112      *
1113      * @param annotationRetention The annotation retention strategy to use.
1114      * @return A new Byte Buddy instance that uses the supplied annotation retention strategy.
1115      */

1116     public ByteBuddy with(AnnotationRetention annotationRetention) {
1117         return new ByteBuddy(classFileVersion,
1118                 namingStrategy,
1119                 auxiliaryTypeNamingStrategy,
1120                 annotationValueFilterFactory,
1121                 annotationRetention,
1122                 implementationContextFactory,
1123                 methodGraphCompiler,
1124                 instrumentedTypeFactory,
1125                 typeValidation,
1126                 visibilityBridgeStrategy,
1127                 classWriterStrategy,
1128                 ignoredMethods);
1129     }
1130
1131     /**
1132      * Creates a new configuration where the {@link net.bytebuddy.implementation.Implementation.Context} of any created
1133      * type is a product of the given implementation context factory. An implementation context might imply unwanted
1134      * side-effects, for example, the creation of an additional synthetic methods in order to support specific features
1135      * for realizing an {@link Implementation}. By default, Byte Buddy supplies a factory that enables all features. When
1136      * redefining a loaded class, it is however required by the JVM that no additional members are added such that a
1137      * {@link net.bytebuddy.implementation.Implementation.Context.Disabled} factory might be more appropriate.
1138      *
1139      * @param implementationContextFactory The implementation context factory to use for defining an instrumented type.
1140      * @return A new Byte Buddy instance that uses the supplied implementation context factory.
1141      */

1142     public ByteBuddy with(Implementation.Context.Factory implementationContextFactory) {
1143         return new ByteBuddy(classFileVersion,
1144                 namingStrategy,
1145                 auxiliaryTypeNamingStrategy,
1146                 annotationValueFilterFactory,
1147                 annotationRetention,
1148                 implementationContextFactory,
1149                 methodGraphCompiler,
1150                 instrumentedTypeFactory,
1151                 typeValidation,
1152                 visibilityBridgeStrategy,
1153                 classWriterStrategy,
1154                 ignoredMethods);
1155     }
1156
1157     /**
1158      * Creates a new configuration where the {@link MethodGraph.Compiler} is used for creating a {@link MethodGraph}
1159      * of the instrumented type. A method graph is a representation of a type's virtual methods, including all information
1160      * on bridge methods that are inserted by the Java compiler. Creating a method graph is a rather expensive operation
1161      * and more efficient strategies might exist for certain types or ava types that are created by alternative JVM
1162      * languages. By default, a general purpose method graph compiler is used that uses the information that is exposed
1163      * by the generic type information that is embedded in any class file.
1164      *
1165      * @param methodGraphCompiler The method graph compiler to use for analyzing the instrumented type.
1166      * @return A new Byte Buddy instance that uses the supplied method graph compiler.
1167      */

1168     public ByteBuddy with(MethodGraph.Compiler methodGraphCompiler) {
1169         return new ByteBuddy(classFileVersion,
1170                 namingStrategy,
1171                 auxiliaryTypeNamingStrategy,
1172                 annotationValueFilterFactory,
1173                 annotationRetention,
1174                 implementationContextFactory,
1175                 methodGraphCompiler,
1176                 instrumentedTypeFactory,
1177                 typeValidation,
1178                 visibilityBridgeStrategy,
1179                 classWriterStrategy,
1180                 ignoredMethods);
1181     }
1182
1183     /**
1184      * Configures Byte Buddy to use the specified factory for creating {@link InstrumentedType}s. Doing so, more efficient
1185      * representations can be chosen when only certain operations are required. By default, all operations are supported.
1186      *
1187      * @param instrumentedTypeFactory The factory to use when creating instrumented types.
1188      * @return A new Byte Buddy instance that uses the supplied factory for creating instrumented types.
1189      */

1190     public ByteBuddy with(InstrumentedType.Factory instrumentedTypeFactory) {
1191         return new ByteBuddy(classFileVersion,
1192                 namingStrategy,
1193                 auxiliaryTypeNamingStrategy,
1194                 annotationValueFilterFactory,
1195                 annotationRetention,
1196                 implementationContextFactory,
1197                 methodGraphCompiler,
1198                 instrumentedTypeFactory,
1199                 typeValidation,
1200                 visibilityBridgeStrategy,
1201                 classWriterStrategy,
1202                 ignoredMethods);
1203     }
1204
1205     /**
1206      * Creates a new configuration that applies the supplied type validation. By default, explicitly type validation is applied
1207      * by Byte Buddy but it might be disabled for performance reason or for voluntarily creating illegal types. The Java virtual
1208      * machine applies its own type validation where some {@link Error} is thrown if a type is invalid, while Byte Buddy throws
1209      * some {@link RuntimeException}.
1210      *
1211      * @param typeValidation The type validation to apply during type creation.
1212      * @return A new Byte Buddy instance that applies the supplied type validation.
1213      */

1214     public ByteBuddy with(TypeValidation typeValidation) {
1215         return new ByteBuddy(classFileVersion,
1216                 namingStrategy,
1217                 auxiliaryTypeNamingStrategy,
1218                 annotationValueFilterFactory,
1219                 annotationRetention,
1220                 implementationContextFactory,
1221                 methodGraphCompiler,
1222                 instrumentedTypeFactory,
1223                 typeValidation,
1224                 visibilityBridgeStrategy,
1225                 classWriterStrategy,
1226                 ignoredMethods);
1227     }
1228
1229     /**
1230      * Creates a new configuration that applies the supplied visibility bridge strategy. By default, visibility bridges
1231      * are create for all methods for which a visibility bridge is normally necessary.
1232      *
1233      * @param visibilityBridgeStrategy The visibility bridge strategy to apply.
1234      * @return A new Byte Buddy instance that applies the supplied visibility bridge strategy.
1235      */

1236     public ByteBuddy with(VisibilityBridgeStrategy visibilityBridgeStrategy) {
1237         return new ByteBuddy(classFileVersion,
1238                 namingStrategy,
1239                 auxiliaryTypeNamingStrategy,
1240                 annotationValueFilterFactory,
1241                 annotationRetention,
1242                 implementationContextFactory,
1243                 methodGraphCompiler,
1244                 instrumentedTypeFactory,
1245                 typeValidation,
1246                 visibilityBridgeStrategy,
1247                 classWriterStrategy,
1248                 ignoredMethods);
1249     }
1250
1251     /**
1252      * Creates a new configuration that applies the supplied class writer strategy. By default, the constant pool of redefined and retransformed
1253      * classes is retained as most changes are additive and this retention improves performance.
1254      *
1255      * @param classWriterStrategy The class writer strategy to apply during type creation.
1256      * @return A new Byte Buddy instance that applies the supplied class writer strategy.
1257      */

1258     public ByteBuddy with(ClassWriterStrategy classWriterStrategy) {
1259         return new ByteBuddy(classFileVersion,
1260                 namingStrategy,
1261                 auxiliaryTypeNamingStrategy,
1262                 annotationValueFilterFactory,
1263                 annotationRetention,
1264                 implementationContextFactory,
1265                 methodGraphCompiler,
1266                 instrumentedTypeFactory,
1267                 typeValidation,
1268                 visibilityBridgeStrategy,
1269                 classWriterStrategy,
1270                 ignoredMethods);
1271     }
1272
1273     /**
1274      * Creates a new configuration where any {@link MethodDescription} that matches the provided method matcher is excluded
1275      * from instrumentation. Any previous matcher for ignored methods is replaced. By default, Byte Buddy ignores any
1276      * synthetic method (bridge methods are handled automatically) and the {@link Object#finalize()} method.
1277      *
1278      * @param ignoredMethods A matcher for identifying methods to be excluded from instrumentation.
1279      * @return A new Byte Buddy instance that excludes any method from instrumentation if it is matched by the supplied matcher.
1280      */

1281     public ByteBuddy ignore(ElementMatcher<? super MethodDescription> ignoredMethods) {
1282         return ignore(new LatentMatcher.Resolved<MethodDescription>(ignoredMethods));
1283     }
1284
1285     /**
1286      * <p>
1287      * Creates a new configuration where any {@link MethodDescription} that matches the provided method matcher is excluded
1288      * from instrumentation. Any previous matcher for ignored methods is replaced. By default, Byte Buddy ignores any
1289      * synthetic method (bridge methods are handled automatically) and the {@link Object#finalize()} method. Using a latent
1290      * matcher gives opportunity to resolve an {@link ElementMatcher} based on the instrumented type before applying the matcher.
1291      * </p>
1292      *
1293      * @param ignoredMethods A matcher for identifying methods to be excluded from instrumentation.
1294      * @return A new Byte Buddy instance that excludes any method from instrumentation if it is matched by the supplied matcher.
1295      */

1296     public ByteBuddy ignore(LatentMatcher<? super MethodDescription> ignoredMethods) {
1297         return new ByteBuddy(classFileVersion,
1298                 namingStrategy,
1299                 auxiliaryTypeNamingStrategy,
1300                 annotationValueFilterFactory,
1301                 annotationRetention,
1302                 implementationContextFactory,
1303                 methodGraphCompiler,
1304                 instrumentedTypeFactory,
1305                 typeValidation,
1306                 visibilityBridgeStrategy,
1307                 classWriterStrategy,
1308                 ignoredMethods);
1309     }
1310
1311     /**
1312      * An implementation fo the {@code values} method of an enumeration type.
1313      */

1314     @HashCodeAndEqualsPlugin.Enhance
1315     protected static class EnumerationImplementation implements Implementation {
1316
1317         /**
1318          * The name of the {@link java.lang.Object#clone()} method.
1319          */

1320         protected static final String CLONE_METHOD_NAME = "clone";
1321
1322         /**
1323          * The name of the {@code valueOf} method that is defined for any enumeration.
1324          */

1325         protected static final String ENUM_VALUE_OF_METHOD_NAME = "valueOf";
1326
1327         /**
1328          * The name of the {@code values} method that is defined for any enumeration.
1329          */

1330         protected static final String ENUM_VALUES_METHOD_NAME = "values";
1331
1332         /**
1333          * The field modifiers to use for any field that is added to an enumeration.
1334          */

1335         private static final int ENUM_FIELD_MODIFIERS = Opcodes.ACC_FINAL | Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC;
1336
1337         /**
1338          * The name of the field containing an array of all enumeration values.
1339          */

1340         private static final String ENUM_VALUES = "$VALUES";
1341
1342         /**
1343          * The names of the enumerations to define for the enumeration.
1344          */

1345         private final List<String> values;
1346
1347         /**
1348          * Creates a new implementation of an enumeration type.
1349          *
1350          * @param values The values of the enumeration.
1351          */

1352         protected EnumerationImplementation(List<String> values) {
1353             this.values = values;
1354         }
1355
1356         /**
1357          * {@inheritDoc}
1358          */

1359         public InstrumentedType prepare(InstrumentedType instrumentedType) {
1360             for (String value : values) {
1361                 instrumentedType = instrumentedType.withField(new FieldDescription.Token(value,
1362                         ENUM_FIELD_MODIFIERS | Opcodes.ACC_ENUM,
1363                         TargetType.DESCRIPTION.asGenericType()));
1364             }
1365             return instrumentedType
1366                     .withField(new FieldDescription.Token(ENUM_VALUES,
1367                             ENUM_FIELD_MODIFIERS | Opcodes.ACC_SYNTHETIC,
1368                             TypeDescription.ArrayProjection.of(TargetType.DESCRIPTION).asGenericType()))
1369                     .withInitializer(new InitializationAppender(values));
1370         }
1371
1372         /**
1373          * {@inheritDoc}
1374          */

1375         public ByteCodeAppender appender(Target implementationTarget) {
1376             return new ValuesMethodAppender(implementationTarget.getInstrumentedType());
1377         }
1378
1379         /**
1380          * A byte code appender for the {@code values} method of any enumeration type.
1381          */

1382         @HashCodeAndEqualsPlugin.Enhance
1383         protected static class ValuesMethodAppender implements ByteCodeAppender {
1384
1385             /**
1386              * The instrumented enumeration type.
1387              */

1388             private final TypeDescription instrumentedType;
1389
1390             /**
1391              * Creates a new appender for the {@code values} method.
1392              *
1393              * @param instrumentedType The instrumented enumeration type.
1394              */

1395             protected ValuesMethodAppender(TypeDescription instrumentedType) {
1396                 this.instrumentedType = instrumentedType;
1397             }
1398
1399             /**
1400              * {@inheritDoc}
1401              */

1402             public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1403                 FieldDescription valuesField = instrumentedType.getDeclaredFields().filter(named(ENUM_VALUES)).getOnly();
1404                 MethodDescription cloneMethod = TypeDescription.Generic.OBJECT.getDeclaredMethods().filter(named(CLONE_METHOD_NAME)).getOnly();
1405                 return new Size(new StackManipulation.Compound(
1406                         FieldAccess.forField(valuesField).read(),
1407                         MethodInvocation.invoke(cloneMethod).virtual(valuesField.getType().asErasure()),
1408                         TypeCasting.to(valuesField.getType().asErasure()),
1409                         MethodReturn.REFERENCE
1410                 ).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
1411             }
1412         }
1413
1414         /**
1415          * A byte code appender for the type initializer of any enumeration type.
1416          */

1417         @HashCodeAndEqualsPlugin.Enhance
1418         protected static class InitializationAppender implements ByteCodeAppender {
1419
1420             /**
1421              * The values of the enumeration that is being created.
1422              */

1423             private final List<String> values;
1424
1425             /**
1426              * Creates an appender for an enumerations type initializer.
1427              *
1428              * @param values The values of the enumeration that is being created.
1429              */

1430             protected InitializationAppender(List<String> values) {
1431                 this.values = values;
1432             }
1433
1434             /**
1435              * {@inheritDoc}
1436              */

1437             public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1438                 TypeDescription instrumentedType = instrumentedMethod.getDeclaringType().asErasure();
1439                 MethodDescription enumConstructor = instrumentedType.getDeclaredMethods()
1440                         .filter(isConstructor().and(takesArguments(String.classint.class)))
1441                         .getOnly();
1442                 int ordinal = 0;
1443                 StackManipulation stackManipulation = StackManipulation.Trivial.INSTANCE;
1444                 List<FieldDescription> enumerationFields = new ArrayList<FieldDescription>(values.size());
1445                 for (String value : values) {
1446                     FieldDescription fieldDescription = instrumentedType.getDeclaredFields().filter(named(value)).getOnly();
1447                     stackManipulation = new StackManipulation.Compound(stackManipulation,
1448                             TypeCreation.of(instrumentedType),
1449                             Duplication.SINGLE,
1450                             new TextConstant(value),
1451                             IntegerConstant.forValue(ordinal++),
1452                             MethodInvocation.invoke(enumConstructor),
1453                             FieldAccess.forField(fieldDescription).write());
1454                     enumerationFields.add(fieldDescription);
1455                 }
1456                 List<StackManipulation> fieldGetters = new ArrayList<StackManipulation>(values.size());
1457                 for (FieldDescription fieldDescription : enumerationFields) {
1458                     fieldGetters.add(FieldAccess.forField(fieldDescription).read());
1459                 }
1460                 stackManipulation = new StackManipulation.Compound(
1461                         stackManipulation,
1462                         ArrayFactory.forType(instrumentedType.asGenericType()).withValues(fieldGetters),
1463                         FieldAccess.forField(instrumentedType.getDeclaredFields().filter(named(ENUM_VALUES)).getOnly()).write()
1464                 );
1465                 return new Size(stackManipulation.apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
1466             }
1467         }
1468     }
1469
1470     /**
1471      * A constructor strategy for implementing a Java record.
1472      */

1473     @HashCodeAndEqualsPlugin.Enhance
1474     protected enum RecordConstructorStrategy implements ConstructorStrategy, Implementation {
1475
1476         /**
1477          * The singleton instance.
1478          */

1479         INSTANCE;
1480
1481         /**
1482          * {@inheritDoc}
1483          */

1484         public List<MethodDescription.Token> extractConstructors(TypeDescription instrumentedType) {
1485             List<ParameterDescription.Token> tokens = new ArrayList<ParameterDescription.Token>(instrumentedType.getRecordComponents().size());
1486             for (RecordComponentDescription.InDefinedShape recordComponent : instrumentedType.getRecordComponents()) {
1487                 tokens.add(new ParameterDescription.Token(recordComponent.getType(),
1488                         recordComponent.getDeclaredAnnotations().filter(targetsElement(ElementType.CONSTRUCTOR))));
1489             }
1490             return Collections.singletonList(new MethodDescription.Token(MethodDescription.CONSTRUCTOR_INTERNAL_NAME,
1491                     Opcodes.ACC_PUBLIC,
1492                     Collections.<TypeVariableToken>emptyList(),
1493                     TypeDescription.Generic.VOID,
1494                     tokens,
1495                     Collections.<TypeDescription.Generic>emptyList(),
1496                     Collections.<AnnotationDescription>emptyList(),
1497                     AnnotationValue.UNDEFINED,
1498                     TypeDescription.Generic.UNDEFINED));
1499         }
1500
1501         /**
1502          * {@inheritDoc}
1503          */

1504         public MethodRegistry inject(TypeDescription instrumentedType, MethodRegistry methodRegistry) {
1505             return methodRegistry.prepend(new LatentMatcher.Resolved<MethodDescription>(isConstructor().and(takesGenericArguments(instrumentedType.getRecordComponents().asTypeList()))),
1506                     new MethodRegistry.Handler.ForImplementation(this),
1507                     MethodAttributeAppender.ForInstrumentedMethod.EXCLUDING_RECEIVER,
1508                     Transformer.ForMethod.NoOp.<MethodDescription>make());
1509         }
1510
1511         /**
1512          * {@inheritDoc}
1513          */

1514         public ByteCodeAppender appender(Target implementationTarget) {
1515             return new Appender(implementationTarget.getInstrumentedType());
1516         }
1517
1518         /**
1519          * {@inheritDoc}
1520          */

1521         public InstrumentedType prepare(InstrumentedType instrumentedType) {
1522             for (RecordComponentDescription.InDefinedShape recordComponent : instrumentedType.getRecordComponents()) {
1523                 instrumentedType = instrumentedType
1524                         .withField(new FieldDescription.Token(recordComponent.getActualName(),
1525                                 Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL,
1526                                 recordComponent.getType(),
1527                                 recordComponent.getDeclaredAnnotations().filter(targetsElement(ElementType.FIELD))))
1528                         .withMethod(new MethodDescription.Token(recordComponent.getActualName(),
1529                                 Opcodes.ACC_PUBLIC,
1530                                 Collections.<TypeVariableToken>emptyList(),
1531                                 recordComponent.getType(),
1532                                 Collections.<ParameterDescription.Token>emptyList(),
1533                                 Collections.<TypeDescription.Generic>emptyList(),
1534                                 recordComponent.getDeclaredAnnotations().filter(targetsElement(ElementType.METHOD)),
1535                                 AnnotationValue.UNDEFINED,
1536                                 TypeDescription.Generic.UNDEFINED));
1537             }
1538             return instrumentedType;
1539         }
1540
1541         /**
1542          * A byte code appender for accessors and the record constructor.
1543          */

1544         @HashCodeAndEqualsPlugin.Enhance
1545         protected static class Appender implements ByteCodeAppender {
1546
1547             /**
1548              * The instrumented type.
1549              */

1550             private final TypeDescription instrumentedType;
1551
1552             /**
1553              * Creates a new byte code appender for accessors and the record constructor.
1554              *
1555              * @param instrumentedType The instrumented type.
1556              */

1557             protected Appender(TypeDescription instrumentedType) {
1558                 this.instrumentedType = instrumentedType;
1559             }
1560
1561             /**
1562              * {@inheritDoc}
1563              */

1564             public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1565                 if (instrumentedMethod.isMethod()) {
1566                     return new Simple(
1567                             MethodVariableAccess.loadThis(),
1568                             FieldAccess.forField(instrumentedType.getDeclaredFields().filter(named(instrumentedMethod.getName())).getOnly()).read(),
1569                             MethodReturn.of(instrumentedMethod.getReturnType())
1570                     ).apply(methodVisitor, implementationContext, instrumentedMethod);
1571                 } else {
1572                     List<StackManipulation> stackManipulations = new ArrayList<StackManipulation>(instrumentedType.getRecordComponents().size() * 3 + 2);
1573                     stackManipulations.add(MethodVariableAccess.loadThis());
1574                     stackManipulations.add(MethodInvocation.invoke(new MethodDescription.Latent(JavaType.RECORD.getTypeStub(), new MethodDescription.Token(Opcodes.ACC_PUBLIC))));
1575                     int offset = 1;
1576                     for (RecordComponentDescription.InDefinedShape recordComponent : instrumentedType.getRecordComponents()) {
1577                         stackManipulations.add(MethodVariableAccess.loadThis());
1578                         stackManipulations.add(MethodVariableAccess.of(recordComponent.getType()).loadFrom(offset));
1579                         stackManipulations.add(FieldAccess.forField(instrumentedType.getDeclaredFields()
1580                                 .filter(named(recordComponent.getActualName()))
1581                                 .getOnly()).write());
1582                         offset += recordComponent.getType().getStackSize().getSize();
1583                     }
1584                     stackManipulations.add(MethodReturn.VOID);
1585                     return new Simple(stackManipulations).apply(methodVisitor, implementationContext, instrumentedMethod);
1586                 }
1587             }
1588         }
1589     }
1590
1591     /**
1592      * Implements the object methods of the Java record type.
1593      */

1594     @HashCodeAndEqualsPlugin.Enhance
1595     protected enum RecordObjectMethod implements Implementation {
1596
1597         /**
1598          * The {@code hashCode} method.
1599          */

1600         HASH_CODE("hashCode", StackManipulation.Trivial.INSTANCE, int.class),
1601
1602         /**
1603          * The {@code equals} method.
1604          */

1605         EQUALS("equals", MethodVariableAccess.REFERENCE.loadFrom(1), boolean.class, Object.class),
1606
1607         /**
1608          * The {@code toString} method.
1609          */

1610         TO_STRING("toString", StackManipulation.Trivial.INSTANCE, String.class);
1611
1612         /**
1613          * The method name.
1614          */

1615         private final String name;
1616
1617         /**
1618          * The stack manipulation to append to the arguments.
1619          */

1620         private final StackManipulation stackManipulation;
1621
1622         /**
1623          * The return type.
1624          */

1625         private final TypeDescription returnType;
1626
1627         /**
1628          * The arguments type.
1629          */

1630         private final List<? extends TypeDescription> arguments;
1631
1632         /**
1633          * Creates a new object method instance for a Java record.
1634          *
1635          * @param name              The method name.
1636          * @param stackManipulation The stack manipulation to append to the arguments.
1637          * @param returnType        The return type.
1638          * @param arguments         The arguments type.
1639          */

1640         RecordObjectMethod(String name, StackManipulation stackManipulation, Class<?> returnType, Class<?>... arguments) {
1641             this.name = name;
1642             this.stackManipulation = stackManipulation;
1643             this.returnType = TypeDescription.ForLoadedType.of(returnType);
1644             this.arguments = new TypeList.ForLoadedTypes(arguments);
1645         }
1646
1647         /**
1648          * {@inheritDoc}
1649          */

1650         public ByteCodeAppender appender(Target implementationTarget) {
1651             StringBuilder stringBuilder = new StringBuilder();
1652             List<Object> methodHandles = new ArrayList<Object>(implementationTarget.getInstrumentedType().getRecordComponents().size());
1653             for (RecordComponentDescription.InDefinedShape recordComponent : implementationTarget.getInstrumentedType().getRecordComponents()) {
1654                 if (stringBuilder.length() > 0) {
1655                     stringBuilder.append(";");
1656                 }
1657                 stringBuilder.append(recordComponent.getActualName());
1658                 methodHandles.add(JavaConstant.MethodHandle.ofGetter(implementationTarget.getInstrumentedType().getDeclaredFields()
1659                         .filter(named(recordComponent.getActualName()))
1660                         .getOnly()).asConstantPoolValue());
1661             }
1662             return new ByteCodeAppender.Simple(MethodVariableAccess.loadThis(),
1663                     stackManipulation,
1664                     MethodInvocation.invoke(new MethodDescription.Latent(JavaType.OBJECT_METHODS.getTypeStub(), new MethodDescription.Token("bootstrap",
1665                             Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
1666                             TypeDescription.Generic.OBJECT,
1667                             Arrays.asList(JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().asGenericType(),
1668                                     TypeDescription.STRING.asGenericType(),
1669                                     JavaType.TYPE_DESCRIPTOR.getTypeStub().asGenericType(),
1670                                     TypeDescription.CLASS.asGenericType(),
1671                                     TypeDescription.STRING.asGenericType(),
1672                                     TypeDescription.ArrayProjection.of(JavaType.METHOD_HANDLE.getTypeStub()).asGenericType())))).dynamic(name,
1673                             returnType,
1674                             CompoundList.of(implementationTarget.getInstrumentedType(), arguments),
1675                             CompoundList.of(Arrays.asList(net.bytebuddy.jar.asm.Type.getType(implementationTarget.getInstrumentedType().getDescriptor()), stringBuilder.toString()), methodHandles)),
1676                     MethodReturn.of(returnType));
1677         }
1678
1679         /**
1680          * {@inheritDoc}
1681          */

1682         public InstrumentedType prepare(InstrumentedType instrumentedType) {
1683             return instrumentedType;
1684         }
1685     }
1686 }
1687