/*
 * Copyright 2014 - 2020 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.dynamic.scaffold;

import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.annotation.AnnotationValue;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.Transformer;
import net.bytebuddy.dynamic.VisibilityBridgeStrategy;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.LoadedTypeInitializer;
import net.bytebuddy.implementation.attribute.MethodAttributeAppender;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.LatentMatcher;
import net.bytebuddy.utility.CompoundList;

import java.util.*;

import static net.bytebuddy.matcher.ElementMatchers.*;

A method registry is responsible for storing information on how a method is intercepted.
/** * A method registry is responsible for storing information on how a method is intercepted. */
public interface MethodRegistry {
Prepends the given method definition to this method registry, i.e. this configuration is applied first.
Params:
  • methodMatcher – A matcher to identify any method that this definition concerns.
  • handler – The handler to instrument any matched method.
  • attributeAppenderFactory – A method attribute appender to apply to any matched method.
  • transformer – The method transformer to be applied to implemented methods.
Returns:An adapted version of this method registry.
/** * Prepends the given method definition to this method registry, i.e. this configuration is applied first. * * @param methodMatcher A matcher to identify any method that this definition concerns. * @param handler The handler to instrument any matched method. * @param attributeAppenderFactory A method attribute appender to apply to any matched method. * @param transformer The method transformer to be applied to implemented methods. * @return An adapted version of this method registry. */
MethodRegistry prepend(LatentMatcher<? super MethodDescription> methodMatcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer);
Appends the given method definition to this method registry, i.e. this configuration is applied last.
Params:
  • methodMatcher – A matcher to identify all entries that are to be matched.
  • handler – The handler to instrument any matched method.
  • attributeAppenderFactory – A method attribute appender to apply to any matched method.
  • transformer – The method transformer to be applied to implemented methods.
Returns:An adapted version of this method registry.
/** * Appends the given method definition to this method registry, i.e. this configuration is applied last. * * @param methodMatcher A matcher to identify all entries that are to be matched. * @param handler The handler to instrument any matched method. * @param attributeAppenderFactory A method attribute appender to apply to any matched method. * @param transformer The method transformer to be applied to implemented methods. * @return An adapted version of this method registry. */
MethodRegistry append(LatentMatcher<? super MethodDescription> methodMatcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer);
Prepares this method registry.
Params:
  • instrumentedType – The instrumented type that should be created.
  • methodGraphCompiler – The method graph compiler to be used for analyzing the fully assembled instrumented type.
  • typeValidation – Determines if a type should be explicitly validated.
  • visibilityBridgeStrategy – The visibility bridge strategy to apply.
  • ignoredMethods – A filter that only matches methods that should be instrumented.
Returns:A prepared version of this method registry.
/** * Prepares this method registry. * * @param instrumentedType The instrumented type that should be created. * @param methodGraphCompiler The method graph compiler to be used for analyzing the fully assembled instrumented type. * @param typeValidation Determines if a type should be explicitly validated. * @param visibilityBridgeStrategy The visibility bridge strategy to apply. * @param ignoredMethods A filter that only matches methods that should be instrumented. * @return A prepared version of this method registry. */
Prepared prepare(InstrumentedType instrumentedType, MethodGraph.Compiler methodGraphCompiler, TypeValidation typeValidation, VisibilityBridgeStrategy visibilityBridgeStrategy, LatentMatcher<? super MethodDescription> ignoredMethods);
A handler for implementing a method.
/** * A handler for implementing a method. */
interface Handler extends InstrumentedType.Prepareable {
Compiles this handler.
Params:
  • implementationTarget – The implementation target to compile this handler for.
Returns:A compiled handler.
/** * Compiles this handler. * * @param implementationTarget The implementation target to compile this handler for. * @return A compiled handler. */
Handler.Compiled compile(Implementation.Target implementationTarget);
A handler for defining an abstract or native method.
/** * A handler for defining an abstract or native method. */
enum ForAbstractMethod implements Handler, Compiled {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType; }
{@inheritDoc}
/** * {@inheritDoc} */
public Compiled compile(Implementation.Target implementationTarget) { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) { return new TypeWriter.MethodPool.Record.ForDefinedMethod.WithoutBody(methodDescription, attributeAppender, visibility); } }
A handler for implementing a visibility bridge.
/** * A handler for implementing a visibility bridge. */
enum ForVisibilityBridge implements Handler {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { throw new IllegalStateException("A visibility bridge handler must not apply any preparations"); }
{@inheritDoc}
/** * {@inheritDoc} */
public Compiled compile(Implementation.Target implementationTarget) { return new Compiled(implementationTarget.getInstrumentedType()); }
A compiled handler for a visibility bridge handler.
/** * A compiled handler for a visibility bridge handler. */
@HashCodeAndEqualsPlugin.Enhance protected static class Compiled implements Handler.Compiled {
The instrumented type.
/** * The instrumented type. */
private final TypeDescription instrumentedType;
Creates a new compiled handler for a visibility bridge.
Params:
  • instrumentedType – The instrumented type.
/** * Creates a new compiled handler for a visibility bridge. * * @param instrumentedType The instrumented type. */
protected Compiled(TypeDescription instrumentedType) { this.instrumentedType = instrumentedType; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) { return TypeWriter.MethodPool.Record.ForDefinedMethod.OfVisibilityBridge.of(instrumentedType, methodDescription, attributeAppender); } } }
A compiled handler for implementing a method.
/** * A compiled handler for implementing a method. */
interface Compiled {
Assembles this compiled entry with a method attribute appender.
Params:
  • methodDescription – The method description to apply with this handler.
  • attributeAppender – The method attribute appender to apply together with this handler.
  • visibility – The represented method's minimum visibility.
Returns:A method pool entry representing this handler and the given attribute appender.
/** * Assembles this compiled entry with a method attribute appender. * * @param methodDescription The method description to apply with this handler. * @param attributeAppender The method attribute appender to apply together with this handler. * @param visibility The represented method's minimum visibility. * @return A method pool entry representing this handler and the given attribute appender. */
TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility); }
A handler for a method that is implemented as byte code.
/** * A handler for a method that is implemented as byte code. */
@HashCodeAndEqualsPlugin.Enhance class ForImplementation implements Handler {
The implementation to apply.
/** * The implementation to apply. */
private final Implementation implementation;
Creates a new handler for implementing a method with byte code.
Params:
  • implementation – The implementation to apply.
/** * Creates a new handler for implementing a method with byte code. * * @param implementation The implementation to apply. */
public ForImplementation(Implementation implementation) { this.implementation = implementation; }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return implementation.prepare(instrumentedType); }
{@inheritDoc}
/** * {@inheritDoc} */
public Compiled compile(Implementation.Target implementationTarget) { return new Compiled(implementation.appender(implementationTarget)); }
A compiled handler for implementing a method.
/** * A compiled handler for implementing a method. */
@HashCodeAndEqualsPlugin.Enhance protected static class Compiled implements Handler.Compiled {
The byte code appender to apply.
/** * The byte code appender to apply. */
private final ByteCodeAppender byteCodeAppender;
Creates a new compiled handler for a method implementation.
Params:
  • byteCodeAppender – The byte code appender to apply.
/** * Creates a new compiled handler for a method implementation. * * @param byteCodeAppender The byte code appender to apply. */
protected Compiled(ByteCodeAppender byteCodeAppender) { this.byteCodeAppender = byteCodeAppender; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) { return new TypeWriter.MethodPool.Record.ForDefinedMethod.WithBody(methodDescription, byteCodeAppender, attributeAppender, visibility); } } }
A handler for defining a default annotation value for a method.
/** * A handler for defining a default annotation value for a method. */
@HashCodeAndEqualsPlugin.Enhance class ForAnnotationValue implements Handler, Compiled {
The annotation value to set as a default value.
/** * The annotation value to set as a default value. */
private final AnnotationValue<?, ?> annotationValue;
Creates a handler for defining a default annotation value for a method.
Params:
  • annotationValue – The annotation value to set as a default value.
/** * Creates a handler for defining a default annotation value for a method. * * @param annotationValue The annotation value to set as a default value. */
public ForAnnotationValue(AnnotationValue<?, ?> annotationValue) { this.annotationValue = annotationValue; }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType; }
{@inheritDoc}
/** * {@inheritDoc} */
public Compiled compile(Implementation.Target implementationTarget) { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) { return new TypeWriter.MethodPool.Record.ForDefinedMethod.WithAnnotationDefaultValue(methodDescription, annotationValue, attributeAppender); } } }
A method registry that fully prepared the instrumented type.
/** * A method registry that fully prepared the instrumented type. */
interface Prepared {
Returns the fully prepared instrumented type.
Returns:The fully prepared instrumented type.
/** * Returns the fully prepared instrumented type. * * @return The fully prepared instrumented type. */
TypeDescription getInstrumentedType();
Returns the declared or virtually inherited methods of this type.
Returns:The declared or virtually inherited methods of this type.
/** * Returns the declared or virtually inherited methods of this type. * * @return The declared or virtually inherited methods of this type. */
MethodList<?> getMethods();
Returns a list of all methods that should be instrumented.
Returns:A list of all methods that should be instrumented.
/** * Returns a list of all methods that should be instrumented. * * @return A list of all methods that should be instrumented. */
MethodList<?> getInstrumentedMethods();
Returns the loaded type initializer of the instrumented type.
Returns:The loaded type initializer of the instrumented type.
/** * Returns the loaded type initializer of the instrumented type. * * @return The loaded type initializer of the instrumented type. */
LoadedTypeInitializer getLoadedTypeInitializer();
The type initializer of the instrumented type.
Returns:The type initializer of the instrumented type.
/** * The type initializer of the instrumented type. * * @return The type initializer of the instrumented type. */
TypeInitializer getTypeInitializer();
Compiles this prepared method registry.
Params:
  • implementationTargetFactory – A factory for creating an implementation target.
  • classFileVersion – The type's class file version.
Returns:A factory for creating an implementation target.
/** * Compiles this prepared method registry. * * @param implementationTargetFactory A factory for creating an implementation target. * @param classFileVersion The type's class file version. * @return A factory for creating an implementation target. */
Compiled compile(Implementation.Target.Factory implementationTargetFactory, ClassFileVersion classFileVersion); }
A compiled version of a method registry.
/** * A compiled version of a method registry. */
interface Compiled extends TypeWriter.MethodPool {
Returns the instrumented type that is to be created.
Returns:The instrumented type that is to be created.
/** * Returns the instrumented type that is to be created. * * @return The instrumented type that is to be created. */
TypeDescription getInstrumentedType();
Returns the declared or virtually inherited methods of this type.
Returns:The declared or virtually inherited methods of this type.
/** * Returns the declared or virtually inherited methods of this type. * * @return The declared or virtually inherited methods of this type. */
MethodList<?> getMethods();
Returns a list of all methods that should be instrumented.
Returns:A list of all methods that should be instrumented.
/** * Returns a list of all methods that should be instrumented. * * @return A list of all methods that should be instrumented. */
MethodList<?> getInstrumentedMethods();
Returns the loaded type initializer of the instrumented type.
Returns:The loaded type initializer of the instrumented type.
/** * Returns the loaded type initializer of the instrumented type. * * @return The loaded type initializer of the instrumented type. */
LoadedTypeInitializer getLoadedTypeInitializer();
The type initializer of the instrumented type.
Returns:The type initializer of the instrumented type.
/** * The type initializer of the instrumented type. * * @return The type initializer of the instrumented type. */
TypeInitializer getTypeInitializer(); }
A default implementation of a method registry.
/** * A default implementation of a method registry. */
@HashCodeAndEqualsPlugin.Enhance class Default implements MethodRegistry {
The list of currently registered entries in their application order.
/** * The list of currently registered entries in their application order. */
private final List<Entry> entries;
Creates a new default method registry without entries.
/** * Creates a new default method registry without entries. */
public Default() { entries = Collections.emptyList(); }
Creates a new default method registry.
Params:
  • entries – The currently registered entries.
/** * Creates a new default method registry. * * @param entries The currently registered entries. */
private Default(List<Entry> entries) { this.entries = entries; }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodRegistry prepend(LatentMatcher<? super MethodDescription> matcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer) { return new Default(CompoundList.of(new Entry(matcher, handler, attributeAppenderFactory, transformer), entries)); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodRegistry append(LatentMatcher<? super MethodDescription> matcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer) { return new Default(CompoundList.of(entries, new Entry(matcher, handler, attributeAppenderFactory, transformer))); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodRegistry.Prepared prepare(InstrumentedType instrumentedType, MethodGraph.Compiler methodGraphCompiler, TypeValidation typeValidation, VisibilityBridgeStrategy visibilityBridgeStrategy, LatentMatcher<? super MethodDescription> ignoredMethods) { LinkedHashMap<MethodDescription, Prepared.Entry> implementations = new LinkedHashMap<MethodDescription, Prepared.Entry>(); Set<Handler> handlers = new HashSet<Handler>(); Set<MethodDescription> declaredMethods = new HashSet<MethodDescription>(instrumentedType.getDeclaredMethods()); for (Entry entry : entries) { if (handlers.add(entry.getHandler())) { InstrumentedType typeDescription = entry.getHandler().prepare(instrumentedType); if (instrumentedType != typeDescription) { // Avoid unnecessary scanning for helper methods if instrumented type was not changed. for (MethodDescription methodDescription : typeDescription.getDeclaredMethods()) { if (!declaredMethods.contains(methodDescription)) { implementations.put(methodDescription, entry.asSupplementaryEntry(methodDescription)); declaredMethods.add(methodDescription); } } instrumentedType = typeDescription; } } } MethodGraph.Linked methodGraph = methodGraphCompiler.compile(instrumentedType); // Casting required for Java 6 compiler. ElementMatcher<? super MethodDescription> relevanceMatcher = (ElementMatcher<? super MethodDescription>) not(anyOf(implementations.keySet())) .and(returns(isVisibleTo(instrumentedType))) .and(hasParameters(whereNone(hasType(not(isVisibleTo(instrumentedType)))))) .and(ignoredMethods.resolve(instrumentedType)); List<MethodDescription> methods = new ArrayList<MethodDescription>(); for (MethodGraph.Node node : methodGraph.listNodes()) { MethodDescription methodDescription = node.getRepresentative(); boolean visibilityBridge = instrumentedType.isPublic() && !instrumentedType.isInterface(); if (relevanceMatcher.matches(methodDescription)) { for (Entry entry : entries) { if (entry.resolve(instrumentedType).matches(methodDescription)) { implementations.put(methodDescription, entry.asPreparedEntry(instrumentedType, methodDescription, node.getMethodTypes(), node.getVisibility())); visibilityBridge = false; break; } } } if (visibilityBridge && !node.getSort().isMadeVisible() && methodDescription.isPublic() && !(methodDescription.isAbstract() || methodDescription.isFinal()) && methodDescription.getDeclaringType().isPackagePrivate() && visibilityBridgeStrategy.generateVisibilityBridge(methodDescription)) { // Visibility bridges are required for public classes that inherit a public method from a package-private class. implementations.put(methodDescription, Prepared.Entry.forVisibilityBridge(methodDescription, node.getVisibility())); } methods.add(methodDescription); } for (MethodDescription methodDescription : CompoundList.of( instrumentedType.getDeclaredMethods().filter(not(isVirtual()).and(relevanceMatcher)), new MethodDescription.Latent.TypeInitializer(instrumentedType))) { for (Entry entry : entries) { if (entry.resolve(instrumentedType).matches(methodDescription)) { implementations.put(methodDescription, entry.asPreparedEntry(instrumentedType, methodDescription, methodDescription.getVisibility())); break; } } methods.add(methodDescription); } return new Prepared(implementations, instrumentedType.getLoadedTypeInitializer(), instrumentedType.getTypeInitializer(), typeValidation.isEnabled() ? instrumentedType.validated() : instrumentedType, methodGraph, new MethodList.Explicit<MethodDescription>(methods)); }
An entry of a default method registry.
/** * An entry of a default method registry. */
@HashCodeAndEqualsPlugin.Enhance protected static class Entry implements LatentMatcher<MethodDescription> {
The latent method matcher that this entry represents.
/** * The latent method matcher that this entry represents. */
private final LatentMatcher<? super MethodDescription> matcher;
The handler to apply to all matched entries.
/** * The handler to apply to all matched entries. */
private final Handler handler;
A method attribute appender factory to apply to all entries.
/** * A method attribute appender factory to apply to all entries. */
private final MethodAttributeAppender.Factory attributeAppenderFactory;
The method transformer to be applied to implemented methods.
/** * The method transformer to be applied to implemented methods. */
private final Transformer<MethodDescription> transformer;
Creates a new entry.
Params:
  • matcher – The latent method matcher that this entry represents.
  • handler – The handler to apply to all matched entries.
  • attributeAppenderFactory – A method attribute appender factory to apply to all entries.
  • transformer – The method transformer to be applied to implemented methods.
/** * Creates a new entry. * * @param matcher The latent method matcher that this entry represents. * @param handler The handler to apply to all matched entries. * @param attributeAppenderFactory A method attribute appender factory to apply to all entries. * @param transformer The method transformer to be applied to implemented methods. */
protected Entry(LatentMatcher<? super MethodDescription> matcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer) { this.matcher = matcher; this.handler = handler; this.attributeAppenderFactory = attributeAppenderFactory; this.transformer = transformer; }
Transforms this entry into a prepared state.
Params:
  • instrumentedType – The instrumented type.
  • methodDescription – The non-transformed method to be implemented.
  • visibility – The represented method's minimum visibility.
Returns:A prepared version of this entry.
/** * Transforms this entry into a prepared state. * * @param instrumentedType The instrumented type. * @param methodDescription The non-transformed method to be implemented. * @param visibility The represented method's minimum visibility. * @return A prepared version of this entry. */
protected Prepared.Entry asPreparedEntry(TypeDescription instrumentedType, MethodDescription methodDescription, Visibility visibility) { return asPreparedEntry(instrumentedType, methodDescription, Collections.<MethodDescription.TypeToken>emptySet(), visibility); }
Transforms this entry into a prepared state.
Params:
  • instrumentedType – The instrumented type.
  • methodDescription – The non-transformed method to be implemented.
  • methodTypes – The method types this method represents.
  • visibility – The represented method's minimum visibility.
Returns:A prepared version of this entry.
/** * Transforms this entry into a prepared state. * * @param instrumentedType The instrumented type. * @param methodDescription The non-transformed method to be implemented. * @param methodTypes The method types this method represents. * @param visibility The represented method's minimum visibility. * @return A prepared version of this entry. */
protected Prepared.Entry asPreparedEntry(TypeDescription instrumentedType, MethodDescription methodDescription, Set<MethodDescription.TypeToken> methodTypes, Visibility visibility) { return new Prepared.Entry(handler, attributeAppenderFactory, transformer.transform(instrumentedType, methodDescription), methodTypes, visibility, false); }
Returns a prepared entry for a supplementary method.
Params:
  • methodDescription – The method to be implemented.
Returns:An entry for a supplementary entry that is defined by a method implementation instance.
/** * Returns a prepared entry for a supplementary method. * * @param methodDescription The method to be implemented. * @return An entry for a supplementary entry that is defined by a method implementation instance. */
protected Prepared.Entry asSupplementaryEntry(MethodDescription methodDescription) { return new Prepared.Entry(handler, MethodAttributeAppender.Explicit.of(methodDescription), methodDescription, Collections.<MethodDescription.TypeToken>emptySet(), methodDescription.getVisibility(), false); }
Returns this entry's handler.
Returns:The handler of this entry.
/** * Returns this entry's handler. * * @return The handler of this entry. */
protected Handler getHandler() { return handler; }
{@inheritDoc}
/** * {@inheritDoc} */
public ElementMatcher<? super MethodDescription> resolve(TypeDescription typeDescription) { return matcher.resolve(typeDescription); } }
A prepared version of a default method registry.
/** * A prepared version of a default method registry. */
@HashCodeAndEqualsPlugin.Enhance protected static class Prepared implements MethodRegistry.Prepared {
A map of all method descriptions mapped to their handling entries.
/** * A map of all method descriptions mapped to their handling entries. */
private final LinkedHashMap<MethodDescription, Entry> implementations;
The loaded type initializer of the instrumented type.
/** * The loaded type initializer of the instrumented type. */
private final LoadedTypeInitializer loadedTypeInitializer;
The type initializer of the instrumented type.
/** * The type initializer of the instrumented type. */
private final TypeInitializer typeInitializer;
The instrumented type.
/** * The instrumented type. */
private final TypeDescription instrumentedType;
A method graph describing the instrumented type.
/** * A method graph describing the instrumented type. */
private final MethodGraph.Linked methodGraph;
The declared or virtually inherited methods of this type.
/** * The declared or virtually inherited methods of this type. */
private final MethodList<?> methods;
Creates a prepared version of a default method registry.
Params:
  • implementations – A map of all method descriptions mapped to their handling entries.
  • loadedTypeInitializer – The loaded type initializer of the instrumented type.
  • typeInitializer – The type initializer of the instrumented type.
  • instrumentedType – The instrumented type.
  • methodGraph – A method graph describing the instrumented type.
  • methods – The declared or virtually inherited methods of this type.
/** * Creates a prepared version of a default method registry. * * @param implementations A map of all method descriptions mapped to their handling entries. * @param loadedTypeInitializer The loaded type initializer of the instrumented type. * @param typeInitializer The type initializer of the instrumented type. * @param instrumentedType The instrumented type. * @param methodGraph A method graph describing the instrumented type. * @param methods The declared or virtually inherited methods of this type. */
protected Prepared(LinkedHashMap<MethodDescription, Entry> implementations, LoadedTypeInitializer loadedTypeInitializer, TypeInitializer typeInitializer, TypeDescription instrumentedType, MethodGraph.Linked methodGraph, MethodList<?> methods) { this.implementations = implementations; this.loadedTypeInitializer = loadedTypeInitializer; this.typeInitializer = typeInitializer; this.instrumentedType = instrumentedType; this.methodGraph = methodGraph; this.methods = methods; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getInstrumentedType() { return instrumentedType; }
{@inheritDoc}
/** * {@inheritDoc} */
public LoadedTypeInitializer getLoadedTypeInitializer() { return loadedTypeInitializer; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeInitializer getTypeInitializer() { return typeInitializer; }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodList<?> getMethods() { return methods; }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodList<?> getInstrumentedMethods() { return new MethodList.Explicit<MethodDescription>(new ArrayList<MethodDescription>(implementations.keySet())).filter(not(isTypeInitializer())); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodRegistry.Compiled compile(Implementation.Target.Factory implementationTargetFactory, ClassFileVersion classFileVersion) { Map<Handler, Handler.Compiled> compilationCache = new HashMap<Handler, Handler.Compiled>(); Map<MethodAttributeAppender.Factory, MethodAttributeAppender> attributeAppenderCache = new HashMap<MethodAttributeAppender.Factory, MethodAttributeAppender>(); LinkedHashMap<MethodDescription, Compiled.Entry> entries = new LinkedHashMap<MethodDescription, Compiled.Entry>(); Implementation.Target implementationTarget = implementationTargetFactory.make(instrumentedType, methodGraph, classFileVersion); for (Map.Entry<MethodDescription, Entry> entry : implementations.entrySet()) { Handler.Compiled cachedHandler = compilationCache.get(entry.getValue().getHandler()); if (cachedHandler == null) { cachedHandler = entry.getValue().getHandler().compile(implementationTarget); compilationCache.put(entry.getValue().getHandler(), cachedHandler); } MethodAttributeAppender cachedAttributeAppender = attributeAppenderCache.get(entry.getValue().getAppenderFactory()); if (cachedAttributeAppender == null) { cachedAttributeAppender = entry.getValue().getAppenderFactory().make(instrumentedType); attributeAppenderCache.put(entry.getValue().getAppenderFactory(), cachedAttributeAppender); } entries.put(entry.getKey(), new Compiled.Entry(cachedHandler, cachedAttributeAppender, entry.getValue().getMethodDescription(), entry.getValue().resolveBridgeTypes(), entry.getValue().getVisibility(), entry.getValue().isBridgeMethod())); } return new Compiled(instrumentedType, loadedTypeInitializer, typeInitializer, methods, entries, classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)); }
An entry of a prepared method registry.
/** * An entry of a prepared method registry. */
@HashCodeAndEqualsPlugin.Enhance protected static class Entry {
The handler for implementing methods.
/** * The handler for implementing methods. */
private final Handler handler;
A attribute appender factory for appending attributes for any implemented method.
/** * A attribute appender factory for appending attributes for any implemented method. */
private final MethodAttributeAppender.Factory attributeAppenderFactory;
The method this entry represents.
/** * The method this entry represents. */
private final MethodDescription methodDescription;
The method's type tokens.
/** * The method's type tokens. */
private final Set<MethodDescription.TypeToken> typeTokens;
The minimum required visibility of this method.
/** * The minimum required visibility of this method. */
private Visibility visibility;
Is true if this entry represents a bridge method.
/** * Is {@code true} if this entry represents a bridge method. */
private final boolean bridgeMethod;
Creates a new prepared entry.
Params:
  • handler – The handler for implementing methods.
  • attributeAppenderFactory – A attribute appender factory for appending attributes for any implemented method.
  • methodDescription – The method this entry represents.
  • typeTokens – A set of bridges representing the bridge methods of this method.
  • visibility – The minimum required visibility of this method.
  • bridgeMethod – true if this entry represents a bridge method.
/** * Creates a new prepared entry. * * @param handler The handler for implementing methods. * @param attributeAppenderFactory A attribute appender factory for appending attributes for any implemented method. * @param methodDescription The method this entry represents. * @param typeTokens A set of bridges representing the bridge methods of this method. * @param visibility The minimum required visibility of this method. * @param bridgeMethod {@code true} if this entry represents a bridge method. */
protected Entry(Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, MethodDescription methodDescription, Set<MethodDescription.TypeToken> typeTokens, Visibility visibility, boolean bridgeMethod) { this.handler = handler; this.attributeAppenderFactory = attributeAppenderFactory; this.methodDescription = methodDescription; this.typeTokens = typeTokens; this.visibility = visibility; this.bridgeMethod = bridgeMethod; }
Creates an entry for a visibility bridge.
Params:
  • bridgeTarget – The bridge method's target.
  • visibility – The represented method's minimum visibility.
Returns:An entry representing a visibility bridge.
/** * Creates an entry for a visibility bridge. * * @param bridgeTarget The bridge method's target. * @param visibility The represented method's minimum visibility. * @return An entry representing a visibility bridge. */
protected static Entry forVisibilityBridge(MethodDescription bridgeTarget, Visibility visibility) { return new Entry(Handler.ForVisibilityBridge.INSTANCE, MethodAttributeAppender.Explicit.of(bridgeTarget), bridgeTarget, Collections.<MethodDescription.TypeToken>emptySet(), visibility, true); }
Returns this entry's handler.
Returns:The entry's handler.
/** * Returns this entry's handler. * * @return The entry's handler. */
protected Handler getHandler() { return handler; }
Returns this entry's attribute appender factory.
Returns:This entry's attribute appender factory.
/** * Returns this entry's attribute appender factory. * * @return This entry's attribute appender factory. */
protected MethodAttributeAppender.Factory getAppenderFactory() { return attributeAppenderFactory; }
Returns the method description this entry represents.
Returns:The method description this entry represents.
/** * Returns the method description this entry represents. * * @return The method description this entry represents. */
protected MethodDescription getMethodDescription() { return methodDescription; }
Resolves the type tokens of all bridge methods that are required to be implemented for this entry.
Returns:A set of type tokens representing the bridge methods required for implementing this type.
/** * Resolves the type tokens of all bridge methods that are required to be implemented for this entry. * * @return A set of type tokens representing the bridge methods required for implementing this type. */
protected Set<MethodDescription.TypeToken> resolveBridgeTypes() { HashSet<MethodDescription.TypeToken> typeTokens = new HashSet<MethodDescription.TypeToken>(this.typeTokens); typeTokens.remove(methodDescription.asTypeToken()); return typeTokens; }
Returns the represented method's minimum visibility.
Returns:The represented method's minimum visibility.
/** * Returns the represented method's minimum visibility. * * @return The represented method's minimum visibility. */
protected Visibility getVisibility() { return visibility; }
Returns true if this entry represents a bridge method.
Returns:true if this entry represents a bridge method.
/** * Returns {@code true} if this entry represents a bridge method. * * @return {@code true} if this entry represents a bridge method. */
protected boolean isBridgeMethod() { return bridgeMethod; } } }
A compiled version of a default method registry.
/** * A compiled version of a default method registry. */
@HashCodeAndEqualsPlugin.Enhance protected static class Compiled implements MethodRegistry.Compiled {
The instrumented type.
/** * The instrumented type. */
private final TypeDescription instrumentedType;
The loaded type initializer of the instrumented type.
/** * The loaded type initializer of the instrumented type. */
private final LoadedTypeInitializer loadedTypeInitializer;
The type initializer of the instrumented type.
/** * The type initializer of the instrumented type. */
private final TypeInitializer typeInitializer;
The declared or virtually inherited methods of this type.
/** * The declared or virtually inherited methods of this type. */
private final MethodList<?> methods;
A map of all method descriptions mapped to their handling entries.
/** * A map of all method descriptions mapped to their handling entries. */
private final LinkedHashMap<MethodDescription, Entry> implementations;
true if the created type supports bridge methods.
/** * {@code true} if the created type supports bridge methods. */
private final boolean supportsBridges;
Creates a new compiled version of a default method registry.
Params:
  • instrumentedType – The instrumented type.
  • loadedTypeInitializer – The loaded type initializer of the instrumented type.
  • typeInitializer – The type initializer of the instrumented type.
  • methods – The declared or virtually inherited methods of this type.
  • implementations – A map of all method descriptions mapped to their handling entries.
  • supportsBridges – true if the created type supports bridge methods.
/** * Creates a new compiled version of a default method registry. * * @param instrumentedType The instrumented type. * @param loadedTypeInitializer The loaded type initializer of the instrumented type. * @param typeInitializer The type initializer of the instrumented type. * @param methods The declared or virtually inherited methods of this type. * @param implementations A map of all method descriptions mapped to their handling entries. * @param supportsBridges {@code true} if the created type supports bridge methods. */
protected Compiled(TypeDescription instrumentedType, LoadedTypeInitializer loadedTypeInitializer, TypeInitializer typeInitializer, MethodList<?> methods, LinkedHashMap<MethodDescription, Entry> implementations, boolean supportsBridges) { this.instrumentedType = instrumentedType; this.loadedTypeInitializer = loadedTypeInitializer; this.typeInitializer = typeInitializer; this.methods = methods; this.implementations = implementations; this.supportsBridges = supportsBridges; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getInstrumentedType() { return instrumentedType; }
{@inheritDoc}
/** * {@inheritDoc} */
public LoadedTypeInitializer getLoadedTypeInitializer() { return loadedTypeInitializer; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeInitializer getTypeInitializer() { return typeInitializer; }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodList<?> getMethods() { return methods; }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodList<?> getInstrumentedMethods() { return new MethodList.Explicit<MethodDescription>(new ArrayList<MethodDescription>(implementations.keySet())).filter(not(isTypeInitializer())); }
{@inheritDoc}
/** * {@inheritDoc} */
public Record target(MethodDescription methodDescription) { Entry entry = implementations.get(methodDescription); return entry == null ? new Record.ForNonImplementedMethod(methodDescription) : entry.bind(instrumentedType, supportsBridges); }
An entry of a compiled method registry.
/** * An entry of a compiled method registry. */
@HashCodeAndEqualsPlugin.Enhance protected static class Entry {
The handler to be used for implementing a method.
/** * The handler to be used for implementing a method. */
private final Handler.Compiled handler;
The attribute appender of a compiled method.
/** * The attribute appender of a compiled method. */
private final MethodAttributeAppender attributeAppender;
The method to be implemented including potential transformations.
/** * The method to be implemented including potential transformations. */
private final MethodDescription methodDescription;
The type tokens representing all bridge methods for the method.
/** * The type tokens representing all bridge methods for the method. */
private final Set<MethodDescription.TypeToken> bridgeTypes;
The represented method's minimum visibility.
/** * The represented method's minimum visibility. */
private final Visibility visibility;
true if this entry represents a bridge method.
/** * {@code true} if this entry represents a bridge method. */
private final boolean bridgeMethod;
Creates a new entry for a compiled method registry.
Params:
  • handler – The handler to be used for implementing a method.
  • attributeAppender – The attribute appender of a compiled method.
  • methodDescription – The method to be implemented including potential transformations.
  • bridgeTypes – The type tokens representing all bridge methods for the method.
  • visibility – The represented method's minimum visibility.
  • bridgeMethod – true if this entry represents a bridge method.
/** * Creates a new entry for a compiled method registry. * * @param handler The handler to be used for implementing a method. * @param attributeAppender The attribute appender of a compiled method. * @param methodDescription The method to be implemented including potential transformations. * @param bridgeTypes The type tokens representing all bridge methods for the method. * @param visibility The represented method's minimum visibility. * @param bridgeMethod {@code true} if this entry represents a bridge method. */
protected Entry(Handler.Compiled handler, MethodAttributeAppender attributeAppender, MethodDescription methodDescription, Set<MethodDescription.TypeToken> bridgeTypes, Visibility visibility, boolean bridgeMethod) { this.handler = handler; this.attributeAppender = attributeAppender; this.methodDescription = methodDescription; this.bridgeTypes = bridgeTypes; this.visibility = visibility; this.bridgeMethod = bridgeMethod; }
Transforms this entry into a method record.
Params:
  • instrumentedType – The instrumented type to bind.
  • supportsBridges – true if the record should support bridge methods.
Returns:A record representing this entry's properties.
/** * Transforms this entry into a method record. * * @param instrumentedType The instrumented type to bind. * @param supportsBridges {@code true} if the record should support bridge methods. * @return A record representing this entry's properties. */
protected Record bind(TypeDescription instrumentedType, boolean supportsBridges) { if (bridgeMethod && !supportsBridges) { return new Record.ForNonImplementedMethod(methodDescription); } Record record = handler.assemble(methodDescription, attributeAppender, visibility); return supportsBridges ? TypeWriter.MethodPool.Record.AccessBridgeWrapper.of(record, instrumentedType, methodDescription, bridgeTypes, attributeAppender) : record; } } } } }