Home | History | Annotate | Download | only in optimizer
      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 
     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 
     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 
    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 
    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