• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

raphw / byte-buddy / #801

27 Oct 2025 09:37AM UTC coverage: 84.715% (-0.4%) from 85.118%
#801

push

raphw
Fix imports.

29586 of 34924 relevant lines covered (84.72%)

0.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.88
/byte-buddy-dep/src/main/java/net/bytebuddy/ByteBuddy.java
1
/*
2
 * Copyright 2014 - Present 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.AccessControllerPlugin;
19
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
20
import net.bytebuddy.description.annotation.AnnotationDescription;
21
import net.bytebuddy.description.annotation.AnnotationValue;
22
import net.bytebuddy.description.field.FieldDescription;
23
import net.bytebuddy.description.method.MethodDescription;
24
import net.bytebuddy.description.method.ParameterDescription;
25
import net.bytebuddy.description.modifier.EnumerationState;
26
import net.bytebuddy.description.modifier.ModifierContributor;
27
import net.bytebuddy.description.modifier.Ownership;
28
import net.bytebuddy.description.modifier.TypeManifestation;
29
import net.bytebuddy.description.modifier.Visibility;
30
import net.bytebuddy.description.type.PackageDescription;
31
import net.bytebuddy.description.type.RecordComponentDescription;
32
import net.bytebuddy.description.type.TypeDefinition;
33
import net.bytebuddy.description.type.TypeDescription;
34
import net.bytebuddy.description.type.TypeList;
35
import net.bytebuddy.description.type.TypeVariableToken;
36
import net.bytebuddy.dynamic.ClassFileLocator;
37
import net.bytebuddy.dynamic.DynamicType;
38
import net.bytebuddy.dynamic.TargetType;
39
import net.bytebuddy.dynamic.Transformer;
40
import net.bytebuddy.dynamic.VisibilityBridgeStrategy;
41
import net.bytebuddy.dynamic.scaffold.ClassWriterStrategy;
42
import net.bytebuddy.dynamic.scaffold.InstrumentedType;
43
import net.bytebuddy.dynamic.scaffold.MethodGraph;
44
import net.bytebuddy.dynamic.scaffold.MethodRegistry;
45
import net.bytebuddy.dynamic.scaffold.TypeValidation;
46
import net.bytebuddy.dynamic.scaffold.inline.DecoratingDynamicTypeBuilder;
47
import net.bytebuddy.dynamic.scaffold.inline.MethodNameTransformer;
48
import net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder;
49
import net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder;
50
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
51
import net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder;
52
import net.bytebuddy.implementation.Implementation;
53
import net.bytebuddy.implementation.MethodCall;
54
import net.bytebuddy.implementation.SuperMethodCall;
55
import net.bytebuddy.implementation.attribute.AnnotationRetention;
56
import net.bytebuddy.implementation.attribute.AnnotationValueFilter;
57
import net.bytebuddy.implementation.attribute.MethodAttributeAppender;
58
import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
59
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
60
import net.bytebuddy.implementation.bytecode.Duplication;
61
import net.bytebuddy.implementation.bytecode.StackManipulation;
62
import net.bytebuddy.implementation.bytecode.TypeCreation;
63
import net.bytebuddy.implementation.bytecode.assign.Assigner;
64
import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
65
import net.bytebuddy.implementation.bytecode.collection.ArrayFactory;
66
import net.bytebuddy.implementation.bytecode.constant.IntegerConstant;
67
import net.bytebuddy.implementation.bytecode.constant.TextConstant;
68
import net.bytebuddy.implementation.bytecode.member.FieldAccess;
69
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
70
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
71
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
72
import net.bytebuddy.matcher.ElementMatcher;
73
import net.bytebuddy.matcher.LatentMatcher;
74
import net.bytebuddy.utility.AsmClassReader;
75
import net.bytebuddy.utility.AsmClassWriter;
76
import net.bytebuddy.utility.CompoundList;
77
import net.bytebuddy.utility.GraalImageCode;
78
import net.bytebuddy.utility.JavaConstant;
79
import net.bytebuddy.utility.JavaType;
80
import net.bytebuddy.utility.RandomString;
81
import net.bytebuddy.utility.nullability.MaybeNull;
82
import net.bytebuddy.utility.privilege.GetSystemPropertyAction;
83
import org.objectweb.asm.MethodVisitor;
84
import org.objectweb.asm.Opcodes;
85

86
import java.lang.annotation.Annotation;
87
import java.lang.annotation.ElementType;
88
import java.lang.reflect.Type;
89
import java.security.PrivilegedAction;
90
import java.util.ArrayList;
91
import java.util.Arrays;
92
import java.util.Collection;
93
import java.util.Collections;
94
import java.util.List;
95
import java.util.Random;
96

97
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
98
import static net.bytebuddy.matcher.ElementMatchers.isDefaultFinalizer;
99
import static net.bytebuddy.matcher.ElementMatchers.isEquals;
100
import static net.bytebuddy.matcher.ElementMatchers.isHashCode;
101
import static net.bytebuddy.matcher.ElementMatchers.isSynthetic;
102
import static net.bytebuddy.matcher.ElementMatchers.isToString;
103
import static net.bytebuddy.matcher.ElementMatchers.named;
104
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
105
import static net.bytebuddy.matcher.ElementMatchers.takesGenericArguments;
106
import static net.bytebuddy.matcher.ElementMatchers.targetsElement;
107

108
/**
109
 * Instances of this class serve as a focus point for configuration of the library's behavior and as an entry point
110
 * to any form of code generation using the library. For this purpose, Byte Buddy offers a fluent API which allows
111
 * for the step-wise generation of a new Java type. A type is generated either by:
112
 * <ul>
113
 * <li><b>Subclassing</b> some type: A subclass - as the name suggests - extends another, existing Java type. Virtual
114
 * members of the generated type's super types can be overridden. Subclasses can also be interface extensions of one
115
 * or several interfaces.</li>
116
 * <li><b>Redefining</b> a type: By redefining a type, it is not only possible to override virtual methods of the
117
 * redefined type but also to redefine existing methods. This way, it is also possible to change the behavior of
118
 * non-virtual methods and constructors of the redefined type.</li>
119
 * <li><b>Rebasing</b> a type: Rebasing a type works similar to creating a subclass, i.e. any method being overridden
120
 * is still capable of invoking any original code of the rebased type. Any rebased method is however inlined into the
121
 * rebased type and any original code is preserved automatically. This way, the type's identity does not change.</li>
122
 * </ul>
123
 * Byte Buddy's API does not change when a type is rebased, redefined or subclassed. All types are created via the
124
 * {@link net.bytebuddy.dynamic.DynamicType.Builder} interface. Byte Buddy's API is expressed by fully immutable
125
 * components and is therefore thread-safe. As a consequence, method calls must be chained for all of Byte Buddy's
126
 * component, e.g. a method call like the following has no effect:
127
 * <pre>
128
 * ByteBuddy byteBuddy = new ByteBuddy();
129
 * byteBuddy.foo()</pre>
130
 * Instead, the following method chain is correct use of the API:
131
 * <pre>
132
 * ByteBuddy byteBuddy = new ByteBuddy().foo();</pre>
133
 * <p>
134
 * For the creation of Java agents, Byte Buddy offers a convenience API implemented by the
135
 * {@link net.bytebuddy.agent.builder.AgentBuilder}. The API wraps a {@link ByteBuddy} instance and offers agent-specific
136
 * configuration opportunities by integrating against the {@link java.lang.instrument.Instrumentation} API.
137
 * </p>
138
 *
139
 * @see net.bytebuddy.agent.builder.AgentBuilder
140
 */
141
@HashCodeAndEqualsPlugin.Enhance
142
public class ByteBuddy {
143

144
    /**
145
     * A property that controls the default naming strategy. If not set, Byte Buddy is generating
146
     * random names for types that are not named explicitly. If set to {@code fixed}, Byte Buddy is
147
     * setting names deterministically without any random element, or to {@code caller}, if a name
148
     * should be fixed but contain the name of the caller class and method. If set to a numeric
149
     * value, Byte Buddy is generating random names, using the number as a seed.
150
     */
151
    public static final String DEFAULT_NAMING_PROPERTY = "net.bytebuddy.naming";
152

153
    /**
154
     * A property that controls the default type validation applied by Byte Buddy. If not set,
155
     * and if not otherwise configured by the user, types will be explicitly validated to
156
     * supply better error messages.
157
     */
158
    public static final String DEFAULT_VALIDATION_PROPERTY = "net.bytebuddy.validation";
159

160
    /**
161
     * The default prefix for the default {@link net.bytebuddy.NamingStrategy}.
162
     */
163
    private static final String BYTE_BUDDY_DEFAULT_PREFIX = "ByteBuddy";
164

165
    /**
166
     * The default suffix when defining a {@link AuxiliaryType.NamingStrategy}.
167
     */
168
    private static final String BYTE_BUDDY_DEFAULT_SUFFIX = "auxiliary";
169

170
    /**
171
     * The default name of a fixed context name for synthetic fields and methods.
172
     */
173
    private static final String BYTE_BUDDY_DEFAULT_CONTEXT_NAME = "synthetic";
174

175
    /**
176
     * The default type validation to apply.
177
     */
178
    private static final TypeValidation DEFAULT_TYPE_VALIDATION;
179

180
    /**
181
     * The default naming strategy or {@code null} if no such strategy is set.
182
     */
183
    @MaybeNull
184
    private static final NamingStrategy DEFAULT_NAMING_STRATEGY;
185

186
    /**
187
     * The default auxiliary naming strategy or {@code null} if no such strategy is set.
188
     */
189
    @MaybeNull
190
    private static final AuxiliaryType.NamingStrategy DEFAULT_AUXILIARY_NAMING_STRATEGY;
191

192
    /**
193
     * The default implementation context factory or {@code null} if no such factory is set.
194
     */
195
    @MaybeNull
196
    private static final Implementation.Context.Factory DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY;
197

198
    /*
199
     * Resolves the default naming strategy.
200
     */
201
    static {
202
        String validation;
203
        try {
204
            validation = doPrivileged(new GetSystemPropertyAction(DEFAULT_VALIDATION_PROPERTY));
1✔
205
        } catch (Throwable ignored) {
×
206
            validation = null;
×
207
        }
1✔
208
        DEFAULT_TYPE_VALIDATION = validation == null || Boolean.parseBoolean(validation)
1✔
209
                ? TypeValidation.ENABLED
210
                : TypeValidation.DISABLED;
211
        String naming;
212
        try {
213
            naming = doPrivileged(new GetSystemPropertyAction(DEFAULT_NAMING_PROPERTY));
1✔
214
        } catch (Throwable ignored) {
×
215
            naming = null;
×
216
        }
1✔
217
        NamingStrategy namingStrategy;
218
        AuxiliaryType.NamingStrategy auxiliaryNamingStrategy;
219
        Implementation.Context.Factory implementationContextFactory;
220
        if (naming == null) {
1✔
221
            if (GraalImageCode.getCurrent().isDefined()) {
1✔
222
                namingStrategy = new NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_PREFIX,
×
223
                        new NamingStrategy.Suffixing.BaseNameResolver.WithCallerSuffix(NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE),
224
                        NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE);
225
                auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
×
226
                implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
×
227
            } else {
228
                namingStrategy = null;
1✔
229
                auxiliaryNamingStrategy = null;
1✔
230
                implementationContextFactory = null;
1✔
231
            }
232
        } else if (naming.equalsIgnoreCase("fixed")) {
×
233
            namingStrategy = new NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_PREFIX,
×
234
                    NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE,
235
                    NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE);
236
            auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
×
237
            implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
×
238
        } else if (naming.equalsIgnoreCase("caller")) {
×
239
            namingStrategy = new NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_PREFIX,
×
240
                    new NamingStrategy.Suffixing.BaseNameResolver.WithCallerSuffix(NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE),
241
                    NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE);
242
            auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
×
243
            implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
×
244
        } else {
245
            long seed;
246
            try {
247
                seed = Long.parseLong(naming);
×
248
            } catch (Exception ignored) {
×
249
                throw new IllegalStateException("'net.bytebuddy.naming' is set to an unknown, non-numeric value: " + naming);
×
250
            }
×
251
            namingStrategy = new NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_PREFIX,
×
252
                    NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE,
253
                    NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE,
254
                    new RandomString(RandomString.DEFAULT_LENGTH, new Random(seed)));
255
            auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
×
256
            implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
×
257
        }
258
        DEFAULT_NAMING_STRATEGY = namingStrategy;
1✔
259
        DEFAULT_AUXILIARY_NAMING_STRATEGY = auxiliaryNamingStrategy;
1✔
260
        DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY = implementationContextFactory;
1✔
261
    }
1✔
262

263
    /**
264
     * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
265
     *
266
     * @param action The action to execute from a privileged context.
267
     * @param <T>    The type of the action's resolved value.
268
     * @return The action's resolved value.
269
     */
270
    @MaybeNull
271
    @AccessControllerPlugin.Enhance
272
    private static <T> T doPrivileged(PrivilegedAction<T> action) {
273
        return action.run();
×
274
    }
275

276
    /**
277
     * The class file version to use for types that are not based on an existing class file.
278
     */
279
    protected final ClassFileVersion classFileVersion;
280

281
    /**
282
     * The naming strategy to use.
283
     */
284
    protected final NamingStrategy namingStrategy;
285

286
    /**
287
     * The naming strategy to use for naming auxiliary types.
288
     */
289
    protected final AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy;
290

291
    /**
292
     * The annotation value filter factory to use.
293
     */
294
    protected final AnnotationValueFilter.Factory annotationValueFilterFactory;
295

296
    /**
297
     * The annotation retention strategy to use.
298
     */
299
    protected final AnnotationRetention annotationRetention;
300

301
    /**
302
     * The implementation context factory to use.
303
     */
304
    protected final Implementation.Context.Factory implementationContextFactory;
305

306
    /**
307
     * The method graph compiler to use.
308
     */
309
    protected final MethodGraph.Compiler methodGraphCompiler;
310

311
    /**
312
     * The instrumented type factory to use.
313
     */
314
    protected final InstrumentedType.Factory instrumentedTypeFactory;
315

316
    /**
317
     * A matcher for identifying methods that should be excluded from instrumentation.
318
     */
319
    protected final LatentMatcher<? super MethodDescription> ignoredMethods;
320

321
    /**
322
     * Determines if a type should be explicitly validated.
323
     */
324
    protected final TypeValidation typeValidation;
325

326
    /**
327
     * The visibility bridge strategy to apply.
328
     */
329
    protected final VisibilityBridgeStrategy visibilityBridgeStrategy;
330

331
    /**
332
     * The class reader factory to use.
333
     */
334
    protected final AsmClassReader.Factory classReaderFactory;
335

336
    /**
337
     * The class writer factory to use.
338
     */
339
    protected final AsmClassWriter.Factory classWriterFactory;
340

341
    /**
342
     * <p>
343
     * Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
344
     * </p>
345
     * <p>
346
     * When creating this configuration, Byte Buddy attempts to discover the current JVM's version. If this
347
     * is not possible, class files are created Java 6-compatible.
348
     * </p>
349
     *
350
     * @see ClassFileVersion#ofThisVm(ClassFileVersion)
351
     */
352
    public ByteBuddy() {
353
        this(ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5));
1✔
354
    }
1✔
355

356
    /**
357
     * Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
358
     *
359
     * @param classFileVersion The class file version to use for types that are not based on an existing class file.
360
     */
361
    public ByteBuddy(ClassFileVersion classFileVersion) {
362
        this(classFileVersion,
1✔
363
                DEFAULT_NAMING_STRATEGY == null
364
                        ? new NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_PREFIX)
365
                        : DEFAULT_NAMING_STRATEGY,
366
                DEFAULT_AUXILIARY_NAMING_STRATEGY == null
367
                        ? new AuxiliaryType.NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_SUFFIX)
368
                        : DEFAULT_AUXILIARY_NAMING_STRATEGY,
369
                AnnotationValueFilter.Default.APPEND_DEFAULTS,
370
                AnnotationRetention.ENABLED,
371
                DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY == null
372
                        ? Implementation.Context.Default.Factory.INSTANCE
373
                        : DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY,
374
                MethodGraph.Compiler.DEFAULT,
375
                InstrumentedType.Factory.Default.MODIFIABLE,
376
                DEFAULT_TYPE_VALIDATION,
377
                VisibilityBridgeStrategy.Default.ALWAYS,
378
                AsmClassReader.Factory.Default.IMPLICIT,
379
                AsmClassWriter.Factory.Default.IMPLICIT,
380
                new LatentMatcher.Resolved<MethodDescription>(isSynthetic().or(isDefaultFinalizer())));
1✔
381
    }
1✔
382

383
    /**
384
     * Creates a new Byte Buddy instance.
385
     *
386
     * @param classFileVersion             The class file version to use for types that are not based on an existing class file.
387
     * @param namingStrategy               The naming strategy to use.
388
     * @param auxiliaryTypeNamingStrategy  The naming strategy to use for naming auxiliary types.
389
     * @param annotationValueFilterFactory The annotation value filter factory to use.
390
     * @param annotationRetention          The annotation retention strategy to use.
391
     * @param implementationContextFactory The implementation context factory to use.
392
     * @param methodGraphCompiler          The method graph compiler to use.
393
     * @param instrumentedTypeFactory      The instrumented type factory to use.
394
     * @param typeValidation               Determines if a type should be explicitly validated.
395
     * @param visibilityBridgeStrategy     The visibility bridge strategy to apply.
396
     * @param classReaderFactory           The class reader factory to use.
397
     * @param classWriterFactory           The class writer factory to use.
398
     * @param ignoredMethods               A matcher for identifying methods that should be excluded from instrumentation.
399
     */
400
    protected ByteBuddy(ClassFileVersion classFileVersion,
401
                        NamingStrategy namingStrategy,
402
                        AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
403
                        AnnotationValueFilter.Factory annotationValueFilterFactory,
404
                        AnnotationRetention annotationRetention,
405
                        Implementation.Context.Factory implementationContextFactory,
406
                        MethodGraph.Compiler methodGraphCompiler,
407
                        InstrumentedType.Factory instrumentedTypeFactory,
408
                        TypeValidation typeValidation,
409
                        VisibilityBridgeStrategy visibilityBridgeStrategy,
410
                        AsmClassReader.Factory classReaderFactory,
411
                        AsmClassWriter.Factory classWriterFactory,
412
                        LatentMatcher<? super MethodDescription> ignoredMethods) {
1✔
413
        this.classFileVersion = classFileVersion;
1✔
414
        this.namingStrategy = namingStrategy;
1✔
415
        this.auxiliaryTypeNamingStrategy = auxiliaryTypeNamingStrategy;
1✔
416
        this.annotationValueFilterFactory = annotationValueFilterFactory;
1✔
417
        this.annotationRetention = annotationRetention;
1✔
418
        this.implementationContextFactory = implementationContextFactory;
1✔
419
        this.methodGraphCompiler = methodGraphCompiler;
1✔
420
        this.instrumentedTypeFactory = instrumentedTypeFactory;
1✔
421
        this.typeValidation = typeValidation;
1✔
422
        this.visibilityBridgeStrategy = visibilityBridgeStrategy;
1✔
423
        this.classReaderFactory = classReaderFactory;
1✔
424
        this.classWriterFactory = classWriterFactory;
1✔
425
        this.ignoredMethods = ignoredMethods;
1✔
426
    }
1✔
427

428
    /**
429
     * <p>
430
     * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
431
     * this interface type is created.
432
     * </p>
433
     * <p>
434
     * When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
435
     * to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
436
     * {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Class, ConstructorStrategy)}.
437
     * </p>
438
     * <p>
439
     * <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
440
     * </p>
441
     * <p>
442
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
443
     * types, a external cache or {@link TypeCache} should be used.
444
     * </p>
445
     *
446
     * @param superType The super class or interface type to extend.
447
     * @param <T>       A loaded type that the generated class is guaranteed to inherit.
448
     * @return A type builder for creating a new class extending the provided class or interface.
449
     */
450
    @SuppressWarnings("unchecked")
451
    public <T> DynamicType.Builder<T> subclass(Class<T> superType) {
452
        return (DynamicType.Builder<T>) subclass(TypeDescription.ForLoadedType.of(superType));
1✔
453
    }
454

455
    /**
456
     * <p>
457
     * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
458
     * this interface type is created.
459
     * </p>
460
     * <p>
461
     * <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
462
     * </p>
463
     * <p>
464
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
465
     * types, a external cache or {@link TypeCache} should be used.
466
     * </p>
467
     *
468
     * @param superType           The super class or interface type to extend.
469
     * @param constructorStrategy A constructor strategy that determines the
470
     * @param <T>                 A loaded type that the generated class is guaranteed to inherit.
471
     * @return A type builder for creating a new class extending the provided class or interface.
472
     */
473
    @SuppressWarnings("unchecked")
474
    public <T> DynamicType.Builder<T> subclass(Class<T> superType, ConstructorStrategy constructorStrategy) {
475
        return (DynamicType.Builder<T>) subclass(TypeDescription.ForLoadedType.of(superType), constructorStrategy);
1✔
476
    }
477

478
    /**
479
     * <p>
480
     * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
481
     * this interface type is created.
482
     * </p>
483
     * <p>
484
     * When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
485
     * to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
486
     * {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Type, ConstructorStrategy)}.
487
     * </p>
488
     * <p>
489
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
490
     * as raw types if they declare type variables.
491
     * </p>
492
     * <p>
493
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
494
     * types, a external cache or {@link TypeCache} should be used.
495
     * </p>
496
     *
497
     * @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
498
     *                  variables that are referenced by the generic type must be declared by the generated subclass before creating
499
     *                  the type.
500
     * @return A type builder for creating a new class extending the provided class or interface.
501
     */
502
    public DynamicType.Builder<?> subclass(Type superType) {
503
        return subclass(TypeDefinition.Sort.describe(superType));
×
504
    }
505

506
    /**
507
     * <p>
508
     * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
509
     * this interface type is created.
510
     * </p>
511
     * <p>
512
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
513
     * as raw types if they declare type variables.
514
     * </p>
515
     * <p>
516
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
517
     * types, a external cache or {@link TypeCache} should be used.
518
     * </p>
519
     *
520
     * @param superType           The super class or interface type to extend. The type must be a raw type or parameterized
521
     *                            type. All type variables that are referenced by the generic type must be declared by the
522
     *                            generated subclass before creating the type.
523
     * @param constructorStrategy A constructor strategy that determines the
524
     * @return A type builder for creating a new class extending the provided class or interface.
525
     */
526
    public DynamicType.Builder<?> subclass(Type superType, ConstructorStrategy constructorStrategy) {
527
        return subclass(TypeDefinition.Sort.describe(superType), constructorStrategy);
×
528
    }
529

530
    /**
531
     * <p>
532
     * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
533
     * this interface type is created.
534
     * </p>
535
     * <p>
536
     * When extending a class, Byte Buddy imitates all visible constructors of the subclassed type and sets them to be {@code public}.
537
     * Any constructor is implemented to only invoke its super type constructor of equal signature. Another behavior can be specified by
538
     * supplying an explicit {@link ConstructorStrategy} by {@link ByteBuddy#subclass(TypeDefinition, ConstructorStrategy)}.
539
     * </p>
540
     * <p>
541
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
542
     * as raw types if they declare type variables.
543
     * </p>
544
     * <p>
545
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
546
     * types, a external cache or {@link TypeCache} should be used.
547
     * </p>
548
     *
549
     * @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
550
     *                  variables that are referenced by the generic type must be declared by the generated subclass before creating
551
     *                  the type.
552
     * @return A type builder for creating a new class extending the provided class or interface.
553
     */
554
    public DynamicType.Builder<?> subclass(TypeDefinition superType) {
555
        return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING);
1✔
556
    }
557

558
    /**
559
     * <p>
560
     * Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
561
     * this interface type is created.
562
     * </p>
563
     * <p>
564
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
565
     * as raw types if they declare type variables.
566
     * </p>
567
     * <p>
568
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
569
     * types, a external cache or {@link TypeCache} should be used.
570
     * </p>
571
     *
572
     * @param superType           The super class or interface type to extend. The type must be a raw type or parameterized
573
     *                            type. All type variables that are referenced by the generic type must be declared by the
574
     *                            generated subclass before creating the type.
575
     * @param constructorStrategy A constructor strategy that determines the
576
     * @return A type builder for creating a new class extending the provided class or interface.
577
     */
578
    public DynamicType.Builder<?> subclass(TypeDefinition superType, ConstructorStrategy constructorStrategy) {
579
        TypeDescription.Generic actualSuperType;
580
        TypeList.Generic interfaceTypes;
581
        if (superType.isPrimitive() || superType.isArray() || superType.isFinal()) {
1✔
582
            throw new IllegalArgumentException("Cannot subclass primitive, array or final types: " + superType);
1✔
583
        } else if (superType.isInterface()) {
1✔
584
            actualSuperType = TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class);
1✔
585
            interfaceTypes = new TypeList.Generic.Explicit(superType);
1✔
586
        } else {
587
            actualSuperType = superType.asGenericType();
1✔
588
            interfaceTypes = new TypeList.Generic.Empty();
1✔
589
        }
590
        return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(namingStrategy.subclass(superType.asGenericType()),
1✔
591
                ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.PLAIN).resolve(superType.getModifiers()),
1✔
592
                actualSuperType).withInterfaces(interfaceTypes),
1✔
593
                classFileVersion,
594
                auxiliaryTypeNamingStrategy,
595
                annotationValueFilterFactory,
596
                annotationRetention,
597
                implementationContextFactory,
598
                methodGraphCompiler,
599
                typeValidation,
600
                visibilityBridgeStrategy,
601
                classReaderFactory,
602
                classWriterFactory,
603
                ignoredMethods,
604
                constructorStrategy);
605
    }
606

607
    /**
608
     * <p>
609
     * Creates a new, plain interface type.
610
     * </p>
611
     * <p>
612
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
613
     * types, a external cache or {@link TypeCache} should be used.
614
     * </p>
615
     *
616
     * @return A type builder that creates a new interface type.
617
     */
618
    public DynamicType.Builder<?> makeInterface() {
619
        return makeInterface(Collections.<TypeDescription>emptyList());
1✔
620
    }
621

622
    /**
623
     * <p>
624
     * Creates a new interface type that extends the provided interface.
625
     * </p>
626
     * <p>
627
     * <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
628
     * </p>
629
     * <p>
630
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
631
     * types, a external cache or {@link TypeCache} should be used.
632
     * </p>
633
     *
634
     * @param interfaceType An interface type that the generated interface implements.
635
     * @param <T>           A loaded type that the generated interface is guaranteed to inherit.
636
     * @return A type builder that creates a new interface type.
637
     */
638
    @SuppressWarnings("unchecked")
639
    public <T> DynamicType.Builder<T> makeInterface(Class<T> interfaceType) {
640
        return (DynamicType.Builder<T>) makeInterface(Collections.<Type>singletonList(interfaceType));
1✔
641
    }
642

643
    /**
644
     * <p>
645
     * Creates a new interface type that extends the provided interface.
646
     * </p>
647
     * <p>
648
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
649
     * as raw types if they declare type variables or an owner type.
650
     * </p>
651
     * <p>
652
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
653
     * types, a external cache or {@link TypeCache} should be used.
654
     * </p>
655
     *
656
     * @param interfaceType The interface types to implement. The types must be raw or parameterized types. All type
657
     *                      variables that are referenced by a parameterized type must be declared by the generated
658
     *                      subclass before creating the type.
659
     * @return A type builder that creates a new interface type.
660
     */
661
    public DynamicType.Builder<?> makeInterface(Type... interfaceType) {
662
        return makeInterface(Arrays.asList(interfaceType));
×
663
    }
664

665
    /**
666
     * <p>
667
     * Creates a new interface type that extends the provided interface.
668
     * </p>
669
     * <p>
670
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
671
     * as raw types if they declare type variables or an owner type.
672
     * </p>
673
     * <p>
674
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
675
     * types, a external cache or {@link TypeCache} should be used.
676
     * </p>
677
     *
678
     * @param interfaceTypes The interface types to implement. The types must be raw or parameterized types. All
679
     *                       type variables that are referenced by a parameterized type must be declared by the
680
     *                       generated subclass before creating the type.
681
     * @return A type builder that creates a new interface type.
682
     */
683
    public DynamicType.Builder<?> makeInterface(List<? extends Type> interfaceTypes) {
684
        return makeInterface(new TypeList.Generic.ForLoadedTypes(interfaceTypes));
1✔
685
    }
686

687
    /**
688
     * <p>
689
     * Creates a new interface type that extends the provided interface.
690
     * </p>
691
     * <p>
692
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
693
     * as raw types if they declare type variables or an owner type.
694
     * </p>
695
     * <p>
696
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
697
     * types, a external cache or {@link TypeCache} should be used.
698
     * </p>
699
     *
700
     * @param interfaceType The interface types to implement. The types must be raw or parameterized types. All
701
     *                      type variables that are referenced by a parameterized type must be declared by the
702
     *                      generated subclass before creating the type.
703
     * @return A type builder that creates a new interface type.
704
     */
705
    public DynamicType.Builder<?> makeInterface(TypeDefinition... interfaceType) {
706
        return makeInterface(Arrays.asList(interfaceType));
×
707
    }
708

709
    /**
710
     * <p>
711
     * Creates a new interface type that extends the provided interface.
712
     * </p>
713
     * <p>
714
     * <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
715
     * as raw types if they declare type variables or an owner type.
716
     * </p>
717
     * <p>
718
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
719
     * types, a external cache or {@link TypeCache} should be used.
720
     * </p>
721
     *
722
     * @param interfaceTypes The interface types to implement. The types must be raw or parameterized types. All
723
     *                       type variables that are referenced by a parameterized type must be declared by the
724
     *                       generated subclass before creating the type.
725
     * @return A type builder that creates a new interface type.
726
     */
727
    public DynamicType.Builder<?> makeInterface(Collection<? extends TypeDefinition> interfaceTypes) {
728
        return subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS).implement(interfaceTypes).modifiers(TypeManifestation.INTERFACE, Visibility.PUBLIC);
1✔
729
    }
730

731
    /**
732
     * <p>
733
     * Creates a new package definition. Package definitions are defined by classes named {@code package-info}
734
     * without any methods or fields but permit annotations. Any field or method definition will cause an
735
     * {@link IllegalStateException} to be thrown when the type is created.
736
     * </p>
737
     * <p>
738
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
739
     * types, a external cache or {@link TypeCache} should be used.
740
     * </p>
741
     *
742
     * @param name The fully qualified name of the package.
743
     * @return A type builder that creates a {@code package-info} class file.
744
     */
745
    public DynamicType.Builder<?> makePackage(String name) {
746
        return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(name + "." + PackageDescription.PACKAGE_CLASS_NAME,
1✔
747
                PackageDescription.PACKAGE_MODIFIERS,
748
                TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class)),
1✔
749
                classFileVersion,
750
                auxiliaryTypeNamingStrategy,
751
                annotationValueFilterFactory,
752
                annotationRetention,
753
                implementationContextFactory,
754
                methodGraphCompiler,
755
                typeValidation,
756
                visibilityBridgeStrategy,
757
                classReaderFactory,
758
                classWriterFactory,
759
                ignoredMethods,
760
                ConstructorStrategy.Default.NO_CONSTRUCTORS);
761
    }
762

763
    /**
764
     * Creates a new Java record. This builder automatically defines fields for record members, standard accessors and a record constructor for any
765
     * defined record component.
766
     *
767
     * @return A dynamic type builder that creates a record.
768
     */
769
    public DynamicType.Builder<?> makeRecord() {
770
        TypeDescription.Generic record = InstrumentedType.Default.of(JavaType.RECORD.getTypeStub().getName(), TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class), Visibility.PUBLIC)
1✔
771
                .withMethod(new MethodDescription.Token(Opcodes.ACC_PROTECTED))
1✔
772
                .withMethod(new MethodDescription.Token("hashCode",
1✔
773
                        Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
774
                        TypeDescription.ForLoadedType.of(int.class).asGenericType()))
1✔
775
                .withMethod(new MethodDescription.Token("equals",
1✔
776
                        Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
777
                        TypeDescription.ForLoadedType.of(boolean.class).asGenericType(),
1✔
778
                        Collections.singletonList(TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class))))
1✔
779
                .withMethod(new MethodDescription.Token("toString",
1✔
780
                        Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
781
                        TypeDescription.ForLoadedType.of(String.class).asGenericType()))
1✔
782
                .asGenericType();
1✔
783
        return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(namingStrategy.subclass(record), Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, record).withRecord(true),
1✔
784
                classFileVersion,
785
                auxiliaryTypeNamingStrategy,
786
                annotationValueFilterFactory,
787
                annotationRetention,
788
                implementationContextFactory,
789
                methodGraphCompiler,
790
                typeValidation,
791
                visibilityBridgeStrategy,
792
                classReaderFactory,
793
                classWriterFactory,
794
                ignoredMethods,
795
                RecordConstructorStrategy.INSTANCE)
796
                .method(isHashCode()).intercept(RecordObjectMethod.HASH_CODE)
1✔
797
                .method(isEquals()).intercept(RecordObjectMethod.EQUALS)
1✔
798
                .method(isToString()).intercept(RecordObjectMethod.TO_STRING);
1✔
799
    }
800

801
    /**
802
     * <p>
803
     * Creates a new {@link Annotation} type. Annotation properties are implemented as non-static, public methods with the
804
     * property type being defined as the return type.
805
     * </p>
806
     * <p>
807
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
808
     * types, a external cache or {@link TypeCache} should be used.
809
     * </p>
810
     *
811
     * @return A type builder that creates a new {@link Annotation} type.
812
     */
813
    public DynamicType.Builder<? extends Annotation> makeAnnotation() {
814
        return new SubclassDynamicTypeBuilder<Annotation>(instrumentedTypeFactory.subclass(namingStrategy.subclass(TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Annotation.class)),
1✔
815
                ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.ANNOTATION).resolve(),
1✔
816
                TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class)).withInterfaces(new TypeList.Generic.Explicit(TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Annotation.class))),
1✔
817
                classFileVersion,
818
                auxiliaryTypeNamingStrategy,
819
                annotationValueFilterFactory,
820
                annotationRetention,
821
                implementationContextFactory,
822
                methodGraphCompiler,
823
                typeValidation,
824
                visibilityBridgeStrategy,
825
                classReaderFactory,
826
                classWriterFactory,
827
                ignoredMethods,
828
                ConstructorStrategy.Default.NO_CONSTRUCTORS);
829
    }
830

831
    /**
832
     * <p>
833
     * Creates a new {@link Enum} type.
834
     * </p>
835
     * <p>
836
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
837
     * types, a external cache or {@link TypeCache} should be used.
838
     * </p>
839
     *
840
     * @param value The names of the type's enumeration constants
841
     * @return A type builder for creating an enumeration type.
842
     */
843
    public DynamicType.Builder<? extends Enum<?>> makeEnumeration(String... value) {
844
        return makeEnumeration(Arrays.asList(value));
1✔
845
    }
846

847
    /**
848
     * <p>
849
     * Creates a new {@link Enum} type.
850
     * </p>
851
     * <p>
852
     * <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
853
     * types, a external cache or {@link TypeCache} should be used.
854
     * </p>
855
     *
856
     * @param values The names of the type's enumeration constants
857
     * @return A type builder for creating an enumeration type.
858
     */
859
    public DynamicType.Builder<? extends Enum<?>> makeEnumeration(Collection<? extends String> values) {
860
        if (values.isEmpty()) {
1✔
861
            throw new IllegalArgumentException("Require at least one enumeration constant");
1✔
862
        }
863
        TypeDescription.Generic enumType = TypeDescription.Generic.Builder.parameterizedType(Enum.class, TargetType.class).build();
1✔
864
        return new SubclassDynamicTypeBuilder<Enum<?>>(instrumentedTypeFactory.subclass(namingStrategy.subclass(enumType),
1✔
865
                ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.FINAL, EnumerationState.ENUMERATION).resolve(),
1✔
866
                enumType),
867
                classFileVersion,
868
                auxiliaryTypeNamingStrategy,
869
                annotationValueFilterFactory,
870
                annotationRetention,
871
                implementationContextFactory,
872
                methodGraphCompiler,
873
                typeValidation,
874
                visibilityBridgeStrategy,
875
                classReaderFactory,
876
                classWriterFactory,
877
                ignoredMethods,
878
                ConstructorStrategy.Default.NO_CONSTRUCTORS)
879
                .defineConstructor(Visibility.PRIVATE).withParameters(String.class, int.class)
1✔
880
                .intercept(SuperMethodCall.INSTANCE)
1✔
881
                .defineMethod(EnumerationImplementation.ENUM_VALUE_OF_METHOD_NAME,
1✔
882
                        TargetType.class,
883
                        Visibility.PUBLIC, Ownership.STATIC).withParameters(String.class)
1✔
884
                .intercept(MethodCall.invoke(enumType.getDeclaredMethods()
1✔
885
                                .filter(named(EnumerationImplementation.ENUM_VALUE_OF_METHOD_NAME).and(takesArguments(Class.class, String.class))).getOnly())
1✔
886
                        .withOwnType().withArgument(0)
1✔
887
                        .withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC))
1✔
888
                .defineMethod(EnumerationImplementation.ENUM_VALUES_METHOD_NAME,
1✔
889
                        TargetType[].class,
890
                        Visibility.PUBLIC, Ownership.STATIC)
891
                .intercept(new EnumerationImplementation(new ArrayList<String>(values)));
1✔
892
    }
893

894
    /**
895
     * <p>
896
     * Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
897
     * by the new implementation.
898
     * </p>
899
     * <p>
900
     * The class file of the redefined type is located by querying the redefined type's class loader by name. For specifying an
901
     * alternative {@link ClassFileLocator}, use {@link ByteBuddy#redefine(Class, ClassFileLocator)}.
902
     * </p>
903
     * <p>
904
     * <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link net.bytebuddy.dynamic.loading.ClassReloadingStrategy},
905
     * 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.
906
     * 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
907
     * {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link net.bytebuddy.implementation.Implementation.Context.Disabled.Factory}
908
     * where the class initializer is retained <i>as is</i>.
909
     * </p>
910
     *
911
     * @param type The type that is being redefined.
912
     * @param <T>  The loaded type of the redefined type.
913
     * @return A type builder for redefining the provided type.
914
     */
915
    public <T> DynamicType.Builder<T> redefine(Class<T> type) {
916
        return redefine(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
1✔
917
    }
918

919
    /**
920
     * <p>
921
     * Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
922
     * by the new implementation.
923
     * </p>
924
     * <p>
925
     * <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link net.bytebuddy.dynamic.loading.ClassReloadingStrategy},
926
     * 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.
927
     * 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
928
     * {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link net.bytebuddy.implementation.Implementation.Context.Disabled.Factory}
929
     * where the class initializer is retained <i>as is</i>.
930
     * </p>
931
     *
932
     * @param type             The type that is being redefined.
933
     * @param classFileLocator The class file locator that is queried for the redefined type's class file.
934
     * @param <T>              The loaded type of the redefined type.
935
     * @return A type builder for redefining the provided type.
936
     */
937
    public <T> DynamicType.Builder<T> redefine(Class<T> type, ClassFileLocator classFileLocator) {
938
        return redefine(TypeDescription.ForLoadedType.of(type), classFileLocator);
1✔
939
    }
940

941
    /**
942
     * <p>
943
     * Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
944
     * by the new implementation.
945
     * </p>
946
     * <p>
947
     * <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link net.bytebuddy.dynamic.loading.ClassReloadingStrategy},
948
     * 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.
949
     * 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
950
     * {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link net.bytebuddy.implementation.Implementation.Context.Disabled.Factory}
951
     * where the class initializer is retained <i>as is</i>.
952
     * </p>
953
     *
954
     * @param type             The type that is being redefined.
955
     * @param classFileLocator The class file locator that is queried for the redefined type's class file.
956
     * @param <T>              The loaded type of the redefined type.
957
     * @return A type builder for redefining the provided type.
958
     */
959
    public <T> DynamicType.Builder<T> redefine(TypeDescription type, ClassFileLocator classFileLocator) {
960
        if (type.isArray() || type.isPrimitive()) {
1✔
961
            throw new IllegalArgumentException("Cannot redefine array or primitive type: " + type);
×
962
        }
963
        return new RedefinitionDynamicTypeBuilder<T>(instrumentedTypeFactory.represent(type),
1✔
964
                classFileVersion,
965
                auxiliaryTypeNamingStrategy,
966
                annotationValueFilterFactory,
967
                annotationRetention,
968
                implementationContextFactory,
969
                methodGraphCompiler,
970
                typeValidation,
971
                visibilityBridgeStrategy,
972
                classReaderFactory,
973
                classWriterFactory,
974
                ignoredMethods,
975
                type,
976
                classFileLocator);
977
    }
978

979
    /**
980
     * <p>
981
     * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
982
     * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
983
     * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
984
     * </p>
985
     * <p>
986
     * The class file of the rebased type is located by querying the rebased type's class loader by name. For specifying an
987
     * alternative {@link ClassFileLocator}, use {@link ByteBuddy#redefine(Class, ClassFileLocator)}.
988
     * </p>
989
     *
990
     * @param type The type that is being rebased.
991
     * @param <T>  The loaded type of the rebased type.
992
     * @return A type builder for rebasing the provided type.
993
     */
994
    public <T> DynamicType.Builder<T> rebase(Class<T> type) {
995
        return rebase(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
1✔
996
    }
997

998
    /**
999
     * <p>
1000
     * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
1001
     * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
1002
     * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
1003
     * </p>
1004
     * <p>
1005
     * When a method is rebased, the original method is copied into a new method with a different name. These names are
1006
     * generated automatically by Byte Buddy unless a {@link MethodNameTransformer} is specified explicitly.
1007
     * Use {@link ByteBuddy#rebase(Class, ClassFileLocator, MethodNameTransformer)} for doing so.
1008
     * </p>
1009
     *
1010
     * @param type             The type that is being rebased.
1011
     * @param classFileLocator The class file locator that is queried for the rebased type's class file.
1012
     * @param <T>              The loaded type of the rebased type.
1013
     * @return A type builder for rebasing the provided type.
1014
     */
1015
    public <T> DynamicType.Builder<T> rebase(Class<T> type, ClassFileLocator classFileLocator) {
1016
        return rebase(TypeDescription.ForLoadedType.of(type), classFileLocator);
1✔
1017
    }
1018

1019
    /**
1020
     * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
1021
     * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
1022
     * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
1023
     *
1024
     * @param type                  The type that is being rebased.
1025
     * @param classFileLocator      The class file locator that is queried for the rebased type's class file.
1026
     * @param methodNameTransformer The method name transformer for renaming a method that is rebased.
1027
     * @param <T>                   The loaded type of the rebased type.
1028
     * @return A type builder for rebasing the provided type.
1029
     */
1030
    public <T> DynamicType.Builder<T> rebase(Class<T> type, ClassFileLocator classFileLocator, MethodNameTransformer methodNameTransformer) {
1031
        return rebase(TypeDescription.ForLoadedType.of(type), classFileLocator, methodNameTransformer);
×
1032
    }
1033

1034
    /**
1035
     * <p>
1036
     * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
1037
     * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
1038
     * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
1039
     * </p>
1040
     * <p>
1041
     * When a method is rebased, the original method is copied into a new method with a different name. These names are
1042
     * generated automatically by Byte Buddy unless a {@link MethodNameTransformer} is specified explicitly.
1043
     * Use {@link ByteBuddy#rebase(TypeDescription, ClassFileLocator, MethodNameTransformer)} for doing so.
1044
     * </p>
1045
     *
1046
     * @param type             The type that is being rebased.
1047
     * @param classFileLocator The class file locator that is queried for the rebased type's class file.
1048
     * @param <T>              The loaded type of the rebased type.
1049
     * @return A type builder for rebasing the provided type.
1050
     */
1051
    public <T> DynamicType.Builder<T> rebase(TypeDescription type, ClassFileLocator classFileLocator) {
1052
        return rebase(type, classFileLocator, MethodNameTransformer.Suffixing.withRandomSuffix());
1✔
1053
    }
1054

1055
    /**
1056
     * Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
1057
     * rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
1058
     * type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
1059
     *
1060
     * @param type                  The type that is being rebased.
1061
     * @param classFileLocator      The class file locator that is queried for the rebased type's class file.
1062
     * @param methodNameTransformer The method name transformer for renaming a method that is rebased.
1063
     * @param <T>                   The loaded type of the rebased type.
1064
     * @return A type builder for rebasing the provided type.
1065
     */
1066
    public <T> DynamicType.Builder<T> rebase(TypeDescription type, ClassFileLocator classFileLocator, MethodNameTransformer methodNameTransformer) {
1067
        if (type.isArray() || type.isPrimitive()) {
1✔
1068
            throw new IllegalArgumentException("Cannot rebase array or primitive type: " + type);
×
1069
        }
1070
        return new RebaseDynamicTypeBuilder<T>(instrumentedTypeFactory.represent(type),
1✔
1071
                classFileVersion,
1072
                auxiliaryTypeNamingStrategy,
1073
                annotationValueFilterFactory,
1074
                annotationRetention,
1075
                implementationContextFactory,
1076
                methodGraphCompiler,
1077
                typeValidation,
1078
                visibilityBridgeStrategy,
1079
                classReaderFactory,
1080
                classWriterFactory,
1081
                ignoredMethods,
1082
                type,
1083
                classFileLocator,
1084
                methodNameTransformer);
1085
    }
1086

1087
    /**
1088
     * Rebases a package. This offers an opportunity to add annotations to the package definition. Packages are defined
1089
     * by classes named {@code package-info} without any methods or fields but permit annotations. Any field or method
1090
     * definition will cause an {@link IllegalStateException} to be thrown when the type is created.
1091
     *
1092
     * @param aPackage         The package that is being rebased.
1093
     * @param classFileLocator The class file locator to use for locating the package's class file.
1094
     * @return A type builder for rebasing the given package.
1095
     */
1096
    public DynamicType.Builder<?> rebase(Package aPackage, ClassFileLocator classFileLocator) {
1097
        return rebase(new PackageDescription.ForLoadedPackage(aPackage), classFileLocator);
1✔
1098
    }
1099

1100
    /**
1101
     * Rebases a package. This offers an opportunity to add annotations to the package definition. Packages are defined
1102
     * by classes named {@code package-info} without any methods or fields but permit annotations. Any field or method
1103
     * definition will cause an {@link IllegalStateException} to be thrown when the type is created.
1104
     *
1105
     * @param aPackage         The package that is being rebased.
1106
     * @param classFileLocator The class file locator to use for locating the package's class file.
1107
     * @return A type builder for rebasing the given package.
1108
     */
1109
    public DynamicType.Builder<?> rebase(PackageDescription aPackage, ClassFileLocator classFileLocator) {
1110
        return rebase(new TypeDescription.ForPackageDescription(aPackage), classFileLocator);
1✔
1111
    }
1112

1113
    /**
1114
     * <p>
1115
     * Decorates a type with {@link net.bytebuddy.asm.AsmVisitorWrapper} and allows adding attributes and annotations. A decoration does
1116
     * not allow for any standard transformations but can be used as a performance optimization compared to a redefinition, especially
1117
     * when implementing a Java agent that only applies ASM-based code changes.
1118
     * </p>
1119
     * <p>
1120
     * <b>Important</b>: Only use this mode to improve performance in a narrowly defined transformation. Using other features as those mentioned
1121
     * might result in an unexpected outcome of the transformation or error. Using decoration also requires the configuration of an
1122
     * {@link Implementation.Context.Factory} that does not attempt any type transformation.
1123
     * </p>
1124
     *
1125
     * @param type The type to decorate.
1126
     * @param <T>  The loaded type of the decorated type.
1127
     * @return A type builder for decorating the provided type.
1128
     */
1129
    public <T> DynamicType.Builder<T> decorate(Class<T> type) {
1130
        return decorate(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
1✔
1131
    }
1132

1133
    /**
1134
     * <p>
1135
     * Decorates a type with {@link net.bytebuddy.asm.AsmVisitorWrapper} and allows adding attributes and annotations. A decoration does
1136
     * not allow for any standard transformations but can be used as a performance optimization compared to a redefinition, especially
1137
     * when implementing a Java agent that only applies ASM-based code changes.
1138
     * </p>
1139
     * <p>
1140
     * <b>Important</b>: Only use this mode to improve performance in a narrowly defined transformation. Using other features as those mentioned
1141
     * might result in an unexpected outcome of the transformation or error. Using decoration also requires the configuration of an
1142
     * {@link Implementation.Context.Factory} that does not attempt any type transformation.
1143
     * </p>
1144
     *
1145
     * @param type             The type to decorate.
1146
     * @param classFileLocator The class file locator to use.
1147
     * @param <T>              The loaded type of the decorated type.
1148
     * @return A type builder for decorating the provided type.
1149
     */
1150
    public <T> DynamicType.Builder<T> decorate(Class<T> type, ClassFileLocator classFileLocator) {
1151
        return decorate(TypeDescription.ForLoadedType.of(type), classFileLocator);
1✔
1152
    }
1153

1154
    /**
1155
     * <p>
1156
     * Decorates a type with {@link net.bytebuddy.asm.AsmVisitorWrapper} and allows adding attributes and annotations. A decoration does
1157
     * not allow for any standard transformations but can be used as a performance optimization compared to a redefinition, especially
1158
     * when implementing a Java agent that only applies ASM-based code changes.
1159
     * </p>
1160
     * <p>
1161
     * <b>Important</b>: Only use this mode to improve performance in a narrowly defined transformation. Using other features as those mentioned
1162
     * might result in an unexpected outcome of the transformation or error. Using decoration also requires the configuration of an
1163
     * {@link Implementation.Context.Factory} that does not attempt any type transformation.
1164
     * </p>
1165
     *
1166
     * @param type             The type to decorate.
1167
     * @param classFileLocator The class file locator to use.
1168
     * @param <T>              The loaded type of the decorated type.
1169
     * @return A type builder for decorating the provided type.
1170
     */
1171
    public <T> DynamicType.Builder<T> decorate(TypeDescription type, ClassFileLocator classFileLocator) {
1172
        if (type.isArray() || type.isPrimitive()) {
1✔
1173
            throw new IllegalArgumentException("Cannot decorate array or primitive type: " + type);
×
1174
        }
1175
        return new DecoratingDynamicTypeBuilder<T>(type,
1✔
1176
                classFileVersion,
1177
                auxiliaryTypeNamingStrategy,
1178
                annotationValueFilterFactory,
1179
                annotationRetention,
1180
                implementationContextFactory,
1181
                methodGraphCompiler,
1182
                typeValidation,
1183
                classReaderFactory,
1184
                classWriterFactory,
1185
                ignoredMethods,
1186
                classFileLocator);
1187
    }
1188

1189
    /**
1190
     * Creates a new configuration where all class files that are not based on an existing class file are created
1191
     * using the supplied class file version. When creating a Byte Buddy instance by {@link ByteBuddy#ByteBuddy()}, the class
1192
     * file version is detected automatically. If the class file version is known before creating a Byte Buddy instance, the
1193
     * {@link ByteBuddy#ByteBuddy(ClassFileVersion)} constructor should be used.
1194
     *
1195
     * @param classFileVersion The class file version to use for types that are not based on an existing class file.
1196
     * @return A new Byte Buddy instance that uses the supplied class file version.
1197
     */
1198
    public ByteBuddy with(ClassFileVersion classFileVersion) {
1199
        return new ByteBuddy(classFileVersion,
×
1200
                namingStrategy,
1201
                auxiliaryTypeNamingStrategy,
1202
                annotationValueFilterFactory,
1203
                annotationRetention,
1204
                implementationContextFactory,
1205
                methodGraphCompiler,
1206
                instrumentedTypeFactory,
1207
                typeValidation,
1208
                visibilityBridgeStrategy,
1209
                classReaderFactory,
1210
                classWriterFactory,
1211
                ignoredMethods);
1212
    }
1213

1214
    /**
1215
     * Creates a new configuration where new types are named by applying the given naming strategy. By default, Byte Buddy
1216
     * simply retains the name of rebased and redefined types but adds a random suffix to the name of created subclasses or
1217
     * -interfaces. If a type is defined within the {@code java.*} namespace, Byte Buddy also adds a suffix to the generated
1218
     * class because this namespace is only available for the bootstrap class loader.
1219
     *
1220
     * @param namingStrategy The naming strategy to apply when creating a new dynamic type.
1221
     * @return A new Byte Buddy instance that uses the supplied naming strategy.
1222
     */
1223
    public ByteBuddy with(NamingStrategy namingStrategy) {
1224
        return new ByteBuddy(classFileVersion,
1✔
1225
                namingStrategy,
1226
                auxiliaryTypeNamingStrategy,
1227
                annotationValueFilterFactory,
1228
                annotationRetention,
1229
                implementationContextFactory,
1230
                methodGraphCompiler,
1231
                instrumentedTypeFactory,
1232
                typeValidation,
1233
                visibilityBridgeStrategy,
1234
                classReaderFactory,
1235
                classWriterFactory,
1236
                ignoredMethods);
1237
    }
1238

1239
    /**
1240
     * Creates a new configuration where auxiliary types are named by applying the given naming strategy. Auxiliary types
1241
     * are helper types that might be required for implementing certain {@link Implementation}s. By default, Byte Buddy
1242
     * adds a random suffix to the instrumented type's name when naming its auxiliary types.
1243
     *
1244
     * @param auxiliaryTypeNamingStrategy The naming strategy to apply when creating a new auxiliary type.
1245
     * @return A new Byte Buddy instance that uses the supplied naming strategy for auxiliary types.
1246
     */
1247
    public ByteBuddy with(AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy) {
1248
        return new ByteBuddy(classFileVersion,
×
1249
                namingStrategy,
1250
                auxiliaryTypeNamingStrategy,
1251
                annotationValueFilterFactory,
1252
                annotationRetention,
1253
                implementationContextFactory,
1254
                methodGraphCompiler,
1255
                instrumentedTypeFactory,
1256
                typeValidation,
1257
                visibilityBridgeStrategy,
1258
                classReaderFactory,
1259
                classWriterFactory,
1260
                ignoredMethods);
1261
    }
1262

1263
    /**
1264
     * Creates a new configuration where annotation values are written according to the given filter factory. Using
1265
     * a filter factory, it is for example possible not to include certain values into a class file such that the
1266
     * runtime returns an annotation type's default value. By default, Byte Buddy includes all values into a class file,
1267
     * also such values for which a default value exists.
1268
     *
1269
     * @param annotationValueFilterFactory The annotation value filter factory to use.
1270
     * @return A new Byte Buddy instance that uses the supplied annotation value filter factory.
1271
     */
1272
    public ByteBuddy with(AnnotationValueFilter.Factory annotationValueFilterFactory) {
1273
        return new ByteBuddy(classFileVersion,
×
1274
                namingStrategy,
1275
                auxiliaryTypeNamingStrategy,
1276
                annotationValueFilterFactory,
1277
                annotationRetention,
1278
                implementationContextFactory,
1279
                methodGraphCompiler,
1280
                instrumentedTypeFactory,
1281
                typeValidation,
1282
                visibilityBridgeStrategy,
1283
                classReaderFactory,
1284
                classWriterFactory,
1285
                ignoredMethods);
1286
    }
1287

1288
    /**
1289
     * <p>
1290
     * Creates a new configuration where annotations that are found in an existing class file are or are not preserved
1291
     * in the format they are discovered, i.e. rewritten in the format they were already present in the class file.
1292
     * By default, Byte Buddy retains annotations when a class is rebased or redefined.
1293
     * </p>
1294
     * <p>
1295
     * <b>Warning</b>: Retaining annotations can cause problems when annotations of a field or method are added based
1296
     * on the annotations of a matched method. Doing so, Byte Buddy might write the annotations of the field or method
1297
     * explicitly to a class file while simultaneously retaining the existing annotation what results in duplicates.
1298
     * When matching fields or methods while adding annotations, disabling annotation retention might be required.
1299
     * </p>
1300
     *
1301
     * @param annotationRetention The annotation retention strategy to use.
1302
     * @return A new Byte Buddy instance that uses the supplied annotation retention strategy.
1303
     */
1304
    public ByteBuddy with(AnnotationRetention annotationRetention) {
1305
        return new ByteBuddy(classFileVersion,
1✔
1306
                namingStrategy,
1307
                auxiliaryTypeNamingStrategy,
1308
                annotationValueFilterFactory,
1309
                annotationRetention,
1310
                implementationContextFactory,
1311
                methodGraphCompiler,
1312
                instrumentedTypeFactory,
1313
                typeValidation,
1314
                visibilityBridgeStrategy,
1315
                classReaderFactory,
1316
                classWriterFactory,
1317
                ignoredMethods);
1318
    }
1319

1320
    /**
1321
     * Creates a new configuration where the {@link net.bytebuddy.implementation.Implementation.Context} of any created
1322
     * type is a product of the given implementation context factory. An implementation context might imply unwanted
1323
     * side-effects, for example, the creation of an additional synthetic methods in order to support specific features
1324
     * for realizing an {@link Implementation}. By default, Byte Buddy supplies a factory that enables all features. When
1325
     * redefining a loaded class, it is however required by the JVM that no additional members are added such that a
1326
     * {@link net.bytebuddy.implementation.Implementation.Context.Disabled} factory might be more appropriate.
1327
     *
1328
     * @param implementationContextFactory The implementation context factory to use for defining an instrumented type.
1329
     * @return A new Byte Buddy instance that uses the supplied implementation context factory.
1330
     */
1331
    public ByteBuddy with(Implementation.Context.Factory implementationContextFactory) {
1332
        return new ByteBuddy(classFileVersion,
1✔
1333
                namingStrategy,
1334
                auxiliaryTypeNamingStrategy,
1335
                annotationValueFilterFactory,
1336
                annotationRetention,
1337
                implementationContextFactory,
1338
                methodGraphCompiler,
1339
                instrumentedTypeFactory,
1340
                typeValidation,
1341
                visibilityBridgeStrategy,
1342
                classReaderFactory,
1343
                classWriterFactory,
1344
                ignoredMethods);
1345
    }
1346

1347
    /**
1348
     * Creates a new configuration where the {@link MethodGraph.Compiler} is used for creating a {@link MethodGraph}
1349
     * of the instrumented type. A method graph is a representation of a type's virtual methods, including all information
1350
     * on bridge methods that are inserted by the Java compiler. Creating a method graph is a rather expensive operation
1351
     * and more efficient strategies might exist for certain types or Java types that are created by alternative JVM
1352
     * languages. By default, a general purpose method graph compiler is used that uses the information that is exposed
1353
     * by the generic type information that is embedded in any class file.
1354
     *
1355
     * @param methodGraphCompiler The method graph compiler to use for analyzing the instrumented type.
1356
     * @return A new Byte Buddy instance that uses the supplied method graph compiler.
1357
     */
1358
    public ByteBuddy with(MethodGraph.Compiler methodGraphCompiler) {
1359
        return new ByteBuddy(classFileVersion,
1✔
1360
                namingStrategy,
1361
                auxiliaryTypeNamingStrategy,
1362
                annotationValueFilterFactory,
1363
                annotationRetention,
1364
                implementationContextFactory,
1365
                methodGraphCompiler,
1366
                instrumentedTypeFactory,
1367
                typeValidation,
1368
                visibilityBridgeStrategy,
1369
                classReaderFactory,
1370
                classWriterFactory,
1371
                ignoredMethods);
1372
    }
1373

1374
    /**
1375
     * Configures Byte Buddy to use the specified factory for creating {@link InstrumentedType}s. Doing so, more efficient
1376
     * representations can be chosen when only certain operations are required. By default, all operations are supported.
1377
     *
1378
     * @param instrumentedTypeFactory The factory to use when creating instrumented types.
1379
     * @return A new Byte Buddy instance that uses the supplied factory for creating instrumented types.
1380
     */
1381
    public ByteBuddy with(InstrumentedType.Factory instrumentedTypeFactory) {
1382
        return new ByteBuddy(classFileVersion,
1✔
1383
                namingStrategy,
1384
                auxiliaryTypeNamingStrategy,
1385
                annotationValueFilterFactory,
1386
                annotationRetention,
1387
                implementationContextFactory,
1388
                methodGraphCompiler,
1389
                instrumentedTypeFactory,
1390
                typeValidation,
1391
                visibilityBridgeStrategy,
1392
                classReaderFactory,
1393
                classWriterFactory,
1394
                ignoredMethods);
1395
    }
1396

1397
    /**
1398
     * Creates a new configuration that applies the supplied type validation. By default, explicitly type validation is applied
1399
     * by Byte Buddy but it might be disabled for performance reason or for voluntarily creating illegal types. The Java virtual
1400
     * machine applies its own type validation where some {@link Error} is thrown if a type is invalid, while Byte Buddy throws
1401
     * some {@link RuntimeException}.
1402
     *
1403
     * @param typeValidation The type validation to apply during type creation.
1404
     * @return A new Byte Buddy instance that applies the supplied type validation.
1405
     */
1406
    public ByteBuddy with(TypeValidation typeValidation) {
1407
        return new ByteBuddy(classFileVersion,
1✔
1408
                namingStrategy,
1409
                auxiliaryTypeNamingStrategy,
1410
                annotationValueFilterFactory,
1411
                annotationRetention,
1412
                implementationContextFactory,
1413
                methodGraphCompiler,
1414
                instrumentedTypeFactory,
1415
                typeValidation,
1416
                visibilityBridgeStrategy,
1417
                classReaderFactory,
1418
                classWriterFactory,
1419
                ignoredMethods);
1420
    }
1421

1422
    /**
1423
     * Creates a new configuration that applies the supplied visibility bridge strategy. By default, visibility bridges
1424
     * are create for all methods for which a visibility bridge is normally necessary.
1425
     *
1426
     * @param visibilityBridgeStrategy The visibility bridge strategy to apply.
1427
     * @return A new Byte Buddy instance that applies the supplied visibility bridge strategy.
1428
     */
1429
    public ByteBuddy with(VisibilityBridgeStrategy visibilityBridgeStrategy) {
1430
        return new ByteBuddy(classFileVersion,
1✔
1431
                namingStrategy,
1432
                auxiliaryTypeNamingStrategy,
1433
                annotationValueFilterFactory,
1434
                annotationRetention,
1435
                implementationContextFactory,
1436
                methodGraphCompiler,
1437
                instrumentedTypeFactory,
1438
                typeValidation,
1439
                visibilityBridgeStrategy,
1440
                classReaderFactory,
1441
                classWriterFactory,
1442
                ignoredMethods);
1443
    }
1444

1445
    /**
1446
     * Creates a new configuration that applies the supplied class writer strategy. By default, the constant pool of redefined and retransformed
1447
     * classes is retained as most changes are additive and this retention improves performance.
1448
     *
1449
     * @param classWriterStrategy The class writer strategy to apply during type creation.
1450
     * @return A new Byte Buddy instance that applies the supplied class writer strategy.
1451
     * @deprecated Use {@link ByteBuddy#with(AsmClassWriter.Factory)}.
1452
     */
1453
    @Deprecated
1454
    public ByteBuddy with(ClassWriterStrategy classWriterStrategy) {
1455
        return new ByteBuddy(classFileVersion,
×
1456
                namingStrategy,
1457
                auxiliaryTypeNamingStrategy,
1458
                annotationValueFilterFactory,
1459
                annotationRetention,
1460
                implementationContextFactory,
1461
                methodGraphCompiler,
1462
                instrumentedTypeFactory,
1463
                typeValidation,
1464
                visibilityBridgeStrategy,
1465
                classReaderFactory,
1466
                new ClassWriterStrategy.Delegating(classWriterStrategy),
1467
                ignoredMethods);
1468
    }
1469

1470
    /**
1471
     * Creates a new configuration that applies the supplied class reader factory.
1472
     *
1473
     * @param classReaderFactory The class reader factory to apply during type creation.
1474
     * @return A new Byte Buddy instance that applies the supplied class reader factory.
1475
     */
1476
    public ByteBuddy with(AsmClassReader.Factory classReaderFactory) {
1477
        return new ByteBuddy(classFileVersion,
×
1478
                namingStrategy,
1479
                auxiliaryTypeNamingStrategy,
1480
                annotationValueFilterFactory,
1481
                annotationRetention,
1482
                implementationContextFactory,
1483
                methodGraphCompiler,
1484
                instrumentedTypeFactory,
1485
                typeValidation,
1486
                visibilityBridgeStrategy,
1487
                classReaderFactory,
1488
                classWriterFactory,
1489
                ignoredMethods);
1490
    }
1491

1492
    /**
1493
     * Creates a new configuration that applies the supplied class writer factory.
1494
     *
1495
     * @param classWriterFactory The class writer factory to apply during type creation.
1496
     * @return A new Byte Buddy instance that applies the supplied class writer factory.
1497
     */
1498
    public ByteBuddy with(AsmClassWriter.Factory classWriterFactory) {
1499
        return new ByteBuddy(classFileVersion,
×
1500
                namingStrategy,
1501
                auxiliaryTypeNamingStrategy,
1502
                annotationValueFilterFactory,
1503
                annotationRetention,
1504
                implementationContextFactory,
1505
                methodGraphCompiler,
1506
                instrumentedTypeFactory,
1507
                typeValidation,
1508
                visibilityBridgeStrategy,
1509
                classReaderFactory,
1510
                classWriterFactory,
1511
                ignoredMethods);
1512
    }
1513

1514
    /**
1515
     * Creates a new configuration that ignores any original {@link AsmClassReader} while creating classes.
1516
     *
1517
     * @return A new Byte Buddy instance that applies the supplied class writer factory.
1518
     */
1519
    public ByteBuddy withIgnoredClassReader() {
1520
        if (classWriterFactory instanceof AsmClassWriter.Factory.Suppressing) {
×
1521
            return this;
×
1522
        }
1523
        return new ByteBuddy(classFileVersion,
×
1524
                namingStrategy,
1525
                auxiliaryTypeNamingStrategy,
1526
                annotationValueFilterFactory,
1527
                annotationRetention,
1528
                implementationContextFactory,
1529
                methodGraphCompiler,
1530
                instrumentedTypeFactory,
1531
                typeValidation,
1532
                visibilityBridgeStrategy,
1533
                classReaderFactory,
1534
                new AsmClassWriter.Factory.Suppressing(classWriterFactory),
1535
                ignoredMethods);
1536
    }
1537

1538
    /**
1539
     * Creates a new configuration where any {@link MethodDescription} that matches the provided method matcher is excluded
1540
     * from instrumentation. Any previous matcher for ignored methods is replaced. By default, Byte Buddy ignores any
1541
     * synthetic method (bridge methods are handled automatically) and the {@link Object#finalize()} method.
1542
     *
1543
     * @param ignoredMethods A matcher for identifying methods to be excluded from instrumentation.
1544
     * @return A new Byte Buddy instance that excludes any method from instrumentation if it is matched by the supplied matcher.
1545
     */
1546
    @SuppressWarnings("overloads")
1547
    public ByteBuddy ignore(ElementMatcher<? super MethodDescription> ignoredMethods) {
1548
        return ignore(new LatentMatcher.Resolved<MethodDescription>(ignoredMethods));
1✔
1549
    }
1550

1551
    /**
1552
     * <p>
1553
     * Creates a new configuration where any {@link MethodDescription} that matches the provided method matcher is excluded
1554
     * from instrumentation. Any previous matcher for ignored methods is replaced. By default, Byte Buddy ignores any
1555
     * synthetic method (bridge methods are handled automatically) and the {@link Object#finalize()} method. Using a latent
1556
     * matcher gives opportunity to resolve an {@link ElementMatcher} based on the instrumented type before applying the matcher.
1557
     * </p>
1558
     *
1559
     * @param ignoredMethods A matcher for identifying methods to be excluded from instrumentation.
1560
     * @return A new Byte Buddy instance that excludes any method from instrumentation if it is matched by the supplied matcher.
1561
     */
1562
    @SuppressWarnings("overloads")
1563
    public ByteBuddy ignore(LatentMatcher<? super MethodDescription> ignoredMethods) {
1564
        return new ByteBuddy(classFileVersion,
1✔
1565
                namingStrategy,
1566
                auxiliaryTypeNamingStrategy,
1567
                annotationValueFilterFactory,
1568
                annotationRetention,
1569
                implementationContextFactory,
1570
                methodGraphCompiler,
1571
                instrumentedTypeFactory,
1572
                typeValidation,
1573
                visibilityBridgeStrategy,
1574
                classReaderFactory,
1575
                classWriterFactory,
1576
                ignoredMethods);
1577
    }
1578

1579
    /**
1580
     * An implementation fo the {@code values} method of an enumeration type.
1581
     */
1582
    @HashCodeAndEqualsPlugin.Enhance
1583
    protected static class EnumerationImplementation implements Implementation {
1584

1585
        /**
1586
         * The name of the {@link java.lang.Object#clone()} method.
1587
         */
1588
        protected static final String CLONE_METHOD_NAME = "clone";
1589

1590
        /**
1591
         * The name of the {@code valueOf} method that is defined for any enumeration.
1592
         */
1593
        protected static final String ENUM_VALUE_OF_METHOD_NAME = "valueOf";
1594

1595
        /**
1596
         * The name of the {@code values} method that is defined for any enumeration.
1597
         */
1598
        protected static final String ENUM_VALUES_METHOD_NAME = "values";
1599

1600
        /**
1601
         * The field modifiers to use for any field that is added to an enumeration.
1602
         */
1603
        private static final int ENUM_FIELD_MODIFIERS = Opcodes.ACC_FINAL | Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC;
1604

1605
        /**
1606
         * The name of the field containing an array of all enumeration values.
1607
         */
1608
        private static final String ENUM_VALUES = "$VALUES";
1609

1610
        /**
1611
         * The names of the enumerations to define for the enumeration.
1612
         */
1613
        private final List<String> values;
1614

1615
        /**
1616
         * Creates a new implementation of an enumeration type.
1617
         *
1618
         * @param values The values of the enumeration.
1619
         */
1620
        protected EnumerationImplementation(List<String> values) {
1✔
1621
            this.values = values;
1✔
1622
        }
1✔
1623

1624
        /**
1625
         * {@inheritDoc}
1626
         */
1627
        public InstrumentedType prepare(InstrumentedType instrumentedType) {
1628
            for (String value : values) {
1✔
1629
                instrumentedType = instrumentedType.withField(new FieldDescription.Token(value,
1✔
1630
                        ENUM_FIELD_MODIFIERS | Opcodes.ACC_ENUM,
1631
                        TargetType.DESCRIPTION.asGenericType()));
1✔
1632
            }
1✔
1633
            return instrumentedType
1✔
1634
                    .withField(new FieldDescription.Token(ENUM_VALUES,
1✔
1635
                            ENUM_FIELD_MODIFIERS | Opcodes.ACC_SYNTHETIC,
1636
                            TypeDescription.ArrayProjection.of(TargetType.DESCRIPTION).asGenericType()))
1✔
1637
                    .withInitializer(new InitializationAppender(values));
1✔
1638
        }
1639

1640
        /**
1641
         * {@inheritDoc}
1642
         */
1643
        public ByteCodeAppender appender(Target implementationTarget) {
1644
            return new ValuesMethodAppender(implementationTarget.getInstrumentedType());
1✔
1645
        }
1646

1647
        /**
1648
         * A byte code appender for the {@code values} method of any enumeration type.
1649
         */
1650
        @HashCodeAndEqualsPlugin.Enhance
1651
        protected static class ValuesMethodAppender implements ByteCodeAppender {
1652

1653
            /**
1654
             * The instrumented enumeration type.
1655
             */
1656
            private final TypeDescription instrumentedType;
1657

1658
            /**
1659
             * Creates a new appender for the {@code values} method.
1660
             *
1661
             * @param instrumentedType The instrumented enumeration type.
1662
             */
1663
            protected ValuesMethodAppender(TypeDescription instrumentedType) {
1✔
1664
                this.instrumentedType = instrumentedType;
1✔
1665
            }
1✔
1666

1667
            /**
1668
             * {@inheritDoc}
1669
             */
1670
            public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1671
                FieldDescription valuesField = instrumentedType.getDeclaredFields().filter(named(ENUM_VALUES)).getOnly();
1✔
1672
                MethodDescription cloneMethod = TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class).getDeclaredMethods().filter(named(CLONE_METHOD_NAME)).getOnly();
1✔
1673
                return new Size(new StackManipulation.Compound(
1✔
1674
                        FieldAccess.forField(valuesField).read(),
1✔
1675
                        MethodInvocation.invoke(cloneMethod).virtual(valuesField.getType().asErasure()),
1✔
1676
                        TypeCasting.to(valuesField.getType().asErasure()),
1✔
1677
                        MethodReturn.REFERENCE
1678
                ).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
1✔
1679
            }
1680
        }
1681

1682
        /**
1683
         * A byte code appender for the type initializer of any enumeration type.
1684
         */
1685
        @HashCodeAndEqualsPlugin.Enhance
1686
        protected static class InitializationAppender implements ByteCodeAppender {
1687

1688
            /**
1689
             * The values of the enumeration that is being created.
1690
             */
1691
            private final List<String> values;
1692

1693
            /**
1694
             * Creates an appender for an enumerations type initializer.
1695
             *
1696
             * @param values The values of the enumeration that is being created.
1697
             */
1698
            protected InitializationAppender(List<String> values) {
1✔
1699
                this.values = values;
1✔
1700
            }
1✔
1701

1702
            /**
1703
             * {@inheritDoc}
1704
             */
1705
            public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1706
                TypeDescription instrumentedType = instrumentedMethod.getDeclaringType().asErasure();
1✔
1707
                MethodDescription enumConstructor = instrumentedType.getDeclaredMethods()
1✔
1708
                        .filter(isConstructor().and(takesArguments(String.class, int.class)))
1✔
1709
                        .getOnly();
1✔
1710
                int ordinal = 0;
1✔
1711
                StackManipulation stackManipulation = StackManipulation.Trivial.INSTANCE;
1✔
1712
                List<FieldDescription> enumerationFields = new ArrayList<FieldDescription>(values.size());
1✔
1713
                for (String value : values) {
1✔
1714
                    FieldDescription fieldDescription = instrumentedType.getDeclaredFields().filter(named(value)).getOnly();
1✔
1715
                    stackManipulation = new StackManipulation.Compound(stackManipulation,
1✔
1716
                            TypeCreation.of(instrumentedType),
1✔
1717
                            Duplication.SINGLE,
1718
                            new TextConstant(value),
1719
                            IntegerConstant.forValue(ordinal++),
1✔
1720
                            MethodInvocation.invoke(enumConstructor),
1✔
1721
                            FieldAccess.forField(fieldDescription).write());
1✔
1722
                    enumerationFields.add(fieldDescription);
1✔
1723
                }
1✔
1724
                List<StackManipulation> fieldGetters = new ArrayList<StackManipulation>(values.size());
1✔
1725
                for (FieldDescription fieldDescription : enumerationFields) {
1✔
1726
                    fieldGetters.add(FieldAccess.forField(fieldDescription).read());
1✔
1727
                }
1✔
1728
                stackManipulation = new StackManipulation.Compound(
1✔
1729
                        stackManipulation,
1730
                        ArrayFactory.forType(instrumentedType.asGenericType()).withValues(fieldGetters),
1✔
1731
                        FieldAccess.forField(instrumentedType.getDeclaredFields().filter(named(ENUM_VALUES)).getOnly()).write()
1✔
1732
                );
1733
                return new Size(stackManipulation.apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
1✔
1734
            }
1735
        }
1736
    }
1737

1738
    /**
1739
     * A constructor strategy for implementing a Java record.
1740
     */
1741
    @HashCodeAndEqualsPlugin.Enhance
1✔
1742
    protected enum RecordConstructorStrategy implements ConstructorStrategy, Implementation {
1743

1744
        /**
1745
         * The singleton instance.
1746
         */
1747
        INSTANCE;
1✔
1748

1749
        /**
1750
         * {@inheritDoc}
1751
         */
1752
        public List<MethodDescription.Token> extractConstructors(TypeDescription instrumentedType) {
1753
            List<ParameterDescription.Token> tokens = new ArrayList<ParameterDescription.Token>(instrumentedType.getRecordComponents().size());
1✔
1754
            for (RecordComponentDescription.InDefinedShape recordComponent : instrumentedType.getRecordComponents()) {
1✔
1755
                tokens.add(new ParameterDescription.Token(recordComponent.getType(),
×
1756
                        recordComponent.getDeclaredAnnotations().filter(targetsElement(ElementType.CONSTRUCTOR)),
×
1757
                        recordComponent.getActualName(),
×
1758
                        ModifierContributor.EMPTY_MASK));
×
1759
            }
×
1760
            return Collections.singletonList(new MethodDescription.Token(MethodDescription.CONSTRUCTOR_INTERNAL_NAME,
1✔
1761
                    Opcodes.ACC_PUBLIC,
1762
                    Collections.<TypeVariableToken>emptyList(),
1✔
1763
                    TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(void.class),
1✔
1764
                    tokens,
1765
                    Collections.<TypeDescription.Generic>emptyList(),
1✔
1766
                    Collections.<AnnotationDescription>emptyList(),
1✔
1767
                    AnnotationValue.UNDEFINED,
1768
                    TypeDescription.Generic.UNDEFINED));
1769
        }
1770

1771
        /**
1772
         * {@inheritDoc}
1773
         */
1774
        public MethodRegistry inject(TypeDescription instrumentedType, MethodRegistry methodRegistry) {
1775
            return methodRegistry.prepend(new LatentMatcher.Resolved<MethodDescription>(isConstructor().and(takesGenericArguments(instrumentedType.getRecordComponents().asTypeList()))),
1✔
1776
                    new MethodRegistry.Handler.ForImplementation(this),
1777
                    MethodAttributeAppender.ForInstrumentedMethod.EXCLUDING_RECEIVER,
1778
                    Transformer.ForMethod.NoOp.<MethodDescription>make());
1✔
1779
        }
1780

1781
        /**
1782
         * {@inheritDoc}
1783
         */
1784
        public ByteCodeAppender appender(Target implementationTarget) {
1785
            return new Appender(implementationTarget.getInstrumentedType());
1✔
1786
        }
1787

1788
        /**
1789
         * {@inheritDoc}
1790
         */
1791
        public InstrumentedType prepare(InstrumentedType instrumentedType) {
1792
            for (RecordComponentDescription.InDefinedShape recordComponent : instrumentedType.getRecordComponents()) {
1✔
1793
                instrumentedType = instrumentedType
×
1794
                        .withField(new FieldDescription.Token(recordComponent.getActualName(),
×
1795
                                Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL,
1796
                                recordComponent.getType(),
×
1797
                                recordComponent.getDeclaredAnnotations().filter(targetsElement(ElementType.FIELD))))
×
1798
                        .withMethod(new MethodDescription.Token(recordComponent.getActualName(),
×
1799
                                Opcodes.ACC_PUBLIC,
1800
                                Collections.<TypeVariableToken>emptyList(),
×
1801
                                recordComponent.getType(),
×
1802
                                Collections.<ParameterDescription.Token>emptyList(),
×
1803
                                Collections.<TypeDescription.Generic>emptyList(),
×
1804
                                recordComponent.getDeclaredAnnotations().filter(targetsElement(ElementType.METHOD)),
×
1805
                                AnnotationValue.UNDEFINED,
1806
                                TypeDescription.Generic.UNDEFINED));
1807
            }
×
1808
            return instrumentedType;
1✔
1809
        }
1810

1811
        /**
1812
         * A byte code appender for accessors and the record constructor.
1813
         */
1814
        @HashCodeAndEqualsPlugin.Enhance
1815
        protected static class Appender implements ByteCodeAppender {
1816

1817
            /**
1818
             * The instrumented type.
1819
             */
1820
            private final TypeDescription instrumentedType;
1821

1822
            /**
1823
             * Creates a new byte code appender for accessors and the record constructor.
1824
             *
1825
             * @param instrumentedType The instrumented type.
1826
             */
1827
            protected Appender(TypeDescription instrumentedType) {
1✔
1828
                this.instrumentedType = instrumentedType;
1✔
1829
            }
1✔
1830

1831
            /**
1832
             * {@inheritDoc}
1833
             */
1834
            public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1835
                if (instrumentedMethod.isMethod()) {
×
1836
                    return new Simple(
×
1837
                            MethodVariableAccess.loadThis(),
×
1838
                            FieldAccess.forField(instrumentedType.getDeclaredFields().filter(named(instrumentedMethod.getName())).getOnly()).read(),
×
1839
                            MethodReturn.of(instrumentedMethod.getReturnType())
×
1840
                    ).apply(methodVisitor, implementationContext, instrumentedMethod);
×
1841
                } else {
1842
                    List<StackManipulation> stackManipulations = new ArrayList<StackManipulation>(instrumentedType.getRecordComponents().size() * 3 + 2);
×
1843
                    stackManipulations.add(MethodVariableAccess.loadThis());
×
1844
                    stackManipulations.add(MethodInvocation.invoke(new MethodDescription.Latent(JavaType.RECORD.getTypeStub(), new MethodDescription.Token(Opcodes.ACC_PUBLIC))));
×
1845
                    int offset = 1;
×
1846
                    for (RecordComponentDescription.InDefinedShape recordComponent : instrumentedType.getRecordComponents()) {
×
1847
                        stackManipulations.add(MethodVariableAccess.loadThis());
×
1848
                        stackManipulations.add(MethodVariableAccess.of(recordComponent.getType()).loadFrom(offset));
×
1849
                        stackManipulations.add(FieldAccess.forField(instrumentedType.getDeclaredFields()
×
1850
                                .filter(named(recordComponent.getActualName()))
×
1851
                                .getOnly()).write());
×
1852
                        offset += recordComponent.getType().getStackSize().getSize();
×
1853
                    }
×
1854
                    stackManipulations.add(MethodReturn.VOID);
×
1855
                    return new Simple(stackManipulations).apply(methodVisitor, implementationContext, instrumentedMethod);
×
1856
                }
1857
            }
1858
        }
1859
    }
1860

1861
    /**
1862
     * Implements the object methods of the Java record type.
1863
     */
1864
    @HashCodeAndEqualsPlugin.Enhance
1✔
1865
    protected enum RecordObjectMethod implements Implementation {
1866

1867
        /**
1868
         * The {@code hashCode} method.
1869
         */
1870
        HASH_CODE("hashCode", StackManipulation.Trivial.INSTANCE, int.class),
1✔
1871

1872
        /**
1873
         * The {@code equals} method.
1874
         */
1875
        EQUALS("equals", MethodVariableAccess.REFERENCE.loadFrom(1), boolean.class, Object.class),
1✔
1876

1877
        /**
1878
         * The {@code toString} method.
1879
         */
1880
        TO_STRING("toString", StackManipulation.Trivial.INSTANCE, String.class);
1✔
1881

1882
        /**
1883
         * The method name.
1884
         */
1885
        private final String name;
1886

1887
        /**
1888
         * The stack manipulation to append to the arguments.
1889
         */
1890
        private final StackManipulation stackManipulation;
1891

1892
        /**
1893
         * The return type.
1894
         */
1895
        private final TypeDescription returnType;
1896

1897
        /**
1898
         * The arguments type.
1899
         */
1900
        private final List<? extends TypeDescription> arguments;
1901

1902
        /**
1903
         * Creates a new object method instance for a Java record.
1904
         *
1905
         * @param name              The method name.
1906
         * @param stackManipulation The stack manipulation to append to the arguments.
1907
         * @param returnType        The return type.
1908
         * @param arguments         The arguments type.
1909
         */
1910
        RecordObjectMethod(String name, StackManipulation stackManipulation, Class<?> returnType, Class<?>... arguments) {
1✔
1911
            this.name = name;
1✔
1912
            this.stackManipulation = stackManipulation;
1✔
1913
            this.returnType = TypeDescription.ForLoadedType.of(returnType);
1✔
1914
            this.arguments = new TypeList.ForLoadedTypes(arguments);
1✔
1915
        }
1✔
1916

1917
        /**
1918
         * {@inheritDoc}
1919
         */
1920
        public ByteCodeAppender appender(Target implementationTarget) {
1921
            StringBuilder stringBuilder = new StringBuilder();
1✔
1922
            List<JavaConstant> methodHandles = new ArrayList<JavaConstant>(implementationTarget.getInstrumentedType().getRecordComponents().size());
1✔
1923
            for (RecordComponentDescription.InDefinedShape recordComponent : implementationTarget.getInstrumentedType().getRecordComponents()) {
1✔
1924
                if (stringBuilder.length() > 0) {
×
1925
                    stringBuilder.append(";");
×
1926
                }
1927
                stringBuilder.append(recordComponent.getActualName());
×
1928
                methodHandles.add(JavaConstant.MethodHandle.ofGetter(implementationTarget.getInstrumentedType().getDeclaredFields()
×
1929
                        .filter(named(recordComponent.getActualName()))
×
1930
                        .getOnly()));
×
1931
            }
×
1932
            return new ByteCodeAppender.Simple(MethodVariableAccess.loadThis(),
1✔
1933
                    stackManipulation,
1934
                    MethodInvocation.invoke(new MethodDescription.Latent(JavaType.OBJECT_METHODS.getTypeStub(), new MethodDescription.Token("bootstrap",
1✔
1935
                            Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
1936
                            TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class),
1✔
1937
                            Arrays.asList(JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().asGenericType(),
1✔
1938
                                    TypeDescription.ForLoadedType.of(String.class).asGenericType(),
1✔
1939
                                    JavaType.TYPE_DESCRIPTOR.getTypeStub().asGenericType(),
1✔
1940
                                    TypeDescription.ForLoadedType.of(Class.class).asGenericType(),
1✔
1941
                                    TypeDescription.ForLoadedType.of(String.class).asGenericType(),
1✔
1942
                                    TypeDescription.ArrayProjection.of(JavaType.METHOD_HANDLE.getTypeStub()).asGenericType())))).dynamic(name,
1✔
1943
                            returnType,
1944
                            CompoundList.of(implementationTarget.getInstrumentedType(), arguments),
1✔
1945
                            CompoundList.of(Arrays.asList(JavaConstant.Simple.of(implementationTarget.getInstrumentedType()), JavaConstant.Simple.ofLoaded(stringBuilder.toString())), methodHandles)),
1✔
1946
                    MethodReturn.of(returnType));
1✔
1947
        }
1948

1949
        /**
1950
         * {@inheritDoc}
1951
         */
1952
        public InstrumentedType prepare(InstrumentedType instrumentedType) {
1953
            return instrumentedType;
1✔
1954
        }
1955
    }
1956
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc