private MethodNode generateStaticInitializerNotifierMethod(MutableClass mutableClass) { MethodNode methodNode = new MethodNode(Opcodes.ACC_STATIC, "<clinit>", "()V", "()V", null); RobolectricGeneratorAdapter generator = new RobolectricGeneratorAdapter(methodNode); generator.push(mutableClass.classType); generator.invokeStatic(Type.getType(RobolectricInternals.class), new Method("classInitializing", "(Ljava/lang/Class;)V")); generator.returnValue(); generator.endMethod(); return methodNode; }
private void addNoArgsConstructor(MutableClass mutableClass) { if (!mutableClass.foundMethods.contains("<init>()V")) { MethodNode defaultConstructor = new MethodNode(Opcodes.ACC_PUBLIC, "<init>", "()V", "()V", null); RobolectricGeneratorAdapter generator = new RobolectricGeneratorAdapter(defaultConstructor); generator.loadThis(); generator.visitMethodInsn(Opcodes.INVOKESPECIAL, mutableClass.classNode.superName, "<init>", "()V", false); generator.loadThis(); generator.invokeVirtual(mutableClass.classType, new Method(ROBO_INIT_METHOD_NAME, "()V")); generator.returnValue(); mutableClass.addMethod(defaultConstructor); } }
private void writeConstructor() { org.objectweb.asm.commons.Method initMethod = new org.objectweb.asm.commons.Method("<init>", Type.VOID_TYPE, new Type[] {targetType}); GeneratorAdapter init = new GeneratorAdapter(ACC_PUBLIC, initMethod, null, null, this); init.loadThis(); init.invokeConstructor(OBJECT_TYPE, OBJECT_INIT); init.loadThis(); init.loadArg(0); init.putField(reflectorType, TARGET_FIELD, targetType); init.returnValue(); init.endMethod(); }
proxyConstructorGenerator.invokeConstructor(getTypeReference(targetClassFullName), new Method(CONSTRUCTOR_NAME, superConstructorDescriptor)); proxyConstructorGenerator.dup(); proxyConstructorGenerator.loadThis(); proxyConstructorGenerator.invokeConstructor(methodType, new Method(CONSTRUCTOR_NAME, getConstructorDescriptor(proxyFullName))); proxyConstructorGenerator.visitInsn(AASTORE); pushResolveInterceptorsCall(proxyConstructorGenerator, i);
/** * Produce a rebased method declaration, also visiting referenced types. */ private Method processMethod(String sourceType, String name, String desc) { Method method = new Method(name, desc); Type[] argumentTypes = method.getArgumentTypes(); for (int i = 0, j = argumentTypes.length; i < j; i++) { argumentTypes[i] = processType(sourceType, argumentTypes[i]); } method = new Method(name, processType(sourceType, method.getReturnType()), argumentTypes); return method; }
generator.invokeVirtual(mutableClass.classType, new Method(ROBO_INIT_METHOD_NAME, "()V")); generateClassHandlerCall(mutableClass, method, ShadowConstants.CONSTRUCTOR_METHOD_NAME, generator);
private @Nullable Method hack(@Nullable Method method) { if (method == null) { return null; } Type[] argumentTypes = method.getArgumentTypes(); Type[] hackedArgumentTypes = new Type[argumentTypes.length]; for (int i = 0; i < argumentTypes.length; i++) { hackedArgumentTypes[i] = hack(argumentTypes[i]); } return new Method(method.getName(), hack(method.getReturnType()), hackedArgumentTypes); }
@Value.Derived Method toAsmMethod() { return new Method(name(), descriptor()); } }
@Override protected void onMethodExit(int opcode) { if (cascadingConstructor) { // need to call MixinInit exactly once, so don't call MixinInit at end of cascading // constructors return; } for (MixinType mixinType : matchedMixinTypes) { String initMethodName = mixinType.initMethodName(); if (initMethodName != null) { loadThis(); invokeVirtual(type, new Method(initMethodName, "()V")); } } } }
@RequiresNonNull("type") private void overrideAndWeaveInheritedMethod(AnalyzedMethod inheritedMethod) { String superName = analyzedClass.superName(); // superName is null only for java.lang.Object which doesn't inherit anything // so safe to assume superName not null here checkNotNull(superName); String[] exceptions = new String[inheritedMethod.exceptions().size()]; for (int i = 0; i < inheritedMethod.exceptions().size(); i++) { exceptions[i] = ClassNames.toInternalName(inheritedMethod.exceptions().get(i)); } List<Advice> advisors = removeSuperseded(inheritedMethod.advisors()); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, inheritedMethod.name(), inheritedMethod.getDesc(), inheritedMethod.signature(), exceptions); mv = visitMethodWithAdvice(mv, ACC_PUBLIC, inheritedMethod.name(), inheritedMethod.getDesc(), advisors); checkNotNull(mv); GeneratorAdapter mg = new GeneratorAdapter(mv, ACC_PUBLIC, inheritedMethod.name(), inheritedMethod.getDesc()); mg.visitCode(); mg.loadThis(); mg.loadArgs(); Type superType = Type.getObjectType(ClassNames.toInternalName(superName)); // method is called invokeConstructor, but should really be called invokeSpecial Method method = new Method(inheritedMethod.name(), inheritedMethod.getDesc()); mg.invokeConstructor(superType, method); mg.returnValue(); mg.endMethod(); }
/** * Creates a new {@link Method}. * * @param constructor a java.lang.reflect constructor descriptor * @return a {@link Method} corresponding to the given Java constructor declaration. */ public static Method getMethod(final java.lang.reflect.Constructor<?> constructor) { return new Method("<init>", Type.getConstructorDescriptor(constructor)); }
/** * Creates a new {@link Method}. * * @param method a java.lang.reflect method descriptor * @return a {@link Method} corresponding to the given Java method declaration. */ public static Method getMethod(final java.lang.reflect.Method method) { return new Method(method.getName(), Type.getMethodDescriptor(method)); }
/** * Returns a new {@link ConstructorRef} that refers to a constructor on the given type with the * given parameter types. */ public static ConstructorRef create(TypeInfo type, Iterable<Type> argTypes) { return create( type, new Method("<init>", Type.VOID_TYPE, Iterables.toArray(argTypes, Type.class))); }
@Override public void onMethodExit(String name, String desc, GeneratorAdapter generatorAdapter) { generatorAdapter.loadThis(); generatorAdapter.invokeStatic(SPARK_RUNTIME_ENV_TYPE, new Method("setContext", Type.VOID_TYPE, new Type[] { contextType })); } });
/** * Returns an expression stub (that points to a non-existing method) whose return type is the * given class. Useful for scenarios where we're reporting an error and just need an Expression of * the appropriate type to be able to continue. */ static Expression stubExpression(Class<?> clazz) { return MethodRef.createStaticMethod( TypeInfo.create( "if.you.see.this.please.report.a.bug.because.an.error.message.was.swallowed"), new org.objectweb.asm.commons.Method("oops", Type.getType(clazz), new Type[0])) .invoke(); }
@Override protected void onFinally(int opcode) { // } finally { // this._datasetRuntimeContext.onMethodExit(); // } loadThis(); getField(datasetType, datasetRuntimeContextField, DATASET_RUNTIME_CONTEXT_TYPE); invokeVirtual(DATASET_RUNTIME_CONTEXT_TYPE, new Method("onMethodExit", Type.getMethodDescriptor(Type.VOID_TYPE))); }
/** Returns the {@link MethodRef} for the generated defaultInstance method. */ private static MethodRef getDefaultInstanceMethod(Descriptor descriptor) { TypeInfo message = messageRuntimeType(descriptor); return MethodRef.createStaticMethod( message, new Method("getDefaultInstance", message.type(), NO_METHOD_ARGS)) .asNonNullable(); }
/** Returns the {@link MethodRef} for the generated newBuilder method. */ private static MethodRef getBuilderMethod(Descriptor descriptor) { TypeInfo message = messageRuntimeType(descriptor); TypeInfo builder = builderRuntimeType(descriptor); return MethodRef.createStaticMethod( message, new Method("newBuilder", builder.type(), NO_METHOD_ARGS)) .asNonNullable(); }
/** Returns the {@link MethodRef} for the generated forNumber method. */ private static MethodRef getForNumberMethod(EnumDescriptor descriptor) { TypeInfo enumType = enumRuntimeType(descriptor); return MethodRef.createStaticMethod( enumType, new Method("forNumber", enumType.type(), ONE_INT_ARG)) // Note: Enum.forNumber() returns null if there is no corresponding enum. If a bad value is // passed in (via unknown types), the generated bytecode will NPE. .asNonNullable() .asCheap(); }
/** Returns the {@link MethodRef} for the get*Case method for oneof fields. */ private static MethodRef getOneOfCaseMethod(OneofDescriptor descriptor) { TypeInfo message = messageRuntimeType(descriptor.getContainingType()); return MethodRef.createInstanceMethod( message, new Method( "get" + underscoresToCamelCase(descriptor.getName(), true) + "Case", TypeInfo.create(JavaQualifiedNames.getCaseEnumClassName(descriptor)).type(), NO_METHOD_ARGS)) .asCheap(); }