diff --git a/byte-buddy-android/src/main/java/net/bytebuddy/android/AndroidClassLoadingStrategy.java b/byte-buddy-android/src/main/java/net/bytebuddy/android/AndroidClassLoadingStrategy.java index 31de2bb51f9..f7916329d82 100644 --- a/byte-buddy-android/src/main/java/net/bytebuddy/android/AndroidClassLoadingStrategy.java +++ b/byte-buddy-android/src/main/java/net/bytebuddy/android/AndroidClassLoadingStrategy.java @@ -235,9 +235,18 @@ class ForSdkCompiler implements DexProcessor { byte[].class, CfOptions.class, DexOptions.class, - DexFile.class), DexOptions.class.getField("targetApiLevel")); - } catch (Throwable throwable) { - dispatcher = new Dispatcher.Unavailable(throwable.getMessage()); + DexFile.class), DexOptions.class.getField("minSdkVersion")); + } catch (Throwable suppressed) { + try { + dispatcher = new Dispatcher.ForLegacyVm(CfTranslator.class.getMethod("translate", + DirectClassFile.class, + byte[].class, + CfOptions.class, + DexOptions.class, + DexFile.class), DexOptions.class.getField("targetApiLevel")); + } catch (Throwable throwable) { + dispatcher = new Dispatcher.Unavailable(throwable.getMessage()); + } } } DISPATCHER = dispatcher; 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 27b94299339..78b43ad3a9f 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 @@ -1258,6 +1258,20 @@ public static Target of(Object value) { return new ForStackManipulation(DoubleConstant.forValue((Double) value)); } else if (value instanceof String) { return new ForStackManipulation(new TextConstant((String) value)); + } else if (value instanceof Enum) { + return new ForStackManipulation(FieldAccess.forEnumeration(new EnumerationDescription.ForLoadedEnumeration((Enum) value))); + } else if (value instanceof EnumerationDescription) { + return new ForStackManipulation(FieldAccess.forEnumeration((EnumerationDescription) value)); + } else if (value instanceof Class) { + return new ForStackManipulation(ClassConstant.of(TypeDescription.ForLoadedType.of((Class) value))); + } else if (value instanceof TypeDescription) { + return new ForStackManipulation(ClassConstant.of((TypeDescription) value)); + } else if (JavaType.METHOD_HANDLE.isInstance(value)) { + return new ForStackManipulation(new JavaConstantValue(JavaConstant.MethodHandle.ofLoaded(value))); + } else if (JavaType.METHOD_TYPE.isInstance(value)) { + return new ForStackManipulation(new JavaConstantValue(JavaConstant.MethodType.ofLoaded(value))); + } else if (value instanceof JavaConstant) { + return new ForStackManipulation(new JavaConstantValue((JavaConstant) value)); } else { throw new IllegalArgumentException("Not a constant value: " + value); } @@ -3633,6 +3647,18 @@ public static OffsetMapping.Factory of(Class annota } else if (value instanceof String) { stackManipulation = new TextConstant((String) value); typeDescription = TypeDescription.STRING; + } else if (value instanceof Class) { + stackManipulation = ClassConstant.of(TypeDescription.ForLoadedType.of((Class) value)); + typeDescription = TypeDescription.CLASS; + } else if (value instanceof TypeDescription) { + stackManipulation = ClassConstant.of((TypeDescription) value); + typeDescription = TypeDescription.CLASS; + } else if (value instanceof Enum) { + stackManipulation = FieldAccess.forEnumeration(new EnumerationDescription.ForLoadedEnumeration((Enum) value)); + typeDescription = TypeDescription.ForLoadedType.of(((Enum) value).getDeclaringClass()); + } else if (value instanceof EnumerationDescription) { + stackManipulation = FieldAccess.forEnumeration((EnumerationDescription) value); + typeDescription = ((EnumerationDescription) value).getEnumerationType(); } else if (JavaType.METHOD_HANDLE.isInstance(value)) { JavaConstant constant = JavaConstant.MethodHandle.ofLoaded(value); stackManipulation = new JavaConstantValue(constant); @@ -3641,6 +3667,9 @@ public static OffsetMapping.Factory of(Class annota JavaConstant constant = JavaConstant.MethodType.ofLoaded(value); stackManipulation = new JavaConstantValue(constant); typeDescription = constant.getType(); + } else if (value instanceof JavaConstant) { + stackManipulation = new JavaConstantValue((JavaConstant) value); + typeDescription = ((JavaConstant) value).getType(); } else { throw new IllegalStateException("Not a constant value: " + value); } diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/InvokeDynamic.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/InvokeDynamic.java index 3468a5b089c..2ef6fbbf489 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/InvokeDynamic.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/InvokeDynamic.java @@ -1294,12 +1294,18 @@ public static ArgumentProvider of(Object value) { return new ForStringConstant((String) value); } else if (value instanceof Class) { return new ForClassConstant(TypeDescription.ForLoadedType.of((Class) value)); + } else if (value instanceof TypeDescription) { + return new ForClassConstant((TypeDescription) value); } else if (value instanceof Enum) { return new ForEnumerationValue(new EnumerationDescription.ForLoadedEnumeration((Enum) value)); + } else if (value instanceof EnumerationDescription) { + return new ForEnumerationValue((EnumerationDescription) value); } else if (JavaType.METHOD_HANDLE.isInstance(value)) { return new ForJavaConstant(JavaConstant.MethodHandle.ofLoaded(value)); } else if (JavaType.METHOD_TYPE.isInstance(value)) { return new ForJavaConstant(JavaConstant.MethodType.ofLoaded(value)); + } else if (value instanceof JavaConstant) { + return new ForJavaConstant((JavaConstant) value); } else { return ForInstance.of(value); } diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/MethodCall.java b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/MethodCall.java index 37a0aa8e48d..205c56062ee 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/MethodCall.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/MethodCall.java @@ -279,7 +279,8 @@ public static MethodCall construct(MethodDescription methodDescription) { /** * Defines a number of arguments to be handed to the method that is being invoked by this implementation. Any - * wrapper type instances for primitive values, instances of {@link java.lang.String} or {@code null} are loaded + * wrapper type instances for primitive values, instances of {@link java.lang.String}, method handles, types, + * method types as well as instances of {@link TypeDescription} or {@link JavaConstant} or {@code null} are loaded * directly onto the operand stack. This might corrupt referential identity for these values. Any other values * are stored within a {@code static} field that is added to the instrumented type. * @@ -1810,8 +1811,6 @@ public ForStackManipulation(StackManipulation stackManipulation, TypeDefinition public static ArgumentLoader.Factory of(Object value) { if (value == null) { return ForNullConstant.INSTANCE; - } else if (value instanceof String) { - return new ForStackManipulation(new TextConstant((String) value), String.class); } else if (value instanceof Boolean) { return new ForStackManipulation(IntegerConstant.forValue((Boolean) value), boolean.class); } else if (value instanceof Byte) { @@ -1828,15 +1827,23 @@ public static ArgumentLoader.Factory of(Object value) { return new ForStackManipulation(FloatConstant.forValue((Float) value), float.class); } else if (value instanceof Double) { return new ForStackManipulation(DoubleConstant.forValue((Double) value), double.class); + } else if (value instanceof String) { + return new ForStackManipulation(new TextConstant((String) value), String.class); } else if (value instanceof Class) { return new ForStackManipulation(ClassConstant.of(TypeDescription.ForLoadedType.of((Class) value)), Class.class); + } else if (value instanceof TypeDescription) { + return new ForStackManipulation(ClassConstant.of((TypeDescription) value), Class.class); + } else if (value instanceof Enum) { + EnumerationDescription enumerationDescription = new EnumerationDescription.ForLoadedEnumeration((Enum) value); + return new ForStackManipulation(FieldAccess.forEnumeration(enumerationDescription), enumerationDescription.getEnumerationType()); + } else if (value instanceof EnumerationDescription) { + return new ForStackManipulation(FieldAccess.forEnumeration((EnumerationDescription) value), ((EnumerationDescription) value).getEnumerationType()); } else if (JavaType.METHOD_HANDLE.isInstance(value)) { return new ForStackManipulation(new JavaConstantValue(JavaConstant.MethodHandle.ofLoaded(value)), JavaType.METHOD_HANDLE.getTypeStub()); } else if (JavaType.METHOD_TYPE.isInstance(value)) { return new ForStackManipulation(new JavaConstantValue(JavaConstant.MethodType.ofLoaded(value)), JavaType.METHOD_TYPE.getTypeStub()); - } else if (value instanceof Enum) { - EnumerationDescription enumerationDescription = new EnumerationDescription.ForLoadedEnumeration((Enum) value); - return new ForStackManipulation(FieldAccess.forEnumeration(enumerationDescription), enumerationDescription.getEnumerationType()); + } else if (value instanceof JavaConstant) { + return new ForStackManipulation(new JavaConstantValue((JavaConstant) value), ((JavaConstant) value).getType()); } else { return new ForInstance.Factory(value); } 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 ed76b7939ef..2b1415af367 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 @@ -18,6 +18,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import net.bytebuddy.build.HashCodeAndEqualsPlugin; import net.bytebuddy.description.annotation.AnnotationDescription; +import net.bytebuddy.description.enumeration.EnumerationDescription; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.ParameterDescription; @@ -28,6 +29,7 @@ import net.bytebuddy.implementation.bytecode.StackManipulation; import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.constant.*; +import net.bytebuddy.implementation.bytecode.member.FieldAccess; import net.bytebuddy.utility.JavaConstant; import net.bytebuddy.utility.JavaType; @@ -269,6 +271,12 @@ public ParameterBinding bind(AnnotationDescription.Loadable annotation, } else if (value instanceof TypeDescription) { stackManipulation = ClassConstant.of((TypeDescription) value); suppliedType = TypeDescription.CLASS; + } else if (value instanceof Enum) { + stackManipulation = FieldAccess.forEnumeration(new EnumerationDescription.ForLoadedEnumeration((Enum) value)); + suppliedType = TypeDescription.ForLoadedType.of(((Enum) value).getDeclaringClass()); + } else if (value instanceof EnumerationDescription) { + stackManipulation = FieldAccess.forEnumeration((EnumerationDescription) value); + suppliedType = ((EnumerationDescription) value).getEnumerationType(); } else if (JavaType.METHOD_HANDLE.isInstance(value)) { stackManipulation = new JavaConstantValue(JavaConstant.MethodHandle.ofLoaded(value)); suppliedType = JavaType.METHOD_HANDLE.getTypeStub(); @@ -278,9 +286,9 @@ public ParameterBinding bind(AnnotationDescription.Loadable annotation, } else if (JavaType.METHOD_TYPE.isInstance(value)) { stackManipulation = new JavaConstantValue(JavaConstant.MethodType.ofLoaded(value)); suppliedType = JavaType.METHOD_HANDLE.getTypeStub(); - } else if (value instanceof JavaConstant.MethodType) { - stackManipulation = new JavaConstantValue((JavaConstant.MethodType) value); - suppliedType = JavaType.METHOD_HANDLE.getTypeStub(); + } else if (value instanceof JavaConstant) { + stackManipulation = new JavaConstantValue((JavaConstant) value); + suppliedType = ((JavaConstant) value).getType(); } else { throw new IllegalStateException("Not able to save in class's constant pool: " + value); } diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionArrayProjectionTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionArrayProjectionTest.java index 942931e149c..7b86b7a751b 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionArrayProjectionTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionArrayProjectionTest.java @@ -53,28 +53,28 @@ public void testIllegalArity() throws Exception { @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableU() throws Exception { super.testTypeVariableU(); } @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableV() throws Exception { super.testTypeVariableV(); } @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableW() throws Exception { super.testTypeVariableW(); } @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableX() throws Exception { super.testTypeVariableX(); } @@ -88,14 +88,14 @@ public void testTypeAnnotationOwnerType() throws Exception { @Test @Override - @Ignore("The Java reflection API does not currently support generic receiver types") + @Ignore("The OpenJDK reflection API does not currently support generic receiver types") public void testGenericTypeAnnotationReceiverTypeOnMethod() throws Exception { super.testGenericTypeAnnotationReceiverTypeOnMethod(); } @Test @Override - @Ignore("The Java reflection API does not currently support generic receiver types") + @Ignore("The OpenJDK reflection API does not currently support generic receiver types") public void testGenericNestedTypeAnnotationReceiverTypeOnMethod() throws Exception { super.testGenericNestedTypeAnnotationReceiverTypeOnMethod(); } @@ -109,14 +109,14 @@ public void testGenericNestedTypeAnnotationReceiverTypeOnConstructor() throws Ex @Test @Override - @Ignore("The Java reflection API does not currently support generic receiver types") + @Ignore("The OpenJDK reflection API does not currently support generic receiver types") public void testGenericInnerTypeAnnotationReceiverTypeOnConstructor() throws Exception { super.testGenericInnerTypeAnnotationReceiverTypeOnConstructor(); } @Test @Override - @Ignore("The Java reflection API does not currently support generic receiver types") + @Ignore("The OpenJDK reflection API does not currently support generic receiver types") public void testGenericInnerTypeAnnotationReceiverTypeOnMethod() throws Exception { super.testGenericInnerTypeAnnotationReceiverTypeOnMethod(); } diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionForLoadedTypeTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionForLoadedTypeTest.java index 9add0cbbba4..aa9eff06ced 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionForLoadedTypeTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/TypeDescriptionForLoadedTypeTest.java @@ -51,28 +51,28 @@ protected TypeDescription.Generic describeInterfaceType(Class type, int index @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableU() throws Exception { super.testTypeVariableU(); } @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableV() throws Exception { super.testTypeVariableV(); } @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableW() throws Exception { super.testTypeVariableW(); } @Test @Override - @Ignore("The OpenJDK reflection API suffers a bug that affects parsing of type variable bounds") + @JavaVersionRule.Enforce(16) public void testTypeVariableX() throws Exception { super.testTypeVariableX(); }