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

📄 codeattributeeditor.java

📁 ProGuard 是一个免费的 Java类文件的压缩
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* * ProGuard -- shrinking, optimization, obfuscation, and preverification *             of Java bytecode. * * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu) * * This program 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 program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; 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.*;import proguard.classfile.attribute.preverification.visitor.*;import proguard.classfile.attribute.visitor.*;import proguard.classfile.instruction.*;import proguard.classfile.instruction.visitor.InstructionVisitor;import proguard.classfile.util.SimplifiedVisitor;/** * This AttributeVisitor accumulates specified changes to code, and then applies * these accumulated changes to the code attributes that it visits. * * @author Eric Lafortune */public class CodeAttributeEditorextends      SimplifiedVisitorimplements   AttributeVisitor,             InstructionVisitor,             ExceptionInfoVisitor,             StackMapFrameVisitor,             VerificationTypeVisitor,             LineNumberInfoVisitor,             LocalVariableInfoVisitor,             LocalVariableTypeInfoVisitor{    private int     codeLength;    private boolean modified;    private boolean simple;    /*private*/public Instruction[]    preInsertions  = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];    /*private*/public Instruction[]    replacements   = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];    /*private*/public Instruction[]    postInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];    private boolean[]        deleted = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];    private int[]   instructionOffsetMap = new int[ClassConstants.TYPICAL_CODE_LENGTH];    private int     newOffset;    private boolean lengthIncreased;    private int expectedStackMapFrameOffset;    private StackSizeUpdater    stackSizeUpdater    = new StackSizeUpdater();    private VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();    private InstructionWriter   instructionWriter   = new InstructionWriter();    /**     * Resets the accumulated code changes.     * @param codeLength the length of the code that will be edited next.     */    public void reset(int codeLength)    {        this.codeLength = codeLength;        // Try to reuse the previous arrays.        if (preInsertions.length < codeLength)        {            preInsertions  = new Instruction[codeLength];            replacements   = new Instruction[codeLength];            postInsertions = new Instruction[codeLength];            deleted        = new boolean[codeLength];        }        else        {            for (int index = 0; index < codeLength; index++)            {                preInsertions[index]  = null;                replacements[index]   = null;                postInsertions[index] = null;                deleted[index]        = false;            }        }        modified = false;        simple   = true;    }    /**     * Remembers to place the given instruction right before the instruction     * at the given offset.     * @param instructionOffset the offset of the instruction.     * @param instruction       the new instruction.     */    public void insertBeforeInstruction(int instructionOffset, Instruction instruction)    {        if (instructionOffset < 0 ||            instructionOffset >= codeLength)        {            throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");        }        preInsertions[instructionOffset] = instruction;        modified = true;        simple   = false;    }    /**     * Remembers to replace the instruction at the given offset by the given     * instruction.     * @param instructionOffset the offset of the instruction to be replaced.     * @param instruction       the new instruction.     */    public void replaceInstruction(int instructionOffset, Instruction instruction)    {        if (instructionOffset < 0 ||            instructionOffset >= codeLength)        {            throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");        }        replacements[instructionOffset] = instruction;        modified = true;    }    /**     * Remembers to place the given instruction right after the instruction     * at the given offset.     * @param instructionOffset the offset of the instruction.     * @param instruction       the new instruction.     */    public void insertAfterInstruction(int instructionOffset, Instruction instruction)    {        if (instructionOffset < 0 ||            instructionOffset >= codeLength)        {            throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");        }        postInsertions[instructionOffset] = instruction;        modified = true;        simple   = false;    }    /**     * Remembers to delete the instruction at the given offset.     * @param instructionOffset the offset of the instruction to be deleted.     */    public void deleteInstruction(int instructionOffset)    {        if (instructionOffset < 0 ||            instructionOffset >= codeLength)        {            throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");        }        deleted[instructionOffset] = true;        modified = true;        simple   = false;    }    /**     * Remembers not to delete the instruction at the given offset.     * @param instructionOffset the offset of the instruction not to be deleted.     */    public void undeleteInstruction(int instructionOffset)    {        if (instructionOffset < 0 ||            instructionOffset >= codeLength)        {            throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");        }        deleted[instructionOffset] = false;    }    /**     * Returns whether the instruction at the given offset has been modified     * in any way.     */    public boolean isModified(int instructionOffset)    {        return preInsertions[instructionOffset]  != null ||               replacements[instructionOffset]   != null ||               postInsertions[instructionOffset] != null ||               deleted[instructionOffset];    }    // Implementations for AttributeVisitor.    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)    {        // Avoid doing any work if nothing is changing anyway.        if (!modified)        {            return;        }        // Check if we can perform a faster simple replacement of instructions.        if (canPerformSimpleReplacements(codeAttribute))        {            // Simply overwrite the instructions.            performSimpleReplacements(codeAttribute);            // Update the maximum stack size and local variable frame size.            stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);            variableSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);        }        else        {            // Move and remap the instructions.            codeAttribute.u4codeLength =                updateInstructions(clazz, method, codeAttribute);            // Remap the exception table.            codeAttribute.exceptionsAccept(clazz, method, this);            // Remove exceptions with empty code blocks.            codeAttribute.u2exceptionTableLength =                removeEmptyExceptions(codeAttribute.exceptionTable,                                      codeAttribute.u2exceptionTableLength);            // 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);            // Make sure instructions are widened if necessary.            instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);        }    }    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.        localVariableTableAttribute.u2localVariableTableLength =            removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,                                      localVariableTableAttribute.u2localVariableTableLength,                                      codeAttribute.u2maxLocals);    }    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)    {        // Remap all local variable table entries.        localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);

⌨️ 快捷键说明

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