📄 usagemarker.java
字号:
/* $Id: UsageMarker.java,v 1.46.2.1 2006/01/16 22:57:56 eric Exp $ * * ProGuard -- shrinking, optimization, and obfuscation of Java class files. * * Copyright (c) 2002-2006 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.shrink;import proguard.classfile.*;import proguard.classfile.attribute.*;import proguard.classfile.attribute.annotation.*;import proguard.classfile.instruction.*;import proguard.classfile.visitor.*;/** * This ClassFileVisitor and MemberInfoVisitor recursively marks all * classes and class elements that are being used. * * @see ClassFileShrinker * * @author Eric Lafortune */public class UsageMarker implements ClassFileVisitor, MemberInfoVisitor, CpInfoVisitor, AttrInfoVisitor, InnerClassesInfoVisitor, ExceptionInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, ElementValueVisitor, InstructionVisitor{ // A visitor info flag to indicate the ProgramMemberInfo object is being used, // if its ClassFile can be determined as being used as well. private static final Object POSSIBLY_USED = new Object(); // A visitor info flag to indicate the visitor accepter is being used. private static final Object USED = new Object(); private MyInterfaceUsageMarker interfaceUsageMarker = new MyInterfaceUsageMarker(); private MyPossiblyUsedMethodUsageMarker possiblyUsedMethodUsageMarker = new MyPossiblyUsedMethodUsageMarker();// private ClassFileVisitor dynamicClassMarker =// new MultiClassFileVisitor(// new ClassFileVisitor[]// {// this,// new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,// ClassConstants.INTERNAL_METHOD_TYPE_INIT,// this)// }); // Implementations for ClassFileVisitor. public void visitProgramClassFile(ProgramClassFile programClassFile) { if (shouldBeMarkedAsUsed(programClassFile)) { // Mark this class. markAsUsed(programClassFile); markProgramClassBody(programClassFile); } } protected void markProgramClassBody(ProgramClassFile programClassFile) { // Mark this class's name. markCpEntry(programClassFile, programClassFile.u2thisClass); // Mark the superclass. if (programClassFile.u2superClass != 0) { markCpEntry(programClassFile, programClassFile.u2superClass); } // Give the interfaces preliminary marks. programClassFile.hierarchyAccept(false, false, true, false, interfaceUsageMarker); // Explicitly mark the <clinit> method. programClassFile.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, this); // Explicitly mark the parameterless <init> method. programClassFile.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT, ClassConstants.INTERNAL_METHOD_TYPE_INIT, this); // Process all methods that have already been marked as possibly used. programClassFile.methodsAccept(possiblyUsedMethodUsageMarker); // Mark the attributes. programClassFile.attributesAccept(this); } public void visitLibraryClassFile(LibraryClassFile libraryClassFile) { if (shouldBeMarkedAsUsed(libraryClassFile)) { markAsUsed(libraryClassFile); // We're not going to analyze all library code. We're assuming that // if this class is being used, all of its methods will be used as // well. We'll mark them as such (here and in all subclasses). // Mark the superclass. ClassFile superClass = libraryClassFile.superClass; if (superClass != null) { superClass.accept(this); } // Mark the interfaces. ClassFile[] interfaceClasses = libraryClassFile.interfaceClasses; if (interfaceClasses != null) { for (int i = 0; i < interfaceClasses.length; i++) { if (interfaceClasses[i] != null) { interfaceClasses[i].accept(this); } } } // Mark all methods. libraryClassFile.methodsAccept(this); } } /** * This ClassFileVisitor marks ProgramClassFile objects as possibly used, * and it visits LibraryClassFile objects with its outer UsageMarker. */ private class MyInterfaceUsageMarker implements ClassFileVisitor { public void visitProgramClassFile(ProgramClassFile programClassFile) { if (shouldBeMarkedAsPossiblyUsed(programClassFile)) { // We can't process the interface yet, because it might not // be required. Give it a preliminary mark. markAsPossiblyUsed(programClassFile); } } public void visitLibraryClassFile(LibraryClassFile libraryClassFile) { // Make sure all library interface methods are marked. UsageMarker.this.visitLibraryClassFile(libraryClassFile); } } private class MyPossiblyUsedMethodUsageMarker implements MemberInfoVisitor { // Implementations for MemberInfoVisitor. public void visitProgramFieldInfo(ProgramClassFile programClassFile, ProgramFieldInfo programFieldInfo) {} public void visitProgramMethodInfo(ProgramClassFile programClassFile, ProgramMethodInfo programMethodInfo) { // Has the method already been referenced? if (isPossiblyUsed(programMethodInfo)) { markAsUsed(programMethodInfo); // Mark the method body. markProgramMethodBody(programClassFile, programMethodInfo); // Note that, if the method has been marked as possibly used, // the method hierarchy has already been marked (cfr. below). } } public void visitLibraryFieldInfo(LibraryClassFile libraryClassFile, LibraryFieldInfo libraryFieldInfo) {} public void visitLibraryMethodInfo(LibraryClassFile libraryClassFile, LibraryMethodInfo libraryMethodInfo) {} } // Implementations for MemberInfoVisitor. public void visitProgramFieldInfo(ProgramClassFile programClassFile, ProgramFieldInfo programFieldInfo) { if (shouldBeMarkedAsUsed(programFieldInfo)) { markAsUsed(programFieldInfo); // Mark the name and descriptor. markCpEntry(programClassFile, programFieldInfo.u2nameIndex); markCpEntry(programClassFile, programFieldInfo.u2descriptorIndex); // Mark the attributes. programFieldInfo.attributesAccept(programClassFile, this); // Mark the classes referenced in the descriptor string. programFieldInfo.referencedClassesAccept(this); } } public void visitProgramMethodInfo(ProgramClassFile programClassFile, ProgramMethodInfo programMethodInfo) { if (shouldBeMarkedAsUsed(programMethodInfo)) { // Is the method's class used? if (isUsed(programClassFile)) { markAsUsed(programMethodInfo); // Mark the method body. markProgramMethodBody(programClassFile, programMethodInfo); // Mark the method hierarchy. markMethodHierarchy(programClassFile, programMethodInfo); } // Hasn't the method been marked as possibly being used yet? else if (shouldBeMarkedAsPossiblyUsed(programMethodInfo)) { // We can't process the method yet, because the class isn't // marked as being used (yet). Give it a preliminary mark. markAsPossiblyUsed(programMethodInfo); // Mark the method hierarchy. markMethodHierarchy(programClassFile, programMethodInfo); } } } public void visitLibraryFieldInfo(LibraryClassFile libraryClassFile, LibraryFieldInfo libraryFieldInfo) {} public void visitLibraryMethodInfo(LibraryClassFile libraryClassFile, LibraryMethodInfo libraryMethodInfo) { if (shouldBeMarkedAsUsed(libraryMethodInfo)) { markAsUsed(libraryMethodInfo); // Mark the method hierarchy. markMethodHierarchy(libraryClassFile, libraryMethodInfo); } } protected void markProgramMethodBody(ProgramClassFile programClassFile, ProgramMethodInfo programMethodInfo) { // Mark the name and descriptor. markCpEntry(programClassFile, programMethodInfo.u2nameIndex); markCpEntry(programClassFile, programMethodInfo.u2descriptorIndex); // Mark the attributes. programMethodInfo.attributesAccept(programClassFile, this); // Mark the classes referenced in the descriptor string. programMethodInfo.referencedClassesAccept(this); } /** * Marks the hierarchy of implementing or overriding methods corresponding * to the given method, if any. */ protected void markMethodHierarchy(ClassFile classFile, MethodInfo methodInfo) { classFile.methodImplementationsAccept(methodInfo, false, this); } // Implementations for CpInfoVisitor. public void visitIntegerCpInfo(ClassFile classFile, IntegerCpInfo integerCpInfo) { if (shouldBeMarkedAsUsed(integerCpInfo)) { markAsUsed(integerCpInfo); } } public void visitLongCpInfo(ClassFile classFile, LongCpInfo longCpInfo) { if (shouldBeMarkedAsUsed(longCpInfo)) { markAsUsed(longCpInfo); } } public void visitFloatCpInfo(ClassFile classFile, FloatCpInfo floatCpInfo) { if (shouldBeMarkedAsUsed(floatCpInfo)) { markAsUsed(floatCpInfo); } } public void visitDoubleCpInfo(ClassFile classFile, DoubleCpInfo doubleCpInfo) { if (shouldBeMarkedAsUsed(doubleCpInfo)) { markAsUsed(doubleCpInfo); } } public void visitStringCpInfo(ClassFile classFile, StringCpInfo stringCpInfo) { if (shouldBeMarkedAsUsed(stringCpInfo)) { markAsUsed(stringCpInfo); markCpEntry(classFile, stringCpInfo.u2stringIndex); // Mark the referenced class and its parameterless constructor, // if the string is being used in a Class.forName construct. //stringCpInfo.referencedClassAccept(dynamicClassMarker); // Mark the referenced class. stringCpInfo.referencedClassAccept(this); } } public void visitUtf8CpInfo(ClassFile classFile, Utf8CpInfo utf8CpInfo) { if (shouldBeMarkedAsUsed(utf8CpInfo)) { markAsUsed(utf8CpInfo); } } public void visitFieldrefCpInfo(ClassFile classFile, FieldrefCpInfo fieldrefCpInfo) { visitRefCpInfo(classFile, fieldrefCpInfo); } public void visitInterfaceMethodrefCpInfo(ClassFile classFile, InterfaceMethodrefCpInfo interfaceMethodrefCpInfo) { visitRefCpInfo(classFile, interfaceMethodrefCpInfo); } public void visitMethodrefCpInfo(ClassFile classFile, MethodrefCpInfo methodrefCpInfo) { visitRefCpInfo(classFile, methodrefCpInfo); } private void visitRefCpInfo(ClassFile classFile, RefCpInfo methodrefCpInfo) { if (shouldBeMarkedAsUsed(methodrefCpInfo)) { markAsUsed(methodrefCpInfo); markCpEntry(classFile, methodrefCpInfo.u2classIndex); markCpEntry(classFile, methodrefCpInfo.u2nameAndTypeIndex); // When compiled with "-target 1.2" or higher, the class or // interface actually containing the referenced method may be // higher up the hierarchy. Make sure it's marked, in case it // isn't used elsewhere. methodrefCpInfo.referencedClassAccept(this); // Mark the referenced method itself. methodrefCpInfo.referencedMemberInfoAccept(this); } } public void visitClassCpInfo(ClassFile classFile, ClassCpInfo classCpInfo) { if (shouldBeMarkedAsUsed(classCpInfo)) { markAsUsed(classCpInfo); markCpEntry(classFile, classCpInfo.u2nameIndex); // Mark the referenced class itself. classCpInfo.referencedClassAccept(this); } } public void visitNameAndTypeCpInfo(ClassFile classFile, NameAndTypeCpInfo nameAndTypeCpInfo) { if (shouldBeMarkedAsUsed(nameAndTypeCpInfo)) { markAsUsed(nameAndTypeCpInfo); markCpEntry(classFile, nameAndTypeCpInfo.u2nameIndex); markCpEntry(classFile, nameAndTypeCpInfo.u2descriptorIndex); } } // Implementations for AttrInfoVisitor.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -