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 */ 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 NameAndType constant pool entries 31 * that are not marked as being used. 32 * 33 * @see NameAndTypeUsageMarker 34 * 35 * @author Eric Lafortune 36 */ 37 public class NameAndTypeShrinker implements ClassVisitor 38 { 39 private int[] constantIndexMap; 40 private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper(); 41 42 43 // Implementations for ClassVisitor. 44 visitProgramClass(ProgramClass programClass)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 54 // Remap all constant pool references. 55 constantPoolRemapper.setConstantIndexMap(constantIndexMap); 56 constantPoolRemapper.visitProgramClass(programClass); 57 } 58 59 visitLibraryClass(LibraryClass libraryClass)60 public void visitLibraryClass(LibraryClass libraryClass) 61 { 62 } 63 64 65 // Small utility methods. 66 67 /** 68 * Removes all NameAndType entries that are not marked as being used 69 * from the given constant pool. 70 * @return the new number of entries. 71 */ shrinkConstantPool(Constant[] constantPool, int length)72 private int shrinkConstantPool(Constant[] constantPool, int length) 73 { 74 // Create a new index map, if necessary. 75 if (constantIndexMap == null || 76 constantIndexMap.length < length) 77 { 78 constantIndexMap = new int[length]; 79 } 80 81 int counter = 1; 82 boolean isUsed = false; 83 84 // Shift the used constant pool entries together. 85 for (int index = 1; index < length; index++) 86 { 87 constantIndexMap[index] = counter; 88 89 Constant constant = constantPool[index]; 90 91 // Don't update the flag if this is the second half of a long entry. 92 if (constant != null) 93 { 94 isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType || 95 NameAndTypeUsageMarker.isUsed(constant); 96 } 97 98 if (isUsed) 99 { 100 constantPool[counter++] = constant; 101 } 102 } 103 104 // Clear the remaining constant pool elements. 105 for (int index = counter; index < length; index++) 106 { 107 constantPool[index] = null; 108 } 109 110 return counter; 111 } 112 } 113