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

📄 classshrinker.java

📁 ProGuard 是一个免费的 Java类文件的压缩
💻 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.shrink;import proguard.classfile.*;import proguard.classfile.attribute.*;import proguard.classfile.attribute.annotation.*;import proguard.classfile.attribute.annotation.visitor.*;import proguard.classfile.attribute.visitor.AttributeVisitor;import proguard.classfile.constant.Constant;import proguard.classfile.editor.ConstantPoolRemapper;import proguard.classfile.util.SimplifiedVisitor;import proguard.classfile.visitor.*;/** * This ClassVisitor removes constant pool entries and class members that * are not marked as being used. * * @see UsageMarker * * @author Eric Lafortune */public class ClassShrinkerextends      SimplifiedVisitorimplements   ClassVisitor,             MemberVisitor,             AttributeVisitor,             AnnotationVisitor,             ElementValueVisitor{    private UsageMarker usageMarker;    private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];    private ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();    /**     * Creates a new ClassShrinker.     * @param usageMarker the usage marker that is used to mark the classes     *                    and class members.     */    public ClassShrinker(UsageMarker usageMarker)    {        this.usageMarker = usageMarker;    }    // Implementations for ClassVisitor.    public void visitProgramClass(ProgramClass programClass)    {        // Shrink the arrays for constant pool, interfaces, fields, methods,        // and class attributes.        programClass.u2interfacesCount =            shrinkConstantIndexArray(programClass.constantPool,                                     programClass.u2interfaces,                                     programClass.u2interfacesCount);        // Shrinking the constant pool also sets up an index map.        programClass.u2constantPoolCount =            shrinkConstantPool(programClass.constantPool,                               programClass.u2constantPoolCount);        programClass.u2fieldsCount =            shrinkArray(programClass.fields,                        programClass.u2fieldsCount);        programClass.u2methodsCount =            shrinkArray(programClass.methods,                        programClass.u2methodsCount);        programClass.u2attributesCount =            shrinkArray(programClass.attributes,                        programClass.u2attributesCount);        // Compact the remaining fields, methods, and attributes,        // and remap their references to the constant pool.        programClass.fieldsAccept(this);        programClass.methodsAccept(this);        programClass.attributesAccept(this);        // Remap all constant pool references.        constantPoolRemapper.setConstantIndexMap(constantIndexMap);        constantPoolRemapper.visitProgramClass(programClass);        // Compact the extra field pointing to the subclasses of this class.        programClass.subClasses =            shrinkToNewArray(programClass.subClasses);    }    public void visitLibraryClass(LibraryClass libraryClass)    {        // Library classes are left unchanged.        // Compact the extra field pointing to the subclasses of this class.        libraryClass.subClasses =            shrinkToNewArray(libraryClass.subClasses);    }    // Implementations for MemberVisitor.    public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)    {        // Shrink the attributes array.        programMember.u2attributesCount =            shrinkArray(programMember.attributes,                        programMember.u2attributesCount);        // Shrink any attributes.        programMember.attributesAccept(programClass, this);    }    // Implementations for AttributeVisitor.    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}    public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)    {        // Shrink the array of InnerClassesInfo objects.        innerClassesAttribute.u2classesCount =            shrinkArray(innerClassesAttribute.classes,                        innerClassesAttribute.u2classesCount);    }    public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)    {        // Sometimes, a class is still referenced (apparently as a dummy class),        // but its enclosing method is not. Then remove the reference to        // the enclosing method.        // E.g. the anonymous inner class javax.swing.JList$1 is defined inside        // a constructor of javax.swing.JList, but it is also referenced as a        // dummy argument in a constructor of javax.swing.JList$ListSelectionHandler.        if (enclosingMethodAttribute.referencedMethod != null &&            !usageMarker.isUsed(enclosingMethodAttribute.referencedMethod))        {            enclosingMethodAttribute.u2nameAndTypeIndex = 0;            enclosingMethodAttribute.referencedMethod = null;        }    }    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)    {        // Shrink the attributes array.        codeAttribute.u2attributesCount =            shrinkArray(codeAttribute.attributes,                        codeAttribute.u2attributesCount);    }    public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)    {        // Shrink the annotations array.        annotationsAttribute.u2annotationsCount =            shrinkArray(annotationsAttribute.annotations,                        annotationsAttribute.u2annotationsCount);        // Shrink the annotations themselves.        annotationsAttribute.annotationsAccept(clazz, this);    }    // Implementations for AnnotationVisitor.    public void visitAnnotation(Clazz clazz, Annotation annotation)    {        // Shrink the element values array.        annotation.u2elementValuesCount =            shrinkArray(annotation.elementValues,                        annotation.u2elementValuesCount);        // Shrink the element values themselves.        annotation.elementValuesAccept(clazz, this);    }    // Implementations for ElementValueVisitor.    public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {}    public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)    {        // Shrink the contained annotation.        annotationElementValue.annotationAccept(clazz, this);    }    public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)    {        // Shrink the element values array.        arrayElementValue.u2elementValuesCount =            shrinkArray(arrayElementValue.elementValues,                        arrayElementValue.u2elementValuesCount);        // Shrink the element values themselves.        arrayElementValue.elementValuesAccept(clazz, annotation, this);    }    // Small utility methods.    /**     * Removes all entries that are not marked as being used from the given     * constant pool.     * @return the new number of entries.     */    private int shrinkConstantPool(Constant[] constantPool, int length)    {        if (constantIndexMap.length < length)        {            constantIndexMap = new int[length];        }        int     counter = 1;        boolean isUsed  = false;        // Shift the used constant pool entries together.        for (int index = 1; index < length; index++)        {            constantIndexMap[index] = counter;            Constant constant = constantPool[index];            // Don't update the flag if this is the second half of a long entry.            if (constant != null)            {                isUsed = usageMarker.isUsed(constant);            }            if (isUsed)            {                constantPool[counter++] = constant;            }        }        // Clear the remaining constant pool elements.        for (int index = counter; index < length; index++)        {            constantPool[index] = null;        }        return counter;    }    /**     * Removes all indices that point to unused constant pool entries     * from the given array.     * @return the new number of indices.     */    private int shrinkConstantIndexArray(Constant[] constantPool, int[] array, int length)    {        int counter = 0;        // Shift the used objects together.        for (int index = 0; index < length; index++)        {            if (usageMarker.isUsed(constantPool[array[index]]))            {                array[counter++] = array[index];            }        }        // Clear the remaining array elements.        for (int index = counter; index < length; index++)        {            array[index] = 0;        }        return counter;    }    /**     * Removes all Clazz objects that are not marked as being used     * from the given array and returns the remaining objects in a an array     * of the right size.     * @return the new array.     */    private Clazz[] shrinkToNewArray(Clazz[] array)    {        if (array == null)        {            return null;        }        // Shrink the given array in-place.        int length = shrinkArray(array, array.length);        if (length == 0)        {            return null;        }        // Return immediately if the array is of right size already.        if (length == array.length)        {            return array;        }        // Copy the remaining elements into a new array of the right size.        Clazz[] newArray = new Clazz[length];        System.arraycopy(array, 0, newArray, 0, length);        return newArray;    }    /**     * Removes all VisitorAccepter objects that are not marked as being used     * from the given array.     * @return the new number of VisitorAccepter objects.     */    private int shrinkArray(VisitorAccepter[] array, int length)    {        int counter = 0;        // Shift the used objects together.        for (int index = 0; index < length; index++)        {            if (usageMarker.isUsed(array[index]))            {                array[counter++] = array[index];            }        }        // Clear the remaining array elements.        for (int index = counter; index < length; index++)        {            array[index] = null;        }        return counter;    }}

⌨️ 快捷键说明

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