1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric (at) 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 */ 21 package proguard.obfuscate; 22 23 import proguard.classfile.*; 24 import proguard.classfile.constant.Constant; 25 import proguard.classfile.editor.ConstantPoolRemapper; 26 import proguard.classfile.visitor.ClassVisitor; 27 28 29 /** 30 * This ClassVisitor removes UTF-8 constant pool entries that are not marked 31 * as being used. 32 * 33 * @see Utf8UsageMarker 34 * 35 * @author Eric Lafortune 36 */ 37 public class Utf8Shrinker implements ClassVisitor 38 { 39 private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE]; 40 private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper(); 41 42 43 // Implementations for ClassVisitor. 44 45 public void visitProgramClass(ProgramClass programClass) 46 { 47 // Shift the used constant pool entries together, filling out the 48 // index map. 49 programClass.u2constantPoolCount = 50 shrinkConstantPool(programClass.constantPool, 51 programClass.u2constantPoolCount); 52 53 // Remap all constant pool references. 54 constantPoolRemapper.setConstantIndexMap(constantIndexMap); 55 constantPoolRemapper.visitProgramClass(programClass); 56 } 57 58 59 public void visitLibraryClass(LibraryClass libraryClass) 60 { 61 } 62 63 64 // Small utility methods. 65 66 /** 67 * Removes all UTF-8 entries that are not marked as being used 68 * from the given constant pool. 69 * @return the new number of entries. 70 */ 71 private int shrinkConstantPool(Constant[] constantPool, int length) 72 { 73 // Create a new index map, if necessary. 74 if (constantIndexMap.length < length) 75 { 76 constantIndexMap = new int[length]; 77 } 78 79 int counter = 1; 80 boolean isUsed = false; 81 82 // Shift the used constant pool entries together. 83 for (int index = 1; index < length; index++) 84 { 85 constantIndexMap[index] = counter; 86 87 Constant constant = constantPool[index]; 88 89 // Don't update the flag if this is the second half of a long entry. 90 if (constant != null) 91 { 92 isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 || 93 Utf8UsageMarker.isUsed(constant); 94 } 95 96 if (isUsed) 97 { 98 constantPool[counter++] = constant; 99 } 100 } 101 102 // Clear the remaining constant pool elements. 103 for (int index = counter; index < length; index++) 104 { 105 constantPool[index] = null; 106 } 107 108 return counter; 109 } 110 } 111