Home | History | Annotate | Download | only in shrink
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) graphics.cornell.edu)
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by the Free
      9  * Software Foundation; either version 2 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, write to the Free Software Foundation, Inc.,
     19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  */
     21 package proguard.shrink;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.constant.*;
     25 import proguard.classfile.constant.visitor.ConstantVisitor;
     26 import proguard.classfile.util.SimplifiedVisitor;
     27 import proguard.classfile.visitor.ClassVisitor;
     28 
     29 
     30 /**
     31  * This ClassVisitor recursively marks all interface
     32  * classes that are being used in the visited class.
     33  *
     34  * @see UsageMarker
     35  *
     36  * @author Eric Lafortune
     37  */
     38 public class InterfaceUsageMarker
     39 extends      SimplifiedVisitor
     40 implements   ClassVisitor,
     41              ConstantVisitor
     42 {
     43     private final UsageMarker usageMarker;
     44 
     45     // Fields acting as a return parameters for several methods.
     46     private boolean used;
     47     private boolean anyUsed;
     48 
     49 
     50     /**
     51      * Creates a new InterfaceUsageMarker.
     52      * @param usageMarker the usage marker that is used to mark the classes
     53      *                    and class members.
     54      */
     55     public InterfaceUsageMarker(UsageMarker usageMarker)
     56     {
     57         this.usageMarker = usageMarker;
     58     }
     59 
     60 
     61     // Implementations for ClassVisitor.
     62 
     63     public void visitProgramClass(ProgramClass programClass)
     64     {
     65         boolean classUsed         = usageMarker.isUsed(programClass);
     66         boolean classPossiblyUsed = usageMarker.isPossiblyUsed(programClass);
     67 
     68         if (classUsed || classPossiblyUsed)
     69         {
     70             // Check if any interfaces are being used.
     71             boolean oldAnyUsed = anyUsed;
     72             anyUsed = false;
     73 
     74             programClass.interfaceConstantsAccept(this);
     75 
     76             classUsed |= anyUsed;
     77             anyUsed = oldAnyUsed;
     78 
     79             // Is this an interface with a preliminary mark?
     80             if (classPossiblyUsed)
     81             {
     82                 // Should it be included now?
     83                 if (classUsed)
     84                 {
     85                     // At least one if this interface's interfaces is being used.
     86                     // Mark this interface as well.
     87                     usageMarker.markAsUsed(programClass);
     88 
     89                     // Mark this interface's name.
     90                     programClass.thisClassConstantAccept(this);
     91 
     92                     // Mark the superclass (java/lang/Object).
     93                     programClass.superClassConstantAccept(this);
     94                 }
     95                 else
     96                 {
     97                     // Unmark this interface, so we don't bother looking at it again.
     98                     usageMarker.markAsUnused(programClass);
     99                 }
    100             }
    101         }
    102 
    103         // The return value.
    104         used = classUsed;
    105     }
    106 
    107 
    108     public void visitLibraryClass(LibraryClass libraryClass)
    109     {
    110         // The return values.
    111         used    = true;
    112         anyUsed = true;
    113     }
    114 
    115 
    116     // Implementations for ConstantVisitor.
    117 
    118     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
    119     {
    120         boolean classUsed = usageMarker.isUsed(classConstant);
    121 
    122         if (!classUsed)
    123         {
    124             // The ClassConstant isn't marked as being used yet. But maybe it
    125             // should be included as an interface, so check the actual class.
    126             classConstant.referencedClassAccept(this);
    127             classUsed = used;
    128 
    129             if (classUsed)
    130             {
    131                 // The class is being used. Mark the ClassConstant as being used
    132                 // as well.
    133                 usageMarker.markAsUsed(classConstant);
    134 
    135                 clazz.constantPoolEntryAccept(classConstant.u2nameIndex, this);
    136             }
    137         }
    138 
    139         // The return values.
    140         used    =  classUsed;
    141         anyUsed |= classUsed;
    142     }
    143 
    144 
    145     public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
    146     {
    147         if (!usageMarker.isUsed(utf8Constant))
    148         {
    149             usageMarker.markAsUsed(utf8Constant);
    150         }
    151     }
    152 }
    153