From 22be227ce0ef36915bf0cdd92218c4b01100f847 Mon Sep 17 00:00:00 2001
From: Rafael Winterhalter
Date: Thu, 21 Apr 2016 09:56:06 +0200
Subject: [PATCH] Improved support for pre-Java 5 byte code.
---
.../main/java/net/bytebuddy/asm/Advice.java | 7 +
.../dynamic/scaffold/TypeWriter.java | 2 +
.../bytebuddy/implementation/FixedValue.java | 8 +-
.../implementation/Implementation.java | 83 ++++++++--
.../bind/annotation/Origin.java | 11 +-
.../TargetMethodAnnotationDrivenBinder.java | 12 +-
.../bytecode/constant/ClassConstant.java | 8 +-
.../constant/JavaInstanceConstant.java | 54 ++++++
.../constant/MethodHandleConstant.java | 155 ------------------
.../bytecode/constant/MethodTypeConstant.java | 87 ----------
.../bytecode/constant/TextConstant.java | 7 +-
.../net/bytebuddy/utility/JavaInstance.java | 25 ++-
.../scaffold/TypeWriterDefaultTest.java | 14 +-
...ImplementationContextDefaultOtherTest.java | 17 ++
.../ImplementationContextDisabledTest.java | 10 ++
.../bind/annotation/OriginBinderTest.java | 7 +-
.../constant/ClassConstantReferenceTest.java | 65 +++++++-
.../bytecode/constant/FieldConstantTest.java | 62 ++++++-
.../constant/JavaInstanceConstantTest.java | 52 ++++++
.../bytecode/constant/MethodConstantTest.java | 10 +-
.../constant/MethodHandleConstantTest.java | 150 -----------------
.../constant/MethodTypeConstantTest.java | 63 -------
...avaInstanceMethodHandleDispatcherTest.java | 7 +
.../utility/JavaInstanceMethodHandleTest.java | 6 +-
24 files changed, 400 insertions(+), 522 deletions(-)
create mode 100644 byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstant.java
delete mode 100644 byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstant.java
delete mode 100644 byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstant.java
create mode 100644 byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstantTest.java
delete mode 100644 byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstantTest.java
delete mode 100644 byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstantTest.java
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 d50ba6ff3a1..14cbaddb6b7 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
@@ -76,6 +76,13 @@
* older class file format version.
*
*
+ * Note: For the purpose of inlining, Java 5 and Java 6 byte code can be seen as the best candidate for advice methods. These versions do
+ * no longer allow subroutines, neither do they already allow invokedynamic instructions or method handles. This way, Java 5 and Java 6 byte
+ * code is compatible to both older and newer versions. One exception for backwards-incompatible byte code is the possibility to load type references
+ * from the constant pool onto the operand stack. These instructions can however easily be transformerd for classes compiled to Java 4 and older
+ * by registering a {@link TypeConstantAdjustment} before the advice visitor.
+ *
+ *
* Note: It is not possible to trigger break points in inlined advice methods as the debugging information of the inlined advice is not
* preserved. It is not possible in Java to reference more than one source file per class what makes translating such debugging information
* impossible. It is however possible to set break points in advice methods when invoking the original advice target. This allows debugging
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 c642e2eb77a..1e0ea9912fa 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
@@ -3014,6 +3014,7 @@ public void visit(int classFileVersionNumber,
TypeDescription.OBJECT :
instrumentedType.getSuperClass().asErasure()).getInternalName(),
instrumentedType.getInterfaces().asErasures().toInternalNames());
+ implementationContext.setClassFileVersion(ClassFileVersion.ofMinorMajor(classFileVersionNumber));
typeAttributeAppender.apply(cv, instrumentedType, annotationValueFilterFactory.on(instrumentedType));
if (!ClassFileVersion.ofMinorMajor(classFileVersionNumber).isAtLeast(ClassFileVersion.JAVA_V8) && instrumentedType.isInterface()) {
implementationContext.prohibitTypeInitializer();
@@ -3496,6 +3497,7 @@ public byte[] create(Implementation.Context.ExtractableView implementationContex
? TypeDescription.OBJECT
: instrumentedType.getSuperClass().asErasure()).getInternalName(),
instrumentedType.getInterfaces().asErasures().toInternalNames());
+ implementationContext.setClassFileVersion(classFileVersion);
typeAttributeAppender.apply(classVisitor, instrumentedType, annotationValueFilterFactory.on(instrumentedType));
for (FieldDescription fieldDescription : instrumentedType.getDeclaredFields()) {
fieldPool.target(fieldDescription).apply(classVisitor, annotationValueFilterFactory);
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/FixedValue.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/FixedValue.java
index 8a53f78b659..535cfb9343b 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/FixedValue.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/FixedValue.java
@@ -57,6 +57,10 @@ protected FixedValue(Assigner assigner, Assigner.Typing typing) {
* When a value is stored in the class's constant pool, its identity is lost. If an object's identity is important, the
* {@link FixedValue#reference(Object)} method should be used instead.
*
+ *
+ * Important: When supplying a method handle or a method type, all types that are implied must be visible to the instrumented
+ * type or an {@link IllegalAccessException} will be thrown at runtime.
+ *
*
* @param fixedValue The fixed value to return from the method.
* @return An implementation for the given {@code fixedValue}.
@@ -114,12 +118,12 @@ public static AssignerConfigurable value(Object fixedValue) {
Assigner.DEFAULT,
Assigner.Typing.STATIC);
} else if (JavaType.METHOD_HANDLE.getTypeStub().isAssignableFrom(type)) {
- return new ForPoolValue(MethodHandleConstant.of(JavaInstance.MethodHandle.ofLoaded(fixedValue)),
+ return new ForPoolValue(new JavaInstanceConstant(JavaInstance.MethodHandle.ofLoaded(fixedValue)),
new TypeDescription.ForLoadedType(type),
Assigner.DEFAULT,
Assigner.Typing.STATIC);
} else if (JavaType.METHOD_TYPE.getTypeStub().represents(type)) {
- return new ForPoolValue(MethodTypeConstant.of(JavaInstance.MethodType.ofLoaded(fixedValue)),
+ return new ForPoolValue(new JavaInstanceConstant(JavaInstance.MethodType.ofLoaded(fixedValue)),
new TypeDescription.ForLoadedType(type),
Assigner.DEFAULT,
Assigner.Typing.STATIC);
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/Implementation.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/Implementation.java
index 69b6fe45097..606911e2fb4 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/Implementation.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/Implementation.java
@@ -406,12 +406,34 @@ interface Context {
*/
FieldDescription.InDefinedShape cache(StackManipulation fieldValue, TypeDescription fieldType);
+ /**
+ * Returns the instrumented type of the current implementation. The instrumented type is exposed with the intend of allowing optimal
+ * byte code generation and not for implementing checks or changing the behavior of a {@link StackManipulation}.
+ *
+ * @return The instrumented type of the current implementation.
+ */
+ TypeDescription getInstrumentedType();
+
+ /**
+ * Returns the class file version of the current implementation.
+ *
+ * @return The class file version of the current implementation.
+ */
+ ClassFileVersion getClassFileVersion();
+
/**
* Represents an extractable view of an {@link Implementation.Context} which
* allows the retrieval of any registered auxiliary type.
*/
interface ExtractableView extends Context {
+ /**
+ * Sets the class file version this implementation context should represent.
+ *
+ * @param classFileVersion The class file version to represent.
+ */
+ void setClassFileVersion(ClassFileVersion classFileVersion);
+
/**
* Determines if this implementation context allows for the retention of a static type initializer.
*
@@ -496,6 +518,49 @@ public String toString() {
}
}
}
+
+ /**
+ * An abstract base implementation of an extractable view of an implementation context.
+ */
+ abstract class AbstractBase implements ExtractableView {
+
+ /**
+ * The instrumented type.
+ */
+ protected final TypeDescription instrumentedType;
+
+ /**
+ * The class file version of the instrumented type.
+ */
+ private ClassFileVersion classFileVersion;
+
+ /**
+ * Create a new extractable view.
+ *
+ * @param instrumentedType The instrumented type.
+ */
+ protected AbstractBase(TypeDescription instrumentedType) {
+ this.instrumentedType = instrumentedType;
+ }
+
+ @Override
+ public void setClassFileVersion(ClassFileVersion classFileVersion) {
+ this.classFileVersion = classFileVersion;
+ }
+
+ @Override
+ public TypeDescription getInstrumentedType() {
+ return instrumentedType;
+ }
+
+ @Override
+ public ClassFileVersion getClassFileVersion() {
+ if (classFileVersion == null) {
+ throw new IllegalStateException("Cannot read class file version before it was set");
+ }
+ return classFileVersion;
+ }
+ }
}
/**
@@ -523,12 +588,7 @@ ExtractableView make(TypeDescription instrumentedType,
* redefining a class when it is not allowed to add methods to a class what is an implicit requirement when copying the static
* initializer block into another method.
*/
- class Disabled implements ExtractableView {
-
- /**
- * The instrumented type.
- */
- private final TypeDescription instrumentedType;
+ class Disabled extends ExtractableView.AbstractBase {
/**
* Creates a new disabled implementation context.
@@ -536,7 +596,7 @@ class Disabled implements ExtractableView {
* @param instrumentedType The instrumented type.
*/
protected Disabled(TypeDescription instrumentedType) {
- this.instrumentedType = instrumentedType;
+ super(instrumentedType);
}
@Override
@@ -624,7 +684,7 @@ public String toString() {
* A default implementation of an {@link Implementation.Context.ExtractableView}
* which serves as its own {@link net.bytebuddy.implementation.auxiliary.AuxiliaryType.MethodAccessorFactory}.
*/
- class Default implements ExtractableView, AuxiliaryType.MethodAccessorFactory {
+ class Default extends ExtractableView.AbstractBase implements AuxiliaryType.MethodAccessorFactory {
/**
* The name suffix to be appended to an accessor method.
@@ -636,11 +696,6 @@ class Default implements ExtractableView, AuxiliaryType.MethodAccessorFactory {
*/
public static final String FIELD_CACHE_PREFIX = "cachedValue";
- /**
- * The instrumented type that this instance represents.
- */
- private final TypeDescription instrumentedType;
-
/**
* The type initializer of the created instrumented type.
*/
@@ -714,7 +769,7 @@ protected Default(TypeDescription instrumentedType,
AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
TypeInitializer typeInitializer,
ClassFileVersion classFileVersion) {
- this.instrumentedType = instrumentedType;
+ super(instrumentedType);
this.auxiliaryTypeNamingStrategy = auxiliaryTypeNamingStrategy;
this.typeInitializer = typeInitializer;
this.classFileVersion = classFileVersion;
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/Origin.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/Origin.java
index e0eccf765a0..2c76fbcceef 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/Origin.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/Origin.java
@@ -8,6 +8,7 @@
import net.bytebuddy.implementation.bind.MethodDelegationBinder;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.implementation.bytecode.constant.*;
+import net.bytebuddy.utility.JavaInstance;
import net.bytebuddy.utility.JavaType;
import java.lang.annotation.*;
@@ -15,6 +16,7 @@
import java.lang.reflect.Method;
/**
+ *
* The origin annotation provides some meta information about the source method that is bound to this method where
* the binding is dependant of the parameter's type:
*
@@ -36,6 +38,11 @@
* is injected. Method type descriptions are only supported for byte code versions starting from Java 7.
*
* Any other parameter type will cause an {@link java.lang.IllegalStateException}.
+ *
+ *
+ * Important: A method handle or method type reference can only be used if the referenced method's types are all visible
+ * to the instrumented type or an {@link IllegalAccessError} will be thrown at runtime.
+ *
*
* @see net.bytebuddy.implementation.MethodDelegation
* @see net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder
@@ -104,9 +111,9 @@ public MethodDelegationBinder.ParameterBinding> bind(AnnotationDescription.Loa
} else if (parameterType.represents(int.class)) {
return new MethodDelegationBinder.ParameterBinding.Anonymous(IntegerConstant.forValue(source.getModifiers()));
} else if (parameterType.equals(JavaType.METHOD_HANDLE.getTypeStub())) {
- return new MethodDelegationBinder.ParameterBinding.Anonymous(MethodHandleConstant.of(source.asDefined()));
+ return new MethodDelegationBinder.ParameterBinding.Anonymous(JavaInstance.MethodHandle.of(source.asDefined()).asStackManipulation());
} else if (parameterType.equals(JavaType.METHOD_TYPE.getTypeStub())) {
- return new MethodDelegationBinder.ParameterBinding.Anonymous(MethodTypeConstant.of(source.asDefined()));
+ return new MethodDelegationBinder.ParameterBinding.Anonymous(JavaInstance.MethodType.of(source.asDefined()).asStackManipulation());
} else {
throw new IllegalStateException("The " + target + " method's " + target.getIndex() +
" parameter is annotated with a Origin annotation with an argument not representing a Class," +
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/TargetMethodAnnotationDrivenBinder.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/TargetMethodAnnotationDrivenBinder.java
index 37feca40e7f..7f08177a436 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/TargetMethodAnnotationDrivenBinder.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bind/annotation/TargetMethodAnnotationDrivenBinder.java
@@ -197,6 +197,10 @@ ParameterBinding> bind(AnnotationDescription.Loadable annotation,
* instances or method handles and method types for classes of a version at least of Java 7. The latter instances can also be
* expressed as unloaded {@link JavaInstance} representations.
*
+ *
+ * Important: When supplying a method handle or a method type, all types that are implied must be visible to the instrumented
+ * type or an {@link IllegalAccessException} will be thrown at runtime.
+ *
*
* @param The bound annotation's type.
*/
@@ -248,16 +252,16 @@ public ParameterBinding> bind(AnnotationDescription.Loadable annotation,
stackManipulation = ClassConstant.of((TypeDescription) value);
suppliedType = TypeDescription.CLASS;
} else if (JavaType.METHOD_HANDLE.getTypeStub().isInstance(value)) {
- stackManipulation = MethodHandleConstant.of(JavaInstance.MethodHandle.ofLoaded(value));
+ stackManipulation = JavaInstance.MethodHandle.ofLoaded(value).asStackManipulation();
suppliedType = JavaType.METHOD_HANDLE.getTypeStub();
} else if (value instanceof JavaInstance.MethodHandle) {
- stackManipulation = MethodHandleConstant.of((JavaInstance.MethodHandle) value);
+ stackManipulation = new JavaInstanceConstant((JavaInstance.MethodHandle) value);
suppliedType = JavaType.METHOD_HANDLE.getTypeStub();
} else if (JavaType.METHOD_TYPE.getTypeStub().isInstance(value)) {
- stackManipulation = MethodTypeConstant.of(JavaInstance.MethodType.ofLoaded(value));
+ stackManipulation = new JavaInstanceConstant(JavaInstance.MethodType.ofLoaded(value));
suppliedType = JavaType.METHOD_HANDLE.getTypeStub();
} else if (value instanceof JavaInstance.MethodType) {
- stackManipulation = MethodTypeConstant.of((JavaInstance.MethodType) value);
+ stackManipulation = new JavaInstanceConstant((JavaInstance.MethodType) value);
suppliedType = JavaType.METHOD_HANDLE.getTypeStub();
} else {
throw new IllegalStateException("Not able to save in class's constant pool: " + value);
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/ClassConstant.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/ClassConstant.java
index 66c49423e0e..f4e8ace0e2f 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/ClassConstant.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/ClassConstant.java
@@ -1,5 +1,6 @@
package net.bytebuddy.implementation.bytecode.constant;
+import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;
@@ -160,7 +161,12 @@ public boolean isValid() {
@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
- methodVisitor.visitLdcInsn(Type.getType(typeDescription.getDescriptor()));
+ if (implementationContext.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V5) && typeDescription.isVisibleTo(implementationContext.getInstrumentedType())) {
+ methodVisitor.visitLdcInsn(Type.getType(typeDescription.getDescriptor()));
+ } else {
+ methodVisitor.visitLdcInsn(typeDescription.getName());
+ methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
+ }
return SIZE;
}
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstant.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstant.java
new file mode 100644
index 00000000000..6a767a1fb69
--- /dev/null
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstant.java
@@ -0,0 +1,54 @@
+package net.bytebuddy.implementation.bytecode.constant;
+
+import net.bytebuddy.implementation.Implementation;
+import net.bytebuddy.implementation.bytecode.StackManipulation;
+import net.bytebuddy.implementation.bytecode.StackSize;
+import net.bytebuddy.utility.JavaInstance;
+import org.objectweb.asm.MethodVisitor;
+
+/**
+ * A constant representing a {@link JavaInstance}.
+ */
+public class JavaInstanceConstant implements StackManipulation {
+
+ /**
+ * The instance to load onto the operand stack.
+ */
+ private final JavaInstance javaInstance;
+
+ /**
+ * Creates a constant pool value representing a {@link JavaInstance}.
+ *
+ * @param javaInstance The instance to load onto the operand stack.
+ */
+ public JavaInstanceConstant(JavaInstance javaInstance) {
+ this.javaInstance = javaInstance;
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
+ methodVisitor.visitLdcInsn(javaInstance.asConstantPoolValue());
+ return StackSize.SINGLE.toIncreasingSize();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return this == other || !(other == null || getClass() != other.getClass())
+ && javaInstance.equals(((JavaInstanceConstant) other).javaInstance);
+ }
+
+ @Override
+ public int hashCode() {
+ return javaInstance.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "JavaInstanceConstant{javaInstance=" + javaInstance + '}';
+ }
+}
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstant.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstant.java
deleted file mode 100644
index d1079727510..00000000000
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstant.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package net.bytebuddy.implementation.bytecode.constant;
-
-import net.bytebuddy.description.field.FieldDescription;
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.implementation.Implementation;
-import net.bytebuddy.implementation.bytecode.StackManipulation;
-import net.bytebuddy.implementation.bytecode.StackSize;
-import net.bytebuddy.utility.JavaInstance;
-import org.objectweb.asm.Handle;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-/**
- * A constant for a Java 7 {@code java.lang.invoke.MethodHandle}.
- */
-public class MethodHandleConstant implements StackManipulation {
-
- /**
- * The size of a {@code java.lang.invoke.MethodHandle} on the operand stack.
- */
- private static final Size SIZE = StackSize.SINGLE.toIncreasingSize();
-
- /**
- * The ASM handle for the creating the given method handle.
- */
- private final Handle handle;
-
- /**
- * Creates a new method handle constant.
- *
- * @param handle The ASM handle for loading the handle onto the operand stack.
- */
- private MethodHandleConstant(Handle handle) {
- this.handle = handle;
- }
-
- /**
- * Creates a method handle for a method.
- *
- * @param methodDescription The method for which a method handle is to be put onto the operand stack.
- * @return A stack manipulation that represents the loading of the handle.
- */
- public static StackManipulation of(MethodDescription.InDefinedShape methodDescription) {
- return methodDescription.isTypeInitializer()
- ? Illegal.INSTANCE
- : new MethodHandleConstant(new Handle(tagFor(methodDescription),
- methodDescription.getDeclaringType().asErasure().getInternalName(),
- methodDescription.getInternalName(),
- methodDescription.getDescriptor(),
- methodDescription.getDeclaringType().isInterface()));
- }
-
- /**
- * Creates stack manipulation for loading the provided method handle onto the operand stack.
- *
- * @param methodHandle The method handle to load onto the operand stack.
- * @return A stack manipulation for loading the provided method handle onto the operand stack.
- */
- public static StackManipulation of(JavaInstance.MethodHandle methodHandle) {
- Type[] parameterType = new Type[methodHandle.getParameterTypes().size()];
- int index = 0;
- for (TypeDescription typeDescription : methodHandle.getParameterTypes()) {
- parameterType[index++] = Type.getType(typeDescription.getDescriptor());
- }
- return new MethodHandleConstant(new Handle(methodHandle.getHandleType().getIdentifier(),
- methodHandle.getOwnerType().getInternalName(),
- methodHandle.getName(),
- Type.getMethodDescriptor(Type.getType(methodHandle.getReturnType().getDescriptor()), parameterType),
- methodHandle.getOwnerType().isInterface()));
- }
-
- /**
- * Looks up the handle tag for the given method.
- *
- * @param methodDescription The method for which a method handle is to be put onto the operand stack.
- * @return The tag for the handle of this method.
- */
- private static int tagFor(MethodDescription.InDefinedShape methodDescription) {
- if (methodDescription.isConstructor()) {
- return Opcodes.H_NEWINVOKESPECIAL;
- } else if (methodDescription.isStatic()) {
- return Opcodes.H_INVOKESTATIC;
- } else if (methodDescription.isPrivate() || methodDescription.isDefaultMethod()) {
- return Opcodes.H_INVOKESPECIAL;
- } else if (methodDescription.getDeclaringType().isInterface()) {
- return Opcodes.H_INVOKEINTERFACE;
- } else {
- return Opcodes.H_INVOKEVIRTUAL;
- }
- }
-
- /**
- * Creates a method handle for a field getter.
- *
- * @param fieldDescription The field for which a get handle is to be put onto the operand stack.
- * @return A stack manipulation that represents the loading of the handle.
- */
- public static StackManipulation ofGetter(FieldDescription.InDefinedShape fieldDescription) {
- return of(fieldDescription, fieldDescription.isStatic() ? Opcodes.H_GETSTATIC : Opcodes.H_GETFIELD);
- }
-
- /**
- * Creates a method handle for a field putter.
- *
- * @param fieldDescription The field for which a put handle is to be put onto the operand stack.
- * @return A stack manipulation that represents the loading of the handle.
- */
- public static StackManipulation ofPutter(FieldDescription.InDefinedShape fieldDescription) {
- return of(fieldDescription, fieldDescription.isStatic() ? Opcodes.H_PUTSTATIC : Opcodes.H_PUTFIELD);
- }
-
- /**
- * Creates a method handle for a field.
- *
- * @param fieldDescription The field for which a handle is to be put onto the operand stack.
- * @param tag The tag for this handle.
- * @return A stack manipulation that represents the loading of the handle.
- */
- private static StackManipulation of(FieldDescription.InDefinedShape fieldDescription, int tag) {
- return new MethodHandleConstant(new Handle(tag,
- fieldDescription.getDeclaringType().getInternalName(),
- fieldDescription.getInternalName(),
- fieldDescription.getDescriptor(),
- fieldDescription.getDeclaringType().isInterface()));
- }
-
- @Override
- public boolean isValid() {
- return true;
- }
-
- @Override
- public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
- methodVisitor.visitLdcInsn(handle);
- return SIZE;
- }
-
- @Override
- public boolean equals(Object other) {
- return this == other || !(other == null || getClass() != other.getClass())
- && handle.equals(((MethodHandleConstant) other).handle);
- }
-
- @Override
- public int hashCode() {
- return handle.hashCode();
- }
-
- @Override
- public String toString() {
- return "MethodHandleConstant{handle=" + handle + '}';
- }
-}
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstant.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstant.java
deleted file mode 100644
index b4b44109882..00000000000
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstant.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package net.bytebuddy.implementation.bytecode.constant;
-
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.implementation.Implementation;
-import net.bytebuddy.implementation.bytecode.StackManipulation;
-import net.bytebuddy.implementation.bytecode.StackSize;
-import net.bytebuddy.utility.JavaInstance;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-
-/**
- * A constant for a Java 7 {@code java.lang.invoke.MethodType}.
- */
-public class MethodTypeConstant implements StackManipulation {
-
- /**
- * The size of a {@code java.lang.invoke.MethodType} on the operand stack.
- */
- private static final Size SIZE = StackSize.SINGLE.toIncreasingSize();
-
- /**
- * The represented method type.
- */
- private final Type methodType;
-
- /**
- * Creates a method type constant for the given method type.
- *
- * @param methodType The represented method type.
- */
- protected MethodTypeConstant(Type methodType) {
- this.methodType = methodType;
- }
-
- /**
- * Transforms the given method into a stack manipulation that loads its type onto the operand stack.
- *
- * @param methodDescription The method of which the method type should be loaded onto the operand stack.
- * @return A stack manipulation that loads the method type of the given method onto the operand stack.
- */
- public static StackManipulation of(MethodDescription.InDefinedShape methodDescription) {
- return new MethodTypeConstant(Type.getMethodType(methodDescription.getDescriptor()));
- }
-
- /**
- * Transforms the given method type into a stack manipulation that loads its type onto the operand stack.
- *
- * @param methodType The method type that should be loaded onto the operand stack.
- * @return A stack manipulation that loads the given method type.
- */
- public static StackManipulation of(JavaInstance.MethodType methodType) {
- Type[] parameterType = new Type[methodType.getParameterTypes().size()];
- int index = 0;
- for (TypeDescription typeDescription : methodType.getParameterTypes()) {
- parameterType[index++] = Type.getType(typeDescription.getDescriptor());
- }
- return new MethodTypeConstant(Type.getMethodType(Type.getType(methodType.getReturnType().getDescriptor()), parameterType));
- }
-
- @Override
- public boolean isValid() {
- return true;
- }
-
- @Override
- public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
- methodVisitor.visitLdcInsn(methodType);
- return SIZE;
- }
-
- @Override
- public boolean equals(Object other) {
- return this == other || !(other == null || getClass() != other.getClass())
- && methodType.equals(((MethodTypeConstant) other).methodType);
- }
-
- @Override
- public int hashCode() {
- return methodType.hashCode();
- }
-
- @Override
- public String toString() {
- return "MethodTypeConstant{methodType=" + methodType + '}';
- }
-}
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/TextConstant.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/TextConstant.java
index b2c42aa001a..c5dae9df2d4 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/TextConstant.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/bytecode/constant/TextConstant.java
@@ -10,11 +10,6 @@
*/
public class TextConstant implements StackManipulation {
- /**
- * The size impact of loading a {@link String} onto the operand stack.
- */
- private static final Size SIZE = StackSize.SINGLE.toIncreasingSize();
-
/**
* The text value to load onto the operand stack.
*/
@@ -37,7 +32,7 @@ public boolean isValid() {
@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
methodVisitor.visitLdcInsn(text);
- return SIZE;
+ return StackSize.SINGLE.toIncreasingSize();
}
@Override
diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/utility/JavaInstance.java b/byte-buddy-dep/src/main/java/net/bytebuddy/utility/JavaInstance.java
index 381b051549a..940f21b70d8 100644
--- a/byte-buddy-dep/src/main/java/net/bytebuddy/utility/JavaInstance.java
+++ b/byte-buddy-dep/src/main/java/net/bytebuddy/utility/JavaInstance.java
@@ -5,8 +5,7 @@
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import net.bytebuddy.implementation.bytecode.StackManipulation;
-import net.bytebuddy.implementation.bytecode.constant.MethodHandleConstant;
-import net.bytebuddy.implementation.bytecode.constant.MethodTypeConstant;
+import net.bytebuddy.implementation.bytecode.constant.JavaInstanceConstant;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -273,7 +272,7 @@ public Object asConstantPoolValue() {
@Override
public StackManipulation asStackManipulation() {
- return MethodTypeConstant.of(this);
+ return new JavaInstanceConstant(this);
}
@Override
@@ -611,7 +610,7 @@ public static MethodHandle of(Constructor> constructor) {
* @param methodDescription The method ro represent.
* @return A method handle representing the given method.
*/
- public static MethodHandle of(MethodDescription methodDescription) {
+ public static MethodHandle of(MethodDescription.InDefinedShape methodDescription) {
return new MethodHandle(HandleType.of(methodDescription),
methodDescription.getDeclaringType().asErasure(),
methodDescription.getInternalName(),
@@ -637,7 +636,7 @@ public static MethodHandle ofSpecial(Method method, Class> type) {
* @param typeDescription The type on which the method is to be invoked on as a special method invocation.
* @return A method handle representing the given method as special method invocation.
*/
- public static MethodHandle ofSpecial(MethodDescription methodDescription, TypeDescription typeDescription) {
+ public static MethodHandle ofSpecial(MethodDescription.InDefinedShape methodDescription, TypeDescription typeDescription) {
if (!methodDescription.isSpecializableFor(typeDescription)) {
throw new IllegalArgumentException("Cannot specialize " + methodDescription + " for " + typeDescription);
}
@@ -664,7 +663,7 @@ public static MethodHandle ofGetter(Field field) {
* @param fieldDescription The field to represent.
* @return A method handle for a setter of the given field.
*/
- public static MethodHandle ofGetter(FieldDescription fieldDescription) {
+ public static MethodHandle ofGetter(FieldDescription.InDefinedShape fieldDescription) {
return new MethodHandle(HandleType.ofGetter(fieldDescription),
fieldDescription.getDeclaringType().asErasure(),
fieldDescription.getInternalName(),
@@ -688,7 +687,7 @@ public static MethodHandle ofSetter(Field field) {
* @param fieldDescription The field to represent.
* @return A method handle for a getter of the given field.
*/
- public static MethodHandle ofSetter(FieldDescription fieldDescription) {
+ public static MethodHandle ofSetter(FieldDescription.InDefinedShape fieldDescription) {
return new MethodHandle(HandleType.ofSetter(fieldDescription),
fieldDescription.getDeclaringType().asErasure(),
fieldDescription.getInternalName(),
@@ -708,7 +707,7 @@ public Object asConstantPoolValue() {
@Override
public StackManipulation asStackManipulation() {
- return MethodHandleConstant.of(this);
+ return new JavaInstanceConstant(this);
}
@Override
@@ -1305,7 +1304,7 @@ public Object publicLookup() {
@Override
public Class> lookupType(Object lookup) {
- throw new IllegalStateException(); // TODO
+ throw new IllegalStateException("Unsupported type on current JVM: java.lang.invoke.MethodHandle");
}
@Override
@@ -1385,7 +1384,7 @@ public enum HandleType {
* @param methodDescription The method for which a handle type should be found.
* @return The handle type for the given method.
*/
- protected static HandleType of(MethodDescription methodDescription) {
+ protected static HandleType of(MethodDescription.InDefinedShape methodDescription) {
if (methodDescription.isStatic()) {
return INVOKE_STATIC;
} else if (methodDescription.isPrivate()) {
@@ -1420,7 +1419,7 @@ protected static HandleType of(int identifier) {
* @param methodDescription The method for which a handle type should be found.
* @return The handle type for the given method.
*/
- protected static HandleType ofSpecial(MethodDescription methodDescription) {
+ protected static HandleType ofSpecial(MethodDescription.InDefinedShape methodDescription) {
if (methodDescription.isStatic() || methodDescription.isAbstract()) {
throw new IllegalArgumentException("Cannot invoke " + methodDescription + " via invokespecial");
}
@@ -1435,7 +1434,7 @@ protected static HandleType ofSpecial(MethodDescription methodDescription) {
* @param fieldDescription The field for which to create a getter handle.
* @return The corresponding handle type.
*/
- protected static HandleType ofGetter(FieldDescription fieldDescription) {
+ protected static HandleType ofGetter(FieldDescription.InDefinedShape fieldDescription) {
return fieldDescription.isStatic()
? GET_STATIC_FIELD
: GET_FIELD;
@@ -1447,7 +1446,7 @@ protected static HandleType ofGetter(FieldDescription fieldDescription) {
* @param fieldDescription The field for which to create a setter handle.
* @return The corresponding handle type.
*/
- protected static HandleType ofSetter(FieldDescription fieldDescription) {
+ protected static HandleType ofSetter(FieldDescription.InDefinedShape fieldDescription) {
return fieldDescription.isStatic()
? PUT_STATIC_FIELD
: PUT_FIELD;
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterDefaultTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterDefaultTest.java
index 650ed5b9493..805f5b60d47 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterDefaultTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterDefaultTest.java
@@ -377,21 +377,11 @@ public void testTypeInitializerOnRebasedLegacyInterface() throws Exception {
.make();
}
- @Test(expected = IllegalStateException.class)
- public void testTypeInLegacyConstantPool() throws Exception {
- new ByteBuddy(ClassFileVersion.JAVA_V4)
- .subclass(Object.class)
- .defineMethod(FOO, Object.class)
- .intercept(FixedValue.value(Object.class))
- .make();
- }
-
@Test
public void testTypeInLegacyConstantPoolRemapped() throws Exception {
Class> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V4)
.with(TypeValidation.DISABLED)
.subclass(Object.class)
- .visit(TypeConstantAdjustment.INSTANCE)
.defineMethod(FOO, Object.class, Visibility.PUBLIC)
.intercept(FixedValue.value(Object.class))
.make()
@@ -405,7 +395,6 @@ public void testArrayTypeInLegacyConstantPoolRemapped() throws Exception {
Class> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V4)
.with(TypeValidation.DISABLED)
.subclass(Object.class)
- .visit(TypeConstantAdjustment.INSTANCE)
.defineMethod(FOO, Object.class, Visibility.PUBLIC)
.intercept(FixedValue.value(Object[].class))
.make()
@@ -419,7 +408,6 @@ public void testPrimitiveTypeInLegacyConstantPoolRemapped() throws Exception {
Class> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V4)
.with(TypeValidation.DISABLED)
.subclass(Object.class)
- .visit(TypeConstantAdjustment.INSTANCE)
.defineMethod(FOO, Object.class, Visibility.PUBLIC)
.intercept(FixedValue.value(int.class))
.make()
@@ -428,6 +416,8 @@ public void testPrimitiveTypeInLegacyConstantPoolRemapped() throws Exception {
assertThat(dynamicType.getDeclaredMethod(FOO).invoke(dynamicType.newInstance()), is((Object) int.class));
}
+ // TODO: Add tests for type adjustment with pre-compiling legacy type
+
@Test(expected = IllegalStateException.class)
public void testMethodTypeInLegacyConstantPool() throws Exception {
new ByteBuddy(ClassFileVersion.JAVA_V4)
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDefaultOtherTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDefaultOtherTest.java
index f8e4c881dc6..9cb10300b6c 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDefaultOtherTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDefaultOtherTest.java
@@ -63,6 +63,23 @@ public void testFrozenTypeInitializerFrozenThrowsExceptionOnDrain() throws Excep
mock(AnnotationValueFilter.Factory.class));
}
+ @Test(expected = IllegalStateException.class)
+ public void testPrematureUse() throws Exception {
+ new Implementation.Context.Default(mock(TypeDescription.class),
+ mock(AuxiliaryType.NamingStrategy.class),
+ mock(TypeInitializer.class),
+ mock(ClassFileVersion.class)).getClassFileVersion();
+ }
+
+ @Test
+ public void testInstrumentationGetter() throws Exception {
+ TypeDescription instrumentedType = mock(TypeDescription.class);
+ assertThat(new Implementation.Context.Default(instrumentedType,
+ mock(AuxiliaryType.NamingStrategy.class),
+ mock(TypeInitializer.class),
+ mock(ClassFileVersion.class)).getInstrumentedType(), is(instrumentedType));
+ }
+
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(Implementation.Context.Default.class).applyBasic();
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDisabledTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDisabledTest.java
index f2e171b3fd0..6db379e0b2c 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDisabledTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/ImplementationContextDisabledTest.java
@@ -108,6 +108,16 @@ public void testDrainWithMatchedCode() throws Exception {
mock(AnnotationValueFilter.Factory.class));
}
+ @Test(expected = IllegalStateException.class)
+ public void testPrematureUse() throws Exception {
+ new Implementation.Context.Disabled(instrumentedType).getClassFileVersion();
+ }
+
+ @Test
+ public void testInstrumentationGetter() throws Exception {
+ assertThat(new Implementation.Context.Disabled(instrumentedType).getInstrumentedType(), is(instrumentedType));
+ }
+
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(Implementation.Context.Disabled.class).apply();
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bind/annotation/OriginBinderTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bind/annotation/OriginBinderTest.java
index 461a2c1deb5..a5bec096b40 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bind/annotation/OriginBinderTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bind/annotation/OriginBinderTest.java
@@ -1,6 +1,8 @@
package net.bytebuddy.implementation.bind.annotation;
import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.method.ParameterDescription;
+import net.bytebuddy.description.method.ParameterList;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bind.MethodDelegationBinder;
@@ -127,6 +129,8 @@ public void testModifierBinding() throws Exception {
@JavaVersionRule.Enforce(7)
public void testMethodHandleBinding() throws Exception {
when(genericTargetType.asErasure()).thenReturn(new TypeDescription.ForLoadedType(JavaType.METHOD_HANDLE.load()));
+ when(methodDescription.getReturnType()).thenReturn(TypeDescription.Generic.VOID);
+ when(methodDescription.getParameters()).thenReturn(new ParameterList.Empty());
TypeDescription typeDescription = mock(TypeDescription.class);
when(typeDescription.asErasure()).thenReturn(typeDescription);
when(methodDescription.getDeclaringType()).thenReturn(typeDescription);
@@ -139,7 +143,8 @@ public void testMethodHandleBinding() throws Exception {
@JavaVersionRule.Enforce(7)
public void testMethodTypeBinding() throws Exception {
when(genericTargetType.asErasure()).thenReturn(new TypeDescription.ForLoadedType(JavaType.METHOD_TYPE.load()));
- when(methodDescription.getDescriptor()).thenReturn(FOO);
+ when(methodDescription.getReturnType()).thenReturn(TypeDescription.Generic.VOID);
+ when(methodDescription.getParameters()).thenReturn(new ParameterList.Empty());
MethodDelegationBinder.ParameterBinding> parameterBinding = Origin.Binder.INSTANCE
.bind(annotationDescription, source, target, implementationTarget, assigner);
assertThat(parameterBinding.isValid(), is(true));
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/ClassConstantReferenceTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/ClassConstantReferenceTest.java
index 9b4ff4aa3be..6472ab8f8df 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/ClassConstantReferenceTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/ClassConstantReferenceTest.java
@@ -1,15 +1,18 @@
package net.bytebuddy.implementation.bytecode.constant;
+import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.test.utility.MockitoRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.mockito.Mock;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import static org.hamcrest.CoreMatchers.is;
@@ -24,7 +27,10 @@ public class ClassConstantReferenceTest {
public TestRule mockitoRule = new MockitoRule(this);
@Mock
- private TypeDescription typeDescription;
+ private TypeDescription typeDescription, instrumentedType;
+
+ @Mock
+ private ClassFileVersion classFileVersion;
@Mock
private MethodVisitor methodVisitor;
@@ -32,8 +38,16 @@ public class ClassConstantReferenceTest {
@Mock
private Implementation.Context implementationContext;
+ @Before
+ public void setUp() throws Exception {
+ when(implementationContext.getInstrumentedType()).thenReturn(instrumentedType);
+ when(implementationContext.getClassFileVersion()).thenReturn(classFileVersion);
+ }
+
@Test
- public void testClassConstant() throws Exception {
+ public void testClassConstantModernVisible() throws Exception {
+ when(typeDescription.isVisibleTo(instrumentedType)).thenReturn(true);
+ when(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)).thenReturn(true);
when(typeDescription.getDescriptor()).thenReturn(FOO);
StackManipulation stackManipulation = ClassConstant.of(typeDescription);
assertThat(stackManipulation.isValid(), is(true));
@@ -41,11 +55,56 @@ public void testClassConstant() throws Exception {
assertThat(size.getSizeImpact(), is(1));
assertThat(size.getMaximalSize(), is(1));
verify(typeDescription).getDescriptor();
+ verify(typeDescription).isVisibleTo(instrumentedType);
verify(typeDescription, times(9)).represents(any(Class.class));
verifyNoMoreInteractions(typeDescription);
verify(methodVisitor).visitLdcInsn(Type.getType(FOO));
verifyNoMoreInteractions(methodVisitor);
- verifyZeroInteractions(implementationContext);
+ }
+
+ @Test
+ public void testClassConstantModernInvisible() throws Exception {
+ when(typeDescription.isVisibleTo(instrumentedType)).thenReturn(false);
+ when(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)).thenReturn(true);
+ when(typeDescription.getName()).thenReturn(FOO);
+ StackManipulation stackManipulation = ClassConstant.of(typeDescription);
+ assertThat(stackManipulation.isValid(), is(true));
+ StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
+ assertThat(size.getSizeImpact(), is(1));
+ assertThat(size.getMaximalSize(), is(1));
+ verify(typeDescription).getName();
+ verify(typeDescription).isVisibleTo(instrumentedType);
+ verify(typeDescription, times(9)).represents(any(Class.class));
+ verifyNoMoreInteractions(typeDescription);
+ verify(methodVisitor).visitLdcInsn(FOO);
+ verify(methodVisitor).visitMethodInsn(Opcodes.INVOKESTATIC,
+ Type.getInternalName(Class.class),
+ "forName",
+ Type.getMethodDescriptor(Type.getType(Class.class), Type.getType(String.class)),
+ false);
+ verifyNoMoreInteractions(methodVisitor);
+ }
+
+ @Test
+ public void testClassConstantLegacy() throws Exception {
+ when(typeDescription.isVisibleTo(instrumentedType)).thenReturn(true);
+ when(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)).thenReturn(false);
+ when(typeDescription.getName()).thenReturn(FOO);
+ StackManipulation stackManipulation = ClassConstant.of(typeDescription);
+ assertThat(stackManipulation.isValid(), is(true));
+ StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
+ assertThat(size.getSizeImpact(), is(1));
+ assertThat(size.getMaximalSize(), is(1));
+ verify(typeDescription).getName();
+ verify(typeDescription, times(9)).represents(any(Class.class));
+ verifyNoMoreInteractions(typeDescription);
+ verify(methodVisitor).visitLdcInsn(FOO);
+ verify(methodVisitor).visitMethodInsn(Opcodes.INVOKESTATIC,
+ Type.getInternalName(Class.class),
+ "forName",
+ Type.getMethodDescriptor(Type.getType(Class.class), Type.getType(String.class)),
+ false);
+ verifyNoMoreInteractions(methodVisitor);
}
@Test
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/FieldConstantTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/FieldConstantTest.java
index bb8ea0796d1..ad17c8d06d2 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/FieldConstantTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/FieldConstantTest.java
@@ -1,5 +1,6 @@
package net.bytebuddy.implementation.bytecode.constant;
+import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
@@ -33,7 +34,7 @@ public class FieldConstantTest {
private FieldDescription.InDefinedShape fieldDescription, cacheField;
@Mock
- private TypeDescription declaringType, cacheDeclaringType, cacheFieldType;
+ private TypeDescription declaringType, cacheDeclaringType, cacheFieldType, instrumentedType;
@Mock
private TypeDescription.Generic genericCacheFieldType;
@@ -41,6 +42,9 @@ public class FieldConstantTest {
@Mock
private MethodVisitor methodVisitor;
+ @Mock
+ private ClassFileVersion classFileVersion;
+
@Mock
private Implementation.Context implementationContext;
@@ -54,6 +58,7 @@ public void setUp() throws Exception {
.thenReturn(cacheField);
when(cacheField.getDeclaringType()).thenReturn(cacheDeclaringType);
when(cacheField.isStatic()).thenReturn(true);
+ when(declaringType.getName()).thenReturn(BAZ);
when(cacheDeclaringType.getInternalName()).thenReturn(BAZ);
when(cacheField.getName()).thenReturn(FOO + BAR);
when(cacheField.getType()).thenReturn(genericCacheFieldType);
@@ -61,10 +66,14 @@ public void setUp() throws Exception {
when(genericCacheFieldType.getStackSize()).thenReturn(StackSize.SINGLE);
when(cacheField.getInternalName()).thenReturn(FOO + BAR);
when(cacheField.getDescriptor()).thenReturn(QUX + BAZ);
+ when(implementationContext.getClassFileVersion()).thenReturn(classFileVersion);
+ when(implementationContext.getInstrumentedType()).thenReturn(instrumentedType);
}
@Test
- public void testConstantCreation() throws Exception {
+ public void testConstantCreationModernVisible() throws Exception {
+ when(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)).thenReturn(true);
+ when(declaringType.isVisibleTo(instrumentedType)).thenReturn(true);
StackManipulation stackManipulation = new FieldConstant(fieldDescription);
assertThat(stackManipulation.isValid(), is(true));
StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
@@ -78,7 +87,54 @@ public void testConstantCreation() throws Exception {
"(Ljava/lang/String;)Ljava/lang/reflect/Field;",
false);
verifyNoMoreInteractions(methodVisitor);
- verifyZeroInteractions(implementationContext);
+ }
+
+ @Test
+ public void testConstantCreationModernInvisible() throws Exception {
+ when(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)).thenReturn(true);
+ when(declaringType.isVisibleTo(instrumentedType)).thenReturn(false);
+ StackManipulation stackManipulation = new FieldConstant(fieldDescription);
+ assertThat(stackManipulation.isValid(), is(true));
+ StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
+ assertThat(size.getSizeImpact(), is(1));
+ assertThat(size.getMaximalSize(), is(2));
+ verify(methodVisitor).visitLdcInsn(BAZ);
+ verify(methodVisitor).visitMethodInsn(Opcodes.INVOKESTATIC,
+ Type.getInternalName(Class.class),
+ "forName",
+ Type.getMethodDescriptor(Type.getType(Class.class), Type.getType(String.class)),
+ false);
+ verify(methodVisitor).visitLdcInsn(BAR);
+ verify(methodVisitor).visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/Class",
+ "getDeclaredField",
+ "(Ljava/lang/String;)Ljava/lang/reflect/Field;",
+ false);
+ verifyNoMoreInteractions(methodVisitor);
+ }
+
+ @Test
+ public void testConstantCreationLegacy() throws Exception {
+ when(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)).thenReturn(false);
+ when(declaringType.isVisibleTo(instrumentedType)).thenReturn(true);
+ StackManipulation stackManipulation = new FieldConstant(fieldDescription);
+ assertThat(stackManipulation.isValid(), is(true));
+ StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
+ assertThat(size.getSizeImpact(), is(1));
+ assertThat(size.getMaximalSize(), is(2));
+ verify(methodVisitor).visitLdcInsn(BAZ);
+ verify(methodVisitor).visitMethodInsn(Opcodes.INVOKESTATIC,
+ Type.getInternalName(Class.class),
+ "forName",
+ Type.getMethodDescriptor(Type.getType(Class.class), Type.getType(String.class)),
+ false);
+ verify(methodVisitor).visitLdcInsn(BAR);
+ verify(methodVisitor).visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/Class",
+ "getDeclaredField",
+ "(Ljava/lang/String;)Ljava/lang/reflect/Field;",
+ false);
+ verifyNoMoreInteractions(methodVisitor);
}
@Test
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstantTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstantTest.java
new file mode 100644
index 00000000000..f44b7d32be8
--- /dev/null
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/JavaInstanceConstantTest.java
@@ -0,0 +1,52 @@
+package net.bytebuddy.implementation.bytecode.constant;
+
+import net.bytebuddy.implementation.Implementation;
+import net.bytebuddy.implementation.bytecode.StackManipulation;
+import net.bytebuddy.test.utility.MockitoRule;
+import net.bytebuddy.test.utility.ObjectPropertyAssertion;
+import net.bytebuddy.utility.JavaInstance;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.mockito.Mock;
+import org.objectweb.asm.MethodVisitor;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.*;
+
+public class JavaInstanceConstantTest {
+
+ private static final String FOO = "foo";
+
+ @Rule
+ public TestRule mockitoRule = new MockitoRule(this);
+
+ @Mock
+ private JavaInstance javaInstance;
+
+ @Mock
+ private MethodVisitor methodVisitor;
+
+ @Mock
+ private Implementation.Context implementationContext;
+
+ @Test
+ public void testMethodHandle() throws Exception {
+ when(javaInstance.asConstantPoolValue()).thenReturn(FOO);
+ StackManipulation stackManipulation = new JavaInstanceConstant(javaInstance);
+ StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
+ assertThat(size.getSizeImpact(), is(1));
+ assertThat(size.getMaximalSize(), is(1));
+ verify(javaInstance).asConstantPoolValue();
+ verifyNoMoreInteractions(javaInstance);
+ verify(methodVisitor).visitLdcInsn(FOO);
+ verifyNoMoreInteractions(methodVisitor);
+ verifyZeroInteractions(implementationContext);
+ }
+
+ @Test
+ public void testObjectProperties() throws Exception {
+ ObjectPropertyAssertion.of(JavaInstanceConstant.class).apply();
+ }
+}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodConstantTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodConstantTest.java
index 17f5ee2c531..1889e7bb091 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodConstantTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodConstantTest.java
@@ -1,5 +1,6 @@
package net.bytebuddy.implementation.bytecode.constant;
+import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.ParameterList;
@@ -38,7 +39,10 @@ public class MethodConstantTest {
private MethodDescription.InDefinedShape methodDescription;
@Mock
- private TypeDescription declaringType, parameterType, fieldType;
+ private TypeDescription declaringType, parameterType, fieldType, instrumentedType;
+
+ @Mock
+ private ClassFileVersion classFileVersion;
@Mock
private TypeDescription.Generic genericFieldType;
@@ -82,6 +86,8 @@ public void setUp() throws Exception {
when(fieldDescription.getInternalName()).thenReturn(FOO);
when(fieldDescription.getDescriptor()).thenReturn(QUX);
when(fieldDescription.asDefined()).thenReturn(fieldDescription);
+ when(implementationContext.getClassFileVersion()).thenReturn(classFileVersion);
+ when(implementationContext.getInstrumentedType()).thenReturn(instrumentedType);
}
@Test
@@ -94,7 +100,6 @@ public void testMethod() throws Exception {
"getDeclaredMethod",
"(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;",
false);
- verifyZeroInteractions(implementationContext);
}
@Test
@@ -120,7 +125,6 @@ public void testConstructor() throws Exception {
"getDeclaredConstructor",
"([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;",
false);
- verifyZeroInteractions(implementationContext);
}
@Test
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstantTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstantTest.java
deleted file mode 100644
index 570fa6c3eba..00000000000
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodHandleConstantTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package net.bytebuddy.implementation.bytecode.constant;
-
-import net.bytebuddy.description.field.FieldDescription;
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.implementation.Implementation;
-import net.bytebuddy.implementation.bytecode.StackManipulation;
-import net.bytebuddy.test.utility.MockitoRule;
-import net.bytebuddy.test.utility.ObjectPropertyAssertion;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.mockito.Mock;
-import org.objectweb.asm.Handle;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.*;
-
-public class MethodHandleConstantTest {
-
- private static final String FOO = "foo", BAR = "bar", QUX = "qux";
-
- @Rule
- public TestRule mockitoRule = new MockitoRule(this);
-
- @Mock
- private MethodDescription.InDefinedShape methodDescription;
-
- @Mock
- private FieldDescription.InDefinedShape fieldDescription;
-
- @Mock
- private TypeDescription typeDescription;
-
- @Mock
- private MethodVisitor methodVisitor;
-
- @Mock
- private Implementation.Context implementationContext;
-
- @Before
- public void setUp() throws Exception {
- when(typeDescription.asErasure()).thenReturn(typeDescription);
- when(methodDescription.getDeclaringType()).thenReturn(typeDescription);
- when(typeDescription.getInternalName()).thenReturn(FOO);
- when(methodDescription.getInternalName()).thenReturn(BAR);
- when(methodDescription.getDescriptor()).thenReturn(QUX);
- when(fieldDescription.getDeclaringType()).thenReturn(typeDescription);
- when(fieldDescription.getInternalName()).thenReturn(FOO);
- when(fieldDescription.getInternalName()).thenReturn(BAR);
- when(fieldDescription.getDescriptor()).thenReturn(QUX);
- }
-
- @After
- public void tearDown() throws Exception {
- verifyZeroInteractions(implementationContext);
- }
-
- @Test
- public void testMethodHandleForStaticMethod() throws Exception {
- when(methodDescription.isStatic()).thenReturn(true);
- testMethodHandle(MethodHandleConstant.of(methodDescription), Opcodes.H_INVOKESTATIC, false);
- }
-
- @Test
- public void testMethodHandleForVirtualMethod() throws Exception {
- testMethodHandle(MethodHandleConstant.of(methodDescription), Opcodes.H_INVOKEVIRTUAL, false);
- }
-
- @Test
- public void testMethodHandleForPrivateMethod() throws Exception {
- when(methodDescription.isPrivate()).thenReturn(true);
- testMethodHandle(MethodHandleConstant.of(methodDescription), Opcodes.H_INVOKESPECIAL, false);
- }
-
- @Test
- public void testMethodHandleForDefaultMethod() throws Exception {
- when(methodDescription.isDefaultMethod()).thenReturn(true);
- testMethodHandle(MethodHandleConstant.of(methodDescription), Opcodes.H_INVOKESPECIAL, false);
- }
-
- @Test
- public void testMethodHandleForInterfaceMethod() throws Exception {
- when(typeDescription.isInterface()).thenReturn(true);
- testMethodHandle(MethodHandleConstant.of(methodDescription), Opcodes.H_INVOKEINTERFACE, true);
- }
-
- @Test
- public void testMethodHandleForConstructorMethod() throws Exception {
- when(methodDescription.isConstructor()).thenReturn(true);
- testMethodHandle(MethodHandleConstant.of(methodDescription), Opcodes.H_NEWINVOKESPECIAL, false);
- }
-
- @Test
- public void testMethodHandleForMemberFieldGetter() throws Exception {
- testMethodHandle(MethodHandleConstant.ofGetter(fieldDescription), Opcodes.H_GETFIELD, false);
- }
-
- @Test
- public void testMethodHandleForMemberFieldPutter() throws Exception {
- testMethodHandle(MethodHandleConstant.ofPutter(fieldDescription), Opcodes.H_PUTFIELD, false);
- }
-
- @Test
- public void testMethodHandleForStaticFieldGetter() throws Exception {
- when(fieldDescription.isStatic()).thenReturn(true);
- testMethodHandle(MethodHandleConstant.ofGetter(fieldDescription), Opcodes.H_GETSTATIC, false);
- }
-
- @Test
- public void testMethodHandleForStaticFieldPutter() throws Exception {
- when(fieldDescription.isStatic()).thenReturn(true);
- testMethodHandle(MethodHandleConstant.ofPutter(fieldDescription), Opcodes.H_PUTSTATIC, false);
- }
-
- private void testMethodHandle(StackManipulation stackManipulation, int handleCode, boolean handleInterface) throws Exception {
- assertThat(stackManipulation.isValid(), is(true));
- StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
- assertThat(size.getSizeImpact(), is(1));
- assertThat(size.getMaximalSize(), is(1));
- verify(methodVisitor).visitLdcInsn(new Handle(handleCode, FOO, BAR, QUX, handleInterface));
- verifyNoMoreInteractions(methodVisitor);
- }
-
- @Test
- public void testMethodHandleForTypeInitializer() throws Exception {
- when(methodDescription.isTypeInitializer()).thenReturn(true);
- StackManipulation stackManipulation = MethodHandleConstant.of(methodDescription);
- assertThat(stackManipulation.isValid(), is(false));
- }
-
- @Test
- public void testObjectProperties() throws Exception {
- final Iterator iterator = Arrays.asList(FOO, BAR).iterator();
- ObjectPropertyAssertion.of(MethodHandleConstant.class).create(new ObjectPropertyAssertion.Creator() {
- @Override
- public Handle create() {
- return new Handle(Opcodes.H_GETFIELD, FOO, BAR, iterator.next(), false);
- }
- }).apply();
- }
-}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstantTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstantTest.java
deleted file mode 100644
index f52d268a001..00000000000
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/implementation/bytecode/constant/MethodTypeConstantTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package net.bytebuddy.implementation.bytecode.constant;
-
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.implementation.Implementation;
-import net.bytebuddy.implementation.bytecode.StackManipulation;
-import net.bytebuddy.test.utility.MockitoRule;
-import net.bytebuddy.test.utility.ObjectPropertyAssertion;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.mockito.Mock;
-import org.mockito.asm.Type;
-import org.objectweb.asm.MethodVisitor;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.when;
-
-public class MethodTypeConstantTest {
-
- private static final String FOO = "foo", BAR = "bar";
-
- @Rule
- public TestRule mockitoRule = new MockitoRule(this);
-
- @Mock
- private MethodDescription.InDefinedShape methodDescription;
-
- @Mock
- private MethodVisitor methodVisitor;
-
- @Mock
- private Implementation.Context implementationContext;
-
- @Before
- public void setUp() throws Exception {
- when(methodDescription.getDescriptor()).thenReturn(FOO);
- }
-
- @Test
- public void testApplication() throws Exception {
- StackManipulation stackManipulation = MethodTypeConstant.of(methodDescription);
- assertThat(stackManipulation.isValid(), is(true));
- StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
- assertThat(size.getSizeImpact(), is(1));
- assertThat(size.getMaximalSize(), is(1));
- }
-
- @Test
- public void testObjectProperties() throws Exception {
- final Iterator iterator = Arrays.asList(Type.getDescriptor(Void.class), Type.getDescriptor(String.class)).iterator();
- ObjectPropertyAssertion.of(MethodTypeConstant.class).refine(new ObjectPropertyAssertion.Refinement() {
- @Override
- public void apply(MethodDescription mock) {
- when(mock.getDescriptor()).thenReturn(iterator.next());
- }
- }).apply();
- }
-}
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleDispatcherTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleDispatcherTest.java
index 53f1cada427..0009f831c0f 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleDispatcherTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleDispatcherTest.java
@@ -9,6 +9,8 @@
import java.util.Arrays;
import java.util.Iterator;
+import static org.mockito.Mockito.mock;
+
public class JavaInstanceMethodHandleDispatcherTest {
@Test(expected = IllegalStateException.class)
@@ -21,6 +23,11 @@ public void testLegacyVmPunlicLookup() throws Exception {
JavaInstance.MethodHandle.Dispatcher.ForLegacyVm.INSTANCE.publicLookup();
}
+ @Test(expected = IllegalStateException.class)
+ public void testLegacyVmLookupType() throws Exception {
+ JavaInstance.MethodHandle.Dispatcher.ForLegacyVm.INSTANCE.lookupType(mock(Object.class));
+ }
+
@Test
public void testObjectProperties() throws Exception {
final Iterator methods1 = Arrays.asList(Foo.class.getDeclaredMethods()).iterator();
diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleTest.java
index 5b990f1c676..65cb59598e2 100644
--- a/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleTest.java
+++ b/byte-buddy-dep/src/test/java/net/bytebuddy/utility/JavaInstanceMethodHandleTest.java
@@ -165,7 +165,7 @@ public void testIllegalParameterThrowsException() throws Exception {
@Test(expected = IllegalArgumentException.class)
public void testStaticMethodNotSpecial() throws Exception {
- MethodDescription methodDescription = mock(MethodDescription.class);
+ MethodDescription.InDefinedShape methodDescription = mock(MethodDescription.InDefinedShape.class);
TypeDescription typeDescription = mock(TypeDescription.class);
when(methodDescription.isStatic()).thenReturn(true);
when(methodDescription.isSpecializableFor(typeDescription)).thenReturn(true);
@@ -174,7 +174,7 @@ public void testStaticMethodNotSpecial() throws Exception {
@Test(expected = IllegalArgumentException.class)
public void testAbstractMethodNotSpecial() throws Exception {
- MethodDescription methodDescription = mock(MethodDescription.class);
+ MethodDescription.InDefinedShape methodDescription = mock(MethodDescription.InDefinedShape.class);
TypeDescription typeDescription = mock(TypeDescription.class);
when(methodDescription.isAbstract()).thenReturn(true);
when(methodDescription.isSpecializableFor(typeDescription)).thenReturn(true);
@@ -183,7 +183,7 @@ public void testAbstractMethodNotSpecial() throws Exception {
@Test(expected = IllegalArgumentException.class)
public void testMethodNotSpecializable() throws Exception {
- MethodDescription methodDescription = mock(MethodDescription.class);
+ MethodDescription.InDefinedShape methodDescription = mock(MethodDescription.InDefinedShape.class);
TypeDescription typeDescription = mock(TypeDescription.class);
when(methodDescription.isSpecializableFor(typeDescription)).thenReturn(false);
JavaInstance.MethodHandle.ofSpecial(methodDescription, typeDescription);