1 22 package proguard.shrink; 23 24 import proguard.*; 25 import proguard.classfile.ClassPool; 26 import proguard.classfile.attribute.visitor.*; 27 import proguard.classfile.visitor.*; 28 29 import java.io.*; 30 31 36 public class Shrinker 37 { 38 private Configuration configuration; 39 40 41 44 public Shrinker(Configuration configuration) 45 { 46 this.configuration = configuration; 47 } 48 49 50 53 public ClassPool execute(ClassPool programClassPool, 54 ClassPool libraryClassPool) throws IOException 55 { 56 if (configuration.keep == null) 58 { 59 throw new IOException("You have to specify '-keep' options for the shrinking step."); 60 } 61 62 programClassPool.classesAccept(new ClassCleaner()); 64 libraryClassPool.classesAccept(new ClassCleaner()); 65 66 UsageMarker usageMarker = configuration.whyAreYouKeeping == null ? 68 new UsageMarker() : 69 new ShortestUsageMarker(); 70 71 ClassPoolVisitor classPoolvisitor = 72 ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep, 73 usageMarker, 74 usageMarker, 75 true, 76 false, 77 false); 78 programClassPool.accept(classPoolvisitor); 80 libraryClassPool.accept(classPoolvisitor); 81 82 programClassPool.classesAccept(new InterfaceUsageMarker(usageMarker)); 84 85 programClassPool.classesAccept( 87 new UsedClassFilter(usageMarker, 88 new MultiClassVisitor(new ClassVisitor[] 89 { 90 new AllAttributeVisitor( 91 new MultiAttributeVisitor(new AttributeVisitor[] 92 { 93 new InnerUsageMarker(usageMarker), 94 new AnnotationUsageMarker(usageMarker), 95 })), 96 new AllMemberVisitor( 97 new AllAttributeVisitor( 98 new AnnotationUsageMarker(usageMarker))) 99 }))); 100 101 if (configuration.whyAreYouKeeping != null) 103 { 104 System.out.println(); 105 106 ShortestUsagePrinter shortestUsagePrinter = 108 new ShortestUsagePrinter((ShortestUsageMarker)usageMarker, 109 configuration.verbose); 110 111 ClassPoolVisitor whyClassPoolvisitor = 112 ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.whyAreYouKeeping, 113 shortestUsagePrinter, 114 shortestUsagePrinter); 115 116 programClassPool.accept(whyClassPoolvisitor); 118 libraryClassPool.accept(whyClassPoolvisitor); 119 } 120 121 if (configuration.printUsage != null) 122 { 123 PrintStream ps = isFile(configuration.printUsage) ? 124 new PrintStream(new BufferedOutputStream(new FileOutputStream(configuration.printUsage))) : 125 System.out; 126 127 programClassPool.classesAcceptAlphabetically( 129 new UsagePrinter(usageMarker, true, ps)); 130 131 if (ps != System.out) 132 { 133 ps.close(); 134 } 135 } 136 137 int originalProgramClassPoolSize = programClassPool.size(); 139 140 ClassPool newProgramClassPool = new ClassPool(); 141 programClassPool.classesAccept( 142 new UsedClassFilter(usageMarker, 143 new MultiClassVisitor( 144 new ClassVisitor[] { 145 new ClassShrinker(usageMarker), 146 new ClassPoolFiller(newProgramClassPool) 147 }))); 148 149 programClassPool.clear(); 150 151 int newProgramClassPoolSize = newProgramClassPool.size(); 153 if (newProgramClassPoolSize == 0) 154 { 155 throw new IOException("The output jar is empty. Did you specify the proper '-keep' options?"); 156 } 157 158 if (configuration.verbose) 159 { 160 System.out.println("Removing unused program classes and class elements..."); 161 System.out.println(" Original number of program classes: " + originalProgramClassPoolSize); 162 System.out.println(" Final number of program classes: " + newProgramClassPoolSize); 163 } 164 165 return newProgramClassPool; 166 } 167 168 169 173 private boolean isFile(File file) 174 { 175 return file.getPath().length() > 0; 176 } 177 } 178 | Popular Tags |