Example usage for org.objectweb.asm Opcodes ALOAD

List of usage examples for org.objectweb.asm Opcodes ALOAD

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes ALOAD.

Prototype

int ALOAD

To view the source code for org.objectweb.asm Opcodes ALOAD.

Click Source Link

Usage

From source file:com.android.build.gradle.internal.incremental.IncrementalSupportVisitor.java

License:Apache License

/***
 * Inserts a trampoline to this class so that the updated methods can make calls to
 * constructors.//from w  ww. j  a v a 2s  .co m
 *
 * <p>
 * Pseudo code for this trampoline:
 * <code>
 *   ClassName(Object[] args, Marker unused) {
 *      String name = (String) args[0];
 *      if (name.equals(
 *          "java/lang/ClassName.(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;")) {
 *        this((String)arg[1], arg[2]);
 *        return
 *      }
 *      if (name.equals("SuperClassName.(Ljava/lang/String;I)V")) {
 *        super((String)arg[1], (int)arg[2]);
 *        return;
 *      }
 *      ...
 *      StringBuilder $local1 = new StringBuilder();
 *      $local1.append("Method not found ");
 *      $local1.append(name);
 *      $local1.append(" in " $classType $super implementation");
 *      throw new $package/InstantReloadException($local1.toString());
 *   }
 * </code>
 */
private void createDispatchingThis() {
    // Gather all methods from itself and its superclasses to generate a giant constructor
    // implementation.
    // This will work fine as long as we don't support adding constructors to classes.
    final Map<String, MethodNode> uniqueMethods = new HashMap<>();

    addAllNewConstructors(uniqueMethods, classNode, true /*keepPrivateConstructors*/);
    for (ClassNode parentNode : parentNodes) {
        addAllNewConstructors(uniqueMethods, parentNode, false /*keepPrivateConstructors*/);
    }

    int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC;

    Method m = new Method(ByteCodeUtils.CONSTRUCTOR, ConstructorRedirection.DISPATCHING_THIS_SIGNATURE);
    MethodVisitor visitor = super.visitMethod(0, m.getName(), m.getDescriptor(), null, null);
    final GeneratorAdapter mv = new GeneratorAdapter(access, m, visitor);

    mv.visitCode();
    // Mark this code as redirection code
    Label label = new Label();
    mv.visitLineNumber(0, label);

    // Get and store the constructor canonical name.
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.push(1);
    mv.visitInsn(Opcodes.AALOAD);
    mv.unbox(Type.getType("Ljava/lang/String;"));
    final int constructorCanonicalName = mv.newLocal(Type.getType("Ljava/lang/String;"));
    mv.storeLocal(constructorCanonicalName);

    new StringSwitch() {

        @Override
        void visitString() {
            mv.loadLocal(constructorCanonicalName);
        }

        @Override
        void visitCase(String canonicalName) {
            MethodNode methodNode = uniqueMethods.get(canonicalName);
            String owner = canonicalName.split("\\.")[0];

            // Parse method arguments and
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            Type[] args = Type.getArgumentTypes(methodNode.desc);
            int argc = 1;
            for (Type t : args) {
                mv.visitVarInsn(Opcodes.ALOAD, 1);
                mv.push(argc + 1);
                mv.visitInsn(Opcodes.AALOAD);
                ByteCodeUtils.unbox(mv, t);
                argc++;
            }

            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, ByteCodeUtils.CONSTRUCTOR, methodNode.desc, false);

            mv.visitInsn(Opcodes.RETURN);
        }

        @Override
        void visitDefault() {
            writeMissingMessageWithHash(mv, visitedClassName);
        }
    }.visit(mv, uniqueMethods.keySet());

    mv.visitMaxs(1, 3);
    mv.visitEnd();
}

From source file:com.android.build.gradle.internal.transforms.InstantRunTransform.java

License:Apache License

/**
 * Use asm to generate a concrete subclass of the AppPathLoaderImpl class.
 * It only implements one method ://www  . j  av a2  s.c o  m
 *      String[] getPatchedClasses();
 *
 * The method is supposed to return the list of classes that were patched in this iteration.
 * This will be used by the InstantRun runtime to load all patched classes and register them
 * as overrides on the original classes.2 class files.
 *
 * @param patchFileContents list of patched class names.
 * @param outputDir output directory where to generate the .class file in.
 */
private static void writePatchFileContents(@NonNull ImmutableList<String> patchFileContents,
        @NonNull File outputDir, long buildId) {

    ClassWriter cw = new ClassWriter(0);
    MethodVisitor mv;

    cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, IncrementalVisitor.APP_PATCHES_LOADER_IMPL,
            null, IncrementalVisitor.ABSTRACT_PATCHES_LOADER_IMPL, null);

    // Add the build ID to force the patch file to be repackaged.
    cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "BUILD_ID", "J", null, buildId);

    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, IncrementalVisitor.ABSTRACT_PATCHES_LOADER_IMPL, "<init>",
                "()V", false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getPatchedClasses", "()[Ljava/lang/String;", null, null);
        mv.visitCode();
        mv.visitIntInsn(Opcodes.BIPUSH, patchFileContents.size());
        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
        for (int index = 0; index < patchFileContents.size(); index++) {
            mv.visitInsn(Opcodes.DUP);
            mv.visitIntInsn(Opcodes.BIPUSH, index);
            mv.visitLdcInsn(patchFileContents.get(index));
            mv.visitInsn(Opcodes.AASTORE);
        }
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(4, 1);
        mv.visitEnd();
    }
    cw.visitEnd();

    byte[] classBytes = cw.toByteArray();
    File outputFile = new File(outputDir, IncrementalVisitor.APP_PATCHES_LOADER_IMPL + ".class");
    try {
        Files.createParentDirs(outputFile);
        Files.write(classBytes, outputFile);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

From source file:com.android.build.gradle.internal2.incremental.ConstructorRedirection.java

License:Apache License

@Override
protected void doRedirect(GeneratorAdapter mv, int change) {
    mv.loadLocal(change);//ww w  . j  a  v a2s.  co  m
    mv.push("init$args." + constructor.args.desc);

    Type arrayType = Type.getType("[Ljava/lang/Object;");
    // init$args args (including this) + locals
    mv.push(types.size() + 1);
    mv.newArray(Type.getType(Object.class));

    int array = mv.newLocal(arrayType);
    mv.dup();
    mv.storeLocal(array);

    // "this" is not ready yet, use null instead.
    mv.dup();
    mv.push(0);
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.arrayStore(Type.getType(Object.class));

    // Set the arguments in positions 1..(n-1);
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(types), 1); // Skip the this value

    // Add the locals array at the last position.
    mv.dup();
    // The index of the last position of the array.
    mv.push(types.size());
    // Create the array with all the local variables declared up to this point.
    ByteCodeUtils.newVariableArray(mv, constructor.variables.subList(0, constructor.localsAtLoadThis));
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE,
            Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    //// At this point, init$args has been called and the result Object is on the stack.
    //// The value of that Object is Object[] with exactly n + 2 elements.
    //// The first element is the resulting local variables
    //// The second element is a string with the qualified name of the constructor to call.
    //// The remaining elements are the constructor arguments.

    // Keep a reference to the new locals array
    mv.dup();
    mv.push(0);
    mv.arrayLoad(Type.getType("[Ljava/lang/Object;"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    mv.storeLocal(array);

    // Call super constructor
    // Put this behind the returned array
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.swap();
    // Push a null for the marker parameter.
    mv.visitInsn(Opcodes.ACONST_NULL);
    // Invoke the constructor
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, ByteCodeUtils.CONSTRUCTOR,
            DISPATCHING_THIS_SIGNATURE, false);

    //        {
    //            // FIXME: Opcodes.INVOKESPECIAL??????this?,?????
    //            mv.visitVarInsn(Opcodes.ALOAD, 0);
    //
    //            List<LocalVariable> variables = ByteCodeUtils.toLocalVariables(types);
    //            for (int i = 1; i < variables.size(); i++) {
    //                LocalVariable variable = variables.get(i);
    //                // Duplicates the array on the stack;
    //                mv.loadLocal(array);
    //                // Sets up the index
    //                mv.push(i + 1);
    //                // Gets the Object value
    //                mv.arrayLoad(Type.getType(Object.class));
    //                mv.unbox(variable.type);
    //            }
    //            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, ByteCodeUtils.CONSTRUCTOR, constructor.originConstructor.desc, false);
    //        }

    // Dispatch to init$body
    mv.loadLocal(change);
    mv.push("init$body." + constructor.body.desc);
    mv.loadLocal(array);

    // Now "this" can be set
    mv.dup();
    mv.push(0);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE,
            Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.pop();
}

From source file:com.android.build.gradle.internal2.incremental.IncrementalChangeVisitor.java

License:Apache License

/**
 * Turns this class into an override class that can be loaded by our custom class loader:
 *<ul>// ww w  .  j a v a2  s.  c  om
 *   <li>Make the class name be OriginalName$override</li>
 *   <li>Ensure the class derives from java.lang.Object, no other inheritance</li>
 *   <li>Ensure the class has a public parameterless constructor that is a noop.</li>
 *</ul>
 */
@Override
public void visit(int version, int access, String name, String signature, String superName,
        String[] interfaces) {
    // TODO: modified by achellies, ?,??,?ClassClass,Opcodes.INVOKESPECIAL?super
    super.visit(version, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, name + OVERRIDE_SUFFIX, signature, superName, // TODO modified by achellies, "java/lang/Object" -> superName
            new String[] { CHANGE_TYPE.getInternalName() });

    if (DEBUG) {
        System.out.println(">>>>>>>> Processing " + name + "<<<<<<<<<<<<<");
    }

    visitedClassName = name;
    visitedSuperName = superName;
    instanceToStaticDescPrefix = "(L" + visitedClassName + ";";

    // Create empty constructor
    MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC, ByteCodeUtils.CONSTRUCTOR, "()V", null, null);
    mv.visitCode();
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, ByteCodeUtils.CONSTRUCTOR, "()V", // TODO modified by achellies, "java/lang/Object" -> superName
            false);
    mv.visitInsn(Opcodes.RETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();

    super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC, "$obsolete", "Z", null,
            null);
}

From source file:com.android.build.gradle.internal2.incremental.IncrementalChangeVisitor.java

License:Apache License

/**
 * To each class, add the dispatch method called by the original code that acts as a trampoline to
 * invoke the changed methods.//from w  w  w.  j a  va2s .c  om
 * <p>
 * Pseudo code:
 * <code>
 *   Object access$dispatch(String name, object[] args) {
 *      if (name.equals(
 *          "firstMethod.(L$type;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;")) {
 *        return firstMethod(($type)arg[0], (String)arg[1], arg[2]);
 *      }
 *      if (name.equals("secondMethod.(L$type;Ljava/lang/String;I;)V")) {
 *        secondMethod(($type)arg[0], (String)arg[1], (int)arg[2]);
 *        return;
 *      }
 *      ...
 *      StringBuilder $local1 = new StringBuilder();
 *      $local1.append("Method not found ");
 *      $local1.append(name);
 *      $local1.append(" in " + visitedClassName +
 *          "$dispatch implementation, restart the application");
 *      throw new $package/InstantReloadException($local1.toString());
 *   }
 * </code>
 */
private void addDispatchMethod() {
    int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_VARARGS;
    Method m = new Method("access$dispatch", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;");
    MethodVisitor visitor = super.visitMethod(access, m.getName(), m.getDescriptor(), null, null);

    final GeneratorAdapter mv = new GeneratorAdapter(access, m, visitor);

    if (TRACING_ENABLED) {
        mv.push("Redirecting ");
        mv.loadArg(0);
        trace(mv, 2);
    }

    List<MethodNode> allMethods = new ArrayList<>();

    // if we are disabled, do not generate any dispatch, the method will throw an exception
    // if invoked which should never happen.
    if (!instantRunDisabled) {
        //noinspection unchecked
        allMethods.addAll(classNode.methods);
        allMethods.addAll(addedMethods);
    }

    final Map<String, MethodNode> methods = new HashMap<>();
    for (MethodNode methodNode : allMethods) {
        if (methodNode.name.equals(ByteCodeUtils.CLASS_INITIALIZER)
                || methodNode.name.equals(ByteCodeUtils.CONSTRUCTOR)) {
            continue;
        }
        if (!isAccessCompatibleWithInstantRun(methodNode.access)) {
            continue;
        }
        methods.put(methodNode.name + "." + methodNode.desc, methodNode);
    }

    new StringSwitch() {
        @Override
        void visitString() {
            mv.visitVarInsn(Opcodes.ALOAD, 1);
        }

        @Override
        void visitCase(String methodName) {
            MethodNode methodNode = methods.get(methodName);
            String name = methodNode.name;
            boolean isStatic = (methodNode.access & Opcodes.ACC_STATIC) != 0;
            String newDesc = computeOverrideMethodDesc(methodNode.desc, isStatic);

            if (TRACING_ENABLED) {
                trace(mv, "M: " + name + " P:" + newDesc);
            }
            Type[] args = Type.getArgumentTypes(newDesc);
            int argc = 0;
            for (Type t : args) {
                mv.visitVarInsn(Opcodes.ALOAD, 2);
                mv.push(argc);
                mv.visitInsn(Opcodes.AALOAD);
                ByteCodeUtils.unbox(mv, t);
                argc++;
            }
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, visitedClassName + "$override",
                    isStatic ? computeOverrideMethodName(name, methodNode.desc) : name, newDesc, false);
            Type ret = Type.getReturnType(methodNode.desc);
            if (ret.getSort() == Type.VOID) {
                mv.visitInsn(Opcodes.ACONST_NULL);
            } else {
                mv.box(ret);
            }
            mv.visitInsn(Opcodes.ARETURN);
        }

        @Override
        void visitDefault() {
            writeMissingMessageWithHash(mv, visitedClassName);
        }
    }.visit(mv, methods.keySet());

    mv.visitMaxs(0, 0);
    mv.visitEnd();

    super.visitEnd();
}

From source file:com.android.build.gradle.internal2.incremental.IncrementalSupportVisitor.java

License:Apache License

/***
 * Inserts a trampoline to this class so that the updated methods can make calls to super
 * class methods.//from  w  w w .jav  a2  s  .  c  om
 * <p>
 * Pseudo code for this trampoline:
 * <code>
 *   Object access$super($classType instance, String name, object[] args) {
 *      switch(name) {
 *          case "firstMethod.(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;":
 *            return super~instance.firstMethod((String)arg[0], arg[1]);
 *          case "secondMethod.(Ljava/lang/String;I)V":
 *            return super~instance.firstMethod((String)arg[0], arg[1]);
 *
 *          default:
 *            StringBuilder $local1 = new StringBuilder();
 *            $local1.append("Method not found ");
 *            $local1.append(name);
 *            $local1.append(" in " $classType $super implementation");
 *            throw new $package/InstantReloadException($local1.toString());
 *      }
 * </code>
 */
private void createAccessSuper() {
    int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_VARARGS;
    Method m = new Method("access$super",
            "(L" + visitedClassName + ";Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;");
    MethodVisitor visitor = super.visitMethod(access, m.getName(), m.getDescriptor(), null, null);

    final GeneratorAdapter mv = new GeneratorAdapter(access, m, visitor);

    // Gather all methods from itself and its superclasses to generate a giant access$super
    // implementation.
    // This will work fine as long as we don't support adding methods to a class.
    final Map<String, MethodReference> uniqueMethods = new HashMap<>();
    if (parentNodes.isEmpty()) {
        // if we cannot determine the parents for this class, let's blindly add all the
        // method of the current class as a gateway to a possible parent version.
        addAllNewMethods(classNode, classNode, uniqueMethods);
    } else {
        // otherwise, use the parent list.
        for (ClassNode parentNode : parentNodes) {
            addAllNewMethods(classNode, parentNode, uniqueMethods);
        }
    }

    new StringSwitch() {
        @Override
        void visitString() {
            mv.visitVarInsn(Opcodes.ALOAD, 1);
        }

        @Override
        void visitCase(String methodName) {
            MethodReference methodRef = uniqueMethods.get(methodName);

            mv.visitVarInsn(Opcodes.ALOAD, 0);

            Type[] args = Type.getArgumentTypes(methodRef.method.desc);
            int argc = 0;
            for (Type t : args) {
                mv.visitVarInsn(Opcodes.ALOAD, 2);
                mv.push(argc);
                mv.visitInsn(Opcodes.AALOAD);
                ByteCodeUtils.unbox(mv, t);
                argc++;
            }

            if (TRACING_ENABLED) {
                trace(mv, "super selected ", methodRef.owner.name, methodRef.method.name,
                        methodRef.method.desc);
            }
            String parentName = findParentClassForMethod(methodRef);
            LOG.verbose("Generating access$super for " + methodRef.method.name + " recv " + parentName);

            // Call super on the other object, yup this works cos we are on the right place to
            // call from.
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, parentName, methodRef.method.name, methodRef.method.desc,
                    false);

            Type ret = Type.getReturnType(methodRef.method.desc);
            if (ret.getSort() == Type.VOID) {
                mv.visitInsn(Opcodes.ACONST_NULL);
            } else {
                mv.box(ret);
            }
            mv.visitInsn(Opcodes.ARETURN);
        }

        @Override
        void visitDefault() {
            writeMissingMessageWithHash(mv, visitedClassName);
        }
    }.visit(mv, uniqueMethods.keySet());

    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:com.android.ide.eclipse.apt.internal.analysis.InnerClassAnalyzer.java

License:Apache License

/**
 * Checks if a method of an inner class accesses the private content of an outer class (field or method)
 * @param methodNode/* w  ww  . ja  v  a2 s  . c o m*/
 * @param method
 * @return True if the outer access is confirmed, false otherwise.
 */
private boolean confirmParentClassAccess(final MethodNode methodNode, final MethodInsnNode method) {
    final String methodNodeName = methodNode.name;
    AbstractInsnNode prev = method.getPrevious();
    boolean result = false;
    while (!result) {
        if (methodNodeName.startsWith("<init>")) {
            if (prev.getOpcode() == Opcodes.ALOAD) {
                final VarInsnNode varInsn = (VarInsnNode) prev;
                result = varInsn.var == 1;
            }
        } else {
            if (prev.getOpcode() == Opcodes.GETFIELD) {
                final FieldInsnNode getField = (FieldInsnNode) prev;
                final String field = getField.owner + getField.name;
                final String testField = mInnerClass.name + "this$0";
                result = field.equals(testField);
            }
        }
        if (prev.getType() == AbstractInsnNode.LINE) {
            break;
        } else {
            prev = prev.getPrevious();
        }
    }
    return result;
}

From source file:com.android.ide.eclipse.apt.internal.analysis.InternalGetSetAnalyzer.java

License:Apache License

/**
 * Checks if a method is a getter/*from  ww  w .ja va  2  s  .  c om*/
 * @param methodTest The method to test
 * @return True if the method is a getter, false otherwise
 */
private boolean isGetter(final MethodNode methodTest) {
    boolean getter = false;
    final String desc = methodTest.desc;
    final Type[] arguments = Type.getArgumentTypes(desc);
    final Type returnType = Type.getReturnType(desc);
    if (arguments.length == 0 && returnType.getSort() != Type.VOID) {
        final InsnList instructions = methodTest.instructions;
        //three next to skip label and line number instructions
        final AbstractInsnNode first = instructions.getFirst().getNext().getNext();
        final int returnOp = returnType.getOpcode(Opcodes.IRETURN);
        final int firstOp = first.getOpcode();
        //check for static getter
        if ((Opcodes.ACC_STATIC & methodTest.access) == 0) {
            if (firstOp == Opcodes.ALOAD) {
                final AbstractInsnNode second = first.getNext();
                if (second.getOpcode() == Opcodes.GETFIELD) {
                    final AbstractInsnNode third = second.getNext();
                    if (third.getOpcode() == returnOp) {
                        getter = true;
                    }
                }
            }
        } else {
            if (firstOp == Opcodes.GETSTATIC) {
                final AbstractInsnNode second = first.getNext();
                if (second.getOpcode() == returnOp) {
                    getter = true;
                }
            }
        }
    }
    return getter;
}

From source file:com.android.ide.eclipse.apt.internal.analysis.InternalGetSetAnalyzer.java

License:Apache License

/**
 * Checks if a method is a setter/*from  w  w  w.  j a v a  2s .  c  om*/
 * @param methodTest The method to be checked
 * @return True if the method is a setter, false otherwise
 */
private boolean isSetter(final MethodNode methodTest) {
    boolean setter = false;
    final String desc = methodTest.desc;
    final Type[] arguments = Type.getArgumentTypes(desc);
    final Type returnType = Type.getReturnType(desc);
    if (arguments.length == 1 && returnType.getSort() == Type.VOID) {
        final InsnList instructions = methodTest.instructions;
        //skip label and line number instructions
        final AbstractInsnNode first = instructions.getFirst().getNext().getNext();
        final int loadOp = arguments[0].getOpcode(Opcodes.ILOAD);
        final int firstOp = first.getOpcode();
        //check for static setter
        if ((Opcodes.ACC_STATIC & methodTest.access) == 0) {
            if (firstOp == Opcodes.ALOAD) {
                final AbstractInsnNode second = first.getNext();
                if (second.getOpcode() == loadOp) {
                    final AbstractInsnNode third = second.getNext();
                    if (third.getOpcode() == Opcodes.PUTFIELD) {
                        //three next to skip label and line number instructions
                        final AbstractInsnNode fourth = third.getNext().getNext().getNext();
                        if (fourth.getOpcode() == Opcodes.RETURN) {
                            setter = true;
                        }
                    }
                }
            }
        } else {
            if (firstOp == loadOp) {
                final AbstractInsnNode second = first.getNext();
                if (second.getOpcode() == Opcodes.PUTSTATIC) {
                    final AbstractInsnNode third = second.getNext().getNext().getNext();
                    if (third.getOpcode() == Opcodes.RETURN) {
                        setter = true;
                    }
                }
            }
        }
    }
    return setter;
}

From source file:com.android.ide.eclipse.apt.internal.analysis.StaticVirtualAnalyzer.java

License:Apache License

@Override
protected Collection<Problem> analyzeMethod(final MethodNode methodNode) {
    final Collection<Problem> problems = new LinkedList<Problem>();
    final int acc = methodNode.access;
    if ((acc & Opcodes.ACC_STATIC) == 0 && (acc & Opcodes.ACC_ABSTRACT) == 0) {
        final InsnList instructions = methodNode.instructions;
        //find if a method load this (ALOAD 0)
        boolean aload0 = false;
        for (int i = 0; i < instructions.size(); i++) {
            final AbstractInsnNode instruction = instructions.get(i);
            if (instruction.getOpcode() == Opcodes.ALOAD) {
                final VarInsnNode aload = (VarInsnNode) instruction;
                aload0 = aload.var == 0;
                if (aload0) {
                    break;
                }/*from ww w . ja va2 s.c o  m*/
            }
        }
        if (!aload0) {
            final Problem problem = new StaticVirtualProblem(instructions.get(1));
            problems.add(problem);
        }
    }
    return problems;
}