⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adviceadapter.java

📁 asm的源码包 并且包含英文的文档
💻 JAVA
📖 第 1 页 / 共 2 页
字号:

                case SWAP: {
                    Object o1 = popValue();
                    Object o2 = popValue();
                    pushValue(o1);
                    pushValue(o2);
                }
                    break;
            }
        } else {
            switch (opcode) {
                case RETURN:
                case IRETURN:
                case FRETURN:
                case ARETURN:
                case LRETURN:
                case DRETURN:
                case ATHROW:
                    onMethodExit(opcode);
                    break;
            }
        }
        mv.visitInsn(opcode);
    }

    public void visitVarInsn(final int opcode, final int var) {
        super.visitVarInsn(opcode, var);

        if (constructor) {
            switch (opcode) {
                case ILOAD:
                case FLOAD:
                    pushValue(OTHER);
                    break;
                case LLOAD:
                case DLOAD:
                    pushValue(OTHER);
                    pushValue(OTHER);
                    break;
                case ALOAD:
                    pushValue(var == 0 ? THIS : OTHER);
                    break;
                case ASTORE:
                case ISTORE:
                case FSTORE:
                    popValue();
                    break;
                case LSTORE:
                case DSTORE:
                    popValue();
                    popValue();
                    break;
            }
        }
    }

    public void visitFieldInsn(
        final int opcode,
        final String owner,
        final String name,
        final String desc)
    {
        mv.visitFieldInsn(opcode, owner, name, desc);

        if (constructor) {
            char c = desc.charAt(0);
            boolean longOrDouble = c == 'J' || c == 'D';
            switch (opcode) {
                case GETSTATIC:
                    pushValue(OTHER);
                    if (longOrDouble) {
                        pushValue(OTHER);
                    }
                    break;
                case PUTSTATIC:
                    popValue();
                    if (longOrDouble) {
                        popValue();
                    }
                    break;
                case PUTFIELD:
                    popValue();
                    if (longOrDouble) {
                        popValue();
                        popValue();
                    }
                    break;
                // case GETFIELD:
                default:
                    if (longOrDouble) {
                        pushValue(OTHER);
                    }
            }
        }
    }

    public void visitIntInsn(final int opcode, final int operand) {
        mv.visitIntInsn(opcode, operand);

        if (constructor && opcode!=NEWARRAY) {
            pushValue(OTHER);
        }
    }

    public void visitLdcInsn(final Object cst) {
        mv.visitLdcInsn(cst);

        if (constructor) {
            pushValue(OTHER);
            if (cst instanceof Double || cst instanceof Long) {
                pushValue(OTHER);
            }
        }
    }

    public void visitMultiANewArrayInsn(final String desc, final int dims) {
        mv.visitMultiANewArrayInsn(desc, dims);

        if (constructor) {
            for (int i = 0; i < dims; i++) {
                popValue();
            }
            pushValue(OTHER);
        }
    }

    public void visitTypeInsn(final int opcode, final String name) {
        mv.visitTypeInsn(opcode, name);

        // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
        if (constructor && opcode == NEW) {
            pushValue(OTHER);
        }
    }

    public void visitMethodInsn(
        final int opcode,
        final String owner,
        final String name,
        final String desc)
    {
        mv.visitMethodInsn(opcode, owner, name, desc);

        if (constructor) {
            Type[] types = Type.getArgumentTypes(desc);
            for (int i = 0; i < types.length; i++) {
                popValue();
                if (types[i].getSize() == 2) {
                    popValue();
                }
            }
            switch (opcode) {
                // case INVOKESTATIC:
                // break;

                case INVOKEINTERFACE:
                case INVOKEVIRTUAL:
                    popValue(); // objectref
                    break;

                case INVOKESPECIAL:
                    Object type = popValue(); // objectref
                    if (type == THIS && !superInitialized) {
                        onMethodEnter();
                        superInitialized = true;
                        // once super has been initialized it is no longer
                        // necessary to keep track of stack state
                        constructor = false;
                    }
                    break;
            }

            Type returnType = Type.getReturnType(desc);
            if (returnType != Type.VOID_TYPE) {
                pushValue(OTHER);
                if (returnType.getSize() == 2) {
                    pushValue(OTHER);
                }
            }
        }
    }

    public void visitJumpInsn(final int opcode, final Label label) {
        mv.visitJumpInsn(opcode, label);

        if (constructor) {
            switch (opcode) {
                case IFEQ:
                case IFNE:
                case IFLT:
                case IFGE:
                case IFGT:
                case IFLE:
                case IFNULL:
                case IFNONNULL:
                    popValue();
                    break;

                case IF_ICMPEQ:
                case IF_ICMPNE:
                case IF_ICMPLT:
                case IF_ICMPGE:
                case IF_ICMPGT:
                case IF_ICMPLE:
                case IF_ACMPEQ:
                case IF_ACMPNE:
                    popValue();
                    popValue();
                    break;

                case JSR:
                    pushValue(OTHER);
                    break;
            }
            addBranch(label);
        }
    }

    public void visitLookupSwitchInsn(
        final Label dflt,
        final int[] keys,
        final Label[] labels)
    {
        mv.visitLookupSwitchInsn(dflt, keys, labels);

        if (constructor) {
            popValue();
            addBranches(dflt, labels);
        }
    }

    public void visitTableSwitchInsn(
        final int min,
        final int max,
        final Label dflt,
        final Label[] labels)
    {
        mv.visitTableSwitchInsn(min, max, dflt, labels);

        if (constructor) {
            popValue();
            addBranches(dflt, labels);
        }
    }

    private void addBranches(final Label dflt, final Label[] labels) {
        addBranch(dflt);
        for (int i = 0; i < labels.length; i++) {
            addBranch(labels[i]);
        }
    }

    private void addBranch(final Label label) {
        if (branches.containsKey(label)) {
            return;
        }
        ArrayList frame = new ArrayList();
        frame.addAll(stackFrame);
        branches.put(label, frame);
    }

    private Object popValue() {
        return stackFrame.remove(stackFrame.size() - 1);
    }

    private Object peekValue() {
        return stackFrame.get(stackFrame.size() - 1);
    }

    private void pushValue(final Object o) {
        stackFrame.add(o);
    }

    /**
     * Called at the beginning of the method or after super class class call in
     * the constructor. <br><br>
     * 
     * <i>Custom code can use or change all the local variables, but should not
     * change state of the stack.</i>
     */
    protected abstract void onMethodEnter();

    /**
     * Called before explicit exit from the method using either return or throw.
     * Top element on the stack contains the return value or exception instance.
     * For example:
     * 
     * <pre>
     *   public void onMethodExit(int opcode) {
     *     if(opcode==RETURN) {
     *         visitInsn(ACONST_NULL);
     *     } else if(opcode==ARETURN || opcode==ATHROW) {
     *         dup();
     *     } else {
     *         if(opcode==LRETURN || opcode==DRETURN) {
     *             dup2();
     *         } else {
     *             dup();
     *         }
     *         box(Type.getReturnType(this.methodDesc));
     *     }
     *     visitIntInsn(SIPUSH, opcode);
     *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
     *   }
     *
     *   // an actual call back method
     *   public static void onExit(int opcode, Object param) {
     *     ...
     * </pre>
     * 
     * <br><br>
     * 
     * <i>Custom code can use or change all the local variables, but should not
     * change state of the stack.</i>
     * 
     * @param opcode one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN,
     *        DRETURN or ATHROW
     * 
     */
    protected abstract void onMethodExit(int opcode);

    // TODO onException, onMethodCall

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -