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

📄 codeattributecomposer.java

📁 ProGuard 是一个免费的 Java类文件的压缩
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * ProGuard -- shrinking, optimization, obfuscation, and preverification *             of Java bytecode. * * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu) * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package proguard.classfile.editor;import proguard.classfile.*;import proguard.classfile.attribute.*;import proguard.classfile.attribute.preverification.visitor.*;import proguard.classfile.attribute.preverification.*;import proguard.classfile.attribute.visitor.*;import proguard.classfile.instruction.*;import proguard.classfile.instruction.visitor.InstructionVisitor;import proguard.classfile.util.SimplifiedVisitor;/** * This AttributeVisitor accumulates instructions and exceptions, and then * copies them into code attributes that it visits. * * @author Eric Lafortune */public class CodeAttributeComposerextends      SimplifiedVisitorimplements   AttributeVisitor,             InstructionVisitor,             ExceptionInfoVisitor,             StackMapFrameVisitor,             VerificationTypeVisitor,             LineNumberInfoVisitor,             LocalVariableInfoVisitor,             LocalVariableTypeInfoVisitor{    //*    private static final boolean DEBUG = false;    /*/    public  static       boolean DEBUG = true;    //*/    private static final int MAXIMUM_LEVELS = 32;    private int maximumCodeLength;    private int codeLength;    private int exceptionTableLength;    private int level = -1;    private byte[]  code                  = new byte[ClassConstants.TYPICAL_CODE_LENGTH];    private int[]   oldInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];    private int[]   codeFragmentOffsets   = new int[MAXIMUM_LEVELS];    private int[]   codeFragmentLengths   = new int[MAXIMUM_LEVELS];    private int[][] instructionOffsetMap  = new int[MAXIMUM_LEVELS][ClassConstants.TYPICAL_CODE_LENGTH];    private ExceptionInfo[] exceptionTable   =  new ExceptionInfo[ClassConstants.TYPICAL_EXCEPTION_TABLE_LENGTH];    private int expectedStackMapFrameOffset;    private StackSizeUpdater    stackSizeUpdater    = new StackSizeUpdater();    private VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();    /**     * Starts a new code definition.     */    public void reset()    {        maximumCodeLength    = 0;        codeLength           = 0;        exceptionTableLength = 0;        level                = -1;    }    /**     * Starts a new code fragment. Branch instructions that are added are     * assumed to be relative within such code fragments.     * @param maximumCodeFragmentLength the maximum length of the code that will     *                                  be added as part of this fragment.     */    public void beginCodeFragment(int maximumCodeFragmentLength)    {        level++;        if (level >= MAXIMUM_LEVELS)        {            throw new IllegalArgumentException("Maximum number of code fragment levels exceeded ["+level+"]");        }        // Make sure there is sufficient space for adding the code fragment.        maximumCodeLength += maximumCodeFragmentLength;        if (code.length < maximumCodeLength)        {            byte[] newCode = new byte[maximumCodeLength];            System.arraycopy(code, 0, newCode, 0, codeLength);            code = newCode;            int[] newOldInstructionOffsets = new int[maximumCodeLength];            System.arraycopy(oldInstructionOffsets, 0, newOldInstructionOffsets, 0, codeLength);            oldInstructionOffsets = newOldInstructionOffsets;        }        // Try to reuse the previous array for this code fragment.        if (instructionOffsetMap[level].length <= maximumCodeFragmentLength)        {            instructionOffsetMap[level] = new int[maximumCodeFragmentLength + 1];        }        // Remember the location of the code fragment.        codeFragmentOffsets[level] = codeLength;        codeFragmentLengths[level] = maximumCodeFragmentLength;    }    /**     * Appends the given instruction with the given old offset.     * @param oldInstructionOffset the old offset of the instruction, to which     *                             branches and other references in the current     *                             code fragment are pointing.     * @param instruction          the instruction to be appended.     */    public void appendInstruction(int         oldInstructionOffset,                                  Instruction instruction)    {        if (DEBUG)        {            System.out.println("["+codeLength+"] <- "+"          ".substring(0, 2*level)+instruction.toString(oldInstructionOffset));        }        // Remember the old offset of the appended instruction.        oldInstructionOffsets[codeLength] = oldInstructionOffset;        // Write the instruction.        instruction.write(code, codeLength);        // Fill out the new offset of the appended instruction.        instructionOffsetMap[level][oldInstructionOffset] = codeLength;        // Continue appending at the next instruction offset.        codeLength += instruction.length(codeLength);    }    /**     * Appends the given label with the given old offset.     * @param oldInstructionOffset the old offset of the label, to which     *                             branches and other references in the current     *                             code fragment are pointing.     */    public void appendLabel(int oldInstructionOffset)    {        if (DEBUG)        {            System.out.println("["+codeLength+"] <- "+"          ".substring(0, 2*level)+"["+oldInstructionOffset+"] (label)");        }        // Fill out the new offset of the appended instruction.        instructionOffsetMap[level][oldInstructionOffset] = codeLength;    }    /**     * Appends the given exception to the exception table.     * @param exceptionInfo the exception to be appended.     */    public void appendException(ExceptionInfo exceptionInfo)    {        if (DEBUG)        {            System.out.print("         "+"          ".substring(0, 2*level)+"Exception ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+": "+exceptionInfo.u2handlerPC+"]");        }        // Remap the exception right away.        visitExceptionInfo(null, null, null, exceptionInfo);        if (DEBUG)        {            System.out.println(" -> ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+": "+exceptionInfo.u2handlerPC+"]");        }        // Don't add the exception if its instruction range is empty.        if (exceptionInfo.u2startPC == exceptionInfo.u2endPC)        {            if (DEBUG)            {                System.out.println("         "+"          ".substring(0, 2*level)+"  (not added because of empty instruction range)");            }            return;        }        // Make sure there is sufficient space in the exception table.        if (exceptionTable.length <= exceptionTableLength)        {            ExceptionInfo[] newExceptionTable = new ExceptionInfo[exceptionTableLength+1];            System.arraycopy(exceptionTable, 0, newExceptionTable, 0, exceptionTableLength);            exceptionTable = newExceptionTable;        }        // Add the exception.        exceptionTable[exceptionTableLength++] = exceptionInfo;    }    /**     * Wraps up the current code fragment, continuing with the previous one on     * the stack.     */    public void endCodeFragment()    {        if (level < 0)        {            throw new IllegalArgumentException("Code fragment not begun ["+level+"]");        }        // Remap the instructions of the code fragment.        int instructionOffset = codeFragmentOffsets[level];        while (instructionOffset < codeLength)        {            // Get the next instruction.            Instruction instruction = InstructionFactory.create(code, instructionOffset);            // Does this instruction still have to be remapped?            if (oldInstructionOffsets[instructionOffset] >= 0)            {                // Adapt the instruction for its new offset.                instruction.accept(null, null, null, instructionOffset, this);                // Write the instruction back.                instruction.write(code, instructionOffset);                // Don't remap this instruction again.                oldInstructionOffsets[instructionOffset] = -1;            }            // Continue remapping at the next instruction offset.            instructionOffset += instruction.length(instructionOffset);        }        // Correct the estimated maximum code length, now that we know the        // actual length of this code fragment.        maximumCodeLength += codeLength - codeFragmentOffsets[level] -                             codeFragmentLengths[level];        level--;    }    // Implementations for AttributeVisitor.    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)    {        if (DEBUG)        {            System.out.println("CodeAttributeComposer: putting results in ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");        }        if (level != -1)        {            throw new IllegalArgumentException("Code fragment not ended ["+level+"]");        }        level++;        // Make sure the code attribute has sufficient space for the composed        // code.        if (codeAttribute.u4codeLength < codeLength)        {            codeAttribute.code = new byte[codeLength];        }        // Copy the composed code over into the code attribute.        codeAttribute.u4codeLength = codeLength;        System.arraycopy(code, 0, codeAttribute.code, 0, codeLength);        // Remove exceptions with empty code blocks (done before).        //exceptionTableLength =        //    removeEmptyExceptions(exceptionTable, exceptionTableLength);        // Make sure the exception table has sufficient space for the composed        // exceptions.        if (codeAttribute.exceptionTable.length < exceptionTableLength)        {            codeAttribute.exceptionTable = new ExceptionInfo[exceptionTableLength];        }        // Copy the exception table.        codeAttribute.u2exceptionTableLength = exceptionTableLength;        System.arraycopy(exceptionTable, 0, codeAttribute.exceptionTable, 0, exceptionTableLength);        // Update the maximum stack size and local variable frame size.        stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);        variableSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);        // Remap  the line number table and the local variable table.        codeAttribute.attributesAccept(clazz, method, this);        // Remap the exception table.        //codeAttribute.exceptionsAccept(clazz, method, this);        // Remove exceptions with empty code blocks (done before).        //codeAttribute.u2exceptionTableLength =        //    removeEmptyExceptions(codeAttribute.exceptionTable,        //                          codeAttribute.u2exceptionTableLength);        level--;    }    public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)    {        // Remap all stack map entries.        expectedStackMapFrameOffset = -1;        stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);    }    public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)    {        // Remap all stack map table entries.        expectedStackMapFrameOffset = 0;        stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);    }    public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)    {        // Remap all line number table entries.        lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);        // Remove line numbers with empty code blocks.        lineNumberTableAttribute.u2lineNumberTableLength =           removeEmptyLineNumbers(lineNumberTableAttribute.lineNumberTable,                                  lineNumberTableAttribute.u2lineNumberTableLength,                                  codeAttribute.u4codeLength);    }    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)    {        // Remap all local variable table entries.        localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);        // Remove local variables with empty code blocks.

⌨️ 快捷键说明

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