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

raphw / byte-buddy / #805

29 Oct 2025 10:00AM UTC coverage: 84.915% (-0.05%) from 84.961%
#805

push

raphw
Fix generic witness.

0 of 1 new or added line in 1 file covered. (0.0%)

158 existing lines in 3 files now uncovered.

29779 of 35069 relevant lines covered (84.92%)

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.InstrumentedType;
42
import net.bytebuddy.dynamic.scaffold.MethodGraph;
43
import net.bytebuddy.dynamic.scaffold.MethodRegistry;
44
import net.bytebuddy.dynamic.scaffold.TypeValidation;
45
import net.bytebuddy.dynamic.scaffold.inline.DecoratingDynamicTypeBuilder;
46
import net.bytebuddy.dynamic.scaffold.inline.MethodNameTransformer;
47
import net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder;
48
import net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder;
49
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
50
import net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder;
51
import net.bytebuddy.implementation.Implementation;
52
import net.bytebuddy.implementation.MethodCall;
53
import net.bytebuddy.implementation.SuperMethodCall;
54
import net.bytebuddy.implementation.attribute.AnnotationRetention;
55
import net.bytebuddy.implementation.attribute.AnnotationValueFilter;
56
import net.bytebuddy.implementation.attribute.MethodAttributeAppender;
57
import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
58
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
59
import net.bytebuddy.implementation.bytecode.Duplication;
60
import net.bytebuddy.implementation.bytecode.StackManipulation;
61
import net.bytebuddy.implementation.bytecode.TypeCreation;
62
import net.bytebuddy.implementation.bytecode.assign.Assigner;
63
import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
64
import net.bytebuddy.implementation.bytecode.collection.ArrayFactory;
65
import net.bytebuddy.implementation.bytecode.constant.IntegerConstant;
66
import net.bytebuddy.implementation.bytecode.constant.TextConstant;
67
import net.bytebuddy.implementation.bytecode.member.FieldAccess;
68
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
69
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
70
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
71
import net.bytebuddy.matcher.ElementMatcher;
72
import net.bytebuddy.matcher.LatentMatcher;
73
import net.bytebuddy.utility.AsmClassReader;
74
import net.bytebuddy.utility.AsmClassWriter;
75
import net.bytebuddy.utility.CompoundList;
76
import net.bytebuddy.utility.GraalImageCode;
77
import net.bytebuddy.utility.JavaConstant;
78
import net.bytebuddy.utility.JavaType;
79
import net.bytebuddy.utility.RandomString;
80
import net.bytebuddy.utility.nullability.MaybeNull;
81
import net.bytebuddy.utility.privilege.GetSystemPropertyAction;
82
import org.objectweb.asm.MethodVisitor;
83
import org.objectweb.asm.Opcodes;
84

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1948
        /**
1949
         * {@inheritDoc}
1950
         */
1951
        public InstrumentedType prepare(InstrumentedType instrumentedType) {
1952
            return instrumentedType;
1✔
1953
        }
1954
    }
1955
}
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