/** * Resolves this {@link Dynamic} constant to resolve the returned instance to the supplied type. The type must be a subtype of the * bootstrap method's return type. Constructors cannot be resolved to a different type. * * @param typeDescription The type to resolve the bootstrapped value to. * @return This dynamic constant but resolved to the supplied type. */ public JavaConstant withType(TypeDescription typeDescription) { if (typeDescription.represents(void.class)) { throw new IllegalArgumentException("Constant value cannot represent void"); } else if (value.getBootstrapMethod().getName().equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME) ? !this.typeDescription.isAssignableTo(typeDescription) : (!typeDescription.asBoxed().isInHierarchyWith(this.typeDescription.asBoxed()))) { throw new IllegalArgumentException(typeDescription + " is not compatible with bootstrapped type " + this.typeDescription); } Object[] bootstrapMethodArgument = new Object[value.getBootstrapMethodArgumentCount()]; for (int index = 0; index < value.getBootstrapMethodArgumentCount(); index++) { bootstrapMethodArgument[index] = value.getBootstrapMethodArgument(index); } return new Dynamic(new ConstantDynamic(value.getName(), typeDescription.getDescriptor(), value.getBootstrapMethod(), bootstrapMethodArgument), typeDescription); }
@Override public boolean equals(Object other) { if (this == other) { return true; } else if (other == null || getClass() != other.getClass()) { return false; } Dynamic dynamic = (Dynamic) other; return value.equals(dynamic.value) && typeDescription.equals(dynamic.typeDescription); } }
/** * Resolves all type references that are referenced by a {@link ConstantDynamic} value. * * @param constant The dynamic constant to resolve. */ protected void resolve(ConstantDynamic constant) { Type methodType = Type.getType(constant.getDescriptor()); resolve(methodType.getReturnType()); for (Type type : methodType.getArgumentTypes()) { resolve(type); } resolve(constant.getBootstrapMethod()); for (int index = 0; index < constant.getBootstrapMethodArgumentCount(); index++) { resolve(constant.getBootstrapMethodArgument(index)); } }
ConstantDynamic constantDynamic = (ConstantDynamic) value; return addConstantDynamic( constantDynamic.getName(), constantDynamic.getDescriptor(), constantDynamic.getBootstrapMethod(), constantDynamic.getBootstrapMethodArgumentsUnsafe()); } else { throw new IllegalArgumentException("value " + value);
/** * Returns a constant {@code null} value of type {@link Object}. * * @return A dynamically resolved null constant. */ public static Dynamic ofNullConstant() { return new Dynamic(new ConstantDynamic("nullConstant", TypeDescription.OBJECT.getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "nullConstant", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;", false)), TypeDescription.OBJECT); }
@Override public int hashCode() { int result = value.hashCode(); result = 31 * result + typeDescription.hashCode(); return result; }
/** * Returns a {@link Class} constant for a primitive type. * * @param typeDescription The primitive type to represent. * @return A dynamically resolved primitive type constant. */ public static JavaConstant ofPrimitiveType(TypeDescription typeDescription) { if (!typeDescription.isPrimitive()) { throw new IllegalArgumentException("Not a primitive type: " + typeDescription); } return new Dynamic(new ConstantDynamic(typeDescription.getDescriptor(), TypeDescription.CLASS.getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "primitiveClass", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Class;", false)), TypeDescription.CLASS); }
/** * Returns a {@link Enum} value constant. * * @param enumerationDescription The enumeration value to represent. * @return A dynamically resolved enumeration constant. */ public static JavaConstant ofEnumeration(EnumerationDescription enumerationDescription) { return new Dynamic(new ConstantDynamic(enumerationDescription.getValue(), enumerationDescription.getEnumerationType().getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "enumConstant", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Enum;", false)), enumerationDescription.getEnumerationType()); }
/** * Resolves a var handle constant for an array. * * @param typeDescription The array type for which the var handle is resolved. * @return A dynamic constant that represents the created var handle constant. */ public static JavaConstant ofArrayVarHandle(TypeDescription typeDescription) { if (!typeDescription.isArray()) { throw new IllegalArgumentException("Not an array type: " + typeDescription); } return new Dynamic(new ConstantDynamic("arrayVarHandle", JavaType.VAR_HANDLE.getTypeStub().getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "arrayVarHandle", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;", false), Type.getType(typeDescription.getDescriptor())), JavaType.VAR_HANDLE.getTypeStub()); }
return new Dynamic(new ConstantDynamic(name, (bootstrapMethod.isConstructor() ? bootstrapMethod.getDeclaringType()
/** * Reads a CONSTANT_Dynamic constant pool entry in {@link #b}. * * @param constantPoolEntryIndex the index of a CONSTANT_Dynamic entry in the class's constant * pool table. * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently * large. It is not automatically resized. * @return the ConstantDynamic corresponding to the specified CONSTANT_Dynamic entry. */ private ConstantDynamic readConstantDynamic( final int constantPoolEntryIndex, final char[] charBuffer) { ConstantDynamic constantDynamic = constantDynamicValues[constantPoolEntryIndex]; if (constantDynamic != null) { return constantDynamic; } int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex]; int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)]; String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer); String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer); int bootstrapMethodOffset = bootstrapMethodOffsets[readUnsignedShort(cpInfoOffset)]; Handle handle = (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer); Object[] bootstrapMethodArguments = new Object[readUnsignedShort(bootstrapMethodOffset + 2)]; bootstrapMethodOffset += 4; for (int i = 0; i < bootstrapMethodArguments.length; i++) { bootstrapMethodArguments[i] = readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer); bootstrapMethodOffset += 2; } return constantDynamicValues[constantPoolEntryIndex] = new ConstantDynamic(name, descriptor, handle, bootstrapMethodArguments); }
return new Dynamic(new ConstantDynamic("invoke", (methodDescription.isConstructor() ? methodDescription.getDeclaringType()