/** * {@inheritDoc} */ public AnnotationAppender onParameterizedType(TypeDescription.Generic parameterizedType) { StringBuilder typePath = new StringBuilder(this.typePath); for (int index = 0; index < parameterizedType.asErasure().getInnerClassCount(); index++) { typePath = typePath.append(INNER_CLASS_PATH); } AnnotationAppender annotationAppender = apply(parameterizedType, typePath.toString()); TypeDescription.Generic ownerType = parameterizedType.getOwnerType(); if (ownerType != null) { annotationAppender = ownerType.accept(new ForTypeAnnotations(annotationAppender, annotationValueFilter, typeReference, this.typePath)); } int index = 0; for (TypeDescription.Generic typeArgument : parameterizedType.getTypeArguments()) { annotationAppender = typeArgument.accept(new ForTypeAnnotations(annotationAppender, annotationValueFilter, typeReference, typePath.toString() + index++ + INDEXED_TYPE_DELIMITER)); } return annotationAppender; }
if (instrumentedMethod.isStatic()) { throw new IllegalStateException("Hash code method must not be static: " + instrumentedMethod); } else if (instrumentedMethod.getParameters().size() != 1 || instrumentedMethod.getParameters().getOnly().getType().isPrimitive()) { throw new IllegalStateException(); } else if (!instrumentedMethod.getReturnType().represents(boolean.class)) { throw new IllegalStateException("Hash code method does not return primitive boolean: " + instrumentedMethod); stackManipulations.add(TypeCasting.to(instrumentedType)); stackManipulations.add(FieldAccess.forField(fieldDescription).read()); NullValueGuard nullValueGuard = fieldDescription.getType().isPrimitive() || fieldDescription.getType().isArray() || nonNullable.matches(fieldDescription) ? NullValueGuard.NoOp.INSTANCE : new NullValueGuard.UsingJump(instrumentedMethod);
/** * {@inheritDoc} */ public Generic findBindingOf(Generic typeVariable) { Generic typeDescription = this; do { TypeList.Generic typeArguments = typeDescription.getTypeArguments(), typeVariables = typeDescription.asErasure().getTypeVariables(); for (int index = 0; index < Math.min(typeArguments.size(), typeVariables.size()); index++) { if (typeVariable.equals(typeVariables.get(index))) { return typeArguments.get(index); } } typeDescription = typeDescription.getOwnerType(); } while (typeDescription != null && typeDescription.getSort().isParameterized()); return Generic.UNDEFINED; }
/** * Append a simple class type * * @param type Type to append * @param output Output to append to * @param <A> Type of output * @return Supplied output to append to */ public <A extends Appendable> A appendSimpleClassTypeSignature(Generic type, A output) { try { output.append(type.asErasure().getSimpleName()); if (type.getSort() == Sort.PARAMETERIZED) { appendTypeArguments(type.getTypeArguments(), output); } return output; } catch (Exception e) { throw new RuntimeException(String.format("Could not write type signature %s", type)); } }
/** * Append a simple class type * * @param type Type to append * @param output Output to append to * @param <A> Type of output * @return Supplied output to append to */ public <A extends Appendable> A appendSimpleClassTypeSignature(Generic type, A output) { try { output.append(type.asErasure().getSimpleName()); if (type.getSort() == Sort.PARAMETERIZED) { appendTypeArguments(type.getTypeArguments(), output); } return output; } catch (Exception e) { throw new RuntimeException(String.format("Could not write type signature %s", type)); } }
/** * Append a type variable signature * * @param typeVariable Type variable to append signature * @param nullable Nullness of type variable * @param output Output to append to * @param <A> Type of output * @return Supplied output to append to */ public <A extends Appendable> A appendTypeVariableSignature(Generic typeVariable, Nullness nullable, A output) { try { output.append('T').append(nullable.getMarker()).append(typeVariable.getTypeName()).append(';'); return output; } catch (Exception e) { throw new RuntimeException(String.format("Could not type variable %s", typeVariable)); } }
/** * Append a type variable signature * * @param typeVariable Type variable to append signature * @param nullable Nullness of type variable * @param output Output to append to * @param <A> Type of output * @return Supplied output to append to */ public <A extends Appendable> A appendTypeVariableSignature(Generic typeVariable, Nullness nullable, A output) { try { output.append('T').append(nullable.getMarker()).append(typeVariable.getTypeName()).append(';'); return output; } catch (Exception e) { throw new RuntimeException(String.format("Could not type variable %s", typeVariable)); } }
private static TypeDescription entityType(TypeDescription.Generic type) { if ( type.getSort().isParameterized() ) { if ( type.asErasure().isAssignableTo( Collection.class ) ) { return type.getTypeArguments().get( 0 ).asErasure(); } if ( type.asErasure().isAssignableTo( Map.class ) ) { return type.getTypeArguments().get( 1 ).asErasure(); } } return type.asErasure(); }
public static LocalVariable from(final Generic type) { if (type.represents(double.class)) { return DOUBLE; } else { return new LocalVariable( type.getTypeName().replace('.', '/'), type.getStackSize() ); } }
MethodDescription instrumentedMethod) { methodVisitor.visitVarInsn( Type.getType( persistentField.getType().asErasure().getDescriptor() ).getOpcode( Opcodes.ILOAD ), 1 ); methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 ); if ( persistentField.getDeclaringType().asErasure().equals( managedCtClass ) ) { if ( persistentField.getType().isPrimitive() ) { if ( persistentField.getType().represents( long.class ) ) { methodVisitor.visitInsn( Opcodes.LCMP ); else if ( persistentField.getType().represents( float.class ) ) { methodVisitor.visitInsn( Opcodes.FCMPL ); else if ( persistentField.getType().represents( double.class ) ) { methodVisitor.visitInsn( Opcodes.DCMPL ); methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null ); return new Size( 1 + 2 * persistentField.getType().asErasure().getStackSize().getSize(), instrumentedMethod.getStackSize() );
if (this.parameterizedType.asErasure().equals(parameterizedType.asErasure())) { Generic fromOwner = this.parameterizedType.getOwnerType(), toOwner = parameterizedType.getOwnerType(); if (fromOwner != null && toOwner != null && !fromOwner.accept(Assigner.INSTANCE).isAssignableFrom(toOwner)) { return false; TypeList.Generic fromArguments = this.parameterizedType.getTypeArguments(), toArguments = parameterizedType.getTypeArguments(); if (fromArguments.size() == toArguments.size()) { for (int index = 0; index < fromArguments.size(); index++) { if (!fromArguments.get(index).accept(ParameterAssigner.INSTANCE).isAssignableFrom(toArguments.get(index))) { return false; Generic superClass = parameterizedType.getSuperClass(); if (superClass != null && isAssignableFrom(superClass)) { return true; for (Generic interfaceType : parameterizedType.getInterfaces()) { if (isAssignableFrom(interfaceType)) { return true;
/** * {@inheritDoc} */ public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) { for (MethodDescription.InDefinedShape methodDescription : typeDescription.getDeclaredMethods() .filter(not(isBridge()).<MethodDescription>and(isAnnotatedWith(Enhance.class)))) { if (methodDescription.isAbstract()) { throw new IllegalStateException("Cannot cache the value of an abstract method: " + methodDescription); } else if (!methodDescription.getParameters().isEmpty()) { throw new IllegalStateException("Cannot cache the value of a method with parameters: " + methodDescription); } else if (methodDescription.getReturnType().represents(void.class)) { throw new IllegalStateException("Cannot cache void result for " + methodDescription); } String name = methodDescription.getDeclaredAnnotations().ofType(Enhance.class).loadSilent().value(); if (name.length() == 0) { name = methodDescription.getName() + NAME_INFIX + randomString.nextString(); } builder = builder .defineField(name, methodDescription.getReturnType().asErasure(), methodDescription.isStatic() ? Ownership.STATIC : Ownership.MEMBER, Visibility.PRIVATE, SyntheticState.SYNTHETIC, FieldPersistence.TRANSIENT) .visit(Advice.withCustomMapping() .bind(CacheField.class, new CacheFieldOffsetMapping(name)) .to(adviceByType.get(methodDescription.getReturnType().isPrimitive() ? methodDescription.getReturnType().asErasure() : TypeDescription.OBJECT), this.classFileLocator) .on(is(methodDescription))); } return builder; }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { if (instrumentedMethod.isStatic()) { throw new IllegalStateException("Hash code method must not be static: " + instrumentedMethod); } else if (!instrumentedMethod.getReturnType().represents(int.class)) { throw new IllegalStateException("Hash code method does not return primitive integer: " + instrumentedMethod); } List<StackManipulation> stackManipulations = new ArrayList<StackManipulation>(2 + fieldDescriptions.size() * 8); stackManipulations.add(initialValue); int padding = 0; for (FieldDescription.InDefinedShape fieldDescription : fieldDescriptions) { stackManipulations.add(IntegerConstant.forValue(multiplier)); stackManipulations.add(Multiplication.INTEGER); stackManipulations.add(MethodVariableAccess.loadThis()); stackManipulations.add(FieldAccess.forField(fieldDescription).read()); NullValueGuard nullValueGuard = fieldDescription.getType().isPrimitive() || fieldDescription.getType().isArray() || nonNullable.matches(fieldDescription) ? NullValueGuard.NoOp.INSTANCE : new NullValueGuard.UsingJump(instrumentedMethod); stackManipulations.add(nullValueGuard.before()); stackManipulations.add(ValueTransformer.of(fieldDescription.getType())); stackManipulations.add(Addition.INTEGER); stackManipulations.add(nullValueGuard.after()); padding = Math.max(padding, nullValueGuard.getRequiredVariablePadding()); } stackManipulations.add(MethodReturn.INTEGER); return new Size(new StackManipulation.Compound(stackManipulations).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize() + padding); } }
@Override public Size apply( MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod ) { methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 ); methodVisitor.visitVarInsn( Type.getType( persistentField.getType().asErasure().getDescriptor() ).getOpcode( Opcodes.ILOAD ), 1 ); methodVisitor.visitMethodInsn( Opcodes.INVOKESPECIAL, managedCtClass.getSuperClass().asErasure().getInternalName(), EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + persistentField.getName(), Type.getMethodDescriptor( Type.getType( void.class ), Type.getType( persistentField.getType().asErasure().getDescriptor() ) ), false ); methodVisitor.visitInsn( Opcodes.RETURN ); return new Size( 1 + persistentField.getType().getStackSize().getSize(), instrumentedMethod.getStackSize() ); } }
/** * {@inheritDoc} */ public void initialize() { if (adviceMethod.getReturnType().represents(boolean.class) || adviceMethod.getReturnType().represents(byte.class) || adviceMethod.getReturnType().represents(short.class) || adviceMethod.getReturnType().represents(char.class) || adviceMethod.getReturnType().represents(int.class)) { methodVisitor.visitInsn(Opcodes.ICONST_0); methodVisitor.visitVarInsn(Opcodes.ISTORE, argumentHandler.exit()); } else if (adviceMethod.getReturnType().represents(long.class)) { methodVisitor.visitInsn(Opcodes.LCONST_0); methodVisitor.visitVarInsn(Opcodes.LSTORE, argumentHandler.exit()); } else if (adviceMethod.getReturnType().represents(float.class)) { methodVisitor.visitInsn(Opcodes.FCONST_0); methodVisitor.visitVarInsn(Opcodes.FSTORE, argumentHandler.exit()); } else if (adviceMethod.getReturnType().represents(double.class)) { methodVisitor.visitInsn(Opcodes.DCONST_0); methodVisitor.visitVarInsn(Opcodes.DSTORE, argumentHandler.exit()); } else if (!adviceMethod.getReturnType().represents(void.class)) { methodVisitor.visitInsn(Opcodes.ACONST_NULL); methodVisitor.visitVarInsn(Opcodes.ASTORE, argumentHandler.exit()); } methodSizeHandler.requireStackSize(adviceMethod.getReturnType().getStackSize().getSize()); }
/** * {@inheritDoc} */ public int prepare(MethodVisitor methodVisitor) { StackSize stackSize; if (!instrumentedMethod.isStatic()) { methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitVarInsn(Opcodes.ASTORE, instrumentedMethod.getStackSize() + exitType.getStackSize().getSize() + StackSize.of(namedTypes.values()) + enterType.getStackSize().getSize()); stackSize = StackSize.SINGLE; } else { stackSize = StackSize.ZERO; } for (ParameterDescription parameterDescription : instrumentedMethod.getParameters()) { Type type = Type.getType(parameterDescription.getType().asErasure().getDescriptor()); methodVisitor.visitVarInsn(type.getOpcode(Opcodes.ILOAD), parameterDescription.getOffset()); methodVisitor.visitVarInsn(type.getOpcode(Opcodes.ISTORE), instrumentedMethod.getStackSize() + exitType.getStackSize().getSize() + StackSize.of(namedTypes.values()) + enterType.getStackSize().getSize() + parameterDescription.getOffset()); stackSize = stackSize.maximum(parameterDescription.getType().getStackSize()); } return stackSize.getSize(); } }
@Override public Size apply( MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod ) { methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 ); methodVisitor.visitMethodInsn( Opcodes.INVOKESPECIAL, managedCtClass.getSuperClass().asErasure().getInternalName(), EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + persistentField.getName(), Type.getMethodDescriptor( Type.getType( persistentField.getType().asErasure().getDescriptor() ) ), false ); methodVisitor.visitInsn( Type.getType( persistentField.getType().asErasure().getDescriptor() ).getOpcode( Opcodes.IRETURN ) ); return new Size( persistentField.getType().getStackSize().getSize(), instrumentedMethod.getStackSize() ); } }
/** * {@inheritDoc} */ protected MethodVisitor doApply(MethodVisitor methodVisitor, Context implementationContext, Assigner assigner, ArgumentHandler.ForAdvice argumentHandler, MethodSizeHandler.ForAdvice methodSizeHandler, StackMapFrameHandler.ForAdvice stackMapFrameHandler, TypeDescription instrumentedType, MethodDescription instrumentedMethod, SuppressionHandler.Bound suppressionHandler, RelocationHandler.Bound relocationHandler) { methodSizeHandler.requireLocalVariableLengthPadding(adviceMethod.getReturnType().getStackSize().getSize()); return super.doApply(methodVisitor, implementationContext, assigner, argumentHandler, methodSizeHandler, stackMapFrameHandler, instrumentedType, instrumentedMethod, suppressionHandler, relocationHandler); } }
/** * {@inheritDoc} */ public StackManipulation toStackManipulation(ParameterDescription target, Assigner assigner, Assigner.Typing typing) { TypeDescription.Generic componentType; if (target.getType().represents(Object.class)) { componentType = TypeDescription.Generic.OBJECT; } else if (target.getType().isArray()) { componentType = target.getType().getComponentType(); } else { throw new IllegalStateException("Cannot set method parameter array for non-array type: " + target); } List<StackManipulation> stackManipulations = new ArrayList<StackManipulation>(parameters.size()); for (ParameterDescription parameter : parameters) { StackManipulation stackManipulation = new StackManipulation.Compound( MethodVariableAccess.load(parameter), assigner.assign(parameter.getType(), componentType, typing) ); if (stackManipulation.isValid()) { stackManipulations.add(stackManipulation); } else { throw new IllegalStateException("Cannot assign " + parameter + " to " + componentType); } } return new StackManipulation.Compound(ArrayFactory.forType(componentType).withValues(stackManipulations)); }
/** * Returns a {@code static}, {@code final} field constant. * * @param fieldDescription The field to represent a value of. * @return A dynamically resolved field value constant. */ public static Dynamic ofField(FieldDescription.InDefinedShape fieldDescription) { if (!fieldDescription.isStatic() || !fieldDescription.isFinal()) { throw new IllegalArgumentException("Field must be static and final: " + fieldDescription); } boolean selfDeclared = fieldDescription.getType().isPrimitive() ? fieldDescription.getType().asErasure().asBoxed().equals(fieldDescription.getType().asErasure()) : fieldDescription.getDeclaringType().equals(fieldDescription.getType().asErasure()); return new Dynamic(new ConstantDynamic(fieldDescription.getInternalName(), fieldDescription.getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "getStaticFinal", selfDeclared ? "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;" : "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;", false), selfDeclared ? new Object[0] : new Object[]{Type.getType(fieldDescription.getDeclaringType().getDescriptor())}), fieldDescription.getType().asErasure()); }