Skip to content

Commit

Permalink
Refactored test case to use lambda factory. Changed default retransfo…
Browse files Browse the repository at this point in the history
…rmation strategy to retransform as it shows to be more robust.
  • Loading branch information
Rafael Winterhalter committed Jan 26, 2016
1 parent 3ba065e commit 9711802
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 61 deletions.
Expand Up @@ -5,7 +5,6 @@


import java.io.*; import java.io.*;
import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation; import java.lang.instrument.Instrumentation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.security.AccessControlContext; import java.security.AccessControlContext;
Expand Down Expand Up @@ -1035,9 +1034,9 @@ public byte[] transform(ClassLoader classLoader,
String internalName, String internalName,
Class<?> redefinedType, Class<?> redefinedType,
ProtectionDomain protectionDomain, ProtectionDomain protectionDomain,
byte[] classFile) throws IllegalClassFormatException { byte[] binaryRepresentation) {
if (internalName != null && isChild(classLoader) && typeName.equals(internalName.replace('/', '.'))) { if (internalName != null && isChild(classLoader) && typeName.equals(internalName.replace('/', '.'))) {
this.binaryRepresentation = classFile; this.binaryRepresentation = binaryRepresentation;
} }
return DO_NOT_TRANSFORM; return DO_NOT_TRANSFORM;
} }
Expand Down
Expand Up @@ -6,7 +6,10 @@


import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.instrument.*; import java.lang.instrument.ClassDefinition;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -96,17 +99,17 @@ protected ClassReloadingStrategy(Instrumentation instrumentation,
* Creates a class reloading strategy for the given instrumentation. The given instrumentation must either * Creates a class reloading strategy for the given instrumentation. The given instrumentation must either
* support {@link java.lang.instrument.Instrumentation#isRedefineClassesSupported()} or * support {@link java.lang.instrument.Instrumentation#isRedefineClassesSupported()} or
* {@link java.lang.instrument.Instrumentation#isRetransformClassesSupported()}. If both modes are supported, * {@link java.lang.instrument.Instrumentation#isRetransformClassesSupported()}. If both modes are supported,
* classes will be transformed using a class redefinition. * classes will be transformed using a class retransformation.
* *
* @param instrumentation The instrumentation to be used by this reloading strategy. * @param instrumentation The instrumentation to be used by this reloading strategy.
* @return A suitable class reloading strategy. * @return A suitable class reloading strategy.
*/ */
public static ClassReloadingStrategy of(Instrumentation instrumentation) { public static ClassReloadingStrategy of(Instrumentation instrumentation) {
Engine engine; Engine engine;
if (instrumentation.isRedefineClassesSupported()) { if (instrumentation.isRetransformClassesSupported()) {
engine = Engine.REDEFINITION;
} else if (instrumentation.isRetransformClassesSupported()) {
engine = Engine.RETRANSFORMATION; engine = Engine.RETRANSFORMATION;
} else if (instrumentation.isRedefineClassesSupported()) {
engine = Engine.REDEFINITION;
} else { } else {
throw new IllegalArgumentException("Instrumentation does not support manipulation of loaded classes: " + instrumentation); throw new IllegalArgumentException("Instrumentation does not support manipulation of loaded classes: " + instrumentation);
} }
Expand Down Expand Up @@ -421,7 +424,7 @@ public byte[] transform(ClassLoader classLoader,
String internalTypeName, String internalTypeName,
Class<?> classBeingRedefined, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException { byte[] classfileBuffer) {
if (internalTypeName == null) { if (internalTypeName == null) {
return NO_REDEFINITION; return NO_REDEFINITION;
} }
Expand Down
Expand Up @@ -6,18 +6,20 @@
import net.bytebuddy.dynamic.ClassFileLocator; import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.implementation.FixedValue; import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.test.utility.AgentAttachmentRule; import net.bytebuddy.test.utility.AgentAttachmentRule;
import net.bytebuddy.test.utility.ClassFileExtraction;
import net.bytebuddy.test.utility.JavaVersionRule; import net.bytebuddy.test.utility.JavaVersionRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion; import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import net.bytebuddy.utility.RandomString; import net.bytebuddy.utility.RandomString;
import org.junit.Ignore;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.MethodRule; import org.junit.rules.MethodRule;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;


import java.lang.instrument.ClassDefinition; import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation; import java.lang.instrument.Instrumentation;
import java.security.AccessController;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.Callable;


import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertEquals;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
Expand All @@ -29,6 +31,8 @@ public class ClassReloadingStrategyTest {


private static final String FOO = "foo", BAR = "bar"; private static final String FOO = "foo", BAR = "bar";


private static final String LAMBDA_SAMPLE_FACTORY = "net.bytebuddy.test.precompiled.LambdaSampleFactory";

@Rule @Rule
public MethodRule agentAttachmentRule = new AgentAttachmentRule(); public MethodRule agentAttachmentRule = new AgentAttachmentRule();


Expand Down Expand Up @@ -185,28 +189,51 @@ public void testEngineSelfReport() throws Exception {


@Test @Test
@JavaVersionRule.Enforce(8) @JavaVersionRule.Enforce(8)
@AgentAttachmentRule.Enforce(retransformsClasses = true, redefinesClasses = true) @AgentAttachmentRule.Enforce(retransformsClasses = true)
@Ignore("Fails on the integration server, should be isolated as test is currently not repeatable")
public void testAnonymousType() throws Exception { public void testAnonymousType() throws Exception {
((Runnable) Class.forName("net.bytebuddy.test.precompiled.AnonymousClassLoader").newInstance()).run(); ClassLoader classLoader = new ByteArrayClassLoader(null,
ClassFileExtraction.of(Class.forName(LAMBDA_SAMPLE_FACTORY)),
null,
AccessController.getContext(),
ByteArrayClassLoader.PersistenceHandler.MANIFEST,
PackageDefinitionStrategy.NoOp.INSTANCE);
Instrumentation instrumentation = ByteBuddyAgent.install();
Class<?> factory = classLoader.loadClass(LAMBDA_SAMPLE_FACTORY);
@SuppressWarnings("unchecked")
Callable<String> instance = (Callable<String>) factory.getDeclaredMethod("nonCapturing").invoke(factory.newInstance());
ClassReloadingStrategy classReloadingStrategy = ClassReloadingStrategy.of(instrumentation).preregistered(instance.getClass());
ClassFileLocator classFileLocator = ClassFileLocator.AgentBased.of(instrumentation, instance.getClass());
try {
assertThat(instance.call(), is(FOO));
new ByteBuddy()
.redefine(instance.getClass(), classFileLocator)
.method(named("call"))
.intercept(FixedValue.value(BAR))
.make()
.load(instance.getClass().getClassLoader(), classReloadingStrategy);
assertThat(instance.call(), is(BAR));
} finally {
classReloadingStrategy.reset(classFileLocator, instance.getClass());
assertThat(instance.call(), is(FOO));
}
} }


@Test @Test
public void testResetEmptyNoEffectImplicitLocator() throws Exception { public void testResetEmptyNoEffectImplicitLocator() throws Exception {
Instrumentation instrumentation = mock(Instrumentation.class); Instrumentation instrumentation = mock(Instrumentation.class);
when(instrumentation.isRedefineClassesSupported()).thenReturn(true); when(instrumentation.isRetransformClassesSupported()).thenReturn(true);
ClassReloadingStrategy.of(instrumentation).reset(); ClassReloadingStrategy.of(instrumentation).reset();
verify(instrumentation, times(2)).isRedefineClassesSupported(); verify(instrumentation, times(2)).isRetransformClassesSupported();
verifyNoMoreInteractions(instrumentation); verifyNoMoreInteractions(instrumentation);
} }


@Test @Test
public void testResetEmptyNoEffect() throws Exception { public void testResetEmptyNoEffect() throws Exception {
Instrumentation instrumentation = mock(Instrumentation.class); Instrumentation instrumentation = mock(Instrumentation.class);
ClassFileLocator classFileLocator = mock(ClassFileLocator.class); ClassFileLocator classFileLocator = mock(ClassFileLocator.class);
when(instrumentation.isRedefineClassesSupported()).thenReturn(true); when(instrumentation.isRetransformClassesSupported()).thenReturn(true);
ClassReloadingStrategy.of(instrumentation).reset(classFileLocator); ClassReloadingStrategy.of(instrumentation).reset(classFileLocator);
verify(instrumentation, times(2)).isRedefineClassesSupported(); verify(instrumentation, times(2)).isRetransformClassesSupported();
verifyNoMoreInteractions(instrumentation); verifyNoMoreInteractions(instrumentation);
verifyZeroInteractions(classFileLocator); verifyZeroInteractions(classFileLocator);
} }
Expand Down
Binary file not shown.

This file was deleted.

0 comments on commit 9711802

Please sign in to comment.