diff --git a/byte-buddy-agent/pom.xml b/byte-buddy-agent/pom.xml
index 3dbfafa2ff8..068c287a26d 100644
--- a/byte-buddy-agent/pom.xml
+++ b/byte-buddy-agent/pom.xml
@@ -5,7 +5,7 @@
byte-buddy-parent
net.bytebuddy
- 1.11.20
+ 1.11.21
byte-buddy-agent
@@ -68,7 +68,7 @@
net.bytebuddy
byte-buddy
- 1.11.19
+ 1.11.20
test
diff --git a/byte-buddy-android-test/pom.xml b/byte-buddy-android-test/pom.xml
index cf745a79299..4eb0633f4f9 100644
--- a/byte-buddy-android-test/pom.xml
+++ b/byte-buddy-android-test/pom.xml
@@ -5,7 +5,7 @@
net.bytebuddy
byte-buddy-parent
- 1.11.20
+ 1.11.21
byte-buddy-android-test
diff --git a/byte-buddy-android/pom.xml b/byte-buddy-android/pom.xml
index 7bbacb4e758..3df8f5a8823 100644
--- a/byte-buddy-android/pom.xml
+++ b/byte-buddy-android/pom.xml
@@ -5,7 +5,7 @@
byte-buddy-parent
net.bytebuddy
- 1.11.20
+ 1.11.21
byte-buddy-android
diff --git a/byte-buddy-benchmark/pom.xml b/byte-buddy-benchmark/pom.xml
index c1c8662e2bc..5886cb1976c 100644
--- a/byte-buddy-benchmark/pom.xml
+++ b/byte-buddy-benchmark/pom.xml
@@ -5,7 +5,7 @@
byte-buddy-parent
net.bytebuddy
- 1.11.20
+ 1.11.21
byte-buddy-benchmark
diff --git a/byte-buddy-dep/pom.xml b/byte-buddy-dep/pom.xml
index bd55478c582..4bf7935910b 100644
--- a/byte-buddy-dep/pom.xml
+++ b/byte-buddy-dep/pom.xml
@@ -5,7 +5,7 @@
net.bytebuddy
byte-buddy-parent
- 1.11.20
+ 1.11.21
byte-buddy-dep
@@ -113,7 +113,7 @@
net.bytebuddy
byte-buddy-maven-plugin
- 1.11.19
+ 1.11.20
compile
@@ -128,19 +128,19 @@
net.bytebuddy
byte-buddy
- 1.11.19
+ 1.11.20
net.bytebuddy.build.HashCodeAndEqualsPlugin$WithNonNullableFields
net.bytebuddy
byte-buddy
- 1.11.19
+ 1.11.20
net.bytebuddy.build.CachedReturnPlugin
net.bytebuddy
byte-buddy
- 1.11.19
+ 1.11.20
net.bytebuddy.build.AccessControllerPlugin
@@ -152,13 +152,13 @@
net.bytebuddy
byte-buddy
- 1.11.19
+ 1.11.20
net.bytebuddy.build.DispatcherAnnotationPlugin
net.bytebuddy
byte-buddy
- 1.11.19
+ 1.11.20
net.bytebuddy.build.RepeatedAnnotationPlugin
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java b/byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java
index 078e7ec016e..2e4d7c0bf98 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java
@@ -4887,16 +4887,20 @@ public interface PostProcessor {
/**
* Resolves this post processor for a given instrumented method.
*
- * @param instrumentedType The instrumented type.
- * @param instrumentedMethod The instrumented method.
- * @param assigner The assigner to use.
- * @param argumentHandler The argument handler for the instrumented method.
+ * @param instrumentedType The instrumented type.
+ * @param instrumentedMethod The instrumented method.
+ * @param assigner The assigner to use.
+ * @param argumentHandler The argument handler to use.
+ * @param stackMapFrameHandler The argument handler for the instrumented method.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @return The stack manipulation to apply.
*/
StackManipulation resolve(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
Assigner assigner,
- ArgumentHandler argumentHandler);
+ ArgumentHandler argumentHandler,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ StackManipulation exceptionHandler);
/**
* A factory for creating a {@link PostProcessor}.
@@ -4977,7 +4981,9 @@ enum NoOp implements PostProcessor, Factory {
public StackManipulation resolve(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
Assigner assigner,
- ArgumentHandler argumentHandler) {
+ ArgumentHandler argumentHandler,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ StackManipulation exceptionHandler) {
return StackManipulation.Trivial.INSTANCE;
}
@@ -5015,10 +5021,17 @@ protected Compound(List postProcessors) {
public StackManipulation resolve(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
Assigner assigner,
- ArgumentHandler argumentHandler) {
+ ArgumentHandler argumentHandler,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ StackManipulation exceptionHandler) {
List stackManipulations = new ArrayList(postProcessors.size());
for (PostProcessor postProcessor : postProcessors) {
- stackManipulations.add(postProcessor.resolve(instrumentedType, instrumentedMethod, assigner, argumentHandler));
+ stackManipulations.add(postProcessor.resolve(instrumentedType,
+ instrumentedMethod,
+ assigner,
+ argumentHandler,
+ stackMapFrameHandler,
+ exceptionHandler));
}
return new StackManipulation.Compound(stackManipulations);
}
@@ -5597,7 +5610,7 @@ public void recordMaxima(int stackSize, int localVariableLength) {
/**
* A handler for computing and translating stack map frames.
*/
- protected interface StackMapFrameHandler {
+ public interface StackMapFrameHandler {
/**
* Translates a frame.
@@ -5632,6 +5645,21 @@ protected interface StackMapFrameHandler {
*/
void injectCompletionFrame(MethodVisitor methodVisitor);
+ /**
+ * A stack map frame handler that can be used within a post processor. Emitting frames via this
+ * handler is the only legal way for a post processor to produce frames.
+ */
+ interface ForPostProcessor {
+
+ /**
+ * Injects a frame that represents the current state.
+ *
+ * @param methodVisitor The method visitor onto which to apply the stack map frame.
+ * @param stack A list of types that are currently on the stack.
+ */
+ void injectIntermediateFrame(MethodVisitor methodVisitor, List extends TypeDescription> stack);
+ }
+
/**
* A stack map frame handler for an instrumented method.
*/
@@ -5685,7 +5713,7 @@ interface ForInstrumentedMethod extends StackMapFrameHandler {
/**
* A stack map frame handler for an advice method.
*/
- interface ForAdvice extends StackMapFrameHandler {
+ interface ForAdvice extends StackMapFrameHandler, ForPostProcessor {
/* marker interface */
}
@@ -5773,6 +5801,13 @@ public void injectStartFrame(MethodVisitor methodVisitor) {
public void injectPostCompletionFrame(MethodVisitor methodVisitor) {
/* do nothing */
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void injectIntermediateFrame(MethodVisitor methodVisitor, List extends TypeDescription> stack) {
+ /* do nothing */
+ }
}
/**
@@ -5800,6 +5835,11 @@ abstract class Default implements ForInstrumentedMethod {
*/
protected final List extends TypeDescription> initialTypes;
+ /**
+ * A list of virtual arguments that are available after the enter advice method is executed.
+ */
+ protected final List extends TypeDescription> latentTypes;
+
/**
* A list of virtual method arguments that are available before the instrumented method is executed.
*/
@@ -5826,6 +5866,7 @@ abstract class Default implements ForInstrumentedMethod {
* @param instrumentedType The instrumented type.
* @param instrumentedMethod The instrumented method.
* @param initialTypes A list of virtual method arguments that are explicitly added before any code execution.
+ * @param latentTypes A list of virtual arguments that are available after the enter advice method is executed.
* @param preMethodTypes A list of virtual method arguments that are available before the instrumented method is executed.
* @param postMethodTypes A list of virtual method arguments that are available after the instrumented method has completed.
* @param expandFrames {@code true} if the meta data handler is expected to expand its frames.
@@ -5833,12 +5874,14 @@ abstract class Default implements ForInstrumentedMethod {
protected Default(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
List extends TypeDescription> initialTypes,
+ List extends TypeDescription> latentTypes,
List extends TypeDescription> preMethodTypes,
List extends TypeDescription> postMethodTypes,
boolean expandFrames) {
this.instrumentedType = instrumentedType;
this.instrumentedMethod = instrumentedMethod;
this.initialTypes = initialTypes;
+ this.latentTypes = latentTypes;
this.preMethodTypes = preMethodTypes;
this.postMethodTypes = postMethodTypes;
this.expandFrames = expandFrames;
@@ -5850,6 +5893,7 @@ protected Default(TypeDescription instrumentedType,
* @param instrumentedType The instrumented type.
* @param instrumentedMethod The instrumented method.
* @param initialTypes A list of virtual method arguments that are explicitly added before any code execution.
+ * @param latentTypes A list of virtual arguments that are available after the enter advice method is executed.
* @param preMethodTypes A list of virtual method arguments that are available before the instrumented method is executed.
* @param postMethodTypes A list of virtual method arguments that are available after the instrumented method has completed.
* @param exitAdvice {@code true} if the current advice implies exit advice.
@@ -5862,6 +5906,7 @@ protected Default(TypeDescription instrumentedType,
protected static ForInstrumentedMethod of(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
List extends TypeDescription> initialTypes,
+ List extends TypeDescription> latentTypes,
List extends TypeDescription> preMethodTypes,
List extends TypeDescription> postMethodTypes,
boolean exitAdvice,
@@ -5874,11 +5919,13 @@ protected static ForInstrumentedMethod of(TypeDescription instrumentedType,
} else if (!exitAdvice && initialTypes.isEmpty()) {
return new Trivial(instrumentedType,
instrumentedMethod,
+ latentTypes,
(readerFlags & ClassReader.EXPAND_FRAMES) != 0);
} else if (copyArguments) {
return new WithPreservedArguments.WithArgumentCopy(instrumentedType,
instrumentedMethod,
initialTypes,
+ latentTypes,
preMethodTypes,
postMethodTypes,
(readerFlags & ClassReader.EXPAND_FRAMES) != 0);
@@ -5886,6 +5933,7 @@ protected static ForInstrumentedMethod of(TypeDescription instrumentedType,
return new WithPreservedArguments.WithoutArgumentCopy(instrumentedType,
instrumentedMethod,
initialTypes,
+ latentTypes,
preMethodTypes,
postMethodTypes,
(readerFlags & ClassReader.EXPAND_FRAMES) != 0,
@@ -5897,7 +5945,7 @@ protected static ForInstrumentedMethod of(TypeDescription instrumentedType,
* {@inheritDoc}
*/
public StackMapFrameHandler.ForAdvice bindEnter(MethodDescription.InDefinedShape adviceMethod) {
- return new ForAdvice(adviceMethod, initialTypes, preMethodTypes, TranslationMode.ENTER, instrumentedMethod.isConstructor()
+ return new ForAdvice(adviceMethod, initialTypes, latentTypes, preMethodTypes, TranslationMode.ENTER, instrumentedMethod.isConstructor()
? Initialization.UNITIALIZED
: Initialization.INITIALIZED);
}
@@ -6146,6 +6194,9 @@ protected enum Initialization {
* {@inheritDoc}
*/
protected Object toFrame(TypeDescription typeDescription) {
+ if (typeDescription.isPrimitive()) {
+ throw new IllegalArgumentException("Cannot assume primitive uninitialized value: " + typeDescription);
+ }
return Opcodes.UNINITIALIZED_THIS;
}
},
@@ -6195,12 +6246,14 @@ protected static class Trivial extends Default {
*
* @param instrumentedType The instrumented type.
* @param instrumentedMethod The instrumented method.
+ * @param latentTypes A list of virtual arguments that are available after the enter advice method is executed.
* @param expandFrames {@code true} if the meta data handler is expected to expand its frames.
*/
- protected Trivial(TypeDescription instrumentedType, MethodDescription instrumentedMethod, boolean expandFrames) {
+ protected Trivial(TypeDescription instrumentedType, MethodDescription instrumentedMethod, List extends TypeDescription> latentTypes, boolean expandFrames) {
super(instrumentedType,
instrumentedMethod,
Collections.emptyList(),
+ latentTypes,
Collections.emptyList(),
Collections.emptyList(),
expandFrames);
@@ -6284,6 +6337,7 @@ protected abstract static class WithPreservedArguments extends Default {
* @param instrumentedType The instrumented type.
* @param instrumentedMethod The instrumented method.
* @param initialTypes A list of virtual method arguments that are explicitly added before any code execution.
+ * @param latentTypes A list of virtual arguments that are available after the enter advice method is executed.
* @param preMethodTypes A list of virtual method arguments that are available before the instrumented method is executed.
* @param postMethodTypes A list of virtual method arguments that are available after the instrumented method has completed.
* @param expandFrames {@code true} if the meta data handler is expected to expand its frames.
@@ -6292,11 +6346,12 @@ protected abstract static class WithPreservedArguments extends Default {
protected WithPreservedArguments(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
List extends TypeDescription> initialTypes,
+ List extends TypeDescription> latentTypes,
List extends TypeDescription> preMethodTypes,
List extends TypeDescription> postMethodTypes,
boolean expandFrames,
boolean allowCompactCompletionFrame) {
- super(instrumentedType, instrumentedMethod, initialTypes, preMethodTypes, postMethodTypes, expandFrames);
+ super(instrumentedType, instrumentedMethod, initialTypes, latentTypes, preMethodTypes, postMethodTypes, expandFrames);
this.allowCompactCompletionFrame = allowCompactCompletionFrame;
}
@@ -6324,6 +6379,7 @@ public StackMapFrameHandler.ForAdvice bindExit(MethodDescription.InDefinedShape
return new ForAdvice(adviceMethod,
CompoundList.of(initialTypes, preMethodTypes, postMethodTypes),
Collections.emptyList(),
+ Collections.emptyList(),
TranslationMode.EXIT,
Initialization.INITIALIZED);
}
@@ -6435,6 +6491,7 @@ protected static class WithoutArgumentCopy extends WithPreservedArguments {
* @param instrumentedType The instrumented type.
* @param instrumentedMethod The instrumented method.
* @param initialTypes A list of virtual method arguments that are explicitly added before any code execution.
+ * @param latentTypes A list of virtual arguments that are available after the enter advice method is executed.
* @param preMethodTypes A list of virtual method arguments that are available before the instrumented method is executed.
* @param postMethodTypes A list of virtual method arguments that are available after the instrumented method has completed.
* @param expandFrames {@code true} if the meta data handler is expected to expand its frames.
@@ -6443,11 +6500,12 @@ protected static class WithoutArgumentCopy extends WithPreservedArguments {
protected WithoutArgumentCopy(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
List extends TypeDescription> initialTypes,
+ List extends TypeDescription> latentTypes,
List extends TypeDescription> preMethodTypes,
List extends TypeDescription> postMethodTypes,
boolean expandFrames,
boolean allowCompactCompletionFrame) {
- super(instrumentedType, instrumentedMethod, initialTypes, preMethodTypes, postMethodTypes, expandFrames, allowCompactCompletionFrame);
+ super(instrumentedType, instrumentedMethod, initialTypes, latentTypes, preMethodTypes, postMethodTypes, expandFrames, allowCompactCompletionFrame);
}
/**
@@ -6489,6 +6547,7 @@ protected static class WithArgumentCopy extends WithPreservedArguments {
* @param instrumentedType The instrumented type.
* @param instrumentedMethod The instrumented method.
* @param initialTypes A list of virtual method arguments that are explicitly added before any code execution.
+ * @param latentTypes The types that are given post execution of a possible enter advice.
* @param preMethodTypes A list of virtual method arguments that are available before the instrumented method is executed.
* @param postMethodTypes A list of virtual method arguments that are available after the instrumented method has completed.
* @param expandFrames {@code true} if the meta data handler is expected to expand its frames.
@@ -6496,10 +6555,11 @@ protected static class WithArgumentCopy extends WithPreservedArguments {
protected WithArgumentCopy(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
List extends TypeDescription> initialTypes,
+ List extends TypeDescription> latentTypes,
List extends TypeDescription> preMethodTypes,
List extends TypeDescription> postMethodTypes,
boolean expandFrames) {
- super(instrumentedType, instrumentedMethod, initialTypes, preMethodTypes, postMethodTypes, expandFrames, true);
+ super(instrumentedType, instrumentedMethod, initialTypes, latentTypes, preMethodTypes, postMethodTypes, expandFrames, true);
}
/**
@@ -6632,6 +6692,11 @@ protected class ForAdvice implements StackMapFrameHandler.ForAdvice {
*/
protected final List extends TypeDescription> startTypes;
+ /**
+ * The types that are given post execution of the advice.
+ */
+ private final List extends TypeDescription> intermediateTypes;
+
/**
* The types provided after execution of the advice code.
*/
@@ -6647,26 +6712,35 @@ protected class ForAdvice implements StackMapFrameHandler.ForAdvice {
*/
private final Initialization initialization;
+ /**
+ * {@code true} if an intermediate frame was yielded.
+ */
+ private boolean intermedate;
+
/**
* Creates a new meta data handler for an advice method.
*
- * @param adviceMethod The method description for which frames are translated.
- * @param startTypes The types provided before execution of the advice code.
- * @param endTypes The types provided after execution of the advice code.
- * @param translationMode The translation mode to apply for this advice method. Should be
- * either {@link TranslationMode#ENTER} or {@link TranslationMode#EXIT}.
- * @param initialization The initialization to apply when resolving a reference to the instance on which a non-static method is invoked.
+ * @param adviceMethod The method description for which frames are translated.
+ * @param startTypes The types provided before execution of the advice code.
+ * @param intermediateTypes The types that are given post execution of the advice.
+ * @param endTypes The types provided after execution of the advice code.
+ * @param translationMode The translation mode to apply for this advice method. Should be
+ * either {@link TranslationMode#ENTER} or {@link TranslationMode#EXIT}.
+ * @param initialization The initialization to apply when resolving a reference to the instance on which a non-static method is invoked.
*/
protected ForAdvice(MethodDescription.InDefinedShape adviceMethod,
List extends TypeDescription> startTypes,
+ List extends TypeDescription> intermediateTypes,
List extends TypeDescription> endTypes,
TranslationMode translationMode,
Initialization initialization) {
this.adviceMethod = adviceMethod;
this.startTypes = startTypes;
+ this.intermediateTypes = intermediateTypes;
this.endTypes = endTypes;
this.translationMode = translationMode;
this.initialization = initialization;
+ intermedate = false;
}
/**
@@ -6727,8 +6801,8 @@ public void injectExceptionFrame(MethodVisitor methodVisitor) {
public void injectCompletionFrame(MethodVisitor methodVisitor) {
if (expandFrames) {
injectFullFrame(methodVisitor, initialization, CompoundList.of(startTypes, endTypes), Collections.emptyList());
- } else if (currentFrameDivergence == 0 && endTypes.size() < 4) {
- if (endTypes.isEmpty()) {
+ } else if (currentFrameDivergence == 0 && (intermedate || endTypes.size() < 4)) {
+ if (intermedate || endTypes.isEmpty()) {
methodVisitor.visitFrame(Opcodes.F_SAME, EMPTY.length, EMPTY, EMPTY.length, EMPTY);
} else {
Object[] local = new Object[endTypes.size()];
@@ -6740,10 +6814,49 @@ public void injectCompletionFrame(MethodVisitor methodVisitor) {
}
} else if (currentFrameDivergence < 3 && endTypes.isEmpty()) {
methodVisitor.visitFrame(Opcodes.F_CHOP, currentFrameDivergence, EMPTY, EMPTY.length, EMPTY);
+ currentFrameDivergence = 0;
} else {
injectFullFrame(methodVisitor, initialization, CompoundList.of(startTypes, endTypes), Collections.emptyList());
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void injectIntermediateFrame(MethodVisitor methodVisitor, List extends TypeDescription> stack) {
+ if (expandFrames) {
+ injectFullFrame(methodVisitor, initialization, CompoundList.of(startTypes, intermediateTypes), stack);
+ } else if (intermedate && stack.size() < 2) {
+ if (stack.isEmpty()) {
+ methodVisitor.visitFrame(Opcodes.F_SAME, EMPTY.length, EMPTY, EMPTY.length, EMPTY);
+ } else {
+ methodVisitor.visitFrame(Opcodes.F_SAME1, EMPTY.length, EMPTY, 1, new Object[]{Initialization.INITIALIZED.toFrame(stack.get(0))});
+ }
+ } else if (currentFrameDivergence == 0
+ && intermediateTypes.size() < 4
+ && (stack.isEmpty() || stack.size() < 2 && intermediateTypes.isEmpty())) {
+ if (intermediateTypes.isEmpty()) {
+ if (stack.isEmpty()) {
+ methodVisitor.visitFrame(Opcodes.F_SAME, EMPTY.length, EMPTY, EMPTY.length, EMPTY);
+ } else {
+ methodVisitor.visitFrame(Opcodes.F_SAME1, EMPTY.length, EMPTY, 1, new Object[]{Initialization.INITIALIZED.toFrame(stack.get(0))});
+ }
+ } else {
+ Object[] local = new Object[intermediateTypes.size()];
+ int index = 0;
+ for (TypeDescription typeDescription : intermediateTypes) {
+ local[index++] = Initialization.INITIALIZED.toFrame(typeDescription);
+ }
+ methodVisitor.visitFrame(Opcodes.F_APPEND, local.length, local, EMPTY.length, EMPTY);
+ }
+ } else if (currentFrameDivergence < 3 && intermediateTypes.isEmpty() && stack.isEmpty()) {
+ methodVisitor.visitFrame(Opcodes.F_CHOP, currentFrameDivergence, EMPTY, EMPTY.length, EMPTY);
+ } else {
+ injectFullFrame(methodVisitor, initialization, CompoundList.of(startTypes, intermediateTypes), stack);
+ }
+ currentFrameDivergence = intermediateTypes.size() - endTypes.size();
+ intermedate = true;
+ }
}
}
}
@@ -7608,6 +7721,13 @@ interface ForMethodEnter extends Resolved {
* @return {@code true} if the first discovered line number information should be prepended to the advice code.
*/
boolean isPrependLineNumber();
+
+ /**
+ * Returns the actual advice type, even if it is not required post advice processing.
+ *
+ * @return The actual advice type, even if it is not required post advice processing.
+ */
+ TypeDefinition getActualAdviceType();
}
/**
@@ -7777,6 +7897,13 @@ public boolean isPrependLineNumber() {
return false;
}
+ /**
+ * {@inheritDoc}
+ */
+ public TypeDefinition getActualAdviceType() {
+ return TypeDescription.VOID;
+ }
+
/**
* {@inheritDoc}
*/
@@ -8004,6 +8131,7 @@ protected Resolved(MethodDescription.InDefinedShape adviceMethod,
* @param instrumentedMethod A description of the instrumented method.
* @param suppressionHandler A bound suppression handler that is used for suppressing exceptions of this advice method.
* @param relocationHandler A bound relocation handler that is responsible for considering a non-standard control flow.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @return A method visitor for visiting the advice method's byte code.
*/
protected abstract MethodVisitor apply(MethodVisitor methodVisitor,
@@ -8015,7 +8143,8 @@ protected abstract MethodVisitor apply(MethodVisitor methodVisitor,
TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler);
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler);
/**
* A bound advice method that copies the code by first extracting the exception table and later appending the
@@ -8073,6 +8202,11 @@ protected class AdviceMethodInliner extends ClassVisitor implements Bound {
*/
protected final RelocationHandler.Bound relocationHandler;
+ /**
+ * The exception handler that is resolved for the instrumented method.
+ */
+ protected final StackManipulation exceptionHandler;
+
/**
* A class reader for parsing the class file containing the represented advice method.
*/
@@ -8096,6 +8230,7 @@ protected class AdviceMethodInliner extends ClassVisitor implements Bound {
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler A bound suppression handler that is used for suppressing exceptions of this advice method.
* @param relocationHandler A bound relocation handler that is responsible for considering a non-standard control flow.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @param classReader A class reader for parsing the class file containing the represented advice method.
*/
protected AdviceMethodInliner(TypeDescription instrumentedType,
@@ -8108,6 +8243,7 @@ protected AdviceMethodInliner(TypeDescription instrumentedType,
StackMapFrameHandler.ForInstrumentedMethod stackMapFrameHandler,
SuppressionHandler.Bound suppressionHandler,
RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler,
ClassReader classReader) {
super(OpenedClassReader.ASM_API);
this.instrumentedType = instrumentedType;
@@ -8119,8 +8255,9 @@ protected AdviceMethodInliner(TypeDescription instrumentedType,
this.methodSizeHandler = methodSizeHandler;
this.stackMapFrameHandler = stackMapFrameHandler;
this.suppressionHandler = suppressionHandler;
- this.classReader = classReader;
this.relocationHandler = relocationHandler;
+ this.exceptionHandler = exceptionHandler;
+ this.classReader = classReader;
labels = new ArrayList();
}
@@ -8180,7 +8317,8 @@ public MethodVisitor visitMethod(int modifiers, String internalName, String desc
instrumentedType,
instrumentedMethod,
suppressionHandler,
- relocationHandler)) : IGNORE_METHOD;
+ relocationHandler,
+ exceptionHandler)) : IGNORE_METHOD;
}
/**
@@ -8439,6 +8577,7 @@ public Bound bind(TypeDescription instrumentedType,
stackMapFrameHandler,
suppressionHandler.bind(exceptionHandler),
relocationHandler.bind(instrumentedMethod, relocation),
+ exceptionHandler,
classReader);
}
@@ -8449,6 +8588,13 @@ public boolean isPrependLineNumber() {
return prependLineNumber;
}
+ /**
+ * {@inheritDoc}
+ */
+ public TypeDefinition getActualAdviceType() {
+ return adviceMethod.getReturnType();
+ }
+
/**
* {@inheritDoc}
*/
@@ -8466,7 +8612,8 @@ protected MethodVisitor apply(MethodVisitor methodVisitor,
TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
return doApply(methodVisitor,
implementationContext,
assigner,
@@ -8476,7 +8623,8 @@ protected MethodVisitor apply(MethodVisitor methodVisitor,
instrumentedType,
instrumentedMethod,
suppressionHandler,
- relocationHandler);
+ relocationHandler,
+ exceptionHandler);
}
/**
@@ -8492,6 +8640,7 @@ protected MethodVisitor apply(MethodVisitor methodVisitor,
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler The bound suppression handler to use.
* @param relocationHandler The bound relocation handler to use.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @return A method visitor for visiting the advice method's byte code.
*/
protected MethodVisitor doApply(MethodVisitor methodVisitor,
@@ -8503,7 +8652,8 @@ protected MethodVisitor doApply(MethodVisitor methodVisitor,
TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
Map offsetMappings = new HashMap();
for (Map.Entry entry : this.offsetMappings.entrySet()) {
offsetMappings.put(entry.getKey(), entry.getValue().resolve(instrumentedType,
@@ -8524,6 +8674,7 @@ protected MethodVisitor doApply(MethodVisitor methodVisitor,
offsetMappings,
suppressionHandler,
relocationHandler,
+ exceptionHandler,
postProcessor,
false);
}
@@ -8604,7 +8755,8 @@ protected MethodVisitor doApply(MethodVisitor methodVisitor,
TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
methodSizeHandler.requireLocalVariableLengthPadding(adviceMethod.getReturnType().getStackSize().getSize());
return super.doApply(methodVisitor,
implementationContext,
@@ -8615,7 +8767,8 @@ protected MethodVisitor doApply(MethodVisitor methodVisitor,
instrumentedType,
instrumentedMethod,
suppressionHandler,
- relocationHandler);
+ relocationHandler,
+ exceptionHandler);
}
}
}
@@ -8731,7 +8884,8 @@ protected MethodVisitor apply(MethodVisitor methodVisitor,
TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
return doApply(methodVisitor,
implementationContext,
assigner,
@@ -8741,7 +8895,8 @@ protected MethodVisitor apply(MethodVisitor methodVisitor,
instrumentedType,
instrumentedMethod,
suppressionHandler,
- relocationHandler);
+ relocationHandler,
+ exceptionHandler);
}
/**
@@ -8757,6 +8912,7 @@ protected MethodVisitor apply(MethodVisitor methodVisitor,
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler The bound suppression handler to use.
* @param relocationHandler The bound relocation handler to use.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @return A method visitor for visiting the advice method's byte code.
*/
private MethodVisitor doApply(MethodVisitor methodVisitor,
@@ -8768,7 +8924,8 @@ private MethodVisitor doApply(MethodVisitor methodVisitor,
TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
Map offsetMappings = new HashMap();
for (Map.Entry entry : this.offsetMappings.entrySet()) {
offsetMappings.put(entry.getKey(), entry.getValue().resolve(instrumentedType,
@@ -8789,6 +8946,7 @@ private MethodVisitor doApply(MethodVisitor methodVisitor,
offsetMappings,
suppressionHandler,
relocationHandler,
+ exceptionHandler,
postProcessor,
true);
}
@@ -8832,6 +8990,7 @@ public Bound bind(TypeDescription instrumentedType,
stackMapFrameHandler,
suppressionHandler.bind(exceptionHandler),
relocationHandler.bind(instrumentedMethod, relocation),
+ exceptionHandler,
classReader);
}
@@ -8981,6 +9140,11 @@ protected static class CodeTranslationVisitor extends MethodVisitor {
*/
private final RelocationHandler.Bound relocationHandler;
+ /**
+ * The exception handler that is resolved for the instrumented method.
+ */
+ private final StackManipulation exceptionHandler;
+
/**
* The post processor to apply.
*/
@@ -9011,6 +9175,7 @@ protected static class CodeTranslationVisitor extends MethodVisitor {
* @param offsetMappings A mapping of offsets to resolved target offsets in the instrumented method.
* @param suppressionHandler A bound suppression handler that is used for suppressing exceptions of this advice method.
* @param relocationHandler A bound relocation handler that is responsible for considering a non-standard control flow.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @param postProcessor The post processor to apply.
* @param exit {@code true} if this visitor is for exit advice.
*/
@@ -9026,6 +9191,7 @@ protected CodeTranslationVisitor(MethodVisitor methodVisitor,
Map offsetMappings,
SuppressionHandler.Bound suppressionHandler,
RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler,
PostProcessor postProcessor,
boolean exit) {
super(OpenedClassReader.ASM_API, new StackAwareMethodVisitor(methodVisitor, instrumentedMethod));
@@ -9041,6 +9207,7 @@ protected CodeTranslationVisitor(MethodVisitor methodVisitor,
this.offsetMappings = offsetMappings;
this.suppressionHandler = suppressionHandler;
this.relocationHandler = relocationHandler;
+ this.exceptionHandler = exceptionHandler;
this.postProcessor = postProcessor;
this.exit = exit;
endOfMethod = new Label();
@@ -9199,7 +9366,7 @@ public void visitEnd() {
methodVisitor.visitVarInsn(Opcodes.ASTORE, exit ? argumentHandler.exit() : argumentHandler.enter());
}
methodSizeHandler.requireStackSize(postProcessor
- .resolve(instrumentedType, instrumentedMethod, assigner, argumentHandler)
+ .resolve(instrumentedType, instrumentedMethod, assigner, argumentHandler, stackMapFrameHandler, exceptionHandler)
.apply(methodVisitor, implementationContext).getMaximalSize());
methodSizeHandler.requireStackSize(relocationHandler.apply(methodVisitor, exit ? argumentHandler.exit() : argumentHandler.enter()));
stackMapFrameHandler.injectCompletionFrame(methodVisitor);
@@ -9454,6 +9621,11 @@ protected abstract static class AdviceMethodWriter implements Bound {
*/
private final RelocationHandler.Bound relocationHandler;
+ /**
+ * The exception handler that is resolved for the instrumented method.
+ */
+ private final StackManipulation exceptionHandler;
+
/**
* The post processor to apply.
*/
@@ -9480,6 +9652,7 @@ protected abstract static class AdviceMethodWriter implements Bound {
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler A bound suppression handler that is used for suppressing exceptions of this advice method.
* @param relocationHandler A bound relocation handler that is responsible for considering a non-standard control flow.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @param delegator The delegator to use.
*/
protected AdviceMethodWriter(MethodDescription.InDefinedShape adviceMethod,
@@ -9495,6 +9668,7 @@ protected AdviceMethodWriter(MethodDescription.InDefinedShape adviceMethod,
StackMapFrameHandler.ForAdvice stackMapFrameHandler,
SuppressionHandler.Bound suppressionHandler,
RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler,
Delegator delegator) {
this.adviceMethod = adviceMethod;
this.instrumentedType = instrumentedType;
@@ -9509,6 +9683,7 @@ protected AdviceMethodWriter(MethodDescription.InDefinedShape adviceMethod,
this.stackMapFrameHandler = stackMapFrameHandler;
this.suppressionHandler = suppressionHandler;
this.relocationHandler = relocationHandler;
+ this.exceptionHandler = exceptionHandler;
this.delegator = delegator;
}
@@ -9553,7 +9728,7 @@ public void apply() {
methodVisitor.visitVarInsn(Opcodes.ASTORE, isExitAdvice() ? argumentHandler.exit() : argumentHandler.enter());
}
methodSizeHandler.requireStackSize(postProcessor
- .resolve(instrumentedType, instrumentedMethod, assigner, argumentHandler)
+ .resolve(instrumentedType, instrumentedMethod, assigner, argumentHandler, stackMapFrameHandler, exceptionHandler)
.apply(methodVisitor, implementationContext).getMaximalSize());
methodSizeHandler.requireStackSize(relocationHandler.apply(methodVisitor, isExitAdvice() ? argumentHandler.exit() : argumentHandler.enter()));
stackMapFrameHandler.injectCompletionFrame(methodVisitor);
@@ -9589,6 +9764,7 @@ protected static class ForMethodEnter extends AdviceMethodWriter {
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler A bound suppression handler that is used for suppressing exceptions of this advice method.
* @param relocationHandler A bound relocation handler that is responsible for considering a non-standard control flow.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @param delegator The delegator to use.
*/
protected ForMethodEnter(MethodDescription.InDefinedShape adviceMethod,
@@ -9604,6 +9780,7 @@ protected ForMethodEnter(MethodDescription.InDefinedShape adviceMethod,
StackMapFrameHandler.ForAdvice stackMapFrameHandler,
SuppressionHandler.Bound suppressionHandler,
RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler,
Delegator delegator) {
super(adviceMethod,
instrumentedType,
@@ -9618,6 +9795,7 @@ protected ForMethodEnter(MethodDescription.InDefinedShape adviceMethod,
stackMapFrameHandler,
suppressionHandler,
relocationHandler,
+ exceptionHandler,
delegator);
}
@@ -9655,6 +9833,7 @@ protected static class ForMethodExit extends AdviceMethodWriter {
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler A bound suppression handler that is used for suppressing exceptions of this advice method.
* @param relocationHandler A bound relocation handler that is responsible for considering a non-standard control flow.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @param delegator The delegator to use.
*/
protected ForMethodExit(MethodDescription.InDefinedShape adviceMethod,
@@ -9670,6 +9849,7 @@ protected ForMethodExit(MethodDescription.InDefinedShape adviceMethod,
StackMapFrameHandler.ForAdvice stackMapFrameHandler,
SuppressionHandler.Bound suppressionHandler,
RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler,
Delegator delegator) {
super(adviceMethod,
instrumentedType,
@@ -9684,6 +9864,7 @@ protected ForMethodExit(MethodDescription.InDefinedShape adviceMethod,
stackMapFrameHandler,
suppressionHandler,
relocationHandler,
+ exceptionHandler,
delegator);
}
@@ -9796,6 +9977,13 @@ public boolean isPrependLineNumber() {
return prependLineNumber;
}
+ /**
+ * {@inheritDoc}
+ */
+ public TypeDefinition getActualAdviceType() {
+ return adviceMethod.getReturnType();
+ }
+
@Override
protected Bound resolve(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
@@ -9816,7 +10004,8 @@ protected Bound resolve(TypeDescription instrumentedType,
methodSizeHandler.bindEnter(adviceMethod),
stackMapFrameHandler.bindEnter(adviceMethod),
suppressionHandler.bind(exceptionHandler),
- relocationHandler.bind(instrumentedMethod, relocation));
+ relocationHandler.bind(instrumentedMethod, relocation),
+ exceptionHandler);
}
/**
@@ -9832,6 +10021,7 @@ protected Bound resolve(TypeDescription instrumentedType,
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler The bound suppression handler to use.
* @param relocationHandler The bound relocation handler to use.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @return An appropriate bound advice dispatcher.
*/
protected Bound doResolve(TypeDescription instrumentedType,
@@ -9843,7 +10033,8 @@ protected Bound doResolve(TypeDescription instrumentedType,
MethodSizeHandler.ForAdvice methodSizeHandler,
StackMapFrameHandler.ForAdvice stackMapFrameHandler,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
List offsetMappings = new ArrayList(this.offsetMappings.size());
for (OffsetMapping offsetMapping : this.offsetMappings.values()) {
offsetMappings.add(offsetMapping.resolve(instrumentedType,
@@ -9865,6 +10056,7 @@ protected Bound doResolve(TypeDescription instrumentedType,
stackMapFrameHandler,
suppressionHandler,
relocationHandler,
+ exceptionHandler,
delegator);
}
@@ -9873,7 +10065,6 @@ protected Bound doResolve(TypeDescription instrumentedType,
*/
protected static class WithRetainedEnterType extends Delegating.Resolved.ForMethodEnter {
-
/**
* Creates a new resolved dispatcher for implementing method enter advice that does expose the enter type.
*
@@ -9940,7 +10131,8 @@ protected Bound doResolve(TypeDescription instrumentedType,
MethodSizeHandler.ForAdvice methodSizeHandler,
StackMapFrameHandler.ForAdvice stackMapFrameHandler,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
methodSizeHandler.requireLocalVariableLengthPadding(adviceMethod.getReturnType().getStackSize().getSize());
return super.doResolve(instrumentedType,
instrumentedMethod,
@@ -9951,7 +10143,8 @@ protected Bound doResolve(TypeDescription instrumentedType,
methodSizeHandler,
stackMapFrameHandler,
suppressionHandler,
- relocationHandler);
+ relocationHandler,
+ exceptionHandler);
}
}
}
@@ -10051,7 +10244,8 @@ protected Bound resolve(TypeDescription instrumentedType,
methodSizeHandler.bindExit(adviceMethod),
stackMapFrameHandler.bindExit(adviceMethod),
suppressionHandler.bind(exceptionHandler),
- relocationHandler.bind(instrumentedMethod, relocation));
+ relocationHandler.bind(instrumentedMethod, relocation),
+ exceptionHandler);
}
/**
@@ -10067,6 +10261,7 @@ protected Bound resolve(TypeDescription instrumentedType,
* @param stackMapFrameHandler A handler for translating and injecting stack map frames.
* @param suppressionHandler The bound suppression handler to use.
* @param relocationHandler The bound relocation handler to use.
+ * @param exceptionHandler The exception handler that is resolved for the instrumented method.
* @return An appropriate bound advice dispatcher.
*/
private Bound doResolve(TypeDescription instrumentedType,
@@ -10078,7 +10273,8 @@ private Bound doResolve(TypeDescription instrumentedType,
MethodSizeHandler.ForAdvice methodSizeHandler,
StackMapFrameHandler.ForAdvice stackMapFrameHandler,
SuppressionHandler.Bound suppressionHandler,
- RelocationHandler.Bound relocationHandler) {
+ RelocationHandler.Bound relocationHandler,
+ StackManipulation exceptionHandler) {
List offsetMappings = new ArrayList(this.offsetMappings.size());
for (OffsetMapping offsetMapping : this.offsetMappings.values()) {
offsetMappings.add(offsetMapping.resolve(instrumentedType,
@@ -10100,6 +10296,7 @@ private Bound doResolve(TypeDescription instrumentedType,
stackMapFrameHandler,
suppressionHandler,
relocationHandler,
+ exceptionHandler,
delegator);
}
@@ -10287,6 +10484,9 @@ protected AdviceVisitor(MethodVisitor methodVisitor,
List initialTypes = CompoundList.of(methodExit.getAdviceType().represents(void.class)
? Collections.emptyList()
: Collections.singletonList(methodExit.getAdviceType().asErasure()), argumentHandler.getNamedTypes());
+ List latentTypes = methodEnter.getActualAdviceType().represents(void.class)
+ ? Collections.emptyList()
+ : Collections.singletonList(methodEnter.getActualAdviceType().asErasure());
List preMethodTypes = methodEnter.getAdviceType().represents(void.class)
? Collections.emptyList()
: Collections.singletonList(methodEnter.getAdviceType().asErasure());
@@ -10299,6 +10499,7 @@ protected AdviceVisitor(MethodVisitor methodVisitor,
stackMapFrameHandler = StackMapFrameHandler.Default.of(instrumentedType,
instrumentedMethod,
initialTypes,
+ latentTypes,
preMethodTypes,
postMethodTypes,
methodExit.isAlive(),
@@ -11658,6 +11859,11 @@ public abstract static class AssignReturned implements PostProcessor {
*/
protected final TypeDescription.Generic type;
+ /**
+ * The exception handler factory to use.
+ */
+ protected final ExceptionHandler.Factory exceptionHandlerFactory;
+
/**
* {@code true} if this post processor is used within exit advice.
*/
@@ -11671,12 +11877,17 @@ public abstract static class AssignReturned implements PostProcessor {
/**
* Creates a new post processor for assigning an advice method's return value.
*
- * @param type The advice method's return type.
- * @param exit {@code true} if this post processor is used within exit advice.
- * @param skipOnDefaultValue {@code true} if a default value indicates that no assignment should be conducted.
- */
- protected AssignReturned(TypeDescription.Generic type, boolean exit, boolean skipOnDefaultValue) {
+ * @param type The advice method's return type.
+ * @param exceptionHandlerFactory The exception handler factory to use.
+ * @param exit {@code true} if this post processor is used within exit advice.
+ * @param skipOnDefaultValue {@code true} if a default value indicates that no assignment should be conducted.
+ */
+ protected AssignReturned(TypeDescription.Generic type,
+ ExceptionHandler.Factory exceptionHandlerFactory,
+ boolean exit,
+ boolean skipOnDefaultValue) {
this.type = type;
+ this.exceptionHandlerFactory = exceptionHandlerFactory;
this.exit = exit;
this.skipOnDefaultValue = skipOnDefaultValue;
}
@@ -11687,7 +11898,9 @@ protected AssignReturned(TypeDescription.Generic type, boolean exit, boolean ski
public StackManipulation resolve(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
Assigner assigner,
- ArgumentHandler argumentHandler) {
+ ArgumentHandler argumentHandler,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ StackManipulation exceptionHandler) {
List stackManipulations = new ArrayList(getHandlers().size());
for (Handler handler : getHandlers()) {
stackManipulations.add(handler.resolve(instrumentedType,
@@ -11697,9 +11910,12 @@ public StackManipulation resolve(TypeDescription instrumentedType,
getType(),
toLoadInstruction(handler, exit ? argumentHandler.exit() : argumentHandler.enter())));
}
+ StackManipulation stackManipulation = exceptionHandlerFactory.wrap(new StackManipulation.Compound(stackManipulations),
+ exceptionHandler,
+ stackMapFrameHandler);
return skipOnDefaultValue
- ? DefaultValueSkip.of(new StackManipulation.Compound(stackManipulations), exit ? argumentHandler.exit() : argumentHandler.enter(), type)
- : new StackManipulation.Compound(stackManipulations);
+ ? DefaultValueSkip.of(stackManipulation, stackMapFrameHandler, exit ? argumentHandler.exit() : argumentHandler.enter(), type)
+ : stackManipulation;
}
/**
@@ -12755,12 +12971,16 @@ protected static class ForArray extends AssignReturned {
/**
* Creates a post processor to assign a returned array value by index.
*
- * @param type The array type that is returned by the advice method.
- * @param exit {@code true} if the post processor is applied to exit advice.
- * @param handlers The handlers to apply.
- */
- protected ForArray(TypeDescription.Generic type, boolean exit, Collection> handlers) {
- super(type, exit, true);
+ * @param type The array type that is returned by the advice method.
+ * @param exceptionHandlerFactory The exception handler factory to use.
+ * @param exit {@code true} if the post processor is applied to exit advice.
+ * @param handlers The handlers to apply.
+ */
+ protected ForArray(TypeDescription.Generic type,
+ ExceptionHandler.Factory exceptionHandlerFactory,
+ boolean exit,
+ Collection> handlers) {
+ super(type, exceptionHandlerFactory, exit, true);
this.handlers = new LinkedHashMap();
for (List collection : handlers) {
for (Handler handler : collection) {
@@ -12805,13 +13025,18 @@ protected static class ForScalar extends AssignReturned {
/**
* Creates a post processor to assign a returned scalar value.
*
- * @param type The type of the advice method.
- * @param exit {@code true} if the post processor is applied to exit advice.
- * @param skipOnDefaultValue {@code true} if a default value indicates that no assignment should be conducted.
- * @param handlers The handlers to apply.
- */
- protected ForScalar(TypeDescription.Generic type, boolean exit, boolean skipOnDefaultValue, Collection> handlers) {
- super(type, exit, skipOnDefaultValue);
+ * @param type The type of the advice method.
+ * @param exceptionHandlerFactory The exception handler factory to use.
+ * @param exit {@code true} if the post processor is applied to exit advice.
+ * @param skipOnDefaultValue {@code true} if a default value indicates that no assignment should be conducted.
+ * @param handlers The handlers to apply.
+ */
+ protected ForScalar(TypeDescription.Generic type,
+ ExceptionHandler.Factory exceptionHandlerFactory,
+ boolean exit,
+ boolean skipOnDefaultValue,
+ Collection> handlers) {
+ super(type, exceptionHandlerFactory, exit, skipOnDefaultValue);
this.handlers = new ArrayList();
for (List collection : handlers) {
for (Handler handler : collection) {
@@ -12852,6 +13077,11 @@ protected static class DefaultValueSkip implements StackManipulation {
*/
private final StackManipulation stackManipulation;
+ /**
+ * The stack map frame handler to use.
+ */
+ private final StackMapFrameHandler.ForPostProcessor stackMapFrameHandler;
+
/**
* The offset of the value of the returned type.
*/
@@ -12865,12 +13095,17 @@ protected static class DefaultValueSkip implements StackManipulation {
/**
* Creates a null-check wrapper.
*
- * @param stackManipulation The wrapped stack manipulation in case the value is not a default value.
- * @param offset The offset of the value of the returned type.
- * @param dispatcher The dispatcher to use.
- */
- protected DefaultValueSkip(StackManipulation stackManipulation, int offset, Dispatcher dispatcher) {
+ * @param stackManipulation The wrapped stack manipulation in case the value is not a default value.
+ * @param stackMapFrameHandler The stack map frame handler to use.
+ * @param offset The offset of the value of the returned type.
+ * @param dispatcher The dispatcher to use.
+ */
+ protected DefaultValueSkip(StackManipulation stackManipulation,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ int offset,
+ Dispatcher dispatcher) {
this.stackManipulation = stackManipulation;
+ this.stackMapFrameHandler = stackMapFrameHandler;
this.offset = offset;
this.dispatcher = dispatcher;
}
@@ -12878,12 +13113,16 @@ protected DefaultValueSkip(StackManipulation stackManipulation, int offset, Disp
/**
* Resolves a skipping stack manipulation for the supplied type.
*
- * @param stackManipulation The stack manipulation to wrap.
- * @param offset The offset of the value of the returned type.
- * @param typeDefinition The type that is returned by the advice method.
+ * @param stackManipulation The stack manipulation to wrap.
+ * @param stackMapFrameHandler The stack map frame handler to use.
+ * @param offset The offset of the value of the returned type.
+ * @param typeDefinition The type that is returned by the advice method.
* @return A suitable stack manipulation.
*/
- protected static StackManipulation of(StackManipulation stackManipulation, int offset, TypeDefinition typeDefinition) {
+ protected static StackManipulation of(StackManipulation stackManipulation,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ int offset,
+ TypeDefinition typeDefinition) {
Dispatcher dispatcher;
if (typeDefinition.isPrimitive()) {
if (typeDefinition.represents(boolean.class)
@@ -12904,7 +13143,7 @@ protected static StackManipulation of(StackManipulation stackManipulation, int o
} else {
dispatcher = Dispatcher.REFERENCE;
}
- return new DefaultValueSkip(stackManipulation, offset, dispatcher);
+ return new DefaultValueSkip(stackManipulation, stackMapFrameHandler, offset, dispatcher);
}
/**
@@ -12921,6 +13160,7 @@ public Size apply(MethodVisitor methodVisitor, Context implementationContext) {
Label label = new Label();
Size size = dispatcher.apply(methodVisitor, offset, label).aggregate(stackManipulation.apply(methodVisitor, implementationContext));
methodVisitor.visitLabel(label);
+ stackMapFrameHandler.injectIntermediateFrame(methodVisitor, Collections.emptyList());
return size;
}
@@ -13007,6 +13247,143 @@ protected Size apply(MethodVisitor methodVisitor, int offset, Label label) {
}
}
+ /**
+ * An exception handler to handle exceptions during assignment.
+ */
+ @HashCodeAndEqualsPlugin.Enhance
+ protected static class ExceptionHandler implements StackManipulation {
+
+ /**
+ * The stack manipulation that represents the assignment.
+ */
+ private final StackManipulation stackManipulation;
+
+ /**
+ * The exception handler to apply.
+ */
+ private final StackManipulation exceptionHandler;
+
+ /**
+ * The exception type to handle.
+ */
+ private final TypeDescription exceptionType;
+
+ /**
+ * The stack map frame handler to use.
+ */
+ private final StackMapFrameHandler.ForPostProcessor stackMapFrameHandler;
+
+ /**
+ * Creates a new exception handler for an assignment.
+ *
+ * @param stackManipulation The stack manipulation that represents the assignment.
+ * @param exceptionHandler The exception handler to apply.
+ * @param exceptionType The exception type to handle.
+ * @param stackMapFrameHandler The stack map frame handler to use.
+ */
+ protected ExceptionHandler(StackManipulation stackManipulation,
+ StackManipulation exceptionHandler,
+ TypeDescription exceptionType,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler) {
+ this.stackManipulation = stackManipulation;
+ this.exceptionHandler = exceptionHandler;
+ this.exceptionType = exceptionType;
+ this.stackMapFrameHandler = stackMapFrameHandler;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isValid() {
+ return stackManipulation.isValid() && exceptionHandler.isValid();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Size apply(MethodVisitor methodVisitor, Context implementationContext) {
+ Label start = new Label(), handler = new Label(), end = new Label();
+ methodVisitor.visitTryCatchBlock(start, handler, handler, exceptionType.getInternalName());
+ methodVisitor.visitLabel(start);
+ Size size = stackManipulation.apply(methodVisitor, implementationContext);
+ methodVisitor.visitJumpInsn(Opcodes.GOTO, end);
+ methodVisitor.visitLabel(handler);
+ stackMapFrameHandler.injectIntermediateFrame(methodVisitor, Collections.singletonList(exceptionType));
+ size = exceptionHandler.apply(methodVisitor, implementationContext).aggregate(size);
+ methodVisitor.visitLabel(end);
+ stackMapFrameHandler.injectIntermediateFrame(methodVisitor, Collections.emptyList());
+ return size;
+ }
+
+ /**
+ * A factory for wrapping an assignment with an exception handler, if appropriate.
+ */
+ public interface Factory {
+
+ /**
+ * Wraps the supplied stack manipulation.
+ *
+ * @param stackManipulation The stack manipulation that represents the assignment.
+ * @param exceptionHandler The exception handler to apply.
+ * @param stackMapFrameHandler The stack map frame handler to use.
+ * @return The resolved stack manipulation.
+ */
+ StackManipulation wrap(StackManipulation stackManipulation,
+ StackManipulation exceptionHandler,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler);
+
+ /**
+ * A non-operational factory that does not produce an exception handler.
+ */
+ enum NoOp implements Factory {
+
+ /**
+ * The singleton instance.
+ */
+ INSTANCE;
+
+ /**
+ * {@inheritDoc}
+ */
+ public StackManipulation wrap(StackManipulation stackManipulation,
+ StackManipulation exceptionHandler,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler) {
+ return stackManipulation;
+ }
+ }
+
+ /**
+ * A factory that creates an exception handler for a given exception type.
+ */
+ @HashCodeAndEqualsPlugin.Enhance
+ class Enabled implements Factory {
+
+ /**
+ * The exception type being handled.
+ */
+ private final TypeDescription exceptionType;
+
+ /**
+ * Creates a factory for an exception handler of the supplied exception type.
+ *
+ * @param exceptionType The exception type being handled.
+ */
+ protected Enabled(TypeDescription exceptionType) {
+ this.exceptionType = exceptionType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StackManipulation wrap(StackManipulation stackManipulation,
+ StackManipulation exceptionHandler,
+ StackMapFrameHandler.ForPostProcessor stackMapFrameHandler) {
+ return new ExceptionHandler(stackManipulation, exceptionHandler, exceptionType, stackMapFrameHandler);
+ }
+ }
+ }
+ }
+
/**
* A handler for an {@link AssignReturned} post processor to assign a value that was returned by
* advice to a value of the instrumented method.
@@ -13134,6 +13511,11 @@ public static class Factory implements PostProcessor.Factory {
*/
private final List extends Handler.Factory>> factories;
+ /**
+ * The exception handler factory to use.
+ */
+ private final ExceptionHandler.Factory exceptionHandlerFactory;
+
/**
* Creates a new factory which a preresolved list of handler factories.
*/
@@ -13144,16 +13526,18 @@ public Factory() {
ToThis.Handler.Factory.INSTANCE,
ToFields.Handler.Factory.INSTANCE,
ToReturned.Handler.Factory.INSTANCE,
- ToThrown.Handler.Factory.INSTANCE));
+ ToThrown.Handler.Factory.INSTANCE), ExceptionHandler.Factory.NoOp.INSTANCE);
}
/**
* Creates a new factory.
*
- * @param factories The handler factories to apply.
+ * @param factories The handler factories to apply.
+ * @param exceptionHandlerFactory The exception handler factory to use.
*/
- protected Factory(List extends Handler.Factory>> factories) {
+ protected Factory(List extends Handler.Factory>> factories, ExceptionHandler.Factory exceptionHandlerFactory) {
this.factories = factories;
+ this.exceptionHandlerFactory = exceptionHandlerFactory;
}
/**
@@ -13186,7 +13570,30 @@ public Factory with(Class extends Annotation> type, List handlers) {
* @return new {@link AssignReturned.Factory} that includes the provided handler factory.
*/
public Factory with(Handler.Factory> factory) {
- return new Factory(CompoundList.of(factories, factory));
+ return new Factory(CompoundList.of(factories, factory), exceptionHandlerFactory);
+ }
+
+ /**
+ * Configures this post processor to handle exceptions during assignment with the advice's {@link Advice.ExceptionHandler}.
+ *
+ * @param exceptionType The {@link Throwable} type to handle.
+ * @return A new assigning post processor that handles the specified exception types.
+ */
+ public PostProcessor.Factory withSuppressed(Class extends Throwable> exceptionType) {
+ return withSuppressed(TypeDescription.ForLoadedType.of(exceptionType));
+ }
+
+ /**
+ * Configures this post processor to handle exceptions during assignment with the advice's {@link Advice.ExceptionHandler}.
+ *
+ * @param exceptionType The {@link Throwable} type to handle.
+ * @return A new assigning post processor that handles the specified exception types.
+ */
+ public PostProcessor.Factory withSuppressed(TypeDescription exceptionType) {
+ if (!exceptionType.isAssignableTo(Throwable.class)) {
+ throw new IllegalArgumentException(exceptionType + " is not a throwable type");
+ }
+ return new Factory(factories, new ExceptionHandler.Factory.Enabled(exceptionType));
}
/**
@@ -13220,9 +13627,13 @@ public PostProcessor make(MethodDescription.InDefinedShape advice, boolean exit)
}
}
}
- return !scalar && advice.getReturnType().isArray()
- ? new ForArray(advice.getReturnType(), exit, handlers.values())
- : new ForScalar(advice.getReturnType(), exit, skipOnDefaultValue, handlers.values());
+ if (handlers.isEmpty()) {
+ return NoOp.INSTANCE;
+ } else {
+ return !scalar && advice.getReturnType().isArray()
+ ? new ForArray(advice.getReturnType(), exceptionHandlerFactory, exit, handlers.values())
+ : new ForScalar(advice.getReturnType(), exceptionHandlerFactory, exit, skipOnDefaultValue, handlers.values());
+ }
}
}
}
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/TypeWriter.java b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/TypeWriter.java
index c49552c0f4f..0ab69c911ab 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/TypeWriter.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/TypeWriter.java
@@ -3982,6 +3982,11 @@ public List getAuxiliaryTypes() {
@HashCodeAndEqualsPlugin.Enhance
protected static class WithFullProcessing extends ForInlining {
+ /**
+ * An empty array to indicate missing frames.
+ */
+ private static final Object[] EMPTY = new Object[0];
+
/**
* The method registry to use.
*/
@@ -5343,14 +5348,54 @@ public AnnotationVisitor visitParameterAnnotation(int index, String descriptor,
public void visitCode() {
record.applyBody(actualMethodVisitor, implementationContext, annotationValueFilterFactory);
actualMethodVisitor.visitEnd();
- mv = resolution.isRebased()
- ? cv.visitMethod(resolution.getResolvedMethod().getActualModifiers(),
- resolution.getResolvedMethod().getInternalName(),
- resolution.getResolvedMethod().getDescriptor(),
- resolution.getResolvedMethod().getGenericSignature(),
- resolution.getResolvedMethod().getExceptionTypes().asErasures().toInternalNames())
- : IGNORE_METHOD;
- super.visitCode();
+ if (resolution.isRebased()) {
+ mv = cv.visitMethod(resolution.getResolvedMethod().getActualModifiers(),
+ resolution.getResolvedMethod().getInternalName(),
+ resolution.getResolvedMethod().getDescriptor(),
+ resolution.getResolvedMethod().getGenericSignature(),
+ resolution.getResolvedMethod().getExceptionTypes().asErasures().toInternalNames());
+ super.visitCode();
+ if (!resolution.getAppendedParameters().isEmpty()
+ && (writerFlags & ClassWriter.COMPUTE_FRAMES) == 0
+ && implementationContext.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V6)) {
+ mv = new FramePaddingMethodVisitor(mv);
+ if ((readerFlags & ClassReader.EXPAND_FRAMES) == 0 && resolution.getAppendedParameters().size() < 4) {
+ super.visitFrame(Opcodes.F_CHOP, resolution.getAppendedParameters().size(), EMPTY, EMPTY.length, EMPTY);
+ } else {
+ Object[] frame = new Object[resolution.getResolvedMethod().getParameters().size()
+ - resolution.getAppendedParameters().size()
+ + 1];
+ frame[0] = Opcodes.UNINITIALIZED_THIS;
+ for (int index = 1; index < frame.length; index++) {
+ TypeDefinition typeDefinition = resolution.getResolvedMethod()
+ .getParameters()
+ .get(index - 1)
+ .getType();
+ if (typeDefinition.represents(boolean.class)
+ || typeDefinition.represents(byte.class)
+ || typeDefinition.represents(short.class)
+ || typeDefinition.represents(char.class)
+ || typeDefinition.represents(int.class)) {
+ frame[index] = Opcodes.INTEGER;
+ } else if (typeDefinition.represents(long.class)) {
+ frame[index] = Opcodes.LONG;
+ } else if (typeDefinition.represents(float.class)) {
+ frame[index] = Opcodes.FLOAT;
+ } else if (typeDefinition.represents(double.class)) {
+ frame[index] = Opcodes.DOUBLE;
+ } else {
+ frame[index] = typeDefinition.asErasure().getInternalName();
+ }
+ }
+ super.visitFrame((readerFlags & ClassReader.EXPAND_FRAMES) == 0
+ ? Opcodes.F_FULL
+ : Opcodes.F_NEW, frame.length, frame, EMPTY.length, EMPTY);
+ }
+ }
+ } else {
+ mv = IGNORE_METHOD;
+ super.visitCode();
+ }
}
@Override
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolver.java b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolver.java
index e5d4dd65eb0..6d3fb3f5e49 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolver.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolver.java
@@ -120,9 +120,9 @@ interface Resolution {
/**
* A rebased method might require additional arguments in order to create a distinct signature.
*
- * @return A list of prepended method parameters.
+ * @return A list of parameters that were appended to the rebased method or constructor.
*/
- TypeList getPrependedParameters();
+ TypeList getAppendedParameters();
/**
* A {@link MethodRebaseResolver.Resolution} of a non-rebased method.
@@ -162,7 +162,7 @@ public MethodDescription.InDefinedShape getResolvedMethod() {
/**
* {@inheritDoc}
*/
- public TypeList getPrependedParameters() {
+ public TypeList getAppendedParameters() {
throw new IllegalStateException("Cannot process additional parameters for non-rebased method: " + methodDescription);
}
}
@@ -218,7 +218,7 @@ public MethodDescription.InDefinedShape getResolvedMethod() {
/**
* {@inheritDoc}
*/
- public TypeList getPrependedParameters() {
+ public TypeList getAppendedParameters() {
return new TypeList.Empty();
}
@@ -378,7 +378,7 @@ public MethodDescription.InDefinedShape getResolvedMethod() {
/**
* {@inheritDoc}
*/
- public TypeList getPrependedParameters() {
+ public TypeList getAppendedParameters() {
return new TypeList.Explicit(placeholderType);
}
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTarget.java b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTarget.java
index de945974a07..f6cd139939b 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTarget.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTarget.java
@@ -112,7 +112,7 @@ private Implementation.SpecialMethodInvocation invokeSuper(MethodGraph.Node node
*/
private Implementation.SpecialMethodInvocation invokeSuper(MethodRebaseResolver.Resolution resolution) {
return resolution.isRebased()
- ? RebasedMethodInvocation.of(resolution.getResolvedMethod(), instrumentedType, resolution.getPrependedParameters())
+ ? RebasedMethodInvocation.of(resolution.getResolvedMethod(), instrumentedType, resolution.getAppendedParameters())
: Implementation.SpecialMethodInvocation.Simple.of(resolution.getResolvedMethod(), instrumentedType);
}
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitor.java b/byte-buddy-dep/src/main/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitor.java
index 25815811c69..e28bfffc5e0 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitor.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitor.java
@@ -73,6 +73,9 @@ public void visitLabel(Label label) {
@Override
public void visitFrame(int type, int localVariableLength, Object[] localVariable, int stackSize, Object[] stack) {
if (padding) {
+ if (type == Opcodes.F_SAME) {
+ return;
+ }
injected = true;
super.visitInsn(Opcodes.NOP);
} else {
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/ByteBuddyTutorialExamplesTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/ByteBuddyTutorialExamplesTest.java
index 8ff99c5283b..7f0d4156c51 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/ByteBuddyTutorialExamplesTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/ByteBuddyTutorialExamplesTest.java
@@ -40,8 +40,6 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
@@ -155,11 +153,10 @@ public void testTutorialGettingStartedClassReloading() throws Exception {
@Test
public void testTutorialGettingStartedTypePool() throws Exception {
TypePool typePool = TypePool.Default.ofSystemLoader();
- ClassLoader classLoader = new URLClassLoader(new URL[0], null); // Assure repeatability.
Class> type = new ByteBuddy().redefine(typePool.describe(UnloadedBar.class.getName()).resolve(), ClassFileLocator.ForClassLoader.ofSystemLoader())
.defineField("qux", String.class)
.make()
- .load(classLoader, ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredField("qux"), notNullValue(java.lang.reflect.Field.class));
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTest.java
index f27baddab7f..a1e6739ecfe 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTest.java
@@ -1,6 +1,7 @@
package net.bytebuddy.asm;
import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import org.junit.Test;
@@ -291,6 +292,108 @@ public void testAssignReturnedToFieldStaticFromStatic() throws Exception {
assertThat(type.getField(BAR).get(null), is((Object) QUX));
}
+ @Test
+ public void testAssignReturnedNoHandler() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(Sample.class)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(ToNothing.class)
+ .on(named(FOO)))
+ .make()
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded();
+ assertThat(type.getMethod(FOO, String.class).invoke(type.getConstructor().newInstance(), FOO), is((Object) FOO));
+ }
+
+ @Test
+ public void testAssignReturnedWithSkip() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(Sample.class)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(WithSkip.class)
+ .on(named(FOO)))
+ .make()
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded();
+ assertThat(type.getMethod(FOO, String.class).invoke(type.getConstructor().newInstance(), FOO), is((Object) FOO));
+ }
+
+ @Test
+ public void testAssignReturnedWithSkipDelegation() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(Sample.class)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(WithSkipDelegation.class)
+ .on(named(FOO)))
+ .make()
+ .load(WithSkipDelegation.class.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
+ .getLoaded();
+ assertThat(type.getMethod(FOO, String.class).invoke(type.getConstructor().newInstance(), FOO), is((Object) FOO));
+ }
+
+ @Test
+ public void testAssignReturnedWithRepeat() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(Sample.class)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(WithRepeat.class)
+ .on(named(FOO)))
+ .make()
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded();
+ assertThat(type.getMethod(FOO, String.class).invoke(type.getConstructor().newInstance(), FOO), is((Object) FOO));
+ }
+
+ @Test
+ public void testAssignReturnedWithRepeatDelegation() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(Sample.class)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(WithRepeatDelegation.class)
+ .on(named(FOO)))
+ .make()
+ .load(WithRepeatDelegation.class.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
+ .getLoaded();
+ assertThat(type.getMethod(FOO, String.class).invoke(type.getConstructor().newInstance(), FOO), is((Object) FOO));
+ }
+
+ @Test(expected = ClassCastException.class)
+ public void testAssignIncompatible() throws Throwable {
+ Class> type = new ByteBuddy()
+ .redefine(Sample.class)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(WithIncompatibleAssignment.class)
+ .on(named(FOO)))
+ .make()
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded();
+ try {
+ type.getMethod(FOO, String.class).invoke(type.getConstructor().newInstance(), FOO);
+ } catch (InvocationTargetException exception) {
+ throw exception.getTargetException();
+ }
+ }
+
+ @Test
+ public void testAssignIncompatibleHandled() throws Throwable {
+ Class> type = new ByteBuddy()
+ .redefine(Sample.class)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory().withSuppressed(ClassCastException.class))
+ .to(WithIncompatibleAssignment.class)
+ .on(named(FOO)))
+ .make()
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded();
+ assertThat(type.getMethod(FOO, String.class).invoke(type.getConstructor().newInstance(), FOO), is((Object) FOO));
+ }
+
@Test(expected = IllegalStateException.class)
public void testArgumentTooFewParameters() {
new ByteBuddy()
@@ -412,6 +515,11 @@ public void testFieldValueStatic() throws Exception {
.make();
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testHandledNotThrowable() {
+ new Advice.AssignReturned.Factory().withSuppressed(TypeDescription.OBJECT);
+ }
+
public static class Sample {
public String foo;
@@ -509,7 +617,7 @@ public static String[] enter(@Advice.AllArguments String[] argument) {
if (argument.length != 2 || !FOO.equals(argument[0]) || !BAR.equals(argument[1])) {
throw new AssertionError();
}
- return new String[] {BAR, FOO};
+ return new String[]{BAR, FOO};
}
@Advice.OnMethodExit
@@ -519,7 +627,7 @@ public static String[] exit(@Advice.AllArguments String[] argument) {
if (argument.length != 2 || !BAR.equals(argument[0]) || !FOO.equals(argument[1])) {
throw new AssertionError();
}
- return new String[] {FOO, QUX};
+ return new String[]{FOO, QUX};
}
}
@@ -531,7 +639,7 @@ public static String[][] enter(@Advice.AllArguments String[] argument) {
if (argument.length != 2 || !FOO.equals(argument[0]) || !BAR.equals(argument[1])) {
throw new AssertionError();
}
- return new String[][] {{BAR, FOO}};
+ return new String[][]{{BAR, FOO}};
}
@Advice.OnMethodExit
@@ -540,7 +648,7 @@ public static String[][] exit(@Advice.AllArguments String[] argument) {
if (argument.length != 2 || !BAR.equals(argument[0]) || !FOO.equals(argument[1])) {
throw new AssertionError();
}
- return new String[][] {{FOO, QUX}};
+ return new String[][]{{FOO, QUX}};
}
}
@@ -579,7 +687,7 @@ public static Sample[] enter(@Advice.This Sample sample) {
}
Sample replacement = new Sample();
replacement.foo = BAR;
- return new Sample[] {replacement};
+ return new Sample[]{replacement};
}
@Advice.OnMethodExit
@@ -590,7 +698,7 @@ public static Sample[] exit(@Advice.This Sample sample) {
}
Sample replacement = new Sample();
replacement.foo = QUX;
- return new Sample[] {replacement};
+ return new Sample[]{replacement};
}
}
@@ -753,7 +861,7 @@ public static Object enter(@Advice.AllArguments String[] argument) {
if (argument.length != 2 || !FOO.equals(argument[0]) || !BAR.equals(argument[1])) {
throw new AssertionError();
}
- return new String[] {BAR, FOO};
+ return new String[]{BAR, FOO};
}
}
@@ -765,7 +873,7 @@ public static Object enter(@Advice.AllArguments String[] argument) {
if (argument.length != 2 || !FOO.equals(argument[0]) || !BAR.equals(argument[1])) {
throw new AssertionError();
}
- return new String[] {BAR, FOO};
+ return new String[]{BAR, FOO};
}
}
@@ -798,4 +906,83 @@ public static String enter(@Advice.FieldValue(BAR) String field) {
return QUX;
}
}
+
+ public static class ToNothing {
+
+ @Advice.OnMethodEnter(suppress = Throwable.class)
+ public static String enter(@Advice.Argument(0) String argument) {
+ if (!FOO.equals(argument)) {
+ throw new AssertionError();
+ }
+ return BAR;
+ }
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ public static String exit(@Advice.Argument(0) String argument) {
+ if (!FOO.equals(argument)) {
+ throw new AssertionError();
+ }
+ return QUX;
+ }
+ }
+
+ public static class WithSkip {
+
+ @Advice.OnMethodEnter(skipOn = String.class)
+ @Advice.AssignReturned.ToArguments(@Advice.AssignReturned.ToArguments.ToArgument(0))
+ public static String enter(@Advice.Argument(0) String argument) {
+ if (!FOO.equals(argument)) {
+ throw new AssertionError();
+ }
+ return null;
+ }
+ }
+
+ public static class WithSkipDelegation {
+
+ @Advice.OnMethodEnter(skipOn = String.class, inline = false)
+ @Advice.AssignReturned.ToArguments(@Advice.AssignReturned.ToArguments.ToArgument(0))
+ public static String enter(@Advice.Argument(0) String argument) {
+ if (!FOO.equals(argument)) {
+ throw new AssertionError();
+ }
+ return null;
+ }
+ }
+
+ public static class WithRepeat {
+
+ @Advice.OnMethodExit(repeatOn = String.class)
+ @Advice.AssignReturned.ToArguments(@Advice.AssignReturned.ToArguments.ToArgument(0))
+ public static String exit(@Advice.Argument(0) String argument) {
+ if (!FOO.equals(argument)) {
+ throw new AssertionError();
+ }
+ return null;
+ }
+ }
+
+ public static class WithRepeatDelegation {
+
+ @Advice.OnMethodExit(repeatOn = String.class, inline = false)
+ @Advice.AssignReturned.ToArguments(@Advice.AssignReturned.ToArguments.ToArgument(0))
+ public static String exit(@Advice.Argument(0) String argument) {
+ if (!FOO.equals(argument)) {
+ throw new AssertionError();
+ }
+ return null;
+ }
+ }
+
+ public static class WithIncompatibleAssignment {
+
+ @Advice.OnMethodEnter(suppress = ClassCastException.class)
+ @Advice.AssignReturned.ToArguments(@Advice.AssignReturned.ToArguments.ToArgument(value = 0, typing = Assigner.Typing.DYNAMIC))
+ public static Object enter(@Advice.Argument(0) String argument) {
+ if (!FOO.equals(argument)) {
+ throw new AssertionError();
+ }
+ return new Object();
+ }
+ }
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTypeTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTypeTest.java
index 02dee6fbb9c..63b6a6f8fc9 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTypeTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceAssignReturnedTypeTest.java
@@ -2,6 +2,7 @@
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+import net.bytebuddy.implementation.bytecode.Throw;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -18,14 +19,38 @@ public class AdviceAssignReturnedTypeTest {
private static final String FOO = "foo";
- private final Class> sample, skipAdvice, noSkipAdvice;
+ private final Class> sample,
+ skipAdvice,
+ noSkipAdvice,
+ skipSuppressionAdvice,
+ noSkipSuppressionAdvice,
+ skipDelegationAdvice,
+ noSkipDelegationAdvice,
+ skipSuppressionDelegationAdvice,
+ noSkipSuppressionDelegationAdvice;
private final Object skipReturn, noSkipReturn;
- public AdviceAssignReturnedTypeTest(Class> sample, Class> skipAdvice, Class> noSkipAdvice, Object skipReturn, Object noSkipReturn) {
+ public AdviceAssignReturnedTypeTest(Class> sample,
+ Class> skipAdvice,
+ Class> noSkipAdvice,
+ Class> skipSuppressionAdvice,
+ Class> noSkipSuppressionAdvice,
+ Class> skipDelegationAdvice,
+ Class> noSkipDelegationAdvice,
+ Class> skipSuppressionDelegationAdvice,
+ Class> noSkipSuppressionDelegationAdvice,
+ Object skipReturn,
+ Object noSkipReturn) {
this.sample = sample;
this.skipAdvice = skipAdvice;
this.noSkipAdvice = noSkipAdvice;
+ this.skipSuppressionAdvice = skipSuppressionAdvice;
+ this.noSkipSuppressionAdvice = noSkipSuppressionAdvice;
+ this.skipDelegationAdvice = skipDelegationAdvice;
+ this.noSkipDelegationAdvice = noSkipDelegationAdvice;
+ this.skipSuppressionDelegationAdvice = skipSuppressionDelegationAdvice;
+ this.noSkipSuppressionDelegationAdvice = noSkipSuppressionDelegationAdvice;
this.skipReturn = skipReturn;
this.noSkipReturn = noSkipReturn;
}
@@ -33,15 +58,105 @@ public AdviceAssignReturnedTypeTest(Class> sample, Class> skipAdvice, Class<
@Parameterized.Parameters
public static Collection data() {
return Arrays.asList(new Object[][]{
- {BooleanSample.class, BooleanSkipAdvice.class, BooleanNoSkipAdvice.class, true, false},
- {ByteSample.class, ByteSkipAdvice.class, ByteNoSkipAdvice.class, (byte) 1, (byte) 0},
- {ShortSample.class, ShortSkipAdvice.class, ShortNoSkipAdvice.class, (short) 1, (short) 0},
- {CharSample.class, CharSkipAdvice.class, CharNoSkipAdvice.class, (char) 1, (char) 0},
- {IntSample.class, IntSkipAdvice.class, IntNoSkipAdvice.class, 1, 0},
- {LongSample.class, LongSkipAdvice.class, LongNoSkipAdvice.class, 1L, 0L},
- {FloatSample.class, FloatSkipAdvice.class, FloatNoSkipAdvice.class, 1f, 0f},
- {DoubleSample.class, DoubleSkipAdvice.class, DoubleNoSkipAdvice.class, 1d, 0d},
- {ReferenceSample.class, ReferenceSkipAdvice.class, ReferenceNoSkipAdvice.class, FOO, null}
+ {BooleanSample.class,
+ BooleanSkipAdvice.class,
+ BooleanNoSkipAdvice.class,
+ BooleanSkipSuppressAdvice.class,
+ BooleanNoSkipSuppressAdvice.class,
+ BooleanSkipDelegationAdvice.class,
+ BooleanNoSkipDelegationAdvice.class,
+ BooleanSkipSuppressDelegationAdvice.class,
+ BooleanNoSkipSuppressDelegationAdvice.class,
+ true,
+ false},
+ {ByteSample.class,
+ ByteSkipAdvice.class,
+ ByteNoSkipAdvice.class,
+ ByteSkipSuppressionAdvice.class,
+ ByteNoSkipSuppressionAdvice.class,
+ ByteSkipDelegationAdvice.class,
+ ByteNoSkipDelegationAdvice.class,
+ ByteSkipSuppressionDelegationAdvice.class,
+ ByteNoSkipSuppressionDelegationAdvice.class,
+ (byte) 1,
+ (byte) 0},
+ {ShortSample.class,
+ ShortSkipAdvice.class,
+ ShortNoSkipAdvice.class,
+ ShortSkipSuppressionAdvice.class,
+ ShortNoSkipSuppressionAdvice.class,
+ ShortSkipDelegationAdvice.class,
+ ShortNoSkipDelegationAdvice.class,
+ ShortSkipSuppressionDelegationAdvice.class,
+ ShortNoSkipSuppressionDelegationAdvice.class,
+ (short) 1,
+ (short) 0},
+ {CharSample.class,
+ CharSkipAdvice.class,
+ CharNoSkipAdvice.class,
+ CharSkipSuppressionAdvice.class,
+ CharNoSkipSuppressionAdvice.class,
+ CharSkipDelegationAdvice.class,
+ CharNoSkipDelegationAdvice.class,
+ CharSkipSuppressionDelegationAdvice.class,
+ CharNoSkipSuppressionDelegationAdvice.class,
+ (char) 1,
+ (char) 0},
+ {IntSample.class,
+ IntSkipAdvice.class,
+ IntNoSkipAdvice.class,
+ IntSkipSuppressionAdvice.class,
+ IntNoSkipSuppressionAdvice.class,
+ IntSkipDelegationAdvice.class,
+ IntNoSkipDelegationAdvice.class,
+ IntSkipSuppressionDelegationAdvice.class,
+ IntNoSkipSuppressionDelegationAdvice.class,
+ 1,
+ 0},
+ {LongSample.class,
+ LongSkipAdvice.class,
+ LongNoSkipAdvice.class,
+ LongSkipSuppressionAdvice.class,
+ LongNoSkipSuppressionAdvice.class,
+ LongSkipDelegationAdvice.class,
+ LongNoSkipDelegationAdvice.class,
+ LongSkipSuppressionDelegationAdvice.class,
+ LongNoSkipSuppressionDelegationAdvice.class,
+ 1L,
+ 0L},
+ {FloatSample.class,
+ FloatSkipAdvice.class,
+ FloatNoSkipAdvice.class,
+ FloatSkipSuppressionAdvice.class,
+ FloatNoSkipSuppressionAdvice.class,
+ FloatSkipDelegationAdvice.class,
+ FloatNoSkipDelegationAdvice.class,
+ FloatSkipSuppressionDelegationAdvice.class,
+ FloatNoSkipSuppressionDelegationAdvice.class,
+ 1f,
+ 0f},
+ {DoubleSample.class,
+ DoubleSkipAdvice.class,
+ DoubleNoSkipAdvice.class,
+ DoubleSkipSuppressionAdvice.class,
+ DoubleNoSkipSuppressionAdvice.class,
+ DoubleSkipDelegationAdvice.class,
+ DoubleNoSkipDelegationAdvice.class,
+ DoubleSkipSuppressionDelegationAdvice.class,
+ DoubleNoSkipSuppressionDelegationAdvice.class,
+ 1d,
+ 0d},
+ {ReferenceSample.class,
+ ReferenceSkipAdvice.class,
+ ReferenceNoSkipAdvice.class,
+ ReferenceSkipSuppressionAdvice.class,
+ ReferenceNoSkipSuppressionAdvice.class,
+ ReferenceSkipDelegationAdvice.class,
+ ReferenceNoSkipDelegationAdvice.class,
+ ReferenceSkipSuppressionDelegationAdvice.class,
+ ReferenceNoSkipSuppressionDelegationAdvice.class,
+ FOO,
+ null}
});
}
@@ -73,6 +188,90 @@ public void testNoSkip() throws Exception {
assertThat(type.getMethod(FOO).invoke(type.getConstructor().newInstance()), is(noSkipReturn));
}
+ @Test
+ public void testSkipSuppression() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(sample)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(skipSuppressionAdvice)
+ .on(named(FOO)))
+ .make()
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded();
+ assertThat(type.getMethod(FOO).invoke(type.getConstructor().newInstance()), is(skipReturn));
+ }
+
+ @Test
+ public void testNoSkipSuppression() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(sample)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(noSkipSuppressionAdvice)
+ .on(named(FOO)))
+ .make()
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded();
+ assertThat(type.getMethod(FOO).invoke(type.getConstructor().newInstance()), is(noSkipReturn));
+ }
+
+ @Test
+ public void testSkipDelegation() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(sample)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(skipDelegationAdvice)
+ .on(named(FOO)))
+ .make()
+ .load(skipDelegationAdvice.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
+ .getLoaded();
+ assertThat(type.getMethod(FOO).invoke(type.getConstructor().newInstance()), is(skipReturn));
+ }
+
+ @Test
+ public void testNoSkipDelegation() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(sample)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(noSkipDelegationAdvice)
+ .on(named(FOO)))
+ .make()
+ .load(noSkipDelegationAdvice.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
+ .getLoaded();
+ assertThat(type.getMethod(FOO).invoke(type.getConstructor().newInstance()), is(noSkipReturn));
+ }
+
+ @Test
+ public void testSkipSuppressionDelegation() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(sample)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(skipSuppressionDelegationAdvice)
+ .on(named(FOO)))
+ .make()
+ .load(skipSuppressionDelegationAdvice.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
+ .getLoaded();
+ assertThat(type.getMethod(FOO).invoke(type.getConstructor().newInstance()), is(skipReturn));
+ }
+
+ @Test
+ public void testNoSkipSuppressionDelegation() throws Exception {
+ Class> type = new ByteBuddy()
+ .redefine(sample)
+ .visit(Advice.withCustomMapping()
+ .with(new Advice.AssignReturned.Factory())
+ .to(noSkipSuppressionDelegationAdvice)
+ .on(named(FOO)))
+ .make()
+ .load(noSkipSuppressionDelegationAdvice.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
+ .getLoaded();
+ assertThat(type.getMethod(FOO).invoke(type.getConstructor().newInstance()), is(noSkipReturn));
+ }
+
public static class BooleanSample {
public boolean foo() {
@@ -100,6 +299,66 @@ public static boolean enter() {
}
}
+ public static class BooleanSkipSuppressAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static boolean enter() {
+ return false;
+ }
+ }
+
+ public static class BooleanNoSkipSuppressAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static boolean enter() {
+ return false;
+ }
+ }
+
+ public static class BooleanSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static boolean enter() {
+ return false;
+ }
+ }
+
+ public static class BooleanNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static boolean enter() {
+ return false;
+ }
+ }
+
+ public static class BooleanSkipSuppressDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static boolean enter() {
+ return false;
+ }
+ }
+
+ public static class BooleanNoSkipSuppressDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static boolean enter() {
+ return false;
+ }
+ }
+
public static class ByteSample {
public byte foo() {
@@ -127,6 +386,66 @@ public static byte enter() {
}
}
+ public static class ByteSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static byte enter() {
+ return 0;
+ }
+ }
+
+ public static class ByteNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static byte enter() {
+ return 0;
+ }
+ }
+
+ public static class ByteSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static byte enter() {
+ return 0;
+ }
+ }
+
+ public static class ByteNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static byte enter() {
+ return 0;
+ }
+ }
+
+ public static class ByteSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static byte enter() {
+ return 0;
+ }
+ }
+
+ public static class ByteNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static byte enter() {
+ return 0;
+ }
+ }
+
public static class ShortSample {
public short foo() {
@@ -154,6 +473,66 @@ public static short enter() {
}
}
+ public static class ShortSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static short enter() {
+ return 0;
+ }
+ }
+
+ public static class ShortNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static short enter() {
+ return 0;
+ }
+ }
+
+ public static class ShortSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static short enter() {
+ return 0;
+ }
+ }
+
+ public static class ShortNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static short enter() {
+ return 0;
+ }
+ }
+
+ public static class ShortSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static short enter() {
+ return 0;
+ }
+ }
+
+ public static class ShortNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static short enter() {
+ return 0;
+ }
+ }
+
public static class CharSample {
public char foo() {
@@ -181,6 +560,66 @@ public static char enter() {
}
}
+ public static class CharSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static char enter() {
+ return 0;
+ }
+ }
+
+ public static class CharNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static char enter() {
+ return 0;
+ }
+ }
+
+ public static class CharSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static char enter() {
+ return 0;
+ }
+ }
+
+ public static class CharNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static char enter() {
+ return 0;
+ }
+ }
+
+ public static class CharSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static char enter() {
+ return 0;
+ }
+ }
+
+ public static class CharNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static char enter() {
+ return 0;
+ }
+ }
+
public static class IntSample {
public int foo() {
@@ -208,6 +647,66 @@ public static int enter() {
}
}
+ public static class IntSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static int enter() {
+ return 0;
+ }
+ }
+
+ public static class IntNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static int enter() {
+ return 0;
+ }
+ }
+
+ public static class IntSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static int enter() {
+ return 0;
+ }
+ }
+
+ public static class IntNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static int enter() {
+ return 0;
+ }
+ }
+
+ public static class IntSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static int enter() {
+ return 0;
+ }
+ }
+
+ public static class IntNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static int enter() {
+ return 0;
+ }
+ }
+
public static class LongSample {
public long foo() {
@@ -235,6 +734,66 @@ public static long enter() {
}
}
+ public static class LongSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static long enter() {
+ return 0;
+ }
+ }
+
+ public static class LongNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static long enter() {
+ return 0;
+ }
+ }
+
+ public static class LongSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static long enter() {
+ return 0;
+ }
+ }
+
+ public static class LongNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static long enter() {
+ return 0;
+ }
+ }
+
+ public static class LongSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static long enter() {
+ return 0;
+ }
+ }
+
+ public static class LongNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static long enter() {
+ return 0;
+ }
+ }
+
public static class FloatSample {
public float foo() {
@@ -262,6 +821,66 @@ public static float enter() {
}
}
+ public static class FloatSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static float enter() {
+ return 0;
+ }
+ }
+
+ public static class FloatNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static float enter() {
+ return 0;
+ }
+ }
+
+ public static class FloatSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static float enter() {
+ return 0;
+ }
+ }
+
+ public static class FloatNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static float enter() {
+ return 0;
+ }
+ }
+
+ public static class FloatSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static float enter() {
+ return 0;
+ }
+ }
+
+ public static class FloatNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static float enter() {
+ return 0;
+ }
+ }
+
public static class DoubleSample {
public double foo() {
@@ -289,6 +908,66 @@ public static double enter() {
}
}
+ public static class DoubleSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static double enter() {
+ return 0;
+ }
+ }
+
+ public static class DoubleNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static double enter() {
+ return 0;
+ }
+ }
+
+ public static class DoubleSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static double enter() {
+ return 0;
+ }
+ }
+
+ public static class DoubleNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static double enter() {
+ return 0;
+ }
+ }
+
+ public static class DoubleSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static double enter() {
+ return 0;
+ }
+ }
+
+ public static class DoubleNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static double enter() {
+ return 0;
+ }
+ }
+
public static class ReferenceSample {
public Object foo() {
@@ -315,4 +994,64 @@ public static Object enter() {
return null;
}
}
+
+ public static class ReferenceSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static Object enter() {
+ return null;
+ }
+ }
+
+ public static class ReferenceNoSkipSuppressionAdvice {
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static Object enter() {
+ return null;
+ }
+ }
+
+ public static class ReferenceSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static Object enter() {
+ return null;
+ }
+ }
+
+ public static class ReferenceNoSkipDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static Object enter() {
+ return null;
+ }
+ }
+
+ public static class ReferenceSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar
+ @Advice.AssignReturned.ToReturned
+ public static Object enter() {
+ return null;
+ }
+ }
+
+ public static class ReferenceNoSkipSuppressionDelegationAdvice {
+
+ @Advice.OnMethodExit(inline = false, suppress = Throwable.class)
+ @Advice.AssignReturned.AsScalar(skipOnDefaultValue = false)
+ @Advice.AssignReturned.ToReturned
+ public static Object enter() {
+ return null;
+ }
+ }
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceTest.java
index 5990ed4ff0e..5c0c0ed765f 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/asm/AdviceTest.java
@@ -1493,7 +1493,9 @@ public Advice.PostProcessor make(final MethodDescription.InDefinedShape advice,
public StackManipulation resolve(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
Assigner assigner,
- Advice.ArgumentHandler argumentHandler) {
+ Advice.ArgumentHandler argumentHandler,
+ Advice.StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ StackManipulation exceptionHandler) {
return new StackManipulation.Compound(
MethodVariableAccess.of(advice.getReturnType()).loadFrom(argumentHandler.enter()),
MethodVariableAccess.store(instrumentedMethod.getParameters().get(0))
@@ -1520,7 +1522,9 @@ public Advice.PostProcessor make(final MethodDescription.InDefinedShape advice,
public StackManipulation resolve(TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
Assigner assigner,
- Advice.ArgumentHandler argumentHandler) {
+ Advice.ArgumentHandler argumentHandler,
+ Advice.StackMapFrameHandler.ForPostProcessor stackMapFrameHandler,
+ StackManipulation exceptionHandler) {
return new StackManipulation.Compound(
MethodVariableAccess.of(advice.getReturnType()).loadFrom(argumentHandler.enter()),
MethodVariableAccess.store(instrumentedMethod.getParameters().get(0))
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/AbstractDynamicTypeBuilderTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/AbstractDynamicTypeBuilderTest.java
index 9315c272173..f82e318c1d2 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/AbstractDynamicTypeBuilderTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/AbstractDynamicTypeBuilderTest.java
@@ -47,8 +47,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.*;
-import java.net.URL;
-import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -122,7 +120,7 @@ public void testMethodDefinition() throws Exception {
.throwing(Exception.class)
.intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Method method = type.getDeclaredMethod(FOO);
assertThat(method.getReturnType(), CoreMatchers.>is(Object.class));
@@ -139,7 +137,7 @@ public void testAbstractMethodDefinition() throws Exception {
.throwing(Exception.class)
.withoutCode()
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Method method = type.getDeclaredMethod(FOO);
assertThat(method.getReturnType(), CoreMatchers.>is(Object.class));
@@ -154,7 +152,7 @@ public void testConstructorDefinition() throws Exception {
.throwing(Exception.class)
.intercept(MethodCall.invoke(Object.class.getDeclaredConstructor()))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Constructor> constructor = type.getDeclaredConstructor(Void.class);
assertThat(constructor.getExceptionTypes(), is(new Class>[]{Exception.class}));
@@ -167,7 +165,7 @@ public void testFieldDefinition() throws Exception {
Class> type = createPlain()
.defineField(FOO, Void.class, Visibility.PUBLIC)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Field field = type.getDeclaredField(FOO);
assertThat(field.getType(), CoreMatchers.>is(Void.class));
@@ -187,7 +185,7 @@ public void testFieldDefaultValueDefinition() throws Exception {
.defineField(DOUBLE_FIELD, double.class, Visibility.PUBLIC, Ownership.STATIC).value(DOUBLE_VALUE)
.defineField(STRING_FIELD, String.class, Visibility.PUBLIC, Ownership.STATIC).value(FOO)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredField(BOOLEAN_FIELD).get(null), is((Object) BOOLEAN_VALUE));
assertThat(type.getDeclaredField(BYTE_FIELD).get(null), is((Object) (byte) INTEGER_VALUE));
@@ -206,7 +204,7 @@ public void testApplicationOrder() throws Exception {
.method(named(TO_STRING)).intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.method(named(TO_STRING)).intercept(new Implementation.Simple(new TextConstant(BAR), MethodReturn.REFERENCE))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.getDeclaredConstructor()
.newInstance()
@@ -232,7 +230,7 @@ public void testConstructorInvokingMethod() throws Exception {
.defineMethod(FOO, Object.class, Visibility.PUBLIC)
.intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Method method = type.getDeclaredMethod(FOO);
assertThat(method.invoke(type.getDeclaredConstructor().newInstance()), is((Object) FOO));
@@ -245,7 +243,7 @@ public void testMethodTransformation() throws Exception {
.intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.transform(Transformer.ForMethod.withModifiers(MethodManifestation.FINAL))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredConstructor().newInstance().toString(), is(FOO));
assertThat(type.getDeclaredMethod(TO_STRING).getModifiers(), is(Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC));
@@ -258,7 +256,7 @@ public void testFieldTransformation() throws Exception {
.field(named(FOO))
.transform(Transformer.ForField.withModifiers(Visibility.PUBLIC))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredField(FOO).getModifiers(), is(Opcodes.ACC_PUBLIC));
}
@@ -270,7 +268,7 @@ public void testIgnoredMethod() throws Exception {
.method(named(TO_STRING))
.intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredConstructor().newInstance().toString(), CoreMatchers.not(FOO));
}
@@ -282,7 +280,7 @@ public void testIgnoredMethodDoesNotApplyForDefined() throws Exception {
.defineMethod(FOO, String.class, Visibility.PUBLIC)
.intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethod(FOO).invoke(type.getDeclaredConstructor().newInstance()), is((Object) FOO));
}
@@ -418,7 +416,7 @@ public void testTypeVariable() throws Exception {
.typeVariable(FOO)
.typeVariable(BAR, String.class)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getTypeParameters().length, is(2));
assertThat(type.getTypeParameters()[0].getName(), is(FOO));
@@ -440,7 +438,7 @@ public TypeVariableToken transform(TypeDescription instrumentedType, TypeVariabl
}
})
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getTypeParameters().length, is(2));
assertThat(type.getTypeParameters()[0].getName(), is(FOO));
@@ -456,7 +454,7 @@ public void testGenericFieldDefinition() throws Exception {
Class> type = createPlain()
.defineField(QUX, list)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredField(QUX).getGenericType(), is(list));
}
@@ -470,7 +468,7 @@ public void testGenericMethodDefinition() throws Exception {
.typeVariable(FOO, Exception.class)
.intercept(StubMethod.INSTANCE)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredMethod(QUX, List.class).getTypeParameters().length, is(1));
assertThat(type.getDeclaredMethod(QUX, List.class).getTypeParameters()[0].getName(), is(FOO));
@@ -488,7 +486,7 @@ public void testHashCodeMethod() throws Exception {
.defineField(FOO, String.class, Visibility.PUBLIC)
.withHashCodeEquals()
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Object left = type.getDeclaredConstructor().newInstance(), right = type.getDeclaredConstructor().newInstance();
left.getClass().getDeclaredField(FOO).set(left, FOO);
@@ -503,7 +501,7 @@ public void testToString() throws Exception {
.defineField(FOO, String.class, Visibility.PUBLIC)
.withToString()
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Object instance = type.getDeclaredConstructor().newInstance();
instance.getClass().getDeclaredField(FOO).set(instance, BAR);
@@ -520,7 +518,7 @@ public void testGenericMethodDefinitionMetaDataParameter() throws Exception {
.typeVariable(FOO, Exception.class)
.intercept(StubMethod.INSTANCE)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(TypeDefinition.Sort.describe(type).getDeclaredMethods().filter(named(QUX)).getOnly().getParameters().getOnly().getName(), is(BAR));
assertThat(TypeDefinition.Sort.describe(type).getDeclaredMethods().filter(named(QUX)).getOnly().getParameters().getOnly().getModifiers(),
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/AbstractDynamicTypeBuilderForInliningTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/AbstractDynamicTypeBuilderForInliningTest.java
index 73ef2993536..cce3de0fb21 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/AbstractDynamicTypeBuilderForInliningTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/AbstractDynamicTypeBuilderForInliningTest.java
@@ -100,7 +100,7 @@ public void testTypeInitializerRetention() throws Exception {
Class> type = create(Qux.class)
.invokable(isTypeInitializer()).intercept(MethodCall.invoke(Qux.class.getDeclaredMethod("invoke")))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredConstructor().newInstance(), notNullValue(Object.class));
assertThat(type.getDeclaredField(FOO).get(null), is((Object) FOO));
@@ -112,7 +112,7 @@ public void testDefaultValue() throws Exception {
Class> dynamicType = create(Baz.class)
.method(named(FOO)).defaultValue(FOO, String.class)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(dynamicType.getDeclaredMethods().length, is(1));
assertThat(dynamicType.getDeclaredMethod(FOO).getDefaultValue(), is((Object) FOO));
@@ -124,7 +124,7 @@ public void testParameterMetaDataRetention() throws Exception {
Class> dynamicType = create(Class.forName(PARAMETER_NAME_CLASS))
.method(named(FOO)).intercept(StubMethod.INSTANCE)
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Class> executable = Class.forName("java.lang.reflect.Executable");
Method getParameters = executable.getDeclaredMethod("getParameters");
@@ -349,7 +349,7 @@ public void testMethodTransformationExistingMethod() throws Exception {
.intercept(new Implementation.Simple(new TextConstant(FOO), MethodReturn.REFERENCE))
.transform(Transformer.ForMethod.withModifiers(MethodManifestation.FINAL))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Method foo = type.getDeclaredMethod(FOO);
assertThat(foo.invoke(type.getDeclaredConstructor().newInstance()), is((Object) FOO));
@@ -362,7 +362,7 @@ public void testFieldTransformationExistingField() throws Exception {
.field(named(FOO))
.transform(Transformer.ForField.withModifiers(Visibility.PUBLIC))
.make()
- .load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER)
+ .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertThat(type.getDeclaredField(FOO).getModifiers(), is(Opcodes.ACC_PUBLIC));
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedConstructorTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedConstructorTest.java
index 5a22afe0581..a1cf1ae0f38 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedConstructorTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedConstructorTest.java
@@ -5,8 +5,6 @@
import net.bytebuddy.description.method.ParameterList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
-import net.bytebuddy.implementation.Implementation;
-import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.StackSize;
import net.bytebuddy.test.utility.MockitoRule;
import org.junit.Before;
@@ -14,7 +12,6 @@
import org.junit.Test;
import org.junit.rules.TestRule;
import org.mockito.Mock;
-import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -74,6 +71,6 @@ public void testPreservation() throws Exception {
assertThat(resolution.getResolvedMethod().getReturnType(), is(TypeDescription.Generic.VOID));
assertThat(resolution.getResolvedMethod().getParameters(), is((ParameterList) new ParameterList.Explicit
.ForTypes(resolution.getResolvedMethod(), parameterType, placeholderType)));
- assertThat(resolution.getPrependedParameters(), equalTo((TypeList) new TypeList.Explicit(rawPlaceholderType)));
+ assertThat(resolution.getAppendedParameters(), equalTo((TypeList) new TypeList.Explicit(rawPlaceholderType)));
}
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedMethodTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedMethodTest.java
index 1cf072fc49b..41a22244404 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedMethodTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionForRebasedMethodTest.java
@@ -4,9 +4,6 @@
import net.bytebuddy.description.method.ParameterDescription;
import net.bytebuddy.description.method.ParameterList;
import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.description.type.TypeList;
-import net.bytebuddy.implementation.Implementation;
-import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.StackSize;
import net.bytebuddy.test.utility.MockitoRule;
import org.junit.Before;
@@ -16,13 +13,11 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.Mock;
-import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.Arrays;
import java.util.Collection;
-import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
@@ -100,6 +95,6 @@ public void testPreservation() throws Exception {
assertThat(resolution.getResolvedMethod().getReturnType(), is(genericReturnType));
assertThat(resolution.getResolvedMethod().getParameters(), is((ParameterList) new ParameterList.Explicit
.ForTypes(resolution.getResolvedMethod(), parameterType)));
- assertThat(resolution.getPrependedParameters().isEmpty(), is(true));
+ assertThat(resolution.getAppendedParameters().isEmpty(), is(true));
}
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionPreservedTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionPreservedTest.java
index 2bc7fd3abfa..42e3a4dd2ae 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionPreservedTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/MethodRebaseResolverResolutionPreservedTest.java
@@ -27,6 +27,6 @@ public void testPreservation() throws Exception {
@Test(expected = IllegalStateException.class)
public void testPreservationCannotAppendArguments() throws Exception {
- new MethodRebaseResolver.Resolution.Preserved(methodDescription).getPrependedParameters();
+ new MethodRebaseResolver.Resolution.Preserved(methodDescription).getAppendedParameters();
}
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseDynamicTypeBuilderTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseDynamicTypeBuilderTest.java
index 4137fc90f88..f4295ba4644 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseDynamicTypeBuilderTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseDynamicTypeBuilderTest.java
@@ -1,6 +1,7 @@
package net.bytebuddy.dynamic.scaffold.inline;
import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.type.PackageDescription;
import net.bytebuddy.description.type.TypeDescription;
@@ -20,12 +21,11 @@
import net.bytebuddy.test.visibility.Sample;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
+import org.objectweb.asm.ClassReader;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
-import java.net.URL;
-import java.net.URLClassLoader;
import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -72,7 +72,7 @@ public void testConstructorRetentionNoAuxiliaryType() throws Exception {
.rebase(Bar.class)
.make();
assertThat(dynamicType.getAuxiliaryTypes().size(), is(0));
- Class> type = dynamicType.load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(0));
Field field = type.getDeclaredField(BAR);
@@ -86,13 +86,42 @@ public void testConstructorRebaseSingleAuxiliaryType() throws Exception {
.constructor(any()).intercept(SuperMethodCall.INSTANCE)
.make();
assertThat(dynamicType.getAuxiliaryTypes().size(), is(1));
- Class> type = dynamicType.load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
assertThat(type.getDeclaredConstructors().length, is(2));
assertThat(type.getDeclaredMethods().length, is(0));
Field field = type.getDeclaredField(BAR);
assertThat(field.get(type.getDeclaredConstructor(String.class).newInstance(FOO)), is((Object) FOO));
}
+ @Test
+ public void testConstructorRebaseSingleAuxiliaryTypeStackMapAdjustment() throws Exception {
+ DynamicType.Unloaded> dynamicType = new ByteBuddy()
+ .rebase(Foobar.class)
+ .constructor(any()).intercept(SuperMethodCall.INSTANCE)
+ .make();
+ assertThat(dynamicType.getAuxiliaryTypes().size(), is(1));
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ assertThat(type.getDeclaredConstructors().length, is(2));
+ assertThat(type.getDeclaredMethods().length, is(0));
+ Field field = type.getDeclaredField(BAR);
+ assertThat(field.get(type.getDeclaredConstructor(String.class).newInstance(FOO)), is((Object) BAR));
+ }
+
+ @Test
+ public void testConstructorRebaseSingleAuxiliaryTypeStackMapAdjustmentExpanded() throws Exception {
+ DynamicType.Unloaded> dynamicType = new ByteBuddy()
+ .rebase(Foobar.class)
+ .constructor(any()).intercept(SuperMethodCall.INSTANCE)
+ .visit(new AsmVisitorWrapper.ForDeclaredMethods().readerFlags(ClassReader.EXPAND_FRAMES))
+ .make();
+ assertThat(dynamicType.getAuxiliaryTypes().size(), is(1));
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ assertThat(type.getDeclaredConstructors().length, is(2));
+ assertThat(type.getDeclaredMethods().length, is(0));
+ Field field = type.getDeclaredField(BAR);
+ assertThat(field.get(type.getDeclaredConstructor(String.class).newInstance(FOO)), is((Object) BAR));
+ }
+
@Test
public void testMethodRebase() throws Exception {
DynamicType.Unloaded> dynamicType = new ByteBuddy()
@@ -100,7 +129,7 @@ public void testMethodRebase() throws Exception {
.method(named(BAR)).intercept(StubMethod.INSTANCE)
.make();
assertThat(dynamicType.getAuxiliaryTypes().size(), is(0));
- Class> type = dynamicType.load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(3));
assertThat(type.getDeclaredMethod(FOO).invoke(null), nullValue(Object.class));
@@ -203,4 +232,20 @@ public static String bar() {
}
}
}
+
+ public static class Foobar {
+
+ public final String bar;
+
+ public Foobar(String foo) {
+ if (foo == null) {
+ throw new AssertionError();
+ }
+ String value = FOO;
+ if (!value.equals(BAR)) {
+ value = BAR;
+ }
+ bar = value;
+ }
+ }
}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTargetTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTargetTest.java
index e2528d591b7..f532bb31a15 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTargetTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RebaseImplementationTargetTest.java
@@ -10,7 +10,6 @@
import net.bytebuddy.implementation.AbstractImplementationTargetTest;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;
-import net.bytebuddy.implementation.bytecode.constant.NullConstant;
import net.bytebuddy.matcher.ElementMatchers;
import org.junit.Before;
import org.junit.Test;
@@ -93,7 +92,7 @@ public void testRebasedMethodIsInvokable() throws Exception {
when(invokableMethod.getDeclaringType()).thenReturn(instrumentedType);
when(resolution.isRebased()).thenReturn(true);
when(resolution.getResolvedMethod()).thenReturn(rebasedMethod);
- when(resolution.getPrependedParameters()).thenReturn(new TypeList.Empty());
+ when(resolution.getAppendedParameters()).thenReturn(new TypeList.Empty());
when(rebasedMethod.isSpecializableFor(instrumentedType)).thenReturn(true);
Implementation.SpecialMethodInvocation specialMethodInvocation = makeImplementationTarget().invokeSuper(rebasedSignatureToken);
assertThat(specialMethodInvocation.isValid(), is(true));
@@ -115,7 +114,7 @@ public void testRebasedConstructorIsInvokable() throws Exception {
when(invokableMethod.getDeclaringType()).thenReturn(instrumentedType);
when(resolution.isRebased()).thenReturn(true);
when(resolution.getResolvedMethod()).thenReturn(rebasedMethod);
- when(resolution.getPrependedParameters()).thenReturn(new TypeList.Explicit(TypeDescription.OBJECT));
+ when(resolution.getAppendedParameters()).thenReturn(new TypeList.Explicit(TypeDescription.OBJECT));
when(rebasedMethod.isSpecializableFor(instrumentedType)).thenReturn(true);
Implementation.SpecialMethodInvocation specialMethodInvocation = makeImplementationTarget().invokeSuper(rebasedSignatureToken);
assertThat(specialMethodInvocation.isValid(), is(true));
@@ -137,7 +136,7 @@ public void testNonSpecializableRebaseMethodIsNotInvokable() throws Exception {
when(invokableMethod.getDeclaringType()).thenReturn(instrumentedType);
when(resolution.isRebased()).thenReturn(true);
when(resolution.getResolvedMethod()).thenReturn(rebasedMethod);
- when(resolution.getPrependedParameters()).thenReturn(new TypeList.Empty());
+ when(resolution.getAppendedParameters()).thenReturn(new TypeList.Empty());
when(rebasedMethod.isSpecializableFor(instrumentedType)).thenReturn(false);
Implementation.SpecialMethodInvocation specialMethodInvocation = makeImplementationTarget().invokeSuper(rebasedSignatureToken);
assertThat(specialMethodInvocation.isValid(), is(false));
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RedefinitionDynamicTypeBuilderTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RedefinitionDynamicTypeBuilderTest.java
index 32f02cb5474..74200af344e 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RedefinitionDynamicTypeBuilderTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/inline/RedefinitionDynamicTypeBuilderTest.java
@@ -17,8 +17,6 @@
import org.junit.Test;
import java.lang.reflect.Field;
-import java.net.URL;
-import java.net.URLClassLoader;
import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -66,7 +64,7 @@ public void testConstructorRetentionNoAuxiliaryType() throws Exception {
.redefine(Bar.class)
.make();
assertThat(dynamicType.getAuxiliaryTypes().size(), is(0));
- Class> type = dynamicType.load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(0));
Field field = type.getDeclaredField(BAR);
@@ -80,7 +78,7 @@ public void testConstructorRebaseSingleAuxiliaryType() throws Exception {
.constructor(any()).intercept(MethodCall.invoke(Object.class.getDeclaredConstructor()))
.make();
assertThat(dynamicType.getAuxiliaryTypes().size(), is(0));
- Class> type = dynamicType.load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(0));
Field field = type.getDeclaredField(BAR);
@@ -94,7 +92,7 @@ public void testMethodRebase() throws Exception {
.method(named(BAR)).intercept(StubMethod.INSTANCE)
.make();
assertThat(dynamicType.getAuxiliaryTypes().size(), is(0));
- Class> type = dynamicType.load(new URLClassLoader(new URL[0], null), ClassLoadingStrategy.Default.WRAPPER).getLoaded();
+ Class> type = dynamicType.load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER).getLoaded();
assertThat(type.getDeclaredConstructors().length, is(1));
assertThat(type.getDeclaredMethods().length, is(2));
assertThat(type.getDeclaredMethod(FOO).invoke(null), nullValue(Object.class));
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/test/utility/LegacyGetPackageClassLoader.java b/byte-buddy-dep/src/test/java/net/bytebuddy/test/utility/LegacyGetPackageClassLoader.java
index a317724f3bf..c0071b8c345 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/test/utility/LegacyGetPackageClassLoader.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/test/utility/LegacyGetPackageClassLoader.java
@@ -1,5 +1,7 @@
package net.bytebuddy.test.utility;
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.Manifest;
@@ -11,7 +13,7 @@
*/
public class LegacyGetPackageClassLoader extends URLClassLoader {
public LegacyGetPackageClassLoader() {
- super(new URL[0], new URLClassLoader(new URL[0], null));
+ super(new URL[0], new URLClassLoader(new URL[0], ClassLoadingStrategy.BOOTSTRAP_LOADER));
}
@Override
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitorTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitorTest.java
index 5f48962703d..2dae2808387 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitorTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/utility/visitor/FramePaddingMethodVisitorTest.java
@@ -72,6 +72,19 @@ public void testFramePadding() throws Exception {
inOrder.verifyNoMoreInteractions();
}
+ @Test
+ public void testFramePaddingIgnoredOnDuplicateOfSameFrame() throws Exception {
+ Method method = MethodVisitor.class.getDeclaredMethod(name, type);
+ FramePaddingMethodVisitor visitor = new FramePaddingMethodVisitor(methodVisitor);
+ visitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+ visitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+ method.invoke(visitor, argument);
+ InOrder inOrder = inOrder(methodVisitor);
+ inOrder.verify(methodVisitor).visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+ method.invoke(inOrder.verify(methodVisitor), argument);
+ inOrder.verifyNoMoreInteractions();
+ }
+
@Test
public void testNoFramePadding() throws Exception {
Method method = MethodVisitor.class.getDeclaredMethod(name, type);
diff --git a/byte-buddy-gradle-plugin/pom.xml b/byte-buddy-gradle-plugin/pom.xml
index 242b5fdc271..b98ca926cb1 100644
--- a/byte-buddy-gradle-plugin/pom.xml
+++ b/byte-buddy-gradle-plugin/pom.xml
@@ -5,7 +5,7 @@
byte-buddy-parent
net.bytebuddy
- 1.11.20
+ 1.11.21
byte-buddy-gradle-plugin
diff --git a/byte-buddy-maven-plugin/pom.xml b/byte-buddy-maven-plugin/pom.xml
index df6ff742f6d..5cb802fe053 100644
--- a/byte-buddy-maven-plugin/pom.xml
+++ b/byte-buddy-maven-plugin/pom.xml
@@ -5,7 +5,7 @@
byte-buddy-parent
net.bytebuddy
- 1.11.20
+ 1.11.21
byte-buddy-maven-plugin
diff --git a/byte-buddy/pom.xml b/byte-buddy/pom.xml
index d55e758d850..e051221ef52 100644
--- a/byte-buddy/pom.xml
+++ b/byte-buddy/pom.xml
@@ -5,7 +5,7 @@
net.bytebuddy
byte-buddy-parent
- 1.11.20
+ 1.11.21
byte-buddy
diff --git a/pom.xml b/pom.xml
index 73bdccd9633..e7e4b4898f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
net.bytebuddy
byte-buddy-parent
- 1.11.20
+ 1.11.21
pom
2014
@@ -134,7 +134,7 @@
scm:git:${repository.url}
scm:git:${repository.url}
${repository.url}
- byte-buddy-1.11.20
+ byte-buddy-1.11.21
diff --git a/release-notes.md b/release-notes.md
index 78c9d732482..6eaaac741bf 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -1,6 +1,11 @@
Byte Buddy release notes
------------------------
+### 11. October 2021: version 1.11.20
+
+- Add option for `AsScalar` annotation to assign default value instead of ignoring it.
+- Add *transform-runtime* goal to Byte Buddy Mojo to allow for running plugins with runtime class path included.
+
### 5. October 2021: version 1.11.19
- Add `Advice.AssignReturned` post processor to allow for assigning values from `Advice` that uses delegation rather than inlining.