Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
Byte Buddy is a Java library for creating Java classes at run time.
This artifact is a build of Byte Buddy with a remaining dependency onto ASM.
You should never depend on this module without repackaging Byte Buddy and ASM into your own namespace.
/*
* Copyright 2014 - Present Rafael Winterhalter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bytebuddy;
import net.bytebuddy.build.AccessControllerPlugin;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationValue;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.ParameterDescription;
import net.bytebuddy.description.modifier.*;
import net.bytebuddy.description.type.*;
import net.bytebuddy.dynamic.*;
import net.bytebuddy.dynamic.scaffold.*;
import net.bytebuddy.dynamic.scaffold.inline.DecoratingDynamicTypeBuilder;
import net.bytebuddy.dynamic.scaffold.inline.MethodNameTransformer;
import net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder;
import net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.implementation.attribute.AnnotationRetention;
import net.bytebuddy.implementation.attribute.AnnotationValueFilter;
import net.bytebuddy.implementation.attribute.MethodAttributeAppender;
import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
import net.bytebuddy.implementation.bytecode.*;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
import net.bytebuddy.implementation.bytecode.collection.ArrayFactory;
import net.bytebuddy.implementation.bytecode.constant.IntegerConstant;
import net.bytebuddy.implementation.bytecode.constant.TextConstant;
import net.bytebuddy.implementation.bytecode.member.FieldAccess;
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.LatentMatcher;
import net.bytebuddy.utility.*;
import net.bytebuddy.utility.nullability.MaybeNull;
import net.bytebuddy.utility.privilege.GetSystemPropertyAction;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.reflect.Type;
import java.security.PrivilegedAction;
import java.util.*;
import static net.bytebuddy.matcher.ElementMatchers.*;
/**
* Instances of this class serve as a focus point for configuration of the library's behavior and as an entry point
* to any form of code generation using the library. For this purpose, Byte Buddy offers a fluent API which allows
* for the step-wise generation of a new Java type. A type is generated either by:
*
*
Subclassing some type: A subclass - as the name suggests - extends another, existing Java type. Virtual
* members of the generated type's super types can be overridden. Subclasses can also be interface extensions of one
* or several interfaces.
*
Redefining a type: By redefining a type, it is not only possible to override virtual methods of the
* redefined type but also to redefine existing methods. This way, it is also possible to change the behavior of
* non-virtual methods and constructors of the redefined type.
*
Rebasing a type: Rebasing a type works similar to creating a subclass, i.e. any method being overridden
* is still capable of invoking any original code of the rebased type. Any rebased method is however inlined into the
* rebased type and any original code is preserved automatically. This way, the type's identity does not change.
*
* Byte Buddy's API does not change when a type is rebased, redefined or subclassed. All types are created via the
* {@link net.bytebuddy.dynamic.DynamicType.Builder} interface. Byte Buddy's API is expressed by fully immutable
* components and is therefore thread-safe. As a consequence, method calls must be chained for all of Byte Buddy's
* component, e.g. a method call like the following has no effect:
*
* ByteBuddy byteBuddy = new ByteBuddy();
* byteBuddy.foo()
* Instead, the following method chain is correct use of the API:
*
* ByteBuddy byteBuddy = new ByteBuddy().foo();
*
* For the creation of Java agents, Byte Buddy offers a convenience API implemented by the
* {@link net.bytebuddy.agent.builder.AgentBuilder}. The API wraps a {@link ByteBuddy} instance and offers agent-specific
* configuration opportunities by integrating against the {@link java.lang.instrument.Instrumentation} API.
*
*
* @see net.bytebuddy.agent.builder.AgentBuilder
*/
@HashCodeAndEqualsPlugin.Enhance
public class ByteBuddy {
/**
* A property that controls the default naming strategy. If not set, Byte Buddy is generating
* random names for types that are not named explicitly. If set to {@code fixed}, Byte Buddy is
* setting names deterministically without any random element, or to {@code caller}, if a name
* should be fixed but contain the name of the caller class and method. If set to a numeric
* value, Byte Buddy is generating random names, using the number as a seed.
*/
public static final String DEFAULT_NAMING_PROPERTY = "net.bytebuddy.naming";
/**
* A property that controls the default type validation applied by Byte Buddy. If not set,
* and if not otherwise configured by the user, types will be explicitly validated to
* supply better error messages.
*/
public static final String DEFAULT_VALIDATION_PROPERTY = "net.bytebuddy.validation";
/**
* The default prefix for the default {@link net.bytebuddy.NamingStrategy}.
*/
private static final String BYTE_BUDDY_DEFAULT_PREFIX = "ByteBuddy";
/**
* The default suffix when defining a {@link AuxiliaryType.NamingStrategy}.
*/
private static final String BYTE_BUDDY_DEFAULT_SUFFIX = "auxiliary";
/**
* The default name of a fixed context name for synthetic fields and methods.
*/
private static final String BYTE_BUDDY_DEFAULT_CONTEXT_NAME = "synthetic";
/**
* The default type validation to apply.
*/
private static final TypeValidation DEFAULT_TYPE_VALIDATION;
/**
* The default naming strategy or {@code null} if no such strategy is set.
*/
@MaybeNull
private static final NamingStrategy DEFAULT_NAMING_STRATEGY;
/**
* The default auxiliary naming strategy or {@code null} if no such strategy is set.
*/
@MaybeNull
private static final AuxiliaryType.NamingStrategy DEFAULT_AUXILIARY_NAMING_STRATEGY;
/**
* The default implementation context factory or {@code null} if no such factory is set.
*/
@MaybeNull
private static final Implementation.Context.Factory DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY;
/*
* Resolves the default naming strategy.
*/
static {
String validation;
try {
validation = doPrivileged(new GetSystemPropertyAction(DEFAULT_VALIDATION_PROPERTY));
} catch (Throwable ignored) {
validation = null;
}
DEFAULT_TYPE_VALIDATION = validation == null || Boolean.parseBoolean(validation)
? TypeValidation.ENABLED
: TypeValidation.DISABLED;
String naming;
try {
naming = doPrivileged(new GetSystemPropertyAction(DEFAULT_NAMING_PROPERTY));
} catch (Throwable ignored) {
naming = null;
}
NamingStrategy namingStrategy;
AuxiliaryType.NamingStrategy auxiliaryNamingStrategy;
Implementation.Context.Factory implementationContextFactory;
if (naming == null) {
if (GraalImageCode.getCurrent().isDefined()) {
namingStrategy = new NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_PREFIX,
new NamingStrategy.Suffixing.BaseNameResolver.WithCallerSuffix(NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE),
NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE);
auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
} else {
namingStrategy = null;
auxiliaryNamingStrategy = null;
implementationContextFactory = null;
}
} else if (naming.equalsIgnoreCase("fixed")) {
namingStrategy = new NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_PREFIX,
NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE,
NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE);
auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
} else if (naming.equalsIgnoreCase("caller")) {
namingStrategy = new NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_PREFIX,
new NamingStrategy.Suffixing.BaseNameResolver.WithCallerSuffix(NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE),
NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE);
auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
} else {
long seed;
try {
seed = Long.parseLong(naming);
} catch (Exception ignored) {
throw new IllegalStateException("'net.bytebuddy.naming' is set to an unknown, non-numeric value: " + naming);
}
namingStrategy = new NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_PREFIX,
NamingStrategy.Suffixing.BaseNameResolver.ForUnnamedType.INSTANCE,
NamingStrategy.BYTE_BUDDY_RENAME_PACKAGE,
new RandomString(RandomString.DEFAULT_LENGTH, new Random(seed)));
auxiliaryNamingStrategy = new AuxiliaryType.NamingStrategy.Suffixing(BYTE_BUDDY_DEFAULT_SUFFIX);
implementationContextFactory = new Implementation.Context.Default.Factory.WithFixedSuffix(BYTE_BUDDY_DEFAULT_CONTEXT_NAME);
}
DEFAULT_NAMING_STRATEGY = namingStrategy;
DEFAULT_AUXILIARY_NAMING_STRATEGY = auxiliaryNamingStrategy;
DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY = implementationContextFactory;
}
/**
* A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
*
* @param action The action to execute from a privileged context.
* @param The type of the action's resolved value.
* @return The action's resolved value.
*/
@MaybeNull
@AccessControllerPlugin.Enhance
private static T doPrivileged(PrivilegedAction action) {
return action.run();
}
/**
* The class file version to use for types that are not based on an existing class file.
*/
protected final ClassFileVersion classFileVersion;
/**
* The naming strategy to use.
*/
protected final NamingStrategy namingStrategy;
/**
* The naming strategy to use for naming auxiliary types.
*/
protected final AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy;
/**
* The annotation value filter factory to use.
*/
protected final AnnotationValueFilter.Factory annotationValueFilterFactory;
/**
* The annotation retention strategy to use.
*/
protected final AnnotationRetention annotationRetention;
/**
* The implementation context factory to use.
*/
protected final Implementation.Context.Factory implementationContextFactory;
/**
* The method graph compiler to use.
*/
protected final MethodGraph.Compiler methodGraphCompiler;
/**
* The instrumented type factory to use.
*/
protected final InstrumentedType.Factory instrumentedTypeFactory;
/**
* A matcher for identifying methods that should be excluded from instrumentation.
*/
protected final LatentMatcher super MethodDescription> ignoredMethods;
/**
* Determines if a type should be explicitly validated.
*/
protected final TypeValidation typeValidation;
/**
* The visibility bridge strategy to apply.
*/
protected final VisibilityBridgeStrategy visibilityBridgeStrategy;
/**
* The class reader factory to use.
*/
protected final AsmClassReader.Factory classReaderFactory;
/**
* The class writer factory to use.
*/
protected final AsmClassWriter.Factory classWriterFactory;
/**
*
* Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
*
*
* When creating this configuration, Byte Buddy attempts to discover the current JVM's version. If this
* is not possible, class files are created Java 6-compatible.
*
*
* @see ClassFileVersion#ofThisVm(ClassFileVersion)
*/
public ByteBuddy() {
this(ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5));
}
/**
* Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
*
* @param classFileVersion The class file version to use for types that are not based on an existing class file.
*/
public ByteBuddy(ClassFileVersion classFileVersion) {
this(classFileVersion,
DEFAULT_NAMING_STRATEGY == null
? new NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_PREFIX)
: DEFAULT_NAMING_STRATEGY,
DEFAULT_AUXILIARY_NAMING_STRATEGY == null
? new AuxiliaryType.NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_SUFFIX)
: DEFAULT_AUXILIARY_NAMING_STRATEGY,
AnnotationValueFilter.Default.APPEND_DEFAULTS,
AnnotationRetention.ENABLED,
DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY == null
? Implementation.Context.Default.Factory.INSTANCE
: DEFAULT_IMPLEMENTATION_CONTEXT_FACTORY,
MethodGraph.Compiler.DEFAULT,
InstrumentedType.Factory.Default.MODIFIABLE,
DEFAULT_TYPE_VALIDATION,
VisibilityBridgeStrategy.Default.ALWAYS,
AsmClassReader.Factory.Default.INSTANCE,
AsmClassWriter.Factory.Default.INSTANCE,
new LatentMatcher.Resolved(isSynthetic().or(isDefaultFinalizer())));
}
/**
* Creates a new Byte Buddy instance.
*
* @param classFileVersion The class file version to use for types that are not based on an existing class file.
* @param namingStrategy The naming strategy to use.
* @param auxiliaryTypeNamingStrategy The naming strategy to use for naming auxiliary types.
* @param annotationValueFilterFactory The annotation value filter factory to use.
* @param annotationRetention The annotation retention strategy to use.
* @param implementationContextFactory The implementation context factory to use.
* @param methodGraphCompiler The method graph compiler to use.
* @param instrumentedTypeFactory The instrumented type factory to use.
* @param typeValidation Determines if a type should be explicitly validated.
* @param visibilityBridgeStrategy The visibility bridge strategy to apply.
* @param classReaderFactory The class reader factory to use.
* @param classWriterFactory The class writer factory to use.
* @param ignoredMethods A matcher for identifying methods that should be excluded from instrumentation.
*/
protected ByteBuddy(ClassFileVersion classFileVersion,
NamingStrategy namingStrategy,
AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
AnnotationValueFilter.Factory annotationValueFilterFactory,
AnnotationRetention annotationRetention,
Implementation.Context.Factory implementationContextFactory,
MethodGraph.Compiler methodGraphCompiler,
InstrumentedType.Factory instrumentedTypeFactory,
TypeValidation typeValidation,
VisibilityBridgeStrategy visibilityBridgeStrategy,
AsmClassReader.Factory classReaderFactory,
AsmClassWriter.Factory classWriterFactory,
LatentMatcher super MethodDescription> ignoredMethods) {
this.classFileVersion = classFileVersion;
this.namingStrategy = namingStrategy;
this.auxiliaryTypeNamingStrategy = auxiliaryTypeNamingStrategy;
this.annotationValueFilterFactory = annotationValueFilterFactory;
this.annotationRetention = annotationRetention;
this.implementationContextFactory = implementationContextFactory;
this.methodGraphCompiler = methodGraphCompiler;
this.instrumentedTypeFactory = instrumentedTypeFactory;
this.typeValidation = typeValidation;
this.visibilityBridgeStrategy = visibilityBridgeStrategy;
this.classReaderFactory = classReaderFactory;
this.classWriterFactory = classWriterFactory;
this.ignoredMethods = ignoredMethods;
}
/**
*
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
*
*
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
* to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
* {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Class, ConstructorStrategy)}.
*
*
* Note: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
*
*
* Note: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
*
*
* @param superType The super class or interface type to extend.
* @param A loaded type that the generated class is guaranteed to inherit.
* @return A type builder for creating a new class extending the provided class or interface.
*/
@SuppressWarnings("unchecked")
public DynamicType.Builder subclass(Class superType) {
return (DynamicType.Builder) subclass(TypeDescription.ForLoadedType.of(superType));
}
/**
*
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
*
*
* Note: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
*
*
* Note: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
*
*
* @param superType The super class or interface type to extend.
* @param constructorStrategy A constructor strategy that determines the
* @param A loaded type that the generated class is guaranteed to inherit.
* @return A type builder for creating a new class extending the provided class or interface.
*/
@SuppressWarnings("unchecked")
public DynamicType.Builder subclass(Class superType, ConstructorStrategy constructorStrategy) {
return (DynamicType.Builder) subclass(TypeDescription.ForLoadedType.of(superType), constructorStrategy);
}
/**
*
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
*
*
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
* to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
* {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Type, ConstructorStrategy)}.
*
*
* Note: This methods implements the supplied types as is, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables.
*
*
* Note: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
*
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
* variables that are referenced by the generic type must be declared by the generated subclass before creating
* the type.
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder> subclass(Type superType) {
return subclass(TypeDefinition.Sort.describe(superType));
}
/**
*
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
*
*
* Note: This methods implements the supplied types as is, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables.
*
*
* Note: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
*
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized
* type. All type variables that are referenced by the generic type must be declared by the
* generated subclass before creating the type.
* @param constructorStrategy A constructor strategy that determines the
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder> subclass(Type superType, ConstructorStrategy constructorStrategy) {
return subclass(TypeDefinition.Sort.describe(superType), constructorStrategy);
}
/**
*
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
*
*
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type and sets them to be {@code public}.
* Any constructor is implemented to only invoke its super type constructor of equal signature. Another behavior can be specified by
* supplying an explicit {@link ConstructorStrategy} by {@link ByteBuddy#subclass(TypeDefinition, ConstructorStrategy)}.
*
*
* Note: This methods implements the supplied types as is, i.e. any {@link TypeDescription} values are implemented
* as raw types if they declare type variables.
*
*
* Note: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
*
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
* variables that are referenced by the generic type must be declared by the generated subclass before creating
* the type.
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder> subclass(TypeDefinition superType) {
return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING);
}
/**
*
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
*
*
* Note: This methods implements the supplied types as is, i.e. any {@link TypeDescription} values are implemented
* as raw types if they declare type variables.
*
*
* Note: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
*
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized
* type. All type variables that are referenced by the generic type must be declared by the
* generated subclass before creating the type.
* @param constructorStrategy A constructor strategy that determines the
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder> subclass(TypeDefinition superType, ConstructorStrategy constructorStrategy) {
TypeDescription.Generic actualSuperType;
TypeList.Generic interfaceTypes;
if (superType.isPrimitive() || superType.isArray() || superType.isFinal()) {
throw new IllegalArgumentException("Cannot subclass primitive, array or final types: " + superType);
} else if (superType.isInterface()) {
actualSuperType = TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class);
interfaceTypes = new TypeList.Generic.Explicit(superType);
} else {
actualSuperType = superType.asGenericType();
interfaceTypes = new TypeList.Generic.Empty();
}
return new SubclassDynamicTypeBuilder