📄 classreferencefixer.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.editor;import proguard.classfile.*;import proguard.classfile.attribute.*;import proguard.classfile.attribute.annotation.*;import proguard.classfile.attribute.annotation.visitor.*;import proguard.classfile.attribute.visitor.*;import proguard.classfile.constant.*;import proguard.classfile.constant.visitor.ConstantVisitor;import proguard.classfile.util.*;import proguard.classfile.visitor.*;/** * This ClassVisitor fixes references of constant pool entries, fields, * methods, and attributes to classes whose names have changed. Descriptors * of member references are not updated yet. * * @see MemberReferenceFixer * @author Eric Lafortune */public class ClassReferenceFixerextends SimplifiedVisitorimplements ClassVisitor, ConstantVisitor, MemberVisitor, AttributeVisitor, InnerClassesInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, ElementValueVisitor{ private boolean ensureUniqueMemberNames; private ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(); /** * Creates a new ClassReferenceFixer. * @param ensureUniqueMemberNames specifies whether class members whose * descriptor changes should get new, unique * names, in order to avoid naming conflicts * with similar methods. */ public ClassReferenceFixer(boolean ensureUniqueMemberNames) { this.ensureUniqueMemberNames = ensureUniqueMemberNames; } // Implementations for ClassVisitor. public void visitProgramClass(ProgramClass programClass) { // Fix the constant pool. programClass.constantPoolEntriesAccept(this); // Fix class members. programClass.fieldsAccept(this); programClass.methodsAccept(this); // Fix the attributes. programClass.attributesAccept(this); } public void visitLibraryClass(LibraryClass libraryClass) { // Fix class members. libraryClass.fieldsAccept(this); libraryClass.methodsAccept(this); } // Implementations for MemberVisitor. public void visitProgramField(ProgramClass programClass, ProgramField programField) { // Has the descriptor changed? String descriptor = programField.getDescriptor(programClass); String newDescriptor = newDescriptor(descriptor, programField.referencedClass); if (!descriptor.equals(newDescriptor)) { // Update the descriptor. programField.u2descriptorIndex = constantPoolEditor.addUtf8Constant(programClass, newDescriptor); // Update the name, if requested. if (ensureUniqueMemberNames) { String name = programField.getName(programClass); String newName = newUniqueMemberName(name, descriptor); programField.u2nameIndex = constantPoolEditor.addUtf8Constant(programClass, newName); } } // Fix the attributes. programField.attributesAccept(programClass, this); } public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { // Has the descriptor changed? String descriptor = programMethod.getDescriptor(programClass); String newDescriptor = newDescriptor(descriptor, programMethod.referencedClasses); if (!descriptor.equals(newDescriptor)) { // Update the descriptor. programMethod.u2descriptorIndex = constantPoolEditor.addUtf8Constant(programClass, newDescriptor); // Update the name, if requested. if (ensureUniqueMemberNames) { String name = programMethod.getName(programClass); String newName = newUniqueMemberName(name, descriptor); programMethod.u2nameIndex = constantPoolEditor.addUtf8Constant(programClass, newName); } } // Fix the attributes. programMethod.attributesAccept(programClass, this); } public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) { // Has the descriptor changed? String descriptor = libraryField.getDescriptor(libraryClass); String newDescriptor = newDescriptor(descriptor, libraryField.referencedClass); // Update the descriptor. libraryField.descriptor = newDescriptor; } public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) { // Has the descriptor changed? String descriptor = libraryMethod.getDescriptor(libraryClass); String newDescriptor = newDescriptor(descriptor, libraryMethod.referencedClasses); // Update the descriptor. libraryMethod.descriptor = newDescriptor; } // Implementations for ConstantVisitor. public void visitAnyConstant(Clazz clazz, Constant constant) {} public void visitStringConstant(Clazz clazz, StringConstant stringConstant) { // Does the string refer to a class, due to a Class.forName construct? Clazz referencedClass = stringConstant.referencedClass; if (referencedClass != null) { // Reconstruct the new class name. String externalClassName = stringConstant.getString(clazz); String internalClassName = ClassUtil.internalClassName(externalClassName); String newInternalClassName = newClassName(internalClassName, referencedClass); // Update the String entry if required. if (!newInternalClassName.equals(internalClassName)) { String newExternalClassName = ClassUtil.externalClassName(newInternalClassName); // Refer to a new Utf8 entry. stringConstant.u2stringIndex = constantPoolEditor.addUtf8Constant((ProgramClass)clazz, newExternalClassName); } } } public void visitClassConstant(Clazz clazz, ClassConstant classConstant) { // Do we know the referenced class? Clazz referencedClass = classConstant.referencedClass; if (referencedClass != null) { // Has the class name changed? String className = classConstant.getName(clazz); String newClassName = newClassName(className, referencedClass); if (!className.equals(newClassName)) { // Refer to a new Utf8 entry. classConstant.u2nameIndex = constantPoolEditor.addUtf8Constant((ProgramClass)clazz, newClassName); } } } // Implementations for AttributeVisitor. public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) { // Fix the inner class names. innerClassesAttribute.innerClassEntriesAccept(clazz, this); } public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // Fix the attributes. codeAttribute.attributesAccept(clazz, method, this); } public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) { // Fix the types of the local variables. localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); } public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) { // Fix the signatures of the local variables. localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); } public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { // Compute the new signature. String signature = clazz.getString(signatureAttribute.u2signatureIndex); String newSignature = newDescriptor(signature, signatureAttribute.referencedClasses); if (!signature.equals(newSignature)) { signatureAttribute.u2signatureIndex = constantPoolEditor.addUtf8Constant((ProgramClass)clazz, newSignature); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -