@HashCodeAndEqualsPlugin.Enhance public class Advice extends Object implements AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper, Implementation
Advice wrappers copy the code of blueprint methods to be executed before and/or after a matched method. To achieve this, a static
method of a class is annotated by Advice.OnMethodEnter
and/or Advice.OnMethodExit
and provided to an instance of this class.
A method that is annotated with Advice.OnMethodEnter
can annotate its parameters with Advice.Argument
where field access to this parameter
is substituted with access to the specified argument of the instrumented method. Alternatively, a parameter can be annotated by Advice.This
where the this
reference of the instrumented method is read when the parameter is accessed. This mechanism can also be used to assign a
new value to the this
reference of an instrumented method. If no annotation is used on a parameter, it is assigned the n
-th
parameter of the instrumented method for the n
-th parameter of the advice method. All parameters must declare the exact same type as
the parameters of the instrumented type or the method's declaring type for the Advice.This
reference respectively if they are not marked as
read-only. In the latter case, it suffices that a parameter type is a super type of the corresponding type of the instrumented method.
A method that is annotated with Advice.OnMethodExit
can equally annotate its parameters with Advice.Argument
and Advice.This
. Additionally,
it can annotate a parameter with Advice.Return
to receive the original method's return value. By reassigning the return value, it is possible
to replace the returned value. If an instrumented method does not return a value, this annotation must not be used. If a method returns
exceptionally, the parameter is set to its default value, i.e. to 0
for primitive types and to null
for reference types. The
parameter's type must be equal to the instrumented method's return type if it is not set to read-only where it suffices to declare the
parameter type to be of any super type to the instrumented method's return type. An exception can be read by annotating a parameter of type
Throwable
annotated with Advice.Thrown
which is assigned the thrown Throwable
or null
if a method returns normally.
Doing so, it is possible to exchange a thrown exception with any checked or unchecked exception.Finally, if a method annotated with
Advice.OnMethodEnter
exists and this method returns a value, this value can be accessed by a parameter annotated with Advice.Enter
.
This parameter must declare the same type as type being returned by the method annotated with Advice.OnMethodEnter
. If the parameter is marked
to be read-only, it suffices that the annotated parameter is of a super type of the return type of the method annotated by
Advice.OnMethodEnter
. If no such method exists or this method returns void
, no such parameter must be declared. Any return value
of a method that is annotated by Advice.OnMethodExit
is discarded.
If any advice method throws an exception, the method is terminated prematurely. If the method annotated by Advice.OnMethodEnter
throws an exception,
the method annotated by Advice.OnMethodExit
method is not invoked. If the instrumented method throws an exception, the method that is annotated by
Advice.OnMethodExit
is only invoked if the Advice.OnMethodExit.onThrowable()
property is set to true
what is the default. If this property
is set to false
, the Advice.Thrown
annotation must not be used on any parameter.
Byte Buddy does not assert the visibility of any types that are referenced within an inlined advice method. It is the responsibility of
the user of this class to assure that all types referenced within the advice methods are visible to the instrumented class. Failing to
do so results in a IllegalAccessError
at the instrumented class's runtime.
Advice can be used either as a AsmVisitorWrapper
where any declared methods of the currently instrumented type are enhanced without
replacing an existing implementation. Alternatively, advice can function as an Implementation
where, by default, the original super
or default method of the instrumented method is invoked. If this is not possible or undesired, the delegate implementation can be changed
by specifying a wrapped implementation explicitly by wrap(Implementation)
.
When using an advice class as a visitor wrapper, native or abstract methods which are silently skipped when advice matches such a method.
Important: Since Java 6, class files contain stack map frames embedded into a method's byte code. When advice methods are compiled
with a class file version less then Java 6 but are used for a class file that was compiled to Java 6 or newer, these stack map frames must be
computed by ASM by using the ClassWriter.COMPUTE_FRAMES
option. If the advice methods do not contain any branching instructions, this is
not required. No action is required if the advice methods are at least compiled with Java 6 but are used on classes older than Java 6. This
limitation only applies to advice methods that are inlined. Also, it is the responsibility of this class's user to assure that the advice method
does not contain byte code constructs that are not supported by the class containing the instrumented method. In particular, pre Java-5
try-finally blocks cannot be inlined into classes with newer byte code levels as the jsr instruction was deprecated. Also, classes prior
to Java 7 do not support the invokedynamic command which must not be contained by an advice method if the instrumented method targets an
older class file format version.
Note: For the purpose of inlining, Java 5 and Java 6 byte code can be seen as the best candidate for advice methods. These versions do
no longer allow subroutines, neither do they already allow invokedynamic instructions or method handles. This way, Java 5 and Java 6 byte
code is compatible to both older and newer versions. One exception for backwards-incompatible byte code is the possibility to load type references
from the constant pool onto the operand stack. These instructions can however easily be transformed for classes compiled to Java 4 and older
by registering a TypeConstantAdjustment
before the advice visitor.
Note: It is not possible to trigger break points in inlined advice methods as the debugging information of the inlined advice is not preserved. It is not possible in Java to reference more than one source file per class what makes translating such debugging information impossible. It is however possible to set break points in advice methods when invoking the original advice target. This allows debugging of advice code within unit tests that invoke the advice method without instrumentation. As a consequence of not transferring debugging information, the names of the parameters of an advice method do not matter when inlining, neither does any meta information on the advice method's body such as annotations or parameter modifiers.
Note: The behavior of this component is undefined if it is supplied with invalid byte code what might result in runtime exceptions.
Note: When using advice from a Java agent with an AgentBuilder
, it often makes sense to not include
any library-specific code in the agent's jar file. For being able to locate the advice code in the context of the library dependencies, Byte
Buddy offers an AgentBuilder.Transformer.ForAdvice
implementation that allows registering the agent's
class file locators for assembly of the advice class's description at runtime and with respect to the specific user dependencies.
Advice.OnMethodEnter
,
Advice.OnMethodExit
Modifier and Type | Class and Description |
---|---|
protected static class |
Advice.AdviceVisitor
A method visitor that weaves the advice methods' byte codes.
|
static interface |
Advice.AllArguments
Assigns an array containing all arguments of the instrumented method to the annotated parameter.
|
protected static class |
Advice.Appender
A byte code appender for implementing
Advice . |
static interface |
Advice.Argument
Indicates that the annotated parameter should be mapped to the parameter with index
Advice.Argument.value() of
the instrumented method. |
static interface |
Advice.ArgumentHandler
An argument handler is responsible for resolving offsets of the local variable array in the context of the applied instrumentation.
|
static class |
Advice.AssignReturned
A post processor that uses the return value of an advice method to define values for fields, arguments, the instrumented
method's return value or the exception being thrown.
|
protected static interface |
Advice.Delegator
Materializes an advice invocation within a delegation.
|
protected static interface |
Advice.Dispatcher
A dispatcher for implementing advice.
|
static interface |
Advice.Enter
Indicates that the annotated parameter should be mapped to the value that is returned by the advice method that is annotated
by
Advice.OnMethodEnter . |
static interface |
Advice.ExceptionHandler
An exception handler is responsible for providing byte code for handling an exception thrown from a suppressing advice method.
|
static interface |
Advice.Exit
Indicates that the annotated parameter should be mapped to the value that is returned by the advice method that is annotated
by
Advice.OnMethodExit . |
static interface |
Advice.FieldValue
Indicates that the annotated parameter should be mapped to a field in the scope of the instrumented method.
|
static interface |
Advice.Local
Declares the annotated parameter as a local variable that is created by Byte Buddy for the instrumented method.
|
protected static interface |
Advice.MethodSizeHandler
A handler for computing the instrumented method's size.
|
static interface |
Advice.OffsetMapping
Represents an offset mapping for an advice method to an alternative offset.
|
static class |
Advice.OnDefaultValue
A marker type to be used as an argument for
Advice.OnMethodEnter.skipOn() . |
static interface |
Advice.OnMethodEnter
Indicates that this method should be inlined before the matched method is invoked.
|
static interface |
Advice.OnMethodExit
Indicates that this method should be executed before exiting the instrumented method.
|
static class |
Advice.OnNonDefaultValue
A marker type to be used as an argument for
Advice.OnMethodEnter.skipOn() . |
static interface |
Advice.Origin
Indicates that the annotated parameter should be mapped to a string representation of the instrumented method,
a constant representing the
Class declaring the adviced method or a Method , Constructor
or java.lang.reflect.Executable representing this method. |
static interface |
Advice.PostProcessor
A post processor for advice methods that is invoked after advice is executed.
|
static interface |
Advice.Return
Indicates that the annotated parameter should be mapped to the return value of the instrumented method.
|
static interface |
Advice.StackMapFrameHandler
A handler for computing and translating stack map frames.
|
static interface |
Advice.StubValue
Indicates that the annotated parameter should always return a default a boxed version of the instrumented methods return value
(i.e.
|
static interface |
Advice.This
Indicates that the annotated parameter should be mapped to the
this reference of the instrumented method. |
static interface |
Advice.Thrown
Indicates that the annotated parameter should be mapped to the
Throwable thrown by the instrumented method or to null
if the method returned regularly. |
static interface |
Advice.Unused
Indicates that the annotated parameter should always return a default value (i.e.
|
static class |
Advice.WithCustomMapping
A builder step for creating an
Advice that uses custom mappings of annotations to constant pool values. |
Implementation.Composable, Implementation.Compound, Implementation.Context, Implementation.Simple, Implementation.SpecialMethodInvocation, Implementation.Target
InstrumentedType.Prepareable.NoOp
Modifier | Constructor and Description |
---|---|
protected |
Advice(Advice.Dispatcher.Resolved.ForMethodEnter methodEnter,
Advice.Dispatcher.Resolved.ForMethodExit methodExit)
Creates a new advice.
|
Modifier and Type | Method and Description |
---|---|
ByteCodeAppender |
appender(Implementation.Target implementationTarget)
Creates a byte code appender that determines the implementation of the instrumented type's methods.
|
protected org.objectweb.asm.MethodVisitor |
doWrap(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
org.objectweb.asm.MethodVisitor methodVisitor,
Implementation.Context implementationContext,
int writerFlags,
int readerFlags)
Wraps the method visitor to implement this advice.
|
AsmVisitorWrapper.ForDeclaredMethods |
on(ElementMatcher<? super MethodDescription> matcher)
Returns an ASM visitor wrapper that matches the given matcher and applies this advice to the matched methods.
|
InstrumentedType |
prepare(InstrumentedType instrumentedType)
Prepares a given instrumented type.
|
static Advice |
to(Class<?> advice)
Implements advice where every matched method is advised by the given type's advisory methods.
|
static Advice |
to(Class<?> enterAdvice,
Class<?> exitAdvice)
Implements advice where every matched method is advised by the given type's advisory methods.
|
static Advice |
to(Class<?> enterAdvice,
Class<?> exitAdvice,
ClassFileLocator classFileLocator)
Implements advice where every matched method is advised by the given type's advisory methods.
|
static Advice |
to(Class<?> advice,
ClassFileLocator classFileLocator)
Implements advice where every matched method is advised by the given type's advisory methods.
|
static Advice |
to(TypeDescription advice)
Implements advice where every matched method is advised by the given type's advisory methods.
|
protected static Advice |
to(TypeDescription advice,
Advice.PostProcessor.Factory postProcessorFactory,
ClassFileLocator classFileLocator,
List<? extends Advice.OffsetMapping.Factory<?>> userFactories,
Advice.Delegator delegator)
Creates a new advice.
|
static Advice |
to(TypeDescription advice,
ClassFileLocator classFileLocator)
Implements advice where every matched method is advised by the given type's advisory methods.
|
static Advice |
to(TypeDescription enterAdvice,
TypeDescription exitAdvice)
Implements advice where every matched method is advised by the given type's advisory methods.
|
protected static Advice |
to(TypeDescription enterAdvice,
TypeDescription exitAdvice,
Advice.PostProcessor.Factory postProcessorFactory,
ClassFileLocator classFileLocator,
List<? extends Advice.OffsetMapping.Factory<?>> userFactories,
Advice.Delegator delegator)
Creates a new advice.
|
static Advice |
to(TypeDescription enterAdvice,
TypeDescription exitAdvice,
ClassFileLocator classFileLocator)
Implements advice where every matched method is advised by the given type's advisory methods.
|
Advice |
withAssigner(Assigner assigner)
Configures this advice to use the specified assigner.
|
static Advice.WithCustomMapping |
withCustomMapping()
Allows for the configuration of custom annotations that are then bound to a dynamically computed, constant value.
|
Advice |
withExceptionHandler(Advice.ExceptionHandler exceptionHandler)
Configures this advice to execute the given exception handler upon a suppressed exception.
|
Advice |
withExceptionHandler(StackManipulation exceptionHandler)
Configures this advice to execute the given stack manipulation upon a suppressed exception.
|
Advice |
withExceptionPrinting()
Configures this advice to call
Throwable.printStackTrace() upon a suppressed exception. |
Implementation |
wrap(Implementation implementation)
Wraps the supplied implementation to have this advice applied around it.
|
org.objectweb.asm.MethodVisitor |
wrap(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
org.objectweb.asm.MethodVisitor methodVisitor,
Implementation.Context implementationContext,
TypePool typePool,
int writerFlags,
int readerFlags)
Wraps a method visitor.
|
protected Advice(Advice.Dispatcher.Resolved.ForMethodEnter methodEnter, Advice.Dispatcher.Resolved.ForMethodExit methodExit)
methodEnter
- The dispatcher for instrumenting the instrumented method upon entering.methodExit
- The dispatcher for instrumenting the instrumented method upon exiting.public static Advice to(Class<?> advice)
advice
- The type declaring the advice.public static Advice to(Class<?> advice, ClassFileLocator classFileLocator)
advice
- The type declaring the advice.classFileLocator
- The class file locator for locating the advisory class's class file.public static Advice to(TypeDescription advice)
false
are resolvable by the returned instance.advice
- The type declaring the advice.public static Advice to(TypeDescription advice, ClassFileLocator classFileLocator)
advice
- A description of the type declaring the advice.classFileLocator
- The class file locator for locating the advisory class's class file.protected static Advice to(TypeDescription advice, Advice.PostProcessor.Factory postProcessorFactory, ClassFileLocator classFileLocator, List<? extends Advice.OffsetMapping.Factory<?>> userFactories, Advice.Delegator delegator)
advice
- A description of the type declaring the advice.postProcessorFactory
- The post processor factory to use.classFileLocator
- The class file locator for locating the advisory class's class file.userFactories
- A list of custom factories for user generated offset mappings.delegator
- The delegator to use.public static Advice to(Class<?> enterAdvice, Class<?> exitAdvice)
enterAdvice
- The type declaring the enter advice.exitAdvice
- The type declaring the exit advice.public static Advice to(Class<?> enterAdvice, Class<?> exitAdvice, ClassFileLocator classFileLocator)
enterAdvice
- The type declaring the enter advice.exitAdvice
- The type declaring the exit advice.classFileLocator
- The class file locator for locating the advisory class's class file.public static Advice to(TypeDescription enterAdvice, TypeDescription exitAdvice)
false
are resolvable by the returned instance.enterAdvice
- The type declaring the enter advice.exitAdvice
- The type declaring the exit advice.public static Advice to(TypeDescription enterAdvice, TypeDescription exitAdvice, ClassFileLocator classFileLocator)
enterAdvice
- The type declaring the enter advice.exitAdvice
- The type declaring the exit advice.classFileLocator
- The class file locator for locating the advisory class's class file.protected static Advice to(TypeDescription enterAdvice, TypeDescription exitAdvice, Advice.PostProcessor.Factory postProcessorFactory, ClassFileLocator classFileLocator, List<? extends Advice.OffsetMapping.Factory<?>> userFactories, Advice.Delegator delegator)
enterAdvice
- The type declaring the enter advice.exitAdvice
- The type declaring the exit advice.postProcessorFactory
- The post processor factory to use.classFileLocator
- The class file locator for locating the advisory class's class file.userFactories
- A list of custom factories for user generated offset mappings.delegator
- The delegator to use.public static Advice.WithCustomMapping withCustomMapping()
Advice
instrumentation with custom values.Advice.OffsetMapping.Factory
public AsmVisitorWrapper.ForDeclaredMethods on(ElementMatcher<? super MethodDescription> matcher)
matcher
- The matcher identifying methods to apply the advice to.public org.objectweb.asm.MethodVisitor wrap(TypeDescription instrumentedType, MethodDescription instrumentedMethod, org.objectweb.asm.MethodVisitor methodVisitor, Implementation.Context implementationContext, TypePool typePool, int writerFlags, int readerFlags)
wrap
in interface AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper
instrumentedType
- The instrumented type.instrumentedMethod
- The method that is currently being defined.methodVisitor
- The original field visitor that defines the given method.implementationContext
- The implementation context to use.typePool
- The type pool to use.writerFlags
- The ASM ClassWriter
reader flags to consider.readerFlags
- The ASM ClassReader
reader flags to consider.protected org.objectweb.asm.MethodVisitor doWrap(TypeDescription instrumentedType, MethodDescription instrumentedMethod, org.objectweb.asm.MethodVisitor methodVisitor, Implementation.Context implementationContext, int writerFlags, int readerFlags)
instrumentedType
- The instrumented type.instrumentedMethod
- The instrumented method.methodVisitor
- The method visitor to write to.implementationContext
- The implementation context to use.writerFlags
- The ASM writer flags to use.readerFlags
- The ASM reader flags to use.public InstrumentedType prepare(InstrumentedType instrumentedType)
prepare
in interface InstrumentedType.Prepareable
instrumentedType
- The instrumented type in its current form.public ByteCodeAppender appender(Implementation.Target implementationTarget)
appender
in interface Implementation
implementationTarget
- The target of the current implementation.InstrumentedType.Prepareable.prepare(InstrumentedType)
.public Advice withAssigner(Assigner assigner)
assigner
- The assigner to use,public Advice withExceptionPrinting()
Throwable.printStackTrace()
upon a suppressed exception.public Advice withExceptionHandler(StackManipulation exceptionHandler)
Throwable
instance on the operand stack. The stack must be empty upon completing the exception handler.exceptionHandler
- The exception handler to apply.public Advice withExceptionHandler(Advice.ExceptionHandler exceptionHandler)
Throwable
instance on the operand stack. The stack must be empty upon completing the exception handler.exceptionHandler
- The exception handler to apply.public Implementation wrap(Implementation implementation)
implementation
- The implementation to wrap.Copyright © 2014–2022. All rights reserved.