1 21 package proguard.shrink; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.annotation.*; 26 import proguard.classfile.attribute.annotation.visitor.*; 27 import proguard.classfile.attribute.visitor.AttributeVisitor; 28 import proguard.classfile.constant.Constant; 29 import proguard.classfile.editor.ConstantPoolRemapper; 30 import proguard.classfile.util.SimplifiedVisitor; 31 import proguard.classfile.visitor.*; 32 33 41 public class ClassShrinker 42 extends SimplifiedVisitor 43 implements ClassVisitor, 44 MemberVisitor, 45 AttributeVisitor, 46 AnnotationVisitor, 47 ElementValueVisitor 48 { 49 private UsageMarker usageMarker; 50 51 private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE]; 52 53 private ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper(); 54 55 56 61 public ClassShrinker(UsageMarker usageMarker) 62 { 63 this.usageMarker = usageMarker; 64 } 65 66 67 69 public void visitProgramClass(ProgramClass programClass) 70 { 71 programClass.u2interfacesCount = 74 shrinkConstantIndexArray(programClass.constantPool, 75 programClass.u2interfaces, 76 programClass.u2interfacesCount); 77 78 programClass.u2constantPoolCount = 80 shrinkConstantPool(programClass.constantPool, 81 programClass.u2constantPoolCount); 82 83 programClass.u2fieldsCount = 84 shrinkArray(programClass.fields, 85 programClass.u2fieldsCount); 86 87 programClass.u2methodsCount = 88 shrinkArray(programClass.methods, 89 programClass.u2methodsCount); 90 91 programClass.u2attributesCount = 92 shrinkArray(programClass.attributes, 93 programClass.u2attributesCount); 94 95 programClass.fieldsAccept(this); 98 programClass.methodsAccept(this); 99 programClass.attributesAccept(this); 100 101 constantPoolRemapper.setConstantIndexMap(constantIndexMap); 103 constantPoolRemapper.visitProgramClass(programClass); 104 105 programClass.subClasses = 107 shrinkToNewArray(programClass.subClasses); 108 } 109 110 111 public void visitLibraryClass(LibraryClass libraryClass) 112 { 113 115 libraryClass.subClasses = 117 shrinkToNewArray(libraryClass.subClasses); 118 } 119 120 121 123 public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) 124 { 125 programMember.u2attributesCount = 127 shrinkArray(programMember.attributes, 128 programMember.u2attributesCount); 129 130 programMember.attributesAccept(programClass, this); 132 } 133 134 135 137 public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 138 139 140 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 141 { 142 innerClassesAttribute.u2classesCount = 144 shrinkArray(innerClassesAttribute.classes, 145 innerClassesAttribute.u2classesCount); 146 } 147 148 149 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 150 { 151 if (enclosingMethodAttribute.referencedMethod != null && 158 !usageMarker.isUsed(enclosingMethodAttribute.referencedMethod)) 159 { 160 enclosingMethodAttribute.u2nameAndTypeIndex = 0; 161 162 enclosingMethodAttribute.referencedMethod = null; 163 } 164 } 165 166 167 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 168 { 169 codeAttribute.u2attributesCount = 171 shrinkArray(codeAttribute.attributes, 172 codeAttribute.u2attributesCount); 173 } 174 175 176 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 177 { 178 annotationsAttribute.u2annotationsCount = 180 shrinkArray(annotationsAttribute.annotations, 181 annotationsAttribute.u2annotationsCount); 182 183 annotationsAttribute.annotationsAccept(clazz, this); 185 } 186 187 188 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 189 { 190 for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) 192 { 193 parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex] = 195 shrinkArray(parameterAnnotationsAttribute.parameterAnnotations[parameterIndex], 196 parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]); 197 } 198 199 parameterAnnotationsAttribute.annotationsAccept(clazz, method, this); 201 } 202 203 204 206 public void visitAnnotation(Clazz clazz, Annotation annotation) 207 { 208 annotation.u2elementValuesCount = 210 shrinkArray(annotation.elementValues, 211 annotation.u2elementValuesCount); 212 213 annotation.elementValuesAccept(clazz, this); 215 } 216 217 218 220 public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {} 221 222 223 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 224 { 225 annotationElementValue.annotationAccept(clazz, this); 227 } 228 229 230 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 231 { 232 arrayElementValue.u2elementValuesCount = 234 shrinkArray(arrayElementValue.elementValues, 235 arrayElementValue.u2elementValuesCount); 236 237 arrayElementValue.elementValuesAccept(clazz, annotation, this); 239 } 240 241 242 244 249 private int shrinkConstantPool(Constant[] constantPool, int length) 250 { 251 if (constantIndexMap.length < length) 252 { 253 constantIndexMap = new int[length]; 254 } 255 256 int counter = 1; 257 boolean isUsed = false; 258 259 for (int index = 1; index < length; index++) 261 { 262 constantIndexMap[index] = counter; 263 264 Constant constant = constantPool[index]; 265 266 if (constant != null) 268 { 269 isUsed = usageMarker.isUsed(constant); 270 } 271 272 if (isUsed) 273 { 274 constantPool[counter++] = constant; 275 } 276 } 277 278 for (int index = counter; index < length; index++) 280 { 281 constantPool[index] = null; 282 } 283 284 return counter; 285 } 286 287 288 293 private int shrinkConstantIndexArray(Constant[] constantPool, int[] array, int length) 294 { 295 int counter = 0; 296 297 for (int index = 0; index < length; index++) 299 { 300 if (usageMarker.isUsed(constantPool[array[index]])) 301 { 302 array[counter++] = array[index]; 303 } 304 } 305 306 for (int index = counter; index < length; index++) 308 { 309 array[index] = 0; 310 } 311 312 return counter; 313 } 314 315 316 322 private Clazz[] shrinkToNewArray(Clazz[] array) 323 { 324 if (array == null) 325 { 326 return null; 327 } 328 329 int length = shrinkArray(array, array.length); 331 if (length == 0) 332 { 333 return null; 334 } 335 336 if (length == array.length) 338 { 339 return array; 340 } 341 342 Clazz[] newArray = new Clazz[length]; 344 System.arraycopy(array, 0, newArray, 0, length); 345 return newArray; 346 } 347 348 349 354 private int shrinkArray(VisitorAccepter[] array, int length) 355 { 356 int counter = 0; 357 358 for (int index = 0; index < length; index++) 360 { 361 if (usageMarker.isUsed(array[index])) 362 { 363 array[counter++] = array[index]; 364 } 365 } 366 367 for (int index = counter; index < length; index++) 369 { 370 array[index] = null; 371 } 372 373 return counter; 374 } 375 } 376 | Popular Tags |