Example usage for org.objectweb.asm ClassVisitor ClassVisitor

List of usage examples for org.objectweb.asm ClassVisitor ClassVisitor

Introduction

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

Prototype

public ClassVisitor(final int api) 

Source Link

Document

Constructs a new ClassVisitor .

Usage

From source file:autostack.Transformer.java

License:Open Source License

public byte[] transform(ClassLoader loader, final String className, Class<?> classBeingRedefined,
        ProtectionDomain protectionDomain, byte[] classfileBuffer) {
    try {//from   w  w  w  .  jav a  2s .com
        if (className == null || className.startsWith("java/") || className.startsWith("sun/")
                || className.startsWith("jdk/internal/") || className.startsWith("org/lwjgl/"))
            return null;
        for (String pack : packages)
            if (!className.startsWith(pack))
                return null;
        ClassReader cr = new ClassReader(classfileBuffer);
        final Map<String, Integer> stackMethods = new HashMap<String, Integer>();
        // Scan all methods that need auto-stack
        if (debugTransform)
            System.out.println("[autostack] scanning methods in class: " + className.replace('/', '.'));
        cr.accept(new ClassVisitor(ASM5) {
            public MethodVisitor visitMethod(final int access, final String methodName, final String methodDesc,
                    String signature, String[] exceptions) {
                if ((access & (ACC_NATIVE | ACC_ABSTRACT)) != 0) {
                    // Don't try to analyze native or abstract methods.
                    return null;
                }
                MethodVisitor mv = new MethodVisitor(ASM5) {
                    boolean mark, catches, notransform, nostackparam, forcestack;

                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                        if ("Lautostack/NoTransform;".equals(desc))
                            notransform = true;
                        else if ("Lautostack/NoStackParam;".equals(desc))
                            nostackparam = true;
                        else if ("Lautostack/UseNewStack;".equals(desc))
                            forcestack = true;
                        return null;
                    }

                    public void visitMethodInsn(int opcode, String owner, String name, String desc,
                            boolean itf) {
                        if (opcode == INVOKESTATIC && !itf && (owner.startsWith("org/lwjgl/")
                                && (name.equals("mallocStack") || name.equals("callocStack"))
                                || owner.equals(MEMORYSTACK) && (name.equals("stackGet")
                                        || name.equals("stackPop") || name.equals("stackPush")
                                        || name.startsWith("stackMalloc") || name.startsWith("stackCalloc")
                                        || name.equals("stackUTF8") || name.equals("stackASCII")
                                        || name.equals("stackUTF16") || name.equals("stackFloats")
                                        || name.equals("stackInts") || name.equals("stackBytes")
                                        || name.equals("stackShorts") || name.equals("stackPointers")
                                        || name.equals("stackLongs")))) {
                            mark = true;
                        }
                    }

                    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
                        catches = true;
                    }

                    public void visitEnd() {
                        int flag = (access & ACC_PRIVATE) != 0 ? 8 : 0;
                        flag |= nostackparam ? 16 : 0;
                        if (mark || notransform || forcestack || nostackparam) {
                            if (notransform) {
                                flag |= 2;
                                if (debugTransform)
                                    System.out.println("[autostack]   will not transform method: "
                                            + className.replace('/', '.') + "." + methodName);
                            } else {
                                if (checkStack)
                                    flag |= 4;
                                flag |= catches ? 1 : 0;
                                if (debugTransform)
                                    System.out.println("[autostack]   will transform method: "
                                            + className.replace('/', '.') + "." + methodName);
                            }
                            stackMethods.put(methodName + methodDesc, Integer.valueOf(flag));
                        }
                    }
                };
                return mv;
            }
        }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
        if (stackMethods.isEmpty())
            return null;

        // Now, transform all such methods
        if (debugTransform)
            System.out.println("[autostack] transforming methods in class: " + className.replace('/', '.'));
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
        cr.accept(new ClassVisitor(ASM5, cw) {
            boolean classDefaultNewStack = defaultNewStack;
            boolean classNoTransform;

            @Override
            public void visit(int version, int access, String name, String signature, String superName,
                    String[] interfaces) {
                cv.visit(version, access, name, signature, superName, interfaces);
                if (!checkStack) {
                    return;
                }
                /* Generate simple synthetic "compare stack pointers and throw if not equal" method */
                MethodVisitor mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStack$",
                        "(II)V", null, new String[] { "java/lang/AssertionError" });
                {
                    mv.visitCode();
                    mv.visitVarInsn(ILOAD, 0);
                    mv.visitVarInsn(ILOAD, 1);
                    Label l0 = new Label();
                    mv.visitJumpInsn(IF_ICMPEQ, l0);
                    mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
                    mv.visitInsn(DUP);
                    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
                    mv.visitInsn(DUP);
                    mv.visitLdcInsn("Stack pointers differ: ");
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitVarInsn(ILOAD, 0);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitLdcInsn(" != ");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                            "()Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitInsn(ATHROW);
                    mv.visitLabel(l0);
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                    mv.visitInsn(RETURN);
                    mv.visitMaxs(5, 2);
                    mv.visitEnd();
                }

                mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStackWithThrowable$",
                        "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", null, null);
                {
                    mv.visitCode();
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitVarInsn(ILOAD, 2);
                    Label l0 = new Label();
                    mv.visitJumpInsn(IF_ICMPEQ, l0);
                    mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
                    mv.visitInsn(DUP);
                    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
                    mv.visitInsn(DUP);
                    mv.visitLdcInsn("Stack pointers differ: ");
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitLdcInsn(" != ");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
                    mv.visitVarInsn(ILOAD, 2);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                            "()Ljava/lang/String;", false);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
                            "(Ljava/lang/String;Ljava/lang/Throwable;)V", false);
                    mv.visitInsn(ARETURN);
                    mv.visitLabel(l0);
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitInsn(ARETURN);
                    mv.visitMaxs(5, 3);
                    mv.visitEnd();
                }
            }

            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                if ("Lautostack/UseCallerStack;".equals(desc)) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]   class declares to use caller stack for all methods, unless overridden by method");
                    classDefaultNewStack = false;
                    return null;
                } else if ("Lautostack/UseNewStack;".equals(desc)) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]   class declares to use new stack for all methods, unless overridden by method");
                    classDefaultNewStack = true;
                    return null;
                } else if ("Lautostack/NoTransform;".equals(desc)) {
                    if (debugTransform)
                        System.out.println("[autostack]   class declares to not transform any methods");
                    classNoTransform = true;
                    return null;
                }
                return cv.visitAnnotation(desc, visible);
            }

            public MethodVisitor visitMethod(final int access, final String name, final String desc,
                    String signature, String[] exceptions) {
                Integer info = stackMethods.get(name + desc);
                if (info == null)
                    return super.visitMethod(access, name, desc, signature, exceptions);
                boolean catches = (info.intValue() & 1) == 1;
                final boolean notransform = classNoTransform || (info.intValue() & 2) == 2;
                if (debugTransform && !notransform)
                    System.out.println(
                            "[autostack]   transform method: " + className.replace('/', '.') + "." + name);
                final boolean memoryStackParam = stackAsParameter && (access & ACC_PRIVATE) != 0
                        && (info.intValue() & 16) == 0;
                MethodVisitor mv;
                final Type[] paramTypes = Type.getArgumentTypes(desc);
                final boolean isStatic = (access & ACC_STATIC) != 0;
                final boolean isConstructor = "<init>".equals(name);
                if (memoryStackParam) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]     changing signature of method to add additional MemoryStack parameter");

                    // Add additional MemoryStack parameter to the method signature index of the local stays the same
                    int paramEndIndex = desc.indexOf(')');
                    String beforeDesc = desc.substring(0, paramEndIndex);
                    String afterDesc = desc.substring(paramEndIndex);
                    mv = super.visitMethod(access | ACC_SYNTHETIC, name,
                            beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, signature, exceptions);

                    // Re-introduce the original method which just delegates
                    if (debugTransform)
                        System.out.println("[autostack]     adding delegate method with original signature");
                    MethodVisitor omv = super.visitMethod(access, name, desc, signature, exceptions);
                    omv.visitCode();
                    int param = 0;
                    if (!isStatic) {
                        omv.visitVarInsn(ALOAD, 0);
                        param++;
                    }
                    for (int i = 0; i < paramTypes.length; i++) {
                        omv.visitVarInsn(paramTypes[i].getOpcode(ILOAD), param);
                        param += paramTypes[i].getSize();
                    }
                    omv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet", "()L" + MEMORYSTACK + ";",
                            false);
                    boolean isPrivate = (access & ACC_PRIVATE) != 0;
                    int opcode = isStatic ? INVOKESTATIC : isPrivate ? INVOKESPECIAL : INVOKEVIRTUAL;
                    omv.visitMethodInsn(opcode, className, name,
                            beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false);
                    Type retType = Type.getReturnType(desc);
                    omv.visitInsn(retType.getOpcode(IRETURN));
                    omv.visitMaxs(-1, -1);
                    omv.visitEnd();
                } else {
                    mv = super.visitMethod(access, name, desc, signature, exceptions);
                }
                if (catches)
                    mv = new TryCatchBlockSorter(mv, access, name, desc, signature, exceptions);
                mv = new MethodVisitor(ASM5, mv) {
                    Label tryLabel = new Label();
                    Label finallyLabel = new Label();
                    int lastLine = 0;
                    boolean newStack = classDefaultNewStack;
                    int stackVarIndex;
                    int stackPointerVarIndex;
                    int firstAdditionalLocal;
                    int additionalLocals;
                    Object[] replacedLocals;

                    public void visitInsn(int opcode) {
                        if (notransform) {
                            mv.visitInsn(opcode);
                            return;
                        }
                        if (opcode >= IRETURN && opcode <= RETURN && (newStack || checkStack)) {
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] restore stack pointer because of return at "
                                        + className.replace('/', '.') + "." + name + ":" + lastLine);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            if (newStack && !checkStack) {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false);
                            } else if (checkStack) {
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, className, "$checkStack$", "(II)V", false);
                            }
                        }
                        mv.visitInsn(opcode);
                    }

                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                        if ("Lautostack/UseCallerStack;".equals(desc)) {
                            if (!notransform) {
                                if (debugTransform)
                                    System.out.println("[autostack]     method declares to use caller stack");
                                newStack = false;
                            }
                            return null;
                        } else if ("Lautostack/UseNewStack;".equals(desc)) {
                            if (!notransform) {
                                if (debugTransform)
                                    System.out.println("[autostack]     method declares to use new stack");
                                newStack = true;
                            }
                            return null;
                        } else if ("Lautostack/NoTransform;".equals(desc)) {
                            return null;
                        } else if ("Lautostack/NoStackParam;".equals(desc)) {
                            return null;
                        }
                        return mv.visitAnnotation(desc, visible);
                    }

                    public void visitVarInsn(int opcode, int var) {
                        if (notransform) {
                            mv.visitVarInsn(opcode, var);
                            return;
                        }
                        if (var >= firstAdditionalLocal)
                            var += additionalLocals;
                        mv.visitVarInsn(opcode, var);
                    }

                    public void visitIincInsn(int var, int increment) {
                        if (notransform) {
                            mv.visitIincInsn(var, increment);
                            return;
                        }
                        if (var >= firstAdditionalLocal)
                            var += additionalLocals;
                        mv.visitIincInsn(var, increment);
                    }

                    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
                        if (notransform) {
                            mv.visitFrame(type, nLocal, local, nStack, stack);
                            return;
                        }
                        if (type == F_FULL) {
                            int noThis = isStatic ? 0 : 1;
                            Object[] locals = new Object[local.length + additionalLocals];
                            if (!isStatic)
                                locals[0] = local[0];
                            int replacementLength = replacedLocals.length;
                            System.arraycopy(replacedLocals, noThis, locals, noThis,
                                    replacementLength - noThis);
                            int len = locals.length - replacementLength;
                            System.arraycopy(local, replacementLength - additionalLocals, locals,
                                    replacementLength, len);
                            mv.visitFrame(type, nLocal + additionalLocals, locals, nStack, stack);
                        } else
                            mv.visitFrame(type, nLocal, local, nStack, stack);
                    }

                    public void visitLocalVariable(String name, String desc, String signature, Label start,
                            Label end, int index) {
                        if (notransform) {
                            mv.visitLocalVariable(className, desc, signature, start, end, index);
                            return;
                        }
                        if (index >= firstAdditionalLocal)
                            index += additionalLocals;
                        mv.visitLocalVariable(name, desc, signature, start, end, index);
                    }

                    private boolean doesNotTakeStackItself(String desc) {
                        return desc.lastIndexOf("L" + MEMORYSTACK + ";)") == -1;
                    }

                    public void visitMethodInsn(int opcode, String owner, String name, String desc,
                            boolean itf) {
                        String completeName = name + desc;
                        Integer info = stackMethods.get(completeName);
                        if (opcode != INVOKESTATIC || notransform) {
                            mv.visitMethodInsn(opcode, owner, name, desc, itf);
                            return;
                        }
                        if (stackAsParameter && info != null && (info.intValue() & 8) != 0
                                && (info.intValue() & 16) == 0) {
                            /* Rewrite invocation to have additional MemoryStack parameter */
                            if (debugTransform)
                                System.out.println(
                                        "[autostack]     rewrite invocation of " + owner.replace('/', '.') + "."
                                                + name + " at line " + lastLine + " --> "
                                                + owner.replace('/', '.') + "." + name + "(..., MemoryStack)");
                            int paramEndIndex = desc.indexOf(')');
                            String beforeDesc = desc.substring(0, paramEndIndex);
                            String afterDesc = desc.substring(paramEndIndex);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitMethodInsn(opcode, owner, name,
                                    beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, itf);
                            return;
                        }
                        if (owner.startsWith("org/lwjgl/")
                                && (name.equals("mallocStack") || name.equals("callocStack"))
                                && doesNotTakeStackItself(desc)) {
                            if (debugTransform)
                                System.out.println(
                                        "[autostack]     rewrite invocation of " + owner.replace('/', '.') + "."
                                                + name + " at line " + lastLine + " --> aload " + stackVarIndex
                                                + "; invokestatic " + owner.replace('/', '.') + "." + name);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            int paramEndIndex = desc.indexOf(')');
                            String beforeDesc = desc.substring(0, paramEndIndex);
                            String afterDesc = desc.substring(paramEndIndex);
                            mv.visitMethodInsn(opcode, owner, name,
                                    beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false);
                        } else if (owner.equals(MEMORYSTACK) && name.equals("stackGet")) {
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.equals("stackPush") || name.equals("stackPop"))) {
                            String newName = "p" + name.substring(6);
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.startsWith("stackMalloc") || name.startsWith("stackCalloc"))) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitInsn(SWAP);
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK) && (name.equals("stackASCII")
                                || name.equals("stackUTF8") || name.equals("stackUTF16"))) {
                            String newName = name.substring(5);
                            boolean withBoolean = desc.startsWith("(Ljava/lang/CharSequence;Z");
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            if (withBoolean) {
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                            } else {
                                mv.visitInsn(SWAP);
                            }
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.equals("stackFloats") || name.equals("stackInts")
                                        || name.equals("stackBytes") || name.equals("stackShorts")
                                        || name.equals("stackPointers")
                                                && (desc.startsWith("([Lorg/lwjgl/system/Pointer;")
                                                        || desc.startsWith("(Lorg/lwjgl/system/Pointer;")))) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            Type[] argTypes = Type.getArgumentTypes(desc);
                            if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 1) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 2) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 3) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP2_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                                mv.visitInsn(SWAP);
                                mv.visitInsn(POP);
                            } else {
                                if (debugTransform)
                                    System.out.println("[autostack]     failed to rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + ". Not yet implemented.");
                                /* Give up. Not possible without an additional local */
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf);
                            }
                        } else if (owner.equals(MEMORYSTACK) && name.equals("stackLongs")) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            Type[] argTypes = Type.getArgumentTypes(desc);
                            if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 1) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else {
                                if (debugTransform)
                                    System.out.println("[autostack]     failed to rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + ". Not yet implemented.");
                                /* Give up. Not possible without an additional local */
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf);
                            }
                        } else {
                            mv.visitMethodInsn(opcode, owner, name, desc, itf);
                        }
                    }

                    public void visitLineNumber(int line, Label start) {
                        mv.visitLineNumber(line, start);
                        lastLine = line;
                    }

                    public void visitCode() {
                        if (notransform) {
                            mv.visitCode();
                            return;
                        }
                        additionalLocals = newStack || checkStack ? 2 : 1;
                        replacedLocals = new Object[paramTypes.length + additionalLocals + (isStatic ? 0 : 1)];
                        if (!newStack && !checkStack) {
                            replacedLocals[replacedLocals.length - 1] = MEMORYSTACK;
                        } else {
                            replacedLocals[replacedLocals.length - 2] = MEMORYSTACK;
                            replacedLocals[replacedLocals.length - 1] = INTEGER;
                        }
                        if (!isStatic)
                            replacedLocals[0] = isConstructor ? TOP : className;
                        int var = isStatic ? 0 : 1;
                        for (int t = 0, i = var; t < paramTypes.length; t++, i++) {
                            Type type = paramTypes[t];
                            var += type.getSize();
                            switch (type.getSort()) {
                            case Type.INT:
                            case Type.BYTE:
                            case Type.BOOLEAN:
                            case Type.SHORT:
                            case Type.CHAR:
                                replacedLocals[i] = INTEGER;
                                break;
                            case Type.LONG:
                                replacedLocals[i] = LONG;
                                break;
                            case Type.FLOAT:
                                replacedLocals[i] = FLOAT;
                                break;
                            case Type.DOUBLE:
                                replacedLocals[i] = DOUBLE;
                                break;
                            case Type.OBJECT:
                            case Type.ARRAY:
                                replacedLocals[i] = type.getInternalName();
                                break;
                            default:
                                throw new AssertionError("Unhandled parameter type: " + type);
                            }
                        }
                        firstAdditionalLocal = var;
                        stackVarIndex = var;
                        stackPointerVarIndex = var + 1;
                        mv.visitCode();
                        if (newStack && !checkStack || checkStack) {
                            if (!memoryStackParam) {
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet",
                                        "()L" + MEMORYSTACK + ";", false);
                                mv.visitInsn(DUP);
                                mv.visitVarInsn(ASTORE, stackVarIndex);
                            } else {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                            }
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                            mv.visitVarInsn(ISTORE, stackPointerVarIndex);
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] save stack pointer [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString",
                                        "(I)Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            mv.visitLabel(tryLabel);
                            if (!memoryStackParam)
                                mv.visitFrame(F_APPEND, 2, new Object[] { MEMORYSTACK, INTEGER }, 0, null);
                            else
                                mv.visitFrame(F_APPEND, 1, new Object[] { INTEGER }, 0, null);
                        } else if (!newStack && !checkStack) {
                            if (!memoryStackParam) {
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet",
                                        "()L" + MEMORYSTACK + ";", false);
                                mv.visitVarInsn(ASTORE, stackVarIndex);
                            }
                            if (debugRuntime) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] current stack pointer is [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString",
                                        "(I)Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            mv.visitLabel(tryLabel);
                            if (!memoryStackParam)
                                mv.visitFrame(F_APPEND, 1, new Object[] { MEMORYSTACK }, 0, null);
                        }
                    }

                    public void visitMaxs(int maxStack, int maxLocals) {
                        if (notransform) {
                            mv.visitMaxs(maxStack, maxLocals);
                            return;
                        }
                        if (newStack && !checkStack || checkStack) {
                            mv.visitLabel(finallyLabel);
                            mv.visitFrame(F_FULL, replacedLocals.length, replacedLocals, 1,
                                    new Object[] { "java/lang/Throwable" });
                            mv.visitTryCatchBlock(tryLabel, finallyLabel, finallyLabel, null);
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] restore stack pointer because of throw [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitInsn(DUP);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString",
                                        "()Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn(
                                        "] at " + className.replace('/', '.') + "." + name + ":" + lastLine);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            if (newStack && !checkStack) {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false);
                            }
                            if (checkStack) {
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, className, "$checkStackWithThrowable$",
                                        "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", false);
                            }
                            mv.visitInsn(ATHROW);
                        }
                        mv.visitMaxs(-1, maxLocals + additionalLocals);
                    }
                };
                return mv;
            }
        }, 0);
        byte[] arr = cw.toByteArray();
        if (trace) {
            cr = new ClassReader(arr);
            cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), 0);
        }
        return arr;
    } catch (Throwable t) {
        t.printStackTrace();
        throw new RuntimeException(t);
    }
}

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Find the return type of the ActorSystem.dispatcher() method. It is ExecutionContextExecutor in
 * Akka 2.3 (Spark 1.2+) and ExecutionContext in Akka 2.2 (Spark < 1.2, which CDAP doesn't support,
 * however the Spark 1.5 in CDH 5.6. still has Akka 2.2, instead of 2.3).
 *
 * @return the return type of the ActorSystem.dispatcher() method or {@code null} if no such method
 *///  w  ww  .ja v  a  2 s  .  c o  m
@Nullable
private Type determineAkkaDispatcherReturnType() {
    try (InputStream is = openResource("akka/actor/ActorSystem.class")) {
        if (is == null) {
            return null;
        }
        final AtomicReference<Type> result = new AtomicReference<>();
        ClassReader cr = new ClassReader(is);
        cr.accept(new ClassVisitor(Opcodes.ASM5) {
            @Override
            public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                    String[] exceptions) {
                if (name.equals("dispatcher") && Type.getArgumentTypes(desc).length == 0) {
                    // Expected to be either ExecutionContext (akka 2.2, only in CDH spark)
                    // or ExecutionContextExecutor (akka 2.3, for open source, HDP spark).
                    Type returnType = Type.getReturnType(desc);
                    if (returnType.equals(EXECUTION_CONTEXT_TYPE)
                            || returnType.equals(EXECUTION_CONTEXT_EXECUTOR_TYPE)) {
                        result.set(returnType);
                    } else {
                        LOG.warn("Unsupported return type of ActorSystem.dispatcher(): {}",
                                returnType.getClassName());
                    }
                }
                return super.visitMethod(access, name, desc, signature, exceptions);
            }
        }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
        return result.get();
    } catch (IOException e) {
        LOG.warn("Failed to determine ActorSystem dispatcher() return type.", e);
        return null;
    }
}

From source file:co.cask.cdap.internal.app.runtime.artifact.ArtifactInspector.java

License:Apache License

/**
 * Detects if a class is annotated with {@link Plugin} without loading the class.
 *
 * @param className name of the class// w w w  .java  2 s .com
 * @param classLoader ClassLoader for loading the class file of the given class
 * @return true if the given class is annotated with {@link Plugin}
 */
private boolean isPlugin(String className, ClassLoader classLoader) {
    try (InputStream is = classLoader.getResourceAsStream(className.replace('.', '/') + ".class")) {
        if (is == null) {
            return false;
        }

        // Use ASM to inspect the class bytecode to see if it is annotated with @Plugin
        final boolean[] isPlugin = new boolean[1];
        ClassReader cr = new ClassReader(is);
        cr.accept(new ClassVisitor(Opcodes.ASM5) {
            @Override
            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                if (Plugin.class.getName().equals(Type.getType(desc).getClassName()) && visible) {
                    isPlugin[0] = true;
                }
                return super.visitAnnotation(desc, visible);
            }
        }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);

        return isPlugin[0];
    } catch (IOException e) {
        // If failed to open the class file, then it cannot be a plugin
        LOG.warn("Failed to open class file for {}", className, e);
        return false;
    }
}

From source file:co.cask.cdap.internal.app.runtime.service.http.HttpHandlerGenerator.java

License:Apache License

/**
 * Inspects the given type and copy/rewrite handler methods from it into the newly generated class.
 *
 * @param delegateType The user handler type
 * @param inspectType The type that needs to be inspected. It's either the delegateType or one of its parents
 *//*from  w ww  . ja  v a 2s . c  o m*/
private void inspectHandler(final TypeToken<?> delegateType, final TypeToken<?> inspectType,
        final String pathPrefix, final Type classType, final ClassWriter classWriter,
        final List<Class<?>> preservedClasses) throws IOException {
    Class<?> rawType = inspectType.getRawType();

    // Visit the delegate class, copy and rewrite handler method, with method body just do delegation
    try (InputStream sourceBytes = rawType.getClassLoader()
            .getResourceAsStream(Type.getInternalName(rawType) + ".class")) {
        ClassReader classReader = new ClassReader(sourceBytes);
        classReader.accept(new ClassVisitor(Opcodes.ASM5) {

            // Only need to visit @Path at the class level if we are inspecting the user handler class
            private final boolean inspectDelegate = delegateType.equals(inspectType);
            private boolean visitedPath = !inspectDelegate;

            @Override
            public void visit(int version, int access, String name, String signature, String superName,
                    String[] interfaces) {
                super.visit(version, access, name, signature, superName, interfaces);
            }

            @Override
            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                // Copy the class annotation if it is @Path. Only do it for one time
                Type type = Type.getType(desc);
                if (inspectDelegate && type.equals(Type.getType(Path.class))) {
                    visitedPath = true;
                    AnnotationVisitor annotationVisitor = classWriter.visitAnnotation(desc, visible);
                    return new AnnotationVisitor(Opcodes.ASM5, annotationVisitor) {
                        @Override
                        public void visit(String name, Object value) {
                            // "value" is the key for the Path annotation string.
                            if (name.equals("value")) {
                                super.visit(name, pathPrefix + value.toString());
                            } else {
                                super.visit(name, value);
                            }
                        }
                    };

                } else {
                    return super.visitAnnotation(desc, visible);
                }
            }

            @Override
            public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                    String[] exceptions) {
                // Create a class-level annotation with the prefix, if the user has not specified any class-level
                // annotation.
                if (!visitedPath) {
                    String pathDesc = Type.getType(Path.class).getDescriptor();
                    AnnotationVisitor annotationVisitor = classWriter.visitAnnotation(pathDesc, true);
                    annotationVisitor.visit("value", pathPrefix);
                    annotationVisitor.visitEnd();
                    visitedPath = true;
                }

                // Copy the method if it is public and annotated with one of the HTTP request method
                MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
                if (!Modifier.isPublic(access)) {
                    return mv;
                }
                return new HandlerMethodVisitor(delegateType, mv, desc, signature, access, name, exceptions,
                        classType, classWriter, preservedClasses);
            }
        }, ClassReader.SKIP_DEBUG);
    }
}

From source file:co.paralleluniverse.common.reflection.AnnotationUtil.java

License:Open Source License

private static boolean hasClassAnnotation(Class<? extends Annotation> annClass, ClassReader r) {
    // annotationName = annotationName.replace('.', '/');
    final String annDesc = Type.getDescriptor(annClass);
    final AtomicBoolean res = new AtomicBoolean(false);
    r.accept(new ClassVisitor(Opcodes.ASM4) {
        @Override//from   ww w  .j  a  v  a2  s . c  o  m
        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
        }

        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            if (desc.equals(annDesc))
                res.set(true);
            return null;
        }
    }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG);
    return res.get();
}

From source file:co.paralleluniverse.common.util.ExtendedStackTrace.java

License:Open Source License

protected /*Executable*/ Member getMethod(final ExtendedStackTraceElement este) {
    if (este.getDeclaringClass() == null)
        return null;
    Member[] ms = getMethods(este.getDeclaringClass());
    Member method = null;//from   w ww  .j av a2s  .c om

    for (Member m : ms) {
        if (este.getMethodName().equals(m.getName())) {
            if (method == null)
                method = m;
            else {
                method = null; // more than one match
                break;
            }
        }
    }
    if (method == null && este.getLineNumber() >= 0) {
        try {
            final AtomicReference<String> descriptor = new AtomicReference<>();
            ASMUtil.accept(este.getDeclaringClass(), ClassReader.SKIP_FRAMES, new ClassVisitor(Opcodes.ASM5) {
                @Override
                public MethodVisitor visitMethod(int access, String name, final String desc, String signature,
                        String[] exceptions) {
                    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
                    if (descriptor.get() == null && este.getMethodName().equals(name)) {
                        mv = new MethodVisitor(api, mv) {
                            int minLine = Integer.MAX_VALUE, maxLine = Integer.MIN_VALUE;

                            @Override
                            public void visitLineNumber(int line, Label start) {
                                if (line < minLine)
                                    minLine = line;
                                if (line > maxLine)
                                    maxLine = line;
                            }

                            @Override
                            public void visitEnd() {
                                if (minLine <= este.getLineNumber() && maxLine >= este.getLineNumber())
                                    descriptor.set(desc);
                                super.visitEnd();
                            }
                        };
                    }
                    return mv;
                }
            });

            if (descriptor.get() != null) {
                final String desc = descriptor.get();
                for (Member m : ms) {
                    if (este.getMethodName().equals(getName(m)) && desc.equals(getDescriptor(m))) {
                        method = m;
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    return method;
}

From source file:com.bit.learning.java.asm.UDFByteCodeVerifier.java

License:Apache License

public Set<String> verify(byte[] bytes) {
    final Set<String> errors = new TreeSet<String>(); // it's a TreeSet for unit tests
    ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5) {
        public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
            errors.add("field declared: " + name);
            return null;
        }/*from   w w w  .j av  a2  s  . c  o m*/

        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {

            if (true) {
                return new EvaluateVisitor(errors);
            }

            if ("<init>".equals(name)) {
                if (Opcodes.ACC_PUBLIC != access)
                    errors.add("constructor not public");
                // allowed constructor - JavaUDF(TypeCodec returnCodec, TypeCodec[] argCodecs)
                return new ConstructorVisitor(errors);
            }
            if ("<init>".equals(name) && CTOR_SIG.equals("()V")) {
                if (Opcodes.ACC_PUBLIC != access)
                    errors.add("constructor not public");
                // allowed constructor - JavaUDF(TypeCodec returnCodec, TypeCodec[] argCodecs)
                return new ConstructorVisitor(errors);
            }

            if ("evaluate".equals(name)) {
                if (Opcodes.ACC_PRIVATE == access) {
                    //This should be right, because user can use private evaluate method
                    errors.add("evaluate is private");
                }

                return new EvaluateVisitor(errors);
            }

            if ("executeImpl".equals(name) && "(ILjava/util/List;)Ljava/nio/ByteBuffer;".equals(desc)) {
                if (Opcodes.ACC_PROTECTED != access)
                    errors.add("executeImpl not protected");
                // the executeImpl method - ByteBuffer executeImpl(int protocolVersion, List<ByteBuffer> params)
                return new ExecuteImplVisitor(errors);
            }
            if ("<clinit>".equals(name)) {
                errors.add("static initializer declared");
            } else {
                //                    errors.add("not allowed method declared: " + name + desc);
                //                    return new ExecuteImplVisitor(errors);
            }
            return null;
        }

        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
            //                if (!JAVA_UDF_NAME.equals(superName)) {
            //                    errors.add("class does not extend " + JavaUDF.class.getName());
            //                }
            //                if (access != (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER)) {
            //                    errors.add("class not public final");
            //                }
            super.visit(version, access, name, signature, superName, interfaces);
        }

        public void visitInnerClass(String name, String outerName, String innerName, int access) {
            errors.add("class declared as inner class");
            super.visitInnerClass(name, outerName, innerName, access);
        }
    };

    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classVisitor, ClassReader.SKIP_DEBUG);

    return errors;
}

From source file:com.blade.kit.AsmKit.java

License:Apache License

/**
 *
 * <p>//  www .  j  a v a2  s .c om
 * ????
 * </p>
 *
 * @param m
 * @return
 */
public static String[] getMethodParamNames(final Method m) throws IOException {
    final String[] paramNames = new String[m.getParameterTypes().length];
    final String n = m.getDeclaringClass().getName();
    ClassReader cr = null;
    try {
        cr = new ClassReader(n);
    } catch (IOException e) {
        return null;
    }
    cr.accept(new ClassVisitor(Opcodes.ASM5) {
        @Override
        public MethodVisitor visitMethod(final int access, final String name, final String desc,
                final String signature, final String[] exceptions) {
            final Type[] args = Type.getArgumentTypes(desc);
            // ?????
            if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) {
                return super.visitMethod(access, name, desc, signature, exceptions);
            }
            MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions);
            return new MethodVisitor(Opcodes.ASM5, v) {
                @Override
                public void visitLocalVariable(String name, String desc, String signature, Label start,
                        Label end, int index) {
                    int i = index - 1;
                    // ???
                    // ???"this"???
                    if (Modifier.isStatic(m.getModifiers())) {
                        i = index;
                    }
                    if (i >= 0 && i < paramNames.length) {
                        paramNames[i] = name;
                    }
                    super.visitLocalVariable(name, desc, signature, start, end, index);
                }
            };
        }
    }, 0);
    return paramNames;
}

From source file:com.diffplug.gradle.autosgi.PluginMetadataGen.java

License:Apache License

/** Loads a class by its FQN.  If it's concrete and implements a plugin, then we'll call generatePlugin. */
private void maybeGeneratePlugin(Path path)
        throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
    ClassReader reader = new ClassReader(Files.readAllBytes(path));
    String plugClassName = asmToJava(reader.getClassName());
    Box.Nullable<String> socketClassName = Box.Nullable.ofNull();
    reader.accept(new ClassVisitor(Opcodes.ASM5) {
        @Override/*from   ww w  .  java  2s  .c o  m*/
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            if (PLUG.equals(desc)) {
                return new AnnotationVisitor(Opcodes.ASM5) {
                    @Override
                    public void visit(String name, Object value) {
                        Preconditions.checkArgument(name.equals("value"),
                                "For @Plug %s, expected 'value' but was '%s'", plugClassName, name);
                        Preconditions.checkArgument(socketClassName.get() == null,
                                "For @Plug %s, multiple annotations: '%s' and '%s'", plugClassName,
                                socketClassName.get(), value);
                        socketClassName.set(((org.objectweb.asm.Type) value).getClassName());
                    }
                };
            } else {
                return null;
            }
        }
    }, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE);
    if (socketClassName.get() == null) {
        return;
    }

    Class<?> plugClass = classLoader.loadClass(plugClassName);
    Class<?> socketClass = classLoader.loadClass(socketClassName.get());
    if (Modifier.isAbstract(plugClass.getModifiers())) {
        throw new IllegalArgumentException(
                "Class " + plugClass + " has @Plug(" + socketClass + ") but it is abstract.");
    }

    String osgiInfContent = generatePlugin(plugClass, socketClass);
    osgiInf.put(plugClass.getName(), osgiInfContent);
}

From source file:com.github.antag99.retinazer.weaver.WeaverMetadata.java

License:Open Source License

public void processMetadata() {
    final ClassVisitor classVisitor = new ClassVisitor(ASM5) {
        @Override/* ww  w .  j  a  v  a 2 s.  c  o  m*/
        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
            WeaverMetadata.this.internalName = name;
            WeaverMetadata.this.superName = name;
            WeaverMetadata.this.interfaces = interfaces != null ? interfaces : new String[0];

            boolean isComponent = false;

            for (String interfaceName : WeaverMetadata.this.interfaces) {
                isComponent |= interfaceName.equals(WeaverConstants.COMPONENT_NAME);
                isComponent |= weaver.getMetadata(interfaceName).componentMetadata != null;

                if (isComponent)
                    break;
            }

            boolean isSystem = false;

            if (!"java/lang/Object".equals(superName)) {
                isSystem |= superName.equals(WeaverConstants.ENTITY_SYSTEM_NAME);
                isSystem |= weaver.getMetadata(superName).systemMetadata != null;
            }

            if (isComponent) {
                cv = (componentMetadata = new ComponentMetadata(cv));
            }

            if (isSystem) {
                cv = (systemMetadata = new SystemMetadata(cv));
            }

            super.visit(version, access, name, signature, superName, interfaces);
        }
    };
    source.accept(classVisitor);
}