Package com.foursquare.heapaudit

Source Code of com.foursquare.heapaudit.HeapMethod

package com.foursquare.heapaudit;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class HeapMethod extends HeapUtil implements MethodVisitor {

    public HeapMethod(MethodVisitor mv,
                      String source,
                      String methodId,
                      boolean suppressAuditing,
                      boolean debugAuditing,
                      boolean traceAuditing,
                      boolean injectRecorder) {

        this.mv = new MethodAdapter(mv);

        this.source = source;

        this.id = methodId;

        this.suppressAuditing = suppressAuditing;

        this.debugAuditing = debugAuditing;

        this.traceAuditing = traceAuditing;

        this.injectRecorder = injectRecorder && HeapUtil.inject(id);

        log(debugAuditing,
            "\t{ # METHOD " + id);

    }

    public final MethodAdapter mv;

    private final String source;

    private final String id;

    private boolean suppressAuditing;

    private final boolean debugAuditing;

    private final boolean traceAuditing;

    private final boolean injectRecorder;

    public HeapVariables lvs = null;

    public AnnotationVisitor visitAnnotationDefault() {

        log(debugAuditing,
            "\t\tvisitAnnotationDefault()");

        return mv.visitAnnotationDefault();

    }

    public AnnotationVisitor visitAnnotation(String desc,
                                             boolean visible) {

        log(debugAuditing,
            "\t\tvisitAnnotation(" + desc + ", " + visible + ")");

        if (desc.equals("Lcom/foursquare/heapaudit/HeapRecorder$Suppress;")) {

            suppressAuditing = true;

        }

        return mv.visitAnnotation(desc,
                                  visible);

    }

    public AnnotationVisitor visitParameterAnnotation(int parameter,
                                                      String desc,
                                                      boolean visible) {

        log(debugAuditing,
            "\t\tvisitParameterAnnotation()");

        return mv.visitParameterAnnotation(parameter,
                                           desc,
                                           visible);
    }

    public void visitAttribute(Attribute attr) {

        log(debugAuditing,
            "\t\tvisitAttribute(" + attr.type + ")");

        mv.visitAttribute(attr);

    }

    public void visitCode() {

        mv.visitCode();

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitCode() " + source + ":" + id);

        visitEnter();

    }

    public void visitFrame(int type,
                           int nLocal,
                           Object[] local,
                           int nStack,
                           Object[] stack) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitFrame()");

        mv.visitFrame(type,
                      nLocal,
                      local,
                      nStack,
                      stack);

    }

    public void visitInsn(int opcode) {

         log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitInsn(" + opcode + ")");

        switch (opcode) {

        case Opcodes.ARETURN:

        case Opcodes.DRETURN:

        case Opcodes.FRETURN:

        case Opcodes.IRETURN:

        case Opcodes.LRETURN:

        case Opcodes.RETURN:

            visitReturn();

            break;

        }

        mv.visitInsn(opcode);

    }

    public void visitLdcInsn(Object cst) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitLdcInsn(" + cst + ")");

        mv.visitLdcInsn(cst);

    }

    public void visitIincInsn(int var,
                              int increment) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitIincInsn()");

        mv.visitIincInsn(var,
                         increment);

    }

    public void visitVarInsn(int opcode,
                             int var) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitVarInsn(" + opcode + ", " + var + ")");

        switch (opcode) {

        case Opcodes.RET:

            visitReturn();

            break;

        }

        mv.visitVarInsn(opcode,
                        var);

    }

    public void visitFieldInsn(int opcode,
                               String owner,
                               String name,
                               String desc) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitFieldInsn(" + opcode + ", " + owner + ", " + name + ", " + desc + ")");

        mv.visitFieldInsn(opcode,
                          owner,
                          name,
                          desc);

    }

    public void visitIntInsn(int opcode,
                             int operand) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitIntInsn(" + opcode + ", " + operand + ")");

        switch (opcode) {

        case Opcodes.NEWARRAY:

            HeapNEWARRAY.before(debugAuditing,
                                traceAuditing,
                                mv,
                                operand);

            break;

        default:

        }

        mv.visitIntInsn(opcode,
                        operand);

        switch (opcode) {

        case Opcodes.NEWARRAY:

            HeapNEWARRAY.after(debugAuditing,
                               traceAuditing,
                               mv,
                               operand);

            break;

        default:

        }

    }

    private int allocating = 0;

    public void visitTypeInsn(int opcode,
                              String type) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitTypeInsn(" + opcode + ", " + type + ")");

        switch (opcode) {

        case Opcodes.NEW:

            ++allocating;

            break;

        case Opcodes.ANEWARRAY:

            HeapANEWARRAY.before(debugAuditing,
                                 traceAuditing,
                                 mv,
                                 type);

            break;

        default:

        }

        mv.visitTypeInsn(opcode,
                         type);

        switch (opcode) {

        case Opcodes.ANEWARRAY:

            HeapANEWARRAY.after(debugAuditing,
                                traceAuditing,
                                mv,
                                type);

            break;

        default:

        }

    }

    public void visitMethodInsn(int opcode,
                                String owner,
                                String name,
                                String signature) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitMethodInsn(" + opcode + ", " + owner + ", " + name + ", " + signature + ")");

        switch (opcode) {

        case Opcodes.INVOKESPECIAL:

            if (name.equals("<init>")) {

                if (allocating > 0) {

                    HeapNEW.before(debugAuditing,
                                   traceAuditing,
                                   mv,
                                   lvs,
                                   signature);

                }

            }
            else if (owner.equals("java/lang/Thread") &&
                     name.equals("init")) {

                if (HeapSettings.threaded) {

                    HeapThreaded.before(debugAuditing,
                                        traceAuditing,
                                        mv,
                                        lvs,
                                        signature);

                }

            }

            break;

        case Opcodes.INVOKESTATIC:

            if (owner.equals("java/lang/reflect/Array") &&
                name.equals("newInstance")) {

                HeapNEWINSTANCE.beforeX(debugAuditing,
                                        traceAuditing,
                                        mv);

            }

            break;

        case Opcodes.INVOKEVIRTUAL:

            if (name.equals("newInstance")) {

                if (owner.equals("java/lang/Class") &&
                    signature.equals("()Ljava/lang/Object;")) {

                    HeapNEWINSTANCE.before(debugAuditing,
                                           traceAuditing,
                                           mv);

                }

            }

            break;

        default:

        }

        mv.visitMethodInsn(opcode,
                           owner,
                           name,
                           signature);

        switch (opcode) {

        case Opcodes.INVOKESPECIAL:

            if (name.equals("<init>")) {

                if (allocating > 0) {

                    --allocating;

                    HeapNEW.after(debugAuditing,
                                  traceAuditing,
                                  mv,
                                  owner);

                }

            }
            else if (owner.equals("java/lang/Object") &&
                     name.equals("clone")) {

                HeapCLONEOBJECT.after(debugAuditing,
                                      traceAuditing,
                                      mv);

            }
            else if (owner.equals("java/lang/Thread") &&
                     name.equals("init")) {

                if (HeapSettings.threaded) {

                    HeapThreaded.after(debugAuditing,
                                       traceAuditing,
                                       mv);

                }

            }

            break;

        case Opcodes.INVOKESTATIC:

            if (owner.equals("java/lang/reflect/Array") &&
                name.equals("newInstance")) {

                if (signature.equals("(Ljava/lang/Class;I)Ljava/lang/Object;")) {

                    HeapNEWINSTANCE.after(debugAuditing,
                                          traceAuditing,
                                          mv);

                }
                else if (signature.equals("(Ljava/lang/Class;[I)Ljava/lang/Object;")) {

                    HeapNEWINSTANCE.afterY(debugAuditing,
                                           traceAuditing,
                                           mv);

                }

            }

            break;

        case Opcodes.INVOKEVIRTUAL:

            if (name.equals("newInstance")) {

                if (owner.equals("java/lang/Class") &&
                    signature.equals("()Ljava/lang/Object;")) {

                    HeapNEWINSTANCE.after(debugAuditing,
                                          traceAuditing,
                                          mv);

                }
                else if (owner.equals("java/lang/reflect/Constructor") &&
                         signature.equals("([Ljava/lang/Object;)Ljava/lang/Object;")) {

                    HeapCLONEOBJECT.after(debugAuditing,
                                          traceAuditing,
                                          mv);

                }

            }
            else if (owner.startsWith("[") &&
                     name.equals("clone")) {

                HeapCLONEARRAY.after(debugAuditing,
                                     traceAuditing,
                                     mv,
                                     owner);

            }

            break;

        default:

        }

    }

    public void visitMultiANewArrayInsn(String desc,
                                        int dims) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitMultiANewArrayInsn(" + desc + ", " + dims + ")");

        mv.visitMultiANewArrayInsn(desc,
                                   dims);

        HeapMULTIARRAY.after(debugAuditing,
                             traceAuditing,
                             mv,
                             desc);

    }

    public void visitJumpInsn(int opcode,
                              Label label) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitJumpInsn(" + opcode + ", " + label + ")");

        mv.visitJumpInsn(opcode,
                         label);

    }

    public void visitLookupSwitchInsn(Label dlft,
                                      int[] keys,
                                      Label[] labels) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitLookupSwitchInsn()");

        mv.visitLookupSwitchInsn(dlft,
                                 keys,
                                 labels);

    }

    public void visitTableSwitchInsn(int min,
                                     int max,
                                     Label dlft,
                                     Label[] labels) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitTableSwitchInsn()");

        mv.visitTableSwitchInsn(min,
                                max,
                                dlft,
                                labels);

    }

    public void visitLabel(Label label) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitLabel() " + source + ":" + label);

        mv.visitLabel(label);

    }

    public void visitTryCatchBlock(Label start,
                                   Label end,
                                   Label handler,
                                   String type) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitTryCatchBlock()");

        mv.visitTryCatchBlock(start,
                              end,
                              handler,
                              type);

    }


    public void visitLocalVariable(String name,
                                   String desc,
                                   String signature,
                                   Label start,
                                   Label end,
                                   int index) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitLocalVariable(" + name + ")");

        mv.visitLocalVariable(name,
                              desc,
                              signature,
                              start,
                              end,
                              index);

    }

    public void visitLineNumber(int line,
                                Label start) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitLineNumber() " + source + ":" + start + "#" + line);

        mv.visitLineNumber(line,
                           start);

    }

    public void visitMaxs(int maxStack,
                          int maxLocals) {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitMaxs(" + maxStack + ", " + maxLocals + ")");

        lvs.declare();

        mv.visitMaxs(maxStack,
                     maxLocals);

    }

    public void visitEnd() {

        log(debugAuditing,
            traceAuditing,
            mv,
            "\t\tvisitEnd()\n\t}");

        mv.visitEnd();

    }

    private void visitEnter() {

        if (suppressAuditing) {

            // STACK: [...]
            mv.visitMethodInsn(Opcodes.INVOKESTATIC,
                               "com/foursquare/heapaudit/HeapRecorder",
                               "suppress",
                               "()Ljava/lang/Object;");
            // STACK: [...|context]
            mv.visitInsn(Opcodes.POP);
            // STACK: [...]

        }
        else if (injectRecorder) {

            // STACK: [...]
            mv.visitLdcInsn(id);
            // STACK: [...|id]
            mv.visitMethodInsn(Opcodes.INVOKESTATIC,
                               "com/foursquare/heapaudit/HeapUtil",
                               "register",
                               "(Ljava/lang/String;)V");
            // STACK: [...]

        }

    }

    private void visitReturn() {

        if (suppressAuditing) {

            // STACK: [...]
            mv.visitMethodInsn(Opcodes.INVOKESTATIC,
                               "com/foursquare/heapaudit/HeapRecorder",
                               "unwind",
                               "()Ljava/lang/Object;");
            // STACK: [...|context]
            mv.visitInsn(Opcodes.POP);
            // STACK: [...]

        }
        else if (injectRecorder) {

            // STACK: [...]
            mv.visitLdcInsn(id);
            // STACK: [...|id]
            mv.visitMethodInsn(Opcodes.INVOKESTATIC,
                               "com/foursquare/heapaudit/HeapUtil",
                               "unregister",
                               "(Ljava/lang/String;)V");
            // STACK: [...]

        }

    }

}
TOP

Related Classes of com.foursquare.heapaudit.HeapMethod

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.