📄 optimizer.java
字号:
/* * 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;import proguard.*;import proguard.evaluation.value.SpecificValueFactory;import proguard.classfile.*;import proguard.classfile.attribute.visitor.*;import proguard.classfile.constant.visitor.AllConstantVisitor;import proguard.classfile.editor.*;import proguard.classfile.instruction.visitor.*;import proguard.classfile.util.MethodLinker;import proguard.classfile.visitor.*;import proguard.optimize.evaluation.*;import proguard.optimize.peephole.*;import proguard.optimize.info.*;import java.io.IOException;/** * This class optimizes class pools according to a given configuration. * * @author Eric Lafortune */public class Optimizer{ private Configuration configuration; /** * Creates a new Optimizer. */ public Optimizer(Configuration configuration) { this.configuration = configuration; } /** * Performs optimization of the given program class pool. */ public boolean execute(ClassPool programClassPool, ClassPool libraryClassPool) throws IOException { // Check if we have at least some keep commands. if (configuration.keep == null && configuration.applyMapping == null && configuration.printMapping == null) { throw new IOException("You have to specify '-keep' options for the optimization step."); } // Create counters to count the numbers of optimizations. ClassCounter singleImplementationCounter = new ClassCounter(); ClassCounter finalClassCounter = new ClassCounter(); MemberCounter finalMethodCounter = new MemberCounter(); MemberCounter privateFieldCounter = new MemberCounter(); MemberCounter privateMethodCounter = new MemberCounter(); MemberCounter staticMethodCounter = new MemberCounter(); MemberCounter writeOnlyFieldCounter = new MemberCounter(); MemberCounter constantFieldCounter = new MemberCounter(); MemberCounter constantMethodCounter = new MemberCounter(); MemberCounter descriptorShrinkCounter = new MemberCounter(); MemberCounter parameterShrinkCounter = new MemberCounter(); MemberCounter variableShrinkCounter = new MemberCounter(); ExceptionCounter exceptionCounter = new ExceptionCounter(); InstructionCounter inliningCounter = new InstructionCounter(); InstructionCounter commonCodeCounter = new InstructionCounter(); InstructionCounter pushCounter = new InstructionCounter(); InstructionCounter branchCounter = new InstructionCounter(); InstructionCounter deletedCounter = new InstructionCounter(); InstructionCounter addedCounter = new InstructionCounter(); InstructionCounter peepholeCounter = new InstructionCounter(); // Clean up any old visitor info. programClassPool.classesAccept(new ClassCleaner()); libraryClassPool.classesAccept(new ClassCleaner()); // Link all methods that should get the same optimization info. programClassPool.classesAccept(new BottomClassFilter( new MethodLinker())); libraryClassPool.classesAccept(new BottomClassFilter( new MethodLinker())); // Create a visitor for marking the seeds. KeepMarker keepMarker = new KeepMarker(); ClassPoolVisitor classPoolvisitor = ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep, keepMarker, keepMarker, false, true, false); // Mark the seeds. programClassPool.accept(classPoolvisitor); libraryClassPool.accept(classPoolvisitor); // All library classes and library class members remain unchanged. libraryClassPool.classesAccept(keepMarker); libraryClassPool.classesAccept(new AllMemberVisitor(keepMarker)); // We also keep all classes that are involved in .class constructs. programClassPool.classesAccept(new AllMethodVisitor( new AllAttributeVisitor( new AllInstructionVisitor( new DotClassClassVisitor(keepMarker))))); // We also keep all classes that are involved in Class.forName constructs. programClassPool.classesAccept(new AllConstantVisitor( new ClassForNameClassVisitor(keepMarker))); // Attach some optimization info to all class members, so it can be // filled out later. programClassPool.classesAccept(new AllMemberVisitor( new MemberOptimizationInfoSetter())); if (configuration.assumeNoSideEffects != null) { // Create a visitor for marking methods that don't have any side effects. NoSideEffectMethodMarker noSideEffectMethodMarker = new NoSideEffectMethodMarker(); ClassPoolVisitor noClassPoolvisitor = ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.assumeNoSideEffects, null, noSideEffectMethodMarker); // Mark the seeds. programClassPool.accept(noClassPoolvisitor); libraryClassPool.accept(noClassPoolvisitor); } // Mark all interfaces that have single implementations. programClassPool.classesAccept(new SingleImplementationMarker(configuration.allowAccessModification, singleImplementationCounter)); // Make classes and methods final, as far as possible. programClassPool.classesAccept(new ClassFinalizer(finalClassCounter, finalMethodCounter)); // Mark all fields that are write-only. programClassPool.classesAccept(new AllMethodVisitor( new AllAttributeVisitor( new AllInstructionVisitor( new MultiInstructionVisitor( new InstructionVisitor[] { new ReadWriteFieldMarker(), }))))); // Mark all used parameters, including the 'this' parameters. programClassPool.classesAccept(new AllMethodVisitor( new OptimizationInfoMemberFilter( new ParameterUsageMarker()))); // Shrink the parameters in the method descriptors. programClassPool.classesAccept(new AllMethodVisitor( new OptimizationInfoMemberFilter( new MethodDescriptorShrinker(descriptorShrinkCounter)))); // Make all non-static methods that don't require the 'this' parameter static. programClassPool.classesAccept(new AllMethodVisitor( new OptimizationInfoMemberFilter( new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_STATIC, new MethodStaticizer(staticMethodCounter))))); // Remove all unused parameters and variables from the code, for // MethodDescriptorShrinker, MethodStaticizer. programClassPool.classesAccept(new AllMethodVisitor( new AllAttributeVisitor( new ParameterShrinker(parameterShrinkCounter)))); // Fix invocations of methods that have become static, for // MethodStaticizer. programClassPool.classesAccept(new AllMethodVisitor( new AllAttributeVisitor( new MethodInvocationFixer()))); // Fix all references to class members, for MethodDescriptorShrinker. programClassPool.classesAccept(new MemberReferenceFixer()); // Mark all methods that have side effects. programClassPool.accept(new SideEffectMethodMarker()); // Perform partial evaluation for filling out fields, method parameters, // and method return values. programClassPool.classesAccept(new AllMethodVisitor( new AllAttributeVisitor( new PartialEvaluator(new SpecificValueFactory(), new UnusedParameterInvocationUnit(new StoringInvocationUnit()), false)))); // Count the write-only fields, and the constant fields and methods. programClassPool.classesAccept(new MultiClassVisitor( new ClassVisitor[]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -