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

📄 codeanalyzer.java

📁 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使
💻 JAVA
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License.  Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */package javassist.bytecode;/** * Utility for computing <code>max_stack</code>. */class CodeAnalyzer implements Opcode {    private ConstPool constPool;    private CodeAttribute codeAttr;    public CodeAnalyzer(CodeAttribute ca) {        codeAttr = ca;        constPool = ca.getConstPool();    }    public int computeMaxStack()        throws BadBytecode    {        /* d = stack[i]         * d == 0: not visited         * d > 0: the depth is d - 1 after executing the bytecode at i.         * d < 0: not visited. the initial depth (before execution) is 1 - d.         */        CodeIterator ci = codeAttr.iterator();        int length = ci.getCodeLength();        int[] stack = new int[length];        constPool = codeAttr.getConstPool();        initStack(stack, codeAttr);        boolean repeat;        do {            repeat = false;            for (int i = 0; i < length; ++i)                if (stack[i] < 0) {                    repeat = true;                    visitBytecode(ci, stack, i);                }        } while (repeat);        int maxStack = 1;        for (int i = 0; i < length; ++i)            if (stack[i] > maxStack)                maxStack = stack[i];        return maxStack - 1;    // the base is 1.    }    private void initStack(int[] stack, CodeAttribute ca) {        stack[0] = -1;        ExceptionTable et = ca.getExceptionTable();        if (et != null) {            int size = et.size();            for (int i = 0; i < size; ++i)                stack[et.handlerPc(i)] = -2;    // an exception is on stack        }    }    private void visitBytecode(CodeIterator ci, int[] stack, int index)        throws BadBytecode    {        int codeLength = stack.length;        ci.move(index);        int stackDepth = -stack[index];        while (ci.hasNext()) {            index = ci.next();            stack[index] = stackDepth;            int op = ci.byteAt(index);            stackDepth = visitInst(op, ci, index, stackDepth);            if (stackDepth < 1)                throw new BadBytecode("stack underflow at " + index);            if (processBranch(op, ci, index, codeLength, stack, stackDepth))                break;            if (isEnd(op))     // return, ireturn, athrow, ...                break;            if (op == JSR || op == JSR_W)                --stackDepth;        }    }    private boolean processBranch(int opcode, CodeIterator ci, int index,                                  int codeLength, int[] stack, int stackDepth)        throws BadBytecode    {        if ((IFEQ <= opcode && opcode <= IF_ACMPNE)                            || opcode == IFNULL || opcode == IFNONNULL) {            int target = index + ci.s16bitAt(index + 1);            checkTarget(index, target, codeLength, stack, stackDepth);        }        else {            int target, index2;            switch (opcode) {            case GOTO :                target = index + ci.s16bitAt(index + 1);                checkTarget(index, target, codeLength, stack, stackDepth);                return true;            case GOTO_W :                target = index + ci.s32bitAt(index + 1);                checkTarget(index, target, codeLength, stack, stackDepth);                return true;            case JSR :            case JSR_W :                if (opcode == JSR)                    target = index + ci.s16bitAt(index + 1);                else                    target = index + ci.s32bitAt(index + 1);                checkTarget(index, target, codeLength, stack, stackDepth);                if (stackDepth == 2)    // stackDepth is 1 if empty                    return false;                else                    throw new BadBytecode(                        "sorry, cannot compute this data flow due to JSR");            case RET :                if (stackDepth == 1)    // stackDepth is 1 if empty                    return true;                else                    throw new BadBytecode(                        "sorry, cannot compute this data flow due to RET");            case LOOKUPSWITCH :            case TABLESWITCH :                index2 = (index & ~3) + 4;                target = index + ci.s32bitAt(index2);                checkTarget(index, target, codeLength, stack, stackDepth);                if (opcode == LOOKUPSWITCH) {                    int npairs = ci.s32bitAt(index2 + 4);                    index2 += 12;                    for (int i = 0; i < npairs; ++i) {                        target = index + ci.s32bitAt(index2);                        checkTarget(index, target, codeLength,                                    stack, stackDepth);                        index2 += 8;                    }                }                else {                    int low = ci.s32bitAt(index2 + 4);                    int high = ci.s32bitAt(index2 + 8);                    int n = high - low + 1;                    index2 += 12;                    for (int i = 0; i < n; ++i) {                        target = index + ci.s32bitAt(index2);                        checkTarget(index, target, codeLength,                                    stack, stackDepth);                        index2 += 4;                    }                }                return true;    // always branch.            }        }        return false;   // may not branch.    }    private void checkTarget(int opIndex, int target, int codeLength,                             int[] stack, int stackDepth)        throws BadBytecode    {        if (target < 0 || codeLength <= target)            throw new BadBytecode("bad branch offset at " + opIndex);        int d = stack[target];        if (d == 0)            stack[target] = -stackDepth;        else if (d != stackDepth && d != -stackDepth)            throw new BadBytecode("verification error (" + stackDepth +                                  "," + d + ") at " + opIndex);    }                                 private static boolean isEnd(int opcode) {        return (IRETURN <= opcode && opcode <= RETURN) || opcode == ATHROW;     }    /**     * Visits an instruction.     */    private int visitInst(int op, CodeIterator ci, int index, int stack)        throws BadBytecode    {        String desc;        switch (op) {        case GETFIELD :            stack += getFieldSize(ci, index) - 1;            break;        case PUTFIELD :            stack -= getFieldSize(ci, index) + 1;            break;        case GETSTATIC :            stack += getFieldSize(ci, index);            break;        case PUTSTATIC :            stack -= getFieldSize(ci, index);            break;        case INVOKEVIRTUAL :        case INVOKESPECIAL :            desc = constPool.getMethodrefType(ci.u16bitAt(index + 1));            stack += Descriptor.dataSize(desc) - 1;            break;        case INVOKESTATIC :            desc = constPool.getMethodrefType(ci.u16bitAt(index + 1));            stack += Descriptor.dataSize(desc);            break;        case INVOKEINTERFACE :            desc = constPool.getInterfaceMethodrefType(                                            ci.u16bitAt(index + 1));            stack += Descriptor.dataSize(desc) - 1;            break;        case ATHROW :            stack = 1;      // the stack becomes empty (1 means no values).            break;        case MULTIANEWARRAY :            stack += 1 - ci.byteAt(index + 3);            break;        case WIDE :            op = ci.byteAt(index + 1);            // don't break here.        default :            stack += STACK_GROW[op];        }        return stack;    }    private int getFieldSize(CodeIterator ci, int index) {        String desc = constPool.getFieldrefType(ci.u16bitAt(index + 1));        return Descriptor.dataSize(desc);    }}

⌨️ 快捷键说明

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