Skip to content

Commit 4a9d3c2

Browse files
authored
Erase bootstrap (#1753)
* Add test for erased bootstrap. * Add basic test. * Create test that fails for erasure. * Retain array structure on erasure. * Improve erasure mechanism. * Refactor towards erasure. * More refactoring. * Fix type token. * Refactor last support API to use of type token. * More refactoring. * More refactoring. * Fix up checkstyle. * More cleanup. * Remove visitor from member substitution. * Clean up return handler. * Add missing javadoc. * Avoid intermediate store of type token. * Increase version number. * Fix tests.
1 parent 97fcc38 commit 4a9d3c2

File tree

16 files changed

+452
-387
lines changed

16 files changed

+452
-387
lines changed

byte-buddy-agent/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>net.bytebuddy</groupId>
77
<artifactId>byte-buddy-parent</artifactId>
8-
<version>1.15.12-SNAPSHOT</version>
8+
<version>1.16.0-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>byte-buddy-agent</artifactId>

byte-buddy-android-test/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>net.bytebuddy</groupId>
77
<artifactId>byte-buddy-parent</artifactId>
8-
<version>1.15.12-SNAPSHOT</version>
8+
<version>1.16.0-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>byte-buddy-android-test</artifactId>

byte-buddy-android/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>net.bytebuddy</groupId>
77
<artifactId>byte-buddy-parent</artifactId>
8-
<version>1.15.12-SNAPSHOT</version>
8+
<version>1.16.0-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>byte-buddy-android</artifactId>

byte-buddy-benchmark/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>net.bytebuddy</groupId>
77
<artifactId>byte-buddy-parent</artifactId>
8-
<version>1.15.12-SNAPSHOT</version>
8+
<version>1.16.0-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>byte-buddy-benchmark</artifactId>

byte-buddy-dep/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>net.bytebuddy</groupId>
77
<artifactId>byte-buddy-parent</artifactId>
8-
<version>1.15.12-SNAPSHOT</version>
8+
<version>1.16.0-SNAPSHOT</version>
99
</parent>
1010

1111
<!--

byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java

Lines changed: 293 additions & 259 deletions
Large diffs are not rendered by default.

byte-buddy-dep/src/main/java/net/bytebuddy/asm/MemberSubstitution.java

Lines changed: 10 additions & 103 deletions
Large diffs are not rendered by default.

byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeDescription.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,8 @@ public Generic onNonGenericType(Generic typeDescription) {
793793
}
794794

795795
/**
796-
* A visitor that generalizes all reference types to {@link Object} but retains primitive types.
796+
* A visitor that generalizes all reference types to {@link Object} but retains primitive types. Arrays
797+
* are retained as such.
797798
*/
798799
enum Generalizing implements Visitor<Generic> {
799800

@@ -805,8 +806,14 @@ enum Generalizing implements Visitor<Generic> {
805806
/**
806807
* {@inheritDoc}
807808
*/
809+
@SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming component type for array type.")
808810
public Generic onGenericArray(Generic genericArray) {
809-
return Sort.describe(Object.class);
811+
int arity = 0;
812+
do {
813+
arity++;
814+
genericArray = genericArray.getComponentType();
815+
} while (genericArray.isArray());
816+
return ArrayProjection.of(TypeDescription.ForLoadedType.of(Object.class), arity).asGenericType();
810817
}
811818

812819
/**
@@ -820,23 +827,30 @@ public Generic onWildcard(Generic wildcard) {
820827
* {@inheritDoc}
821828
*/
822829
public Generic onParameterizedType(Generic parameterizedType) {
823-
return Sort.describe(Object.class);
830+
return TypeDescription.ForLoadedType.of(Object.class).asGenericType();
824831
}
825832

826833
/**
827834
* {@inheritDoc}
828835
*/
829836
public Generic onTypeVariable(Generic typeVariable) {
830-
return Sort.describe(Object.class);
837+
return TypeDescription.ForLoadedType.of(Object.class).asGenericType();
831838
}
832839

833840
/**
834841
* {@inheritDoc}
835842
*/
843+
@SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming component type for array type.")
836844
public Generic onNonGenericType(Generic typeDescription) {
837-
return typeDescription.isPrimitive()
845+
int arity = 0;
846+
Generic componentType = typeDescription;
847+
while (componentType.isArray()) {
848+
arity++;
849+
componentType = componentType.getComponentType();
850+
}
851+
return componentType.isPrimitive()
838852
? typeDescription
839-
: Sort.describe(Object.class);
853+
: ArrayProjection.of(TypeDescription.ForLoadedType.of(Object.class), arity).asGenericType();
840854
}
841855
}
842856

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2014 - Present Rafael Winterhalter
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package net.bytebuddy.test.precompiled.v7;
17+
18+
import java.lang.invoke.ConstantCallSite;
19+
import java.lang.invoke.MethodHandles;
20+
import java.lang.invoke.MethodType;
21+
22+
public class AdviceBootstrapErased {
23+
24+
public static ConstantCallSite bootstrap(MethodHandles.Lookup lookup,
25+
String invokedMethodName,
26+
MethodType erasedMethodType,
27+
String invokedClassName,
28+
String invokedMethodDescriptor) throws Exception {
29+
return new ConstantCallSite(lookup.findStatic(Class.forName(invokedClassName, false, lookup.lookupClass().getClassLoader()),
30+
invokedMethodName,
31+
MethodType.fromMethodDescriptorString(invokedMethodDescriptor, lookup.lookupClass().getClassLoader())).asType(erasedMethodType));
32+
}
33+
}

byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceTest.java

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.bytebuddy.asm;
22

33
import net.bytebuddy.ByteBuddy;
4+
import net.bytebuddy.description.annotation.AnnotationDescription;
45
import net.bytebuddy.description.method.MethodDescription;
56
import net.bytebuddy.description.modifier.Ownership;
67
import net.bytebuddy.description.modifier.Visibility;
@@ -20,7 +21,9 @@
2021
import net.bytebuddy.matcher.ElementMatchers;
2122
import net.bytebuddy.pool.TypePool;
2223
import net.bytebuddy.test.packaging.AdviceTestHelper;
24+
import net.bytebuddy.test.utility.DebuggingWrapper;
2325
import net.bytebuddy.test.utility.JavaVersionRule;
26+
import net.bytebuddy.utility.JavaConstant;
2427
import net.bytebuddy.utility.JavaType;
2528
import org.junit.Rule;
2629
import org.junit.Test;
@@ -272,6 +275,37 @@ public void testTrivialAdviceWithDelegationBootstrapped() throws Exception {
272275
assertThat(type.getDeclaredField(EXIT).get(null), is((Object) 1));
273276
}
274277

278+
@Test
279+
@JavaVersionRule.Enforce(value = 7, target = TypedAdviceDelegation.class)
280+
public void testErasedAdviceWithDelegationBootstrapped() throws Exception {
281+
Class<?> bootstrap = Class.forName("net.bytebuddy.test.precompiled.v7.AdviceBootstrapErased");
282+
Class<?> type = new ByteBuddy()
283+
.redefine(TypedAdviceDelegation.class)
284+
.visit(DebuggingWrapper.makeDefault())
285+
.visit(Advice.withCustomMapping().bootstrap(bootstrap.getMethod("bootstrap",
286+
JavaType.METHOD_HANDLES_LOOKUP.load(),
287+
String.class,
288+
JavaType.METHOD_TYPE.load(),
289+
String.class,
290+
String.class), new Advice.BootstrapArgumentResolver.Factory() {
291+
public Advice.BootstrapArgumentResolver resolve(final MethodDescription.InDefinedShape adviceMethod, boolean exit) {
292+
return new Advice.BootstrapArgumentResolver() {
293+
public List<JavaConstant> resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod) {
294+
return Arrays.asList(
295+
JavaConstant.Simple.ofLoaded(adviceMethod.getDeclaringType().getName()),
296+
JavaConstant.Simple.ofLoaded(adviceMethod.getDescriptor()));
297+
}
298+
};
299+
}
300+
}, TypeDescription.Generic.Visitor.Generalizing.INSTANCE).to(TypedAdviceDelegation.class).on(named(FOO)))
301+
.make()
302+
.load(bootstrap.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
303+
.getLoaded();
304+
assertThat(type.getDeclaredMethod(FOO, String.class).invoke(type.getDeclaredConstructor().newInstance(), FOO), is((Object) FOO));
305+
assertThat(type.getDeclaredField(ENTER).get(null), is((Object) 1));
306+
assertThat(type.getDeclaredField(EXIT).get(null), is((Object) 1));
307+
}
308+
275309
@Test
276310
public void testTrivialAdviceWithSuppression() throws Exception {
277311
Class<?> type = new ByteBuddy()
@@ -1643,7 +1677,9 @@ public void testAssigningEnterPostProcessorInline() throws Exception {
16431677
Class<?> type = new ByteBuddy()
16441678
.redefine(PostProcessorInline.class)
16451679
.visit(Advice.withCustomMapping().with(new Advice.PostProcessor.Factory() {
1646-
public Advice.PostProcessor make(final MethodDescription.InDefinedShape advice, boolean exit) {
1680+
public Advice.PostProcessor make(List<? extends AnnotationDescription> annotations,
1681+
final TypeDescription returnType,
1682+
boolean exit) {
16471683
return new Advice.PostProcessor() {
16481684
public StackManipulation resolve(TypeDescription instrumentedType,
16491685
MethodDescription instrumentedMethod,
@@ -1652,7 +1688,7 @@ public StackManipulation resolve(TypeDescription instrumentedType,
16521688
Advice.StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
16531689
StackManipulation exceptionHandler) {
16541690
return new StackManipulation.Compound(
1655-
MethodVariableAccess.of(advice.getReturnType()).loadFrom(argumentHandler.enter()),
1691+
MethodVariableAccess.of(returnType).loadFrom(argumentHandler.enter()),
16561692
MethodVariableAccess.store(instrumentedMethod.getParameters().get(0))
16571693
);
16581694
}
@@ -1670,7 +1706,9 @@ public void testAssigningEnterPostProcessorDelegate() throws Exception {
16701706
Class<?> type = new ByteBuddy()
16711707
.redefine(PostProcessorDelegate.class)
16721708
.visit(Advice.withCustomMapping().with(new Advice.PostProcessor.Factory() {
1673-
public Advice.PostProcessor make(final MethodDescription.InDefinedShape advice, boolean exit) {
1709+
public Advice.PostProcessor make(List<? extends AnnotationDescription> annotations,
1710+
final TypeDescription returnType,
1711+
boolean exit) {
16741712
return new Advice.PostProcessor() {
16751713
public StackManipulation resolve(TypeDescription instrumentedType,
16761714
MethodDescription instrumentedMethod,
@@ -1679,7 +1717,7 @@ public StackManipulation resolve(TypeDescription instrumentedType,
16791717
Advice.StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
16801718
StackManipulation exceptionHandler) {
16811719
return new StackManipulation.Compound(
1682-
MethodVariableAccess.of(advice.getReturnType()).loadFrom(argumentHandler.enter()),
1720+
MethodVariableAccess.of(returnType).loadFrom(argumentHandler.enter()),
16831721
MethodVariableAccess.store(instrumentedMethod.getParameters().get(0))
16841722
);
16851723
}
@@ -2467,6 +2505,34 @@ private static void exit() {
24672505
}
24682506
}
24692507

2508+
2509+
@SuppressWarnings("unused")
2510+
public static class TypedAdviceDelegation {
2511+
2512+
public static int enter, exit;
2513+
2514+
public String foo(String argument) {
2515+
return argument;
2516+
}
2517+
2518+
@Advice.OnMethodEnter(inline = false)
2519+
private static String enter(@Advice.Argument(0) String argument) {
2520+
if (!FOO.equals(argument)) {
2521+
throw new AssertionError();
2522+
}
2523+
enter++;
2524+
return BAR;
2525+
}
2526+
2527+
@Advice.OnMethodExit(inline = false, onThrowable = Exception.class)
2528+
private static void exit(@Advice.Enter String enter) {
2529+
if (!BAR.equals(enter)) {
2530+
throw new AssertionError();
2531+
}
2532+
exit++;
2533+
}
2534+
}
2535+
24702536
@SuppressWarnings("unused")
24712537
public static class EmptyMethod {
24722538

0 commit comments

Comments
 (0)