Skip to content

Commit

Permalink
Added support for retaining type initializers and specifying redefini…
Browse files Browse the repository at this point in the history
…tion for agent builders. This allows for using type redefinition effectively where it is not allowed to add fields or methods.
  • Loading branch information
Rafael Winterhalter committed Oct 15, 2015
1 parent 858a504 commit 81c565b
Show file tree
Hide file tree
Showing 16 changed files with 792 additions and 302 deletions.
248 changes: 75 additions & 173 deletions byte-buddy-dep/src/main/java/net/bytebuddy/ByteBuddy.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ public interface AgentBuilder {
*/
AgentBuilder withBinaryLocator(BinaryLocator binaryLocator);

/**
* efines the use of the given definition handler that determines if a type should be rebased or redefined.
*
* @param definitionHandler The definition handler to use.
* @return A new instance of this agent builder which uses the given definition handler.
*/
AgentBuilder withDefinitionHandler(DefinitionHandler definitionHandler);

/**
* Enables the use of the given native method prefix for instrumented methods. Note that this prefix is also
* applied when preserving non-native methods. The use of this prefix is also registered when installing the
Expand Down Expand Up @@ -327,6 +335,63 @@ public String toString() {
}
}

/**
* A definition handler is responsible for creating a type builder for a type that is being instrumented.
*/
interface DefinitionHandler {

/**
* Creates a type builder for a given type.
*
* @param typeDescription The type being instrumented.
* @param byteBuddy The Byte Buddy configuration.
* @param classFileLocator The class file locator to use.
* @param methodNameTransformer The method name transformer to use.
* @return A type builder for the given arguments.
*/
DynamicType.Builder<?> builder(TypeDescription typeDescription,
ByteBuddy byteBuddy,
ClassFileLocator classFileLocator,
MethodRebaseResolver.MethodNameTransformer methodNameTransformer);

/**
* A default implementation of a definition handler.
*/
enum Default implements DefinitionHandler {

/**
* A definition handler that performs a rebasing for all types.
*/
REBASE {
@Override
public DynamicType.Builder<?> builder(TypeDescription typeDescription,
ByteBuddy byteBuddy,
ClassFileLocator classFileLocator,
MethodRebaseResolver.MethodNameTransformer methodNameTransformer) {
return byteBuddy.rebase(typeDescription, classFileLocator, methodNameTransformer);
}
},

/**
* A definition handler that performas a redefition for all types.
*/
REDEFINE {
@Override
public DynamicType.Builder<?> builder(TypeDescription typeDescription,
ByteBuddy byteBuddy,
ClassFileLocator classFileLocator,
MethodRebaseResolver.MethodNameTransformer methodNameTransformer) {
return byteBuddy.redefine(typeDescription, classFileLocator);
}
};

@Override
public String toString() {
return "AgentBuilder.DefinitionHandler.Default." + name();
}
}
}

/**
* A transformer allows to apply modifications to a {@link net.bytebuddy.dynamic.DynamicType}. Such a modification
* is then applied to any instrumented type that was matched by the preceding matcher.
Expand Down Expand Up @@ -765,6 +830,11 @@ class Default implements AgentBuilder {
*/
private final BinaryLocator binaryLocator;

/**
* The definition handler to use.
*/
private final DefinitionHandler definitionHandler;

/**
* The listener to notify on transformations.
*/
Expand Down Expand Up @@ -820,6 +890,7 @@ public Default() {
public Default(ByteBuddy byteBuddy) {
this(nonNull(byteBuddy),
BinaryLocator.Default.INSTANCE,
DefinitionHandler.Default.REBASE,
Listener.NoOp.INSTANCE,
NO_NATIVE_PREFIX,
AccessController.getContext(),
Expand All @@ -834,6 +905,7 @@ public Default(ByteBuddy byteBuddy) {
*
* @param byteBuddy The Byte Buddy instance to be used.
* @param binaryLocator The binary locator to use.
* @param definitionHandler The definition handler to use.
* @param listener The listener to notify on transformations.
* @param nativeMethodPrefix The native method prefix to use which might also represent
* {@link net.bytebuddy.agent.builder.AgentBuilder.Default#NO_NATIVE_PREFIX}
Expand All @@ -851,6 +923,7 @@ public Default(ByteBuddy byteBuddy) {
*/
protected Default(ByteBuddy byteBuddy,
BinaryLocator binaryLocator,
DefinitionHandler definitionHandler,
Listener listener,
String nativeMethodPrefix,
AccessControlContext accessControlContext,
Expand All @@ -860,6 +933,7 @@ protected Default(ByteBuddy byteBuddy,
List<Transformation> transformations) {
this.byteBuddy = byteBuddy;
this.binaryLocator = binaryLocator;
this.definitionHandler = definitionHandler;
this.listener = listener;
this.nativeMethodPrefix = nativeMethodPrefix;
this.accessControlContext = accessControlContext;
Expand Down Expand Up @@ -888,6 +962,7 @@ public Identified rebase(ElementMatcher<? super TypeDescription> typeMatcher, El
public AgentBuilder withByteBuddy(ByteBuddy byteBuddy) {
return new Default(nonNull(byteBuddy),
binaryLocator,
definitionHandler,
listener,
nativeMethodPrefix,
accessControlContext,
Expand All @@ -901,6 +976,7 @@ public AgentBuilder withByteBuddy(ByteBuddy byteBuddy) {
public AgentBuilder withListener(Listener listener) {
return new Default(byteBuddy,
binaryLocator,
definitionHandler,
new Listener.Compound(this.listener, nonNull(listener)),
nativeMethodPrefix,
accessControlContext,
Expand All @@ -910,10 +986,25 @@ public AgentBuilder withListener(Listener listener) {
transformations);
}

@Override
public AgentBuilder withDefinitionHandler(DefinitionHandler definitionHandler) {
return new Default(byteBuddy,
binaryLocator,
nonNull(definitionHandler),
listener,
nativeMethodPrefix,
accessControlContext,
disableSelfInitialization,
retransformation,
bootstrapInjectionStrategy,
transformations);
}

@Override
public AgentBuilder withBinaryLocator(BinaryLocator binaryLocator) {
return new Default(byteBuddy,
nonNull(binaryLocator),
definitionHandler,
listener,
nativeMethodPrefix,
accessControlContext,
Expand All @@ -930,6 +1021,7 @@ public AgentBuilder withNativeMethodPrefix(String prefix) {
}
return new Default(byteBuddy,
binaryLocator,
definitionHandler,
listener,
prefix,
accessControlContext,
Expand All @@ -943,6 +1035,7 @@ public AgentBuilder withNativeMethodPrefix(String prefix) {
public AgentBuilder withAccessControlContext(AccessControlContext accessControlContext) {
return new Default(byteBuddy,
binaryLocator,
definitionHandler,
listener,
nativeMethodPrefix,
accessControlContext,
Expand All @@ -956,6 +1049,7 @@ public AgentBuilder withAccessControlContext(AccessControlContext accessControlC
public AgentBuilder allowRetransformation() {
return new Default(byteBuddy,
binaryLocator,
definitionHandler,
listener,
nativeMethodPrefix,
accessControlContext,
Expand All @@ -969,6 +1063,7 @@ public AgentBuilder allowRetransformation() {
public AgentBuilder disableSelfInitialization() {
return new Default(byteBuddy,
binaryLocator,
definitionHandler,
listener,
nativeMethodPrefix,
accessControlContext,
Expand All @@ -982,6 +1077,7 @@ public AgentBuilder disableSelfInitialization() {
public AgentBuilder enableBootstrapInjection(File folder, Instrumentation instrumentation) {
return new Default(byteBuddy,
binaryLocator,
definitionHandler,
listener,
nativeMethodPrefix,
accessControlContext,
Expand Down Expand Up @@ -1015,11 +1111,11 @@ public ClassFileTransformer installOn(Instrumentation instrumentation) {
}
}
if (retransformedTypes.size() > 0) {
try {
instrumentation.retransformClasses(retransformedTypes.toArray(new Class<?>[retransformedTypes.size()]));
} catch (UnmodifiableClassException exception) {
throw new IllegalStateException("Cannot retransform classes: " + retransformedTypes, exception);
}
try {
instrumentation.retransformClasses(retransformedTypes.toArray(new Class<?>[retransformedTypes.size()]));
} catch (UnmodifiableClassException exception) {
throw new IllegalStateException("Cannot retransform classes: " + retransformedTypes, exception);
}
}
}
return classFileTransformer;
Expand Down Expand Up @@ -1048,6 +1144,7 @@ public boolean equals(Object other) {
&& byteBuddy.equals(aDefault.byteBuddy)
&& listener.equals(aDefault.listener)
&& nativeMethodPrefix.equals(aDefault.nativeMethodPrefix)
&& definitionHandler.equals(aDefault.definitionHandler)
&& accessControlContext.equals(aDefault.accessControlContext)
&& disableSelfInitialization == aDefault.disableSelfInitialization
&& retransformation == aDefault.retransformation
Expand All @@ -1061,6 +1158,7 @@ public int hashCode() {
int result = byteBuddy.hashCode();
result = 31 * result + binaryLocator.hashCode();
result = 31 * result + listener.hashCode();
result = 31 * result + definitionHandler.hashCode();
result = 31 * result + nativeMethodPrefix.hashCode();
result = 31 * result + accessControlContext.hashCode();
result = 31 * result + (disableSelfInitialization ? 1 : 0);
Expand All @@ -1075,6 +1173,7 @@ public String toString() {
return "AgentBuilder.Default{" +
"byteBuddy=" + byteBuddy +
", binaryLocator=" + binaryLocator +
", definitionHandler=" + definitionHandler +
", listener=" + listener +
", nativeMethodPrefix=" + nativeMethodPrefix +
", accessControlContext=" + accessControlContext +
Expand Down Expand Up @@ -1636,7 +1735,7 @@ public byte[] transform(ClassLoader classLoader,
for (Transformation transformation : transformations) {
if (transformation.matches(typeDescription, classLoader, classBeingRedefined, protectionDomain)) {
DynamicType.Unloaded<?> dynamicType = initializationStrategy.apply(
transformation.transform(byteBuddy.rebase(typeDescription,
transformation.transform(definitionHandler.builder(typeDescription, byteBuddy,
initialized.getClassFileLocator(),
methodNameTransformer), typeDescription)).make();
Map<TypeDescription, LoadedTypeInitializer> loadedTypeInitializers = dynamicType.getLoadedTypeInitializers();
Expand Down Expand Up @@ -1732,6 +1831,11 @@ public AgentBuilder withListener(Listener listener) {
return materialize().withListener(listener);
}

@Override
public AgentBuilder withDefinitionHandler(DefinitionHandler definitionHandler) {
return materialize().withDefinitionHandler(definitionHandler);
}

@Override
public AgentBuilder withBinaryLocator(BinaryLocator binaryLocator) {
return materialize().withBinaryLocator(binaryLocator);
Expand Down Expand Up @@ -1785,6 +1889,7 @@ public ClassFileTransformer installOnByteBuddyAgent() {
protected AgentBuilder materialize() {
return new Default(byteBuddy,
binaryLocator,
definitionHandler,
listener,
nativeMethodPrefix,
accessControlContext,
Expand Down
Loading

0 comments on commit 81c565b

Please sign in to comment.