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

📄 evaluationsimplifier.java

📁 ProGuard 是一个免费的 Java类文件的压缩
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* * 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.optimize.evaluation;import proguard.classfile.*;import proguard.classfile.attribute.*;import proguard.classfile.attribute.visitor.AttributeVisitor;import proguard.classfile.editor.CodeAttributeEditor;import proguard.classfile.instruction.*;import proguard.classfile.instruction.visitor.InstructionVisitor;import proguard.classfile.util.*;import proguard.evaluation.value.*;import proguard.optimize.info.SideEffectInstructionChecker;/** * This AttributeVisitor simplifies the code attributes that it visits, based * on partial evaluation. * * @author Eric Lafortune */public class EvaluationSimplifierextends      SimplifiedVisitorimplements   AttributeVisitor,             InstructionVisitor{    //*    private static final boolean DEBUG_RESULTS  = false;    private static final boolean DEBUG_ANALYSIS = false;    private static final boolean DEBUG          = false;    /*/    private static boolean DEBUG_RESULTS  = true;    private static boolean DEBUG_ANALYSIS = true;    private static boolean DEBUG          = true;    //*/    private InstructionVisitor extraPushInstructionVisitor;    private InstructionVisitor extraBranchInstructionVisitor;    private InstructionVisitor extraDeletedInstructionVisitor;    private InstructionVisitor extraAddedInstructionVisitor;    private PartialEvaluator             partialEvaluator;    private SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);    private CodeAttributeEditor          codeAttributeEditor          = new CodeAttributeEditor();    private boolean[] isNecessary  = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];    private boolean[] isSimplified = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];    /**     * Creates a new EvaluationSimplifier.     */    public EvaluationSimplifier()    {        this(new PartialEvaluator(), null, null, null, null);    }    /**     * Creates a new EvaluationSimplifier.     * @param partialEvaluator               the partial evaluator that will     *                                       execute the code and provide     *                                       information about the results.     * @param extraPushInstructionVisitor    an optional extra visitor for all     *                                       simplified push instructions.     * @param extraBranchInstructionVisitor  an optional extra visitor for all     *                                       simplified branch instructions.     * @param extraDeletedInstructionVisitor an optional extra visitor for all     *                                       deleted instructions.     * @param extraAddedInstructionVisitor   an optional extra visitor for all     *                                       added instructions.     */    public EvaluationSimplifier(PartialEvaluator   partialEvaluator,                                InstructionVisitor extraPushInstructionVisitor,                                InstructionVisitor extraBranchInstructionVisitor,                                InstructionVisitor extraDeletedInstructionVisitor,                                InstructionVisitor extraAddedInstructionVisitor)    {        this.partialEvaluator                      = partialEvaluator;        this.extraPushInstructionVisitor           = extraPushInstructionVisitor;        this.extraBranchInstructionVisitor         = extraBranchInstructionVisitor;        this.extraDeletedInstructionVisitor        = extraDeletedInstructionVisitor;        this.extraAddedInstructionVisitor          = extraAddedInstructionVisitor;    }    // Implementations for AttributeVisitor.    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)    {//        DEBUG = DEBUG_ANALYSIS = DEBUG_RESULTS =//            clazz.getName().equals("abc/Def") &&//            method.getName(clazz).equals("abc");        // TODO: Remove this when the partial evaluator has stabilized.        // Catch any unexpected exceptions from the actual visiting method.        try        {            // Process the code.            visitCodeAttribute0(clazz, method, codeAttribute);        }        catch (RuntimeException ex)        {            System.err.println("Unexpected error while optimizing after partial evaluation:");            System.err.println("  Class       = ["+clazz.getName()+"]");            System.err.println("  Method      = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");            System.err.println("  Exception   = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");            System.err.println("Not optimizing this method");            if (DEBUG)            {                throw ex;            }        }    }    public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)    {        if (DEBUG_RESULTS)        {            System.out.println();            System.out.println("Class "+ClassUtil.externalClassName(clazz.getName()));            System.out.println("Method "+ClassUtil.externalFullMethodDescription(clazz.getName(),                                                                                 0,                                                                                 method.getName(clazz),                                                                                 method.getDescriptor(clazz)));        }        // Initialize the necessary array.        initializeNecessary(codeAttribute);        // Evaluate the method.        partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);        int codeLength = codeAttribute.u4codeLength;        // Reset the code changes.        codeAttributeEditor.reset(codeLength);        // Replace any instructions that can be simplified.        if (DEBUG_ANALYSIS) System.out.println("Instruction simplification:");        codeAttribute.instructionsAccept(clazz, method, this);        // Mark all essential instructions that have been encountered as used.        if (DEBUG_ANALYSIS) System.out.println("Usage initialization: ");        // The invocation of the "super" or "this" <init> method inside a        // constructor is always necessary.        int superInitializationOffset = partialEvaluator.superInitializationOffset();        if (superInitializationOffset != PartialEvaluator.NONE)        {            if (DEBUG_ANALYSIS) System.out.print(superInitializationOffset+"(super.<init>),");            isNecessary[superInitializationOffset] = true;        }        // Also mark infinite loops and instructions that cause side effects.        int offset = 0;        do        {            if (partialEvaluator.isTraced(offset))            {                Instruction instruction = InstructionFactory.create(codeAttribute.code,                                                                    offset);                // Mark that the instruction is necessary if it is an infinite loop.                if (instruction.opcode == InstructionConstants.OP_GOTO &&                    partialEvaluator.branchTargets(offset).instructionOffsetValue().instructionOffset(0) == offset)                {                    if (DEBUG_ANALYSIS) System.out.print(offset+"(infinite loop),");                    isNecessary[offset] = true;                }                // Mark that the instruction is necessary if it has side effects.                else if (sideEffectInstructionChecker.hasSideEffects(clazz,                                                                     method,                                                                     codeAttribute,                                                                     offset,                                                                     instruction))                {                    if (DEBUG_ANALYSIS) System.out.print(offset+",");                    isNecessary[offset] = true;                }            }            offset++;        }        while (offset < codeLength);        if (DEBUG_ANALYSIS) System.out.println();        // Mark all other instructions on which the essential instructions        // depend. Instead of doing this recursively, we loop across all        // instructions, starting at the last one, and restarting at any        // higher, previously unmarked instruction that is being marked.        if (DEBUG_ANALYSIS) System.out.println("Usage marking:");        int lowestNecessaryOffset = codeLength;        offset = codeLength - 1;        do        {            int nextOffset = offset - 1;            // Update the lowest index of all marked instructions higher up.            if (isNecessary[offset])            {                lowestNecessaryOffset = offset;            }            // Check if this instruction is a branch origin from a branch that            // straddles some marked code.            nextOffset = markStraddlingBranches(offset,                                                partialEvaluator.branchTargets(offset),                                                true,                                                lowestNecessaryOffset,                                                nextOffset);            // Mark the producers on which this instruction depends.            if (isNecessary[offset] &&                !isSimplified[offset])            {                nextOffset = markProducers(offset, nextOffset);            }            // Update the lowest index of all marked instructions higher up.            if (isNecessary[offset])            {                lowestNecessaryOffset = offset;            }            // Check if this instruction is a branch target from a branch that            // straddles some marked code.            nextOffset = markStraddlingBranches(offset,                                                partialEvaluator.branchOrigins(offset),                                                false,                                                lowestNecessaryOffset,                                                nextOffset);            if (DEBUG_ANALYSIS)            {                if (nextOffset >= offset)                {                    System.out.println();                }            }            // Update the lowest index of all marked instructions higher up.            if (isNecessary[offset])            {                lowestNecessaryOffset = offset;            }            // Update the index of the instruction to be investigated next.            offset = nextOffset;        }        while (offset >= 0);        if (DEBUG_ANALYSIS) System.out.println();        // Insert pop instructions before unmarked popping instructions,        // if required to keep the stack consistent.        if (DEBUG_ANALYSIS) System.out.println("Unmarked pop fixing:");        // Also figure out the offset of the last dup/swap instruction.        int highestDupOffset = -1;        offset = codeLength - 1;        do        {            if (partialEvaluator.isTraced(offset) &&                !isNecessary[offset] &&                !isSimplified[offset])            {                Instruction instruction = InstructionFactory.create(codeAttribute.code,                                                                    offset);                // Make sure any non-dup/swap instructions are always consistent                // at this offset.                if (!isDupOrSwap(instruction))                {                    // Make sure any popping instructions are always                    // consistent after this offset.                    fixPopInstruction(clazz,                                      codeAttribute,                                      offset,                                      instruction);                }                else if (highestDupOffset < 0)                {

⌨️ 快捷键说明

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