// In ProGuard publicvoidexecute()throws IOException { ... readInput(); ... if (configuration.shrink) { shrink(); }
這裡省略不是主要的操作,直接看到shrink():
// In ProGuard privatevoidshrink()throws IOException { ... // Perform the actual shrinking. programClassPool = new Shrinker(configuration).execute(programClassPool, libraryClassPool); }
// In Shrinker public ClassPool execute(ClassPool programClassPool, ClassPool libraryClassPool)throws IOException { ... ClassPool newProgramClassPool = new ClassPool(); programClassPool.classesAccept( new UsedClassFilter(usageMarker, new MultiClassVisitor( new ClassShrinker(usageMarker), new ClassPoolFiller(newProgramClassPool) )));
// In MultiClassVisitor publicvoidvisitProgramClass(ProgramClass programClass){ for (int index = 0; index < classVisitorCount; index++) { classVisitors[index].visitProgramClass(programClass); } }
// In ClassShrinker publicvoidvisitProgramClass(ProgramClass programClass){ ... int oldFieldsCount = programClass.u2fieldsCount; programClass.u2fieldsCount = shrinkArray(programClass.fields, programClass.u2fieldsCount); ... }
privateintshrinkArray(VisitorAccepter[] array, int length){ int counter = 0; for (int index = 0; index < length; index++) { VisitorAccepter visitorAccepter = array[index];
if (usageMarker.isUsed(visitorAccepter)) { array[counter++] = visitorAccepter; } }
// Clear any remaining array elements. if (counter < length) { Arrays.fill(array, counter, length, null); } return counter; }
// In Shrinker public ClassPool execute(ClassPool programClassPool, ClassPool libraryClassPool)throws IOException { ... // Create a visitor for marking the seeds. UsageMarker usageMarker = configuration.whyAreYouKeeping == null ? new UsageMarker() : new ShortestUsageMarker();
// Automatically mark the parameterless constructors of seed classes, // mainly for convenience and for backward compatibility. ClassVisitor classUsageMarker = new MultiClassVisitor(new ClassVisitor[] { usageMarker, new NamedMethodVisitor(ClassConstants.METHOD_NAME_INIT, ClassConstants.METHOD_TYPE_INIT, usageMarker) });
// If the class name has wildcards, only visit classes with matching names. if (... || extendsClassName != null || containsWildCards(className)) { combinedClassVisitor = new ClassNameFilter(classNameMatcher, combinedClassVisitor);
// We'll have to visit all classes now. className = null; } ...
以上得到的都會在包進去ClassNameFilter,className此時又復原回null。
// If it's specified, start visiting from the extended class. if (... || extendsClassName != null) { // Start visiting from the extended class. combinedClassVisitor = new ClassHierarchyTraveler(false, false, false, true, combinedClassVisitor); ... // If specified, only visit extended classes with matching names. if (extendsClassName != null) { ... else { // Start visiting from the named extended class. className = extendsClassName; } } }
// If specified, visit a single named class, otherwise visit all classes. return className != null ? new NamedClassVisitor(combinedClassVisitor, className) : new AllClassVisitor(combinedClassVisitor); }
// In MultiClassPoolVisitor publicvoidvisitClassPool(ClassPool classPool){ for (int index = 0; index < classPoolVisitorCount; index++) { classPoolVisitors[index].visitClassPool(classPool); } }
// In UsageMarker publicvoidvisitProgramClass(ProgramClass programClass){ if (shouldBeMarkedAsUsed(programClass)) { // Mark this class. markAsUsed(programClass); markProgramClassBody(programClass); } }
// In UsageMaker publicvoidvisitProgramMethod(ProgramClass programClass, ProgramMethod programMethod){ if (shouldBeMarkedAsUsed(programMethod)) { // Is the method's class used? if (isUsed(programClass)) { markAsUsed(programMethod); // Mark the method body. markProgramMethodBody(programClass, programMethod); // Mark the method hierarchy. markMethodHierarchy(programClass, programMethod); }
// Hasn't the method been marked as possibly being used yet? elseif (shouldBeMarkedAsPossiblyUsed(programMethod)) { // We can't process the method yet, because the class isn't // marked as being used (yet). Give it a preliminary mark. markAsPossiblyUsed(programMethod); // Mark the method hierarchy. markMethodHierarchy(programClass, programMethod); } } }