StringSharer.java revision b72c5c2e5482cf10117b2b25f642f7616b2326c3
1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.classfile.util; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.Attribute; 25import proguard.classfile.attribute.visitor.AttributeVisitor; 26import proguard.classfile.constant.*; 27import proguard.classfile.constant.visitor.ConstantVisitor; 28import proguard.classfile.visitor.ClassVisitor; 29 30/** 31 * This ClassVisitor shares strings in the class files that it visits. 32 * 33 * @author Eric Lafortune 34 */ 35public class StringSharer 36extends SimplifiedVisitor 37implements ClassVisitor, 38 ConstantVisitor, 39 AttributeVisitor 40{ 41 // A fields acting as an argument for the visitor methods. 42 private String name; 43 private String type; 44 45 46 // Implementations for ClassVisitor. 47 48 public void visitProgramClass(ProgramClass programClass) 49 { 50 // Replace name strings in the constant pool by shared strings. 51 programClass.constantPoolEntriesAccept(this); 52 53 // Replace attribute name strings in the constant pool by internalized 54 // strings. 55 programClass.attributesAccept(this); 56 } 57 58 59 public void visitLibraryClass(LibraryClass libraryClass) 60 { 61 // Replace the super class name string by the shared name string. 62 Clazz superClass = libraryClass.superClass; 63 if (superClass != null) 64 { 65 libraryClass.superClassName = superClass.getName(); 66 } 67 } 68 69 70 // Implementations for ConstantVisitor. 71 72 73 public void visitAnyConstant(Clazz clazz, Constant constant) {} 74 75 76 public void visitAnyStringConstant(Clazz clazz, StringConstant stringConstant) 77 { 78 Member referencedMember = stringConstant.referencedMember; 79 if (referencedMember != null) 80 { 81 Clazz referencedClass = stringConstant.referencedClass; 82 83 // Put the actual class member's name in the class pool. 84 name = referencedMember.getName(referencedClass); 85 clazz.constantPoolEntryAccept(stringConstant.u2stringIndex, this); 86 } 87 } 88 89 90 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 91 { 92 Member referencedMember = refConstant.referencedMember; 93 if (referencedMember != null) 94 { 95 Clazz referencedClass = refConstant.referencedClass; 96 97 // Put the actual class member's name and type strings in the class 98 // pool. 99 name = referencedMember.getName(referencedClass); 100 type = referencedMember.getDescriptor(referencedClass); 101 clazz.constantPoolEntryAccept(refConstant.u2nameAndTypeIndex, this); 102 } 103 } 104 105 106 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 107 { 108 if (name != null) 109 { 110 // Put the actual class member's name and type strings in the class 111 // pool. 112 clazz.constantPoolEntryAccept(nameAndTypeConstant.u2nameIndex, this); 113 name = type; 114 clazz.constantPoolEntryAccept(nameAndTypeConstant.u2descriptorIndex, this); 115 } 116 } 117 118 119 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 120 { 121 Clazz referencedClass = classConstant.referencedClass; 122 if (referencedClass != null) 123 { 124 // Put the actual class's name string in the class pool. 125 name = referencedClass.getName(); 126 clazz.constantPoolEntryAccept(classConstant.u2nameIndex, this); 127 } 128 } 129 130 131 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 132 { 133 // Do we have a new string to put into this constant? 134 if (name != null) 135 { 136 // Replace the string, if it's actually the same. 137 if (name.equals(utf8Constant.getString())) 138 { 139 utf8Constant.setString(name); 140 } 141 142 name = null; 143 } 144 } 145 146 147 // Implementations for AttributeVisitor. 148 149 public void visitAnyAttribute(Clazz clazz, Attribute attribute) 150 { 151 // Put the internalized attribute's name string in the class pool. 152 name = attribute.getAttributeName(clazz).intern(); 153 clazz.constantPoolEntryAccept(attribute.u2attributeNameIndex, this); 154 } 155} 156