1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2005 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.objectweb.asm.optimizer; 31 32 import java.io.File; 33 import java.io.FileInputStream; 34 import java.io.FileOutputStream; 35 import java.io.IOException; 36 import java.io.OutputStream; 37 import java.util.Comparator; 38 import java.util.Iterator; 39 import java.util.Set; 40 import java.util.TreeSet; 41 42 import org.objectweb.asm.ClassReader; 43 import org.objectweb.asm.ClassWriter; 44 45 /** 46 * A class file shrinker utility. 47 * 48 * @author Eric Bruneton 49 */ 50 public class Shrinker { 51 main(final String[] args)52 public static void main(final String[] args) throws IOException { 53 NameMapping mapping = new NameMapping(args[0]); 54 File f = new File(args[1]); 55 File d = new File(args[2]); 56 optimize(f, d, mapping); 57 Iterator i = mapping.unused.iterator(); 58 while (i.hasNext()) { 59 System.out.println("INFO: unused mapping " + i.next()); 60 } 61 } 62 optimize(final File f, final File d, final NameMapping mapping)63 static void optimize(final File f, final File d, final NameMapping mapping) 64 throws IOException 65 { 66 if (f.isDirectory()) { 67 File[] files = f.listFiles(); 68 for (int i = 0; i < files.length; ++i) { 69 optimize(files[i], d, mapping); 70 } 71 } else if (f.getName().endsWith(".class")) { 72 ConstantPool cp = new ConstantPool(); 73 ClassReader cr = new ClassReader(new FileInputStream(f)); 74 ClassWriter cw = new ClassWriter(false); 75 ClassConstantsCollector ccc = new ClassConstantsCollector(cw, cp); 76 ClassOptimizer co = new ClassOptimizer(ccc, mapping); 77 cr.accept(co, true); 78 79 Set constants = new TreeSet(new ConstantComparator()); 80 constants.addAll(cp.values()); 81 82 cr = new ClassReader(cw.toByteArray()); 83 cw = new ClassWriter(false); 84 Iterator i = constants.iterator(); 85 while (i.hasNext()) { 86 Constant c = (Constant) i.next(); 87 c.write(cw); 88 } 89 cr.accept(cw, true); 90 91 String n = mapping.map(co.getClassName()); 92 File g = new File(d, n + ".class"); 93 if (!g.exists() || g.lastModified() < f.lastModified()) { 94 g.getParentFile().mkdirs(); 95 OutputStream os = new FileOutputStream(g); 96 os.write(cw.toByteArray()); 97 os.close(); 98 } 99 } 100 } 101 102 static class ConstantComparator implements Comparator { 103 compare(final Object o1, final Object o2)104 public int compare(final Object o1, final Object o2) { 105 Constant c1 = (Constant) o1; 106 Constant c2 = (Constant) o2; 107 int d = getSort(c1) - getSort(c2); 108 if (d == 0) { 109 switch (c1.type) { 110 case 'I': 111 return new Integer(c1.intVal).compareTo(new Integer(c2.intVal)); 112 case 'J': 113 return new Long(c1.longVal).compareTo(new Long(c2.longVal)); 114 case 'F': 115 return new Float(c1.floatVal).compareTo(new Float(c2.floatVal)); 116 case 'D': 117 return new Double(c1.doubleVal).compareTo(new Double(c2.doubleVal)); 118 case 's': 119 case 'S': 120 case 'C': 121 return c1.strVal1.compareTo(c2.strVal1); 122 case 'T': 123 d = c1.strVal1.compareTo(c2.strVal1); 124 if (d == 0) { 125 d = c1.strVal2.compareTo(c2.strVal2); 126 } 127 break; 128 default: 129 d = c1.strVal1.compareTo(c2.strVal1); 130 if (d == 0) { 131 d = c1.strVal2.compareTo(c2.strVal2); 132 if (d == 0) { 133 d = c1.strVal3.compareTo(c2.strVal3); 134 } 135 } 136 } 137 } 138 return d; 139 } 140 getSort(Constant c)141 private int getSort(Constant c) { 142 switch (c.type) { 143 case 'I': 144 return 0; 145 case 'J': 146 return 1; 147 case 'F': 148 return 2; 149 case 'D': 150 return 3; 151 case 's': 152 return 4; 153 case 'S': 154 return 5; 155 case 'C': 156 return 6; 157 case 'T': 158 return 7; 159 case 'G': 160 return 8; 161 case 'M': 162 return 9; 163 default: 164 return 10; 165 } 166 } 167 } 168 } 169