Skip to content

Commit

Permalink
Refactored type initializer to be represented as its own instance. Ad…
Browse files Browse the repository at this point in the history
…ded missing code injection in instrumented type builder.
  • Loading branch information
Rafael Winterhalter committed Jul 7, 2015
1 parent e76df48 commit c259430
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 35 deletions.
Expand Up @@ -894,24 +894,6 @@ public Latent(TypeDescription declaringType,
this.defaultValue = defaultValue;
}

/**
* Creates a latent method description of a type initializer ({@code <clinit>}) for a given type.
*
* @param declaringType The type that for which a type initializer should be created.
* @return A method description of the type initializer of the given type.
*/
public static MethodDescription typeInitializerOf(TypeDescription declaringType) {
return new Latent(declaringType,
MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME,
TYPE_INITIALIZER_MODIFIER,
Collections.<GenericTypeDescription>emptyList(),
TypeDescription.VOID,
Collections.<ParameterDescription.Token>emptyList(),
Collections.<GenericTypeDescription>emptyList(),
Collections.<AnnotationDescription>emptyList(),
MethodDescription.NO_DEFAULT_VALUE);
}

@Override
public GenericTypeDescription getReturnType() {
return returnType.accept(GenericTypeDescription.Visitor.Substitutor.ForAttachment.of(this));
Expand Down Expand Up @@ -956,6 +938,60 @@ public Object getDefaultValue() {
public GenericTypeList getTypeVariables() {
return GenericTypeList.ForDetachedTypes.OfTypeVariable.attach(this, typeVariables);
}

public static class TypeInitializer extends MethodDescription.AbstractMethodDescription {

private final TypeDescription typeDescription;

public TypeInitializer(TypeDescription typeDescription) {
this.typeDescription = typeDescription;
}

@Override
public GenericTypeDescription getReturnType() {
return TypeDescription.VOID;
}

@Override
public ParameterList getParameters() {
return new ParameterList.Empty();
}

@Override
public GenericTypeList getExceptionTypes() {
return new GenericTypeList.Empty();
}

@Override
public Object getDefaultValue() {
return NO_DEFAULT_VALUE;
}

@Override
public GenericTypeList getTypeVariables() {
return new GenericTypeList.Empty();
}

@Override
public AnnotationList getDeclaredAnnotations() {
return new AnnotationList.Empty();
}

@Override
public TypeDescription getDeclaringType() {
return typeDescription;
}

@Override
public int getModifiers() {
return TYPE_INITIALIZER_MODIFIER;
}

@Override
public String getInternalName() {
return MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME;
}
}
}

class Token implements ByteCodeElement.Token<Token> {
Expand Down
Expand Up @@ -374,7 +374,7 @@ public InstrumentedType withInitializer(ByteCodeAppender byteCodeAppender) {
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
typeInitializer.expandWith(byteCodeAppender),
loadedTypeInitializer);
}

Expand Down
Expand Up @@ -12,7 +12,6 @@

import java.util.*;

import static net.bytebuddy.description.method.MethodDescription.Latent.typeInitializerOf;
import static net.bytebuddy.matcher.ElementMatchers.*;
import static net.bytebuddy.utility.ByteBuddyCommons.join;

Expand Down Expand Up @@ -416,9 +415,8 @@ public MethodRegistry.Prepared prepare(InstrumentedType instrumentedType,
}
}
MethodLookupEngine.Finding finding = methodLookupEngine.process(instrumentedType);
ElementMatcher<? super MethodDescription> instrumented = not(anyOf(implementations.keySet())).and(methodFilter.resolve(instrumentedType));
List<MethodDescription> methodDescriptions = join(typeInitializerOf(instrumentedType), finding.getInvokableMethods().filter(instrumented));
for (MethodDescription methodDescription : methodDescriptions) {
List<MethodDescription> relevant = finding.getInvokableMethods().filter(not(anyOf(implementations.keySet())).and(methodFilter.resolve(instrumentedType)));
for (MethodDescription methodDescription : join(new MethodDescription.Latent.TypeInitializer(instrumentedType), relevant)) {
for (Entry entry : entries) {
if (entry.resolve(instrumentedType).matches(methodDescription)) {
implementations.put(methodDescription, entry);
Expand Down
Expand Up @@ -765,7 +765,7 @@ public void drain(ClassVisitor classVisitor, TypeWriter.MethodPool methodPool, I
if (injectedCode.isDefined()) {
typeInitializer = typeInitializer.expandWith(injectedCode.getByteCodeAppender());
}
MethodDescription typeInitializerMethod = MethodDescription.Latent.typeInitializerOf(instrumentedType);
MethodDescription typeInitializerMethod = new MethodDescription.Latent.TypeInitializer(instrumentedType);
TypeWriter.MethodPool.Entry initializerEntry = methodPool.target(typeInitializerMethod);
if (initializerEntry.getSort().isImplemented() && typeInitializer.isDefined()) {
initializerEntry = initializerEntry.prepend(typeInitializer);
Expand Down
Expand Up @@ -31,7 +31,7 @@ protected MethodDescription describe(Constructor<?> constructor) {
@Test
public void testTypeInitializer() throws Exception {
TypeDescription typeDescription = mock(TypeDescription.class);
MethodDescription typeInitializer = MethodDescription.Latent.typeInitializerOf(typeDescription);
MethodDescription typeInitializer = new MethodDescription.Latent.TypeInitializer(typeDescription);
assertThat(typeInitializer.getDeclaringType(), is(typeDescription));
assertThat(typeInitializer.getReturnType(), is((GenericTypeDescription) new TypeDescription.ForLoadedType(void.class)));
assertThat(typeInitializer.getParameters(), is((ParameterList) new ParameterList.Empty()));
Expand Down
Expand Up @@ -160,6 +160,7 @@ public void testAnnotationDefinition() throws Exception {
public void testEnumerationDefinition() throws Exception {
Class<? extends Enum<?>> type = new ByteBuddy()
.makeEnumeration(FOO, BAR)
.classVisitor(DebuggingWrapper.makeDefault())
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Expand Down
Expand Up @@ -205,7 +205,7 @@ public void testInitialContextIsEmpty() throws Exception {
when(entry.getSort()).thenReturn(TypeWriter.MethodPool.Entry.Sort.SKIP);
implementationContext.drain(classVisitor, methodPool, injectedCode);
verifyZeroInteractions(classVisitor);
verify(methodPool).target(MethodDescription.Latent.typeInitializerOf(instrumentedType));
verify(methodPool).target(new MethodDescription.Latent.TypeInitializer(instrumentedType));
verifyNoMoreInteractions(methodPool);
verify(injectedCode).isDefined();
verifyNoMoreInteractions(injectedCode);
Expand Down Expand Up @@ -266,7 +266,7 @@ public void testDrainUserCodeNoInjectedCodeNoTypeInitializer() throws Exception
when(entry.getSort()).thenReturn(TypeWriter.MethodPool.Entry.Sort.IMPLEMENT);
implementationContext.drain(classVisitor, methodPool, injectedCode);
verify(entry).getSort();
verify(entry).apply(classVisitor, implementationContext, MethodDescription.Latent.typeInitializerOf(instrumentedType));
verify(entry).apply(classVisitor, implementationContext, new MethodDescription.Latent.TypeInitializer(instrumentedType));
verifyNoMoreInteractions(entry);
verifyZeroInteractions(classVisitor);
verify(typeInitializer, atLeast(1)).isDefined();
Expand Down Expand Up @@ -296,7 +296,7 @@ public void testDrainNoUserCodeInjectedCodeNoTypeInitializer() throws Exception
verify(otherTypeInitializer, atLeast(1)).isDefined();
verify(otherTypeInitializer).withReturn();
verifyNoMoreInteractions(otherTypeInitializer);
verify(terminationAppender).apply(methodVisitor, implementationContext, MethodDescription.Latent.typeInitializerOf(instrumentedType));
verify(terminationAppender).apply(methodVisitor, implementationContext, new MethodDescription.Latent.TypeInitializer(instrumentedType));
verifyNoMoreInteractions(terminationAppender);
}

Expand All @@ -317,7 +317,7 @@ public void testDrainNoUserCodeNoInjectedCodeTypeInitializer() throws Exception
verifyNoMoreInteractions(typeInitializer);
verify(injectedCode, atLeast(1)).isDefined();
verifyNoMoreInteractions(injectedCode);
verify(terminationAppender).apply(methodVisitor, implementationContext, MethodDescription.Latent.typeInitializerOf(instrumentedType));
verify(terminationAppender).apply(methodVisitor, implementationContext, new MethodDescription.Latent.TypeInitializer(instrumentedType));
verifyNoMoreInteractions(terminationAppender);
}

Expand All @@ -334,7 +334,7 @@ public void testDrainUserCodeNoInjectedCodeTypeInitializer() throws Exception {
verify(entry).getSort();
verify(entry).prepend(typeInitializer);
verifyNoMoreInteractions(entry);
verify(otherEntry).apply(classVisitor, implementationContext, MethodDescription.Latent.typeInitializerOf(instrumentedType));
verify(otherEntry).apply(classVisitor, implementationContext, new MethodDescription.Latent.TypeInitializer(instrumentedType));
verify(typeInitializer, atLeast(1)).isDefined();
verifyNoMoreInteractions(typeInitializer);
verify(injectedCode, atLeast(1)).isDefined();
Expand Down Expand Up @@ -371,7 +371,7 @@ public void testDrainFieldCacheEntries() throws Exception {
verify(otherTypeInitializer).expandWith(any(ByteCodeAppender.class));
verify(thirdTypeInitializer).withReturn();
verify(thirdTypeInitializer).isDefined();
verify(terminationAppender).apply(methodVisitor, implementationContext, MethodDescription.Latent.typeInitializerOf(instrumentedType));
verify(terminationAppender).apply(methodVisitor, implementationContext, new MethodDescription.Latent.TypeInitializer(instrumentedType));
verifyNoMoreInteractions(terminationAppender);
}

Expand All @@ -384,7 +384,7 @@ public void testCannotRegisterFieldAfterDraining() throws Exception {
when(entry.getSort()).thenReturn(TypeWriter.MethodPool.Entry.Sort.SKIP);
implementationContext.drain(classVisitor, methodPool, injectedCode);
verifyZeroInteractions(classVisitor);
verify(methodPool).target(MethodDescription.Latent.typeInitializerOf(instrumentedType));
verify(methodPool).target(new MethodDescription.Latent.TypeInitializer(instrumentedType));
verifyNoMoreInteractions(methodPool);
verify(injectedCode).isDefined();
verifyNoMoreInteractions(injectedCode);
Expand Down
Expand Up @@ -545,7 +545,7 @@ public void testSortIsMethod() throws Exception {
assertThat(ElementMatchers.isMethod()
.matches(new MethodDescription.ForLoadedConstructor(Object.class.getDeclaredConstructor())), is(false));
assertThat(ElementMatchers.isMethod()
.matches(MethodDescription.Latent.typeInitializerOf(mock(TypeDescription.class))), is(false));
.matches(new MethodDescription.Latent.TypeInitializer(mock(TypeDescription.class))), is(false));
}

@Test
Expand All @@ -555,7 +555,7 @@ public void testSortIsConstructor() throws Exception {
assertThat(ElementMatchers.isConstructor()
.matches(new MethodDescription.ForLoadedConstructor(Object.class.getDeclaredConstructor())), is(true));
assertThat(ElementMatchers.isConstructor()
.matches(MethodDescription.Latent.typeInitializerOf(mock(TypeDescription.class))), is(false));
.matches(new MethodDescription.Latent.TypeInitializer(mock(TypeDescription.class))), is(false));
}

@Test
Expand All @@ -574,7 +574,7 @@ public void testSortIsTypeInitializer() throws Exception {
assertThat(ElementMatchers.isTypeInitializer()
.matches(new MethodDescription.ForLoadedConstructor(Object.class.getDeclaredConstructor())), is(false));
assertThat(ElementMatchers.isTypeInitializer()
.matches(MethodDescription.Latent.typeInitializerOf(mock(TypeDescription.class))), is(true));
.matches(new MethodDescription.Latent.TypeInitializer(mock(TypeDescription.class))), is(true));
}

@Test
Expand Down

0 comments on commit c259430

Please sign in to comment.