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

📄 classclassfornamereferenceinitializer.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.classfile.util;import proguard.classfile.*;import proguard.classfile.attribute.CodeAttribute;import proguard.classfile.constant.*;import proguard.classfile.instruction.*;import proguard.classfile.instruction.visitor.InstructionVisitor;import proguard.classfile.constant.visitor.ConstantVisitor;import proguard.util.ClassNameListMatcher;/** * This InstructionVisitor initializes any special <code>Class.forName</code> or * <code>.class</code> references of all classes it visits. More specifically, * it fills out the references of String constant pool entries that refer to a * class in the program class pool or in the library class pool. * <p> * It optionally prints notes if on usage of * <code>(SomeClass)Class.forName(variable).newInstance()</code>. * <p> * The class hierarchy must be initialized before using this visitor. * * @see ClassReferenceInitializer * * @author Eric Lafortune */public class ClassClassForNameReferenceInitializerextends      SimplifiedVisitorimplements   InstructionVisitor,             ConstantVisitor{    private ClassPool            programClassPool;    private ClassPool            libraryClassPool;    private WarningPrinter       notePrinter;    private ClassNameListMatcher noteExceptionMatcher;    // Fields to remember the previous StringConstant and MethodRefConstant objects    // while visiting all instructions (to find Class.forName, class$, and    // Class.newInstance invocations, and possible class casts afterwards).    private int ldcStringConstantIndex              = -1;    private int invokestaticMethodRefConstantIndex  = -1;    private int invokevirtualMethodRefConstantIndex = -1;    private ClassForNameChecker     classForNameChecker     = new ClassForNameChecker();    private ClassNewInstanceChecker classNewInstanceChecker = new ClassNewInstanceChecker();    /**     * Creates a new ClassClassForNameReferenceInitializer that optionally     * prints notes, with optional class specifications for which never to     * print notes.     */    public ClassClassForNameReferenceInitializer(ClassPool            programClassPool,                                                 ClassPool            libraryClassPool,                                                 WarningPrinter       notePrinter,                                                 ClassNameListMatcher noteExceptionMatcher)    {        this.programClassPool     = programClassPool;        this.libraryClassPool     = libraryClassPool;        this.notePrinter          = notePrinter;        this.noteExceptionMatcher = noteExceptionMatcher;    }    // Implementations for InstructionVisitor.    public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)    {        // Nothing interesting; just forget any stored indices.        clearConstantPoolIndices();    }    public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)    {        // Nothing interesting; just forget any stored indices.        clearConstantPoolIndices();    }    public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)    {        // Nothing interesting; just forget any stored indices.        clearConstantPoolIndices();    }    public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)    {        // Nothing interesting; just forget any stored indices.        clearConstantPoolIndices();    }    public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)    {        // Just ignore generic instructions and reset the constant pool indices.        switch (variableInstruction.opcode)        {            case InstructionConstants.OP_ICONST_0:            case InstructionConstants.OP_ICONST_1:                // Still remember any loaded string; this instruction may be                // setting up the second argument for class$(String, boolean).                break;            default:                ldcStringConstantIndex = -1;                break;        }        invokestaticMethodRefConstantIndex  = -1;        invokevirtualMethodRefConstantIndex = -1;    }    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)    {        int currentConstantIndex = constantInstruction.constantIndex;        switch (constantInstruction.opcode)        {            case InstructionConstants.OP_LDC:            case InstructionConstants.OP_LDC_W:                // Are we loading a constant String?                int currentTag = clazz.getTag(currentConstantIndex);                if (currentTag == ClassConstants.CONSTANT_String)                {                    // Remember it; it might be the argument of                    // Class.forName(String), class$(String), or                    // class$(String, boolean).                    ldcStringConstantIndex = currentConstantIndex;                }                else                {                    ldcStringConstantIndex = -1;                }                invokestaticMethodRefConstantIndex  = -1;                invokevirtualMethodRefConstantIndex = -1;                break;            case InstructionConstants.OP_INVOKESTATIC:                // Are we invoking a static method that might have a constant                // String argument?                if (ldcStringConstantIndex > 0)                {                    // Check whether the method reference points to Class.forName.                    if (classForNameChecker.check(clazz, currentConstantIndex))                    {                        // Fill out the class reference in the String.                        clazz.constantPoolEntryAccept(ldcStringConstantIndex, this);                    }                    // We've dealt with this invocation, so we can forget about it.                    invokestaticMethodRefConstantIndex = -1;                }                else                {                    // Remember it; it might still be a Class.forName with a                    // variable String argument.                    invokestaticMethodRefConstantIndex = currentConstantIndex;                }                ldcStringConstantIndex              = -1;                invokevirtualMethodRefConstantIndex = -1;                break;            case InstructionConstants.OP_INVOKEVIRTUAL:                // Are we invoking a virtual method right after a static method?                if (invokestaticMethodRefConstantIndex > 0)                {                    // Remember it; it might be Class.newInstance after a Class.forName.                    invokevirtualMethodRefConstantIndex = currentConstantIndex;                }                else                {                    invokestaticMethodRefConstantIndex  = -1;                    invokevirtualMethodRefConstantIndex = -1;                }                ldcStringConstantIndex = -1;                break;            case InstructionConstants.OP_CHECKCAST:                // Are we checking a cast right after a static method and a                // virtual method?                if (invokestaticMethodRefConstantIndex  > 0 &&                    invokevirtualMethodRefConstantIndex > 0)                {                    // Check whether the first method reference points to Class.forName,                    // and the second method reference to Class.newInstance.                    if (classForNameChecker.check(clazz, invokestaticMethodRefConstantIndex) &&                        classNewInstanceChecker.check(clazz, invokevirtualMethodRefConstantIndex))                    {                        // Note which class is being cast to.                        clazz.constantPoolEntryAccept(currentConstantIndex, this);                    }                }                // We've handled the special case; forget about the indices.                clearConstantPoolIndices();                break;            default:                // Nothing interesting; just forget any stored indices.                clearConstantPoolIndices();                break;        }    }    // Implementations for ConstantVisitor.    /**     * Fills out the link to the referenced Clazz.     */    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)    {        // Save a reference to the corresponding class.        String externalClassName = stringConstant.getString(clazz);        String internalClassName = ClassUtil.internalClassName(externalClassName);        stringConstant.referencedClass = findClass(internalClassName);    }    /**     * Prints out a note about the class cast to this class, if applicable.     */    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)    {        if (notePrinter != null &&            (noteExceptionMatcher == null ||             !noteExceptionMatcher.matches(classConstant.getName(clazz))))        {            notePrinter.print("Note: " +                              ClassUtil.externalClassName(clazz.getName()) +                              " calls '(" +                              ClassUtil.externalClassName(classConstant.getName(clazz)) +                              ")Class.forName(variable).newInstance()'");        }    }    // Small utility methods.    /**     * Clears all references to the constant pool.     */    private void clearConstantPoolIndices()    {        ldcStringConstantIndex              = -1;        invokestaticMethodRefConstantIndex  = -1;        invokevirtualMethodRefConstantIndex = -1;    }    /**     * Returns the class with the given name, either for the program class pool     * or from the library class pool, or <code>null</code> if it can't be found.     */    private Clazz findClass(String name)    {        // First look for the class in the program class pool.        Clazz clazz = programClassPool.getClass(name);        // Otherwise look for the class in the library class pool.        if (clazz == null)        {            clazz = libraryClassPool.getClass(name);        }        return clazz;    }}

⌨️ 快捷键说明

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