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.attribute.*;
     25 import proguard.classfile.attribute.annotation.*;
     26 import proguard.classfile.attribute.preverification.*;
     27 import proguard.classfile.attribute.preverification.visitor.*;
     28 import proguard.classfile.attribute.visitor.*;
     29 import proguard.classfile.constant.*;
     30 import proguard.classfile.constant.visitor.*;
     31 import proguard.classfile.instruction.*;
     32 import proguard.classfile.instruction.visitor.InstructionVisitor;
     33 import proguard.classfile.util.*;
     34 import proguard.classfile.visitor.*;
     35 
     36 
     37 /**
     38  * This ClassVisitor and MemberVisitor recursively marks all classes and class
     39  * elements that are being used.
     40  *
     41  * @see ClassShrinker
     42  *
     43  * @author Eric Lafortune
     44  */
     45 class      UsageMarker
     46 extends    SimplifiedVisitor
     47 implements ClassVisitor,
     48            MemberVisitor,
     49            ConstantVisitor,
     50            AttributeVisitor,
     51            InnerClassesInfoVisitor,
     52            ExceptionInfoVisitor,
     53            StackMapFrameVisitor,
     54            VerificationTypeVisitor,
     55            ParameterInfoVisitor,
     56            LocalVariableInfoVisitor,
     57            LocalVariableTypeInfoVisitor,
     58 //         AnnotationVisitor,
     59 //         ElementValueVisitor,
     60            InstructionVisitor
     61 {
     62     // A visitor info flag to indicate the ProgramMember object is being used,
     63     // if its Clazz can be determined as being used as well.
     64     private static final Object POSSIBLY_USED = new Object();
     65     // A visitor info flag to indicate the visitor accepter is being used.
     66     private static final Object USED          = new Object();
     67 
     68 
     69     private final MyInterfaceUsageMarker          interfaceUsageMarker           = new MyInterfaceUsageMarker();
     70     private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker  = new MyPossiblyUsedMemberUsageMarker();
     71     private final MemberVisitor                   nonEmptyMethodUsageMarker      = new AllAttributeVisitor(
     72                                                                                    new MyNonEmptyMethodUsageMarker());
     73     private final ConstantVisitor                 parameterlessConstructorMarker = new ConstantTagFilter(new int[] { ClassConstants.CONSTANT_String, ClassConstants.CONSTANT_Class },
     74                                                                                    new ReferencedClassVisitor(
     75                                                                                    new NamedMethodVisitor(ClassConstants.METHOD_NAME_INIT,
     76                                                                                                           ClassConstants.METHOD_TYPE_INIT,
     77                                                                                                           this)));
     78 
     79     // Implementations for ClassVisitor.
     80 
     81     public void visitProgramClass(ProgramClass programClass)
     82     {
     83         if (shouldBeMarkedAsUsed(programClass))
     84         {
     85             // Mark this class.
     86             markAsUsed(programClass);
     87 
     88             markProgramClassBody(programClass);
     89         }
     90     }
     91 
     92 
     93     protected void markProgramClassBody(ProgramClass programClass)
     94     {
     95         // Mark this class's name.
     96         markConstant(programClass, programClass.u2thisClass);
     97 
     98         // Mark the superclass.
     99         if (programClass.u2superClass != 0)
    100         {
    101             markConstant(programClass, programClass.u2superClass);
    102         }
    103 
    104         // Give the interfaces preliminary marks.
    105         programClass.hierarchyAccept(false, false, true, false,
    106                                      interfaceUsageMarker);
    107 
    108         // Explicitly mark the <clinit> method, if it's not empty.
    109         programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT,
    110                                   ClassConstants.METHOD_TYPE_CLINIT,
    111                                   nonEmptyMethodUsageMarker);
    112 
    113         // Process all class members that have already been marked as possibly used.
    114         programClass.fieldsAccept(possiblyUsedMemberUsageMarker);
    115         programClass.methodsAccept(possiblyUsedMemberUsageMarker);
    116 
    117         // Mark the attributes.
    118         programClass.attributesAccept(this);
    119     }
    120 
    121 
    122     public void visitLibraryClass(LibraryClass libraryClass)
    123     {
    124         if (shouldBeMarkedAsUsed(libraryClass))
    125         {
    126             markAsUsed(libraryClass);
    127 
    128             // We're not going to analyze all library code. We're assuming that
    129             // if this class is being used, all of its methods will be used as
    130             // well. We'll mark them as such (here and in all subclasses).
    131 
    132             // Mark the superclass.
    133             Clazz superClass = libraryClass.superClass;
    134             if (superClass != null)
    135             {
    136                 superClass.accept(this);
    137             }
    138 
    139             // Mark the interfaces.
    140             Clazz[] interfaceClasses = libraryClass.interfaceClasses;
    141             if (interfaceClasses != null)
    142             {
    143                 for (int index = 0; index < interfaceClasses.length; index++)
    144                 {
    145                     if (interfaceClasses[index] != null)
    146                     {
    147                         interfaceClasses[index].accept(this);
    148                     }
    149                 }
    150             }
    151 
    152             // Mark all methods.
    153             libraryClass.methodsAccept(this);
    154         }
    155     }
    156 
    157 
    158     /**
    159      * This ClassVisitor marks ProgramClass objects as possibly used,
    160      * and it visits LibraryClass objects with its outer UsageMarker.
    161      */
    162     private class MyInterfaceUsageMarker
    163     implements    ClassVisitor
    164     {
    165         public void visitProgramClass(ProgramClass programClass)
    166         {
    167             if (shouldBeMarkedAsPossiblyUsed(programClass))
    168             {
    169                 // We can't process the interface yet, because it might not
    170                 // be required. Give it a preliminary mark.
    171                 markAsPossiblyUsed(programClass);
    172             }
    173         }
    174 
    175         public void visitLibraryClass(LibraryClass libraryClass)
    176         {
    177             // Make sure all library interface methods are marked.
    178             UsageMarker.this.visitLibraryClass(libraryClass);
    179         }
    180     }
    181 
    182 
    183     /**
    184      * This MemberVisitor marks ProgramField and ProgramMethod objects that
    185      * have already been marked as possibly used.
    186      */
    187     private class MyPossiblyUsedMemberUsageMarker
    188     extends       SimplifiedVisitor
    189     implements    MemberVisitor
    190     {
    191         // Implementations for MemberVisitor.
    192 
    193         public void visitProgramField(ProgramClass programClass, ProgramField programField)
    194         {
    195             // Has the method already been referenced?
    196             if (isPossiblyUsed(programField))
    197             {
    198                 markAsUsed(programField);
    199 
    200                 // Mark the name and descriptor.
    201                 markConstant(programClass, programField.u2nameIndex);
    202                 markConstant(programClass, programField.u2descriptorIndex);
    203 
    204                 // Mark the attributes.
    205                 programField.attributesAccept(programClass, UsageMarker.this);
    206 
    207                 // Mark the classes referenced in the descriptor string.
    208                 programField.referencedClassesAccept(UsageMarker.this);
    209             }
    210         }
    211 
    212 
    213         public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
    214         {
    215             // Has the method already been referenced?
    216             if (isPossiblyUsed(programMethod))
    217             {
    218                 markAsUsed(programMethod);
    219 
    220                 // Mark the method body.
    221                 markProgramMethodBody(programClass, programMethod);
    222 
    223                 // Note that, if the method has been marked as possibly used,
    224                 // the method hierarchy has already been marked (cfr. below).
    225             }
    226         }
    227     }
    228 
    229 
    230     /**
    231      * This AttributeVisitor marks ProgramMethod objects of non-empty methods.
    232      */
    233     private class MyNonEmptyMethodUsageMarker
    234     extends       SimplifiedVisitor
    235     implements    AttributeVisitor
    236     {
    237         // Implementations for AttributeVisitor.
    238 
    239         public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
    240 
    241 
    242         public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
    243         {
    244             if (codeAttribute.u4codeLength > 1)
    245             {
    246                 method.accept(clazz, UsageMarker.this);
    247             }
    248         }
    249     }
    250 
    251 
    252     // Implementations for MemberVisitor.
    253 
    254     public void visitProgramField(ProgramClass programClass, ProgramField programField)
    255     {
    256         if (shouldBeMarkedAsUsed(programField))
    257         {
    258             // Is the field's class used?
    259             if (isUsed(programClass))
    260             {
    261                 markAsUsed(programField);
    262 
    263                 // Mark the field body.
    264                 markProgramFieldBody(programClass, programField);
    265             }
    266 
    267             // Hasn't the field been marked as possibly being used yet?
    268             else if (shouldBeMarkedAsPossiblyUsed(programField))
    269             {
    270                 // We can't process the field yet, because the class isn't
    271                 // marked as being used (yet). Give it a preliminary mark.
    272                 markAsPossiblyUsed(programField);
    273             }
    274         }
    275     }
    276 
    277 
    278     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
    279     {
    280         if (shouldBeMarkedAsUsed(programMethod))
    281         {
    282             // Is the method's class used?
    283             if (isUsed(programClass))
    284             {
    285                 markAsUsed(programMethod);
    286 
    287                 // Mark the method body.
    288                 markProgramMethodBody(programClass, programMethod);
    289 
    290                 // Mark the method hierarchy.
    291                 markMethodHierarchy(programClass, programMethod);
    292             }
    293 
    294             // Hasn't the method been marked as possibly being used yet?
    295             else if (shouldBeMarkedAsPossiblyUsed(programMethod))
    296             {
    297                 // We can't process the method yet, because the class isn't
    298                 // marked as being used (yet). Give it a preliminary mark.
    299                 markAsPossiblyUsed(programMethod);
    300 
    301                 // Mark the method hierarchy.
    302                 markMethodHierarchy(programClass, programMethod);
    303             }
    304         }
    305     }
    306 
    307 
    308     public void visitLibraryField(LibraryClass programClass, LibraryField programField) {}
    309 
    310 
    311     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
    312     {
    313         if (shouldBeMarkedAsUsed(libraryMethod))
    314         {
    315             markAsUsed(libraryMethod);
    316 
    317             // Mark the method hierarchy.
    318             markMethodHierarchy(libraryClass, libraryMethod);
    319         }
    320     }
    321 
    322 
    323     protected void markProgramFieldBody(ProgramClass programClass, ProgramField programField)
    324     {
    325         // Mark the name and descriptor.
    326         markConstant(programClass, programField.u2nameIndex);
    327         markConstant(programClass, programField.u2descriptorIndex);
    328 
    329         // Mark the attributes.
    330         programField.attributesAccept(programClass, this);
    331 
    332         // Mark the classes referenced in the descriptor string.
    333         programField.referencedClassesAccept(this);
    334     }
    335 
    336 
    337     protected void markProgramMethodBody(ProgramClass programClass, ProgramMethod programMethod)
    338     {
    339         // Mark the name and descriptor.
    340         markConstant(programClass, programMethod.u2nameIndex);
    341         markConstant(programClass, programMethod.u2descriptorIndex);
    342 
    343         // Mark the attributes.
    344         programMethod.attributesAccept(programClass, this);
    345 
    346         // Mark the classes referenced in the descriptor string.
    347         programMethod.referencedClassesAccept(this);
    348     }
    349 
    350 
    351     /**
    352      * Marks the hierarchy of implementing or overriding methods corresponding
    353      * to the given method, if any.
    354      */
    355     protected void markMethodHierarchy(Clazz clazz, Method method)
    356     {
    357         int accessFlags = method.getAccessFlags();
    358         if ((accessFlags &
    359              (ClassConstants.ACC_PRIVATE |
    360               ClassConstants.ACC_STATIC)) == 0 &&
    361             !ClassUtil.isInitializer(method.getName(clazz)))
    362         {
    363             // We can skip private and static methods in the hierarchy, and
    364             // also abstract methods, unless they might widen a current
    365             // non-public access.
    366             int requiredUnsetAccessFlags =
    367                 ClassConstants.ACC_PRIVATE |
    368                 ClassConstants.ACC_STATIC  |
    369                 ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 :
    370                      ClassConstants.ACC_ABSTRACT);
    371 
    372             clazz.accept(new ConcreteClassDownTraveler(
    373                          new ClassHierarchyTraveler(true, true, false, true,
    374                          new NamedMethodVisitor(method.getName(clazz),
    375                                                 method.getDescriptor(clazz),
    376                          new MemberAccessFilter(0, requiredUnsetAccessFlags,
    377                          this)))));
    378         }
    379     }
    380 
    381 
    382     // Implementations for ConstantVisitor.
    383 
    384     public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
    385     {
    386         if (shouldBeMarkedAsUsed(integerConstant))
    387         {
    388             markAsUsed(integerConstant);
    389         }
    390     }
    391 
    392 
    393     public void visitLongConstant(Clazz clazz, LongConstant longConstant)
    394     {
    395         if (shouldBeMarkedAsUsed(longConstant))
    396         {
    397             markAsUsed(longConstant);
    398         }
    399     }
    400 
    401 
    402     public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
    403     {
    404         if (shouldBeMarkedAsUsed(floatConstant))
    405         {
    406             markAsUsed(floatConstant);
    407         }
    408     }
    409 
    410 
    411     public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
    412     {
    413         if (shouldBeMarkedAsUsed(doubleConstant))
    414         {
    415             markAsUsed(doubleConstant);
    416         }
    417     }
    418 
    419 
    420     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
    421     {
    422         if (shouldBeMarkedAsUsed(stringConstant))
    423         {
    424             markAsUsed(stringConstant);
    425 
    426             markConstant(clazz, stringConstant.u2stringIndex);
    427 
    428             // Mark the referenced class and class member, if any.
    429             stringConstant.referencedClassAccept(this);
    430             stringConstant.referencedMemberAccept(this);
    431         }
    432     }
    433 
    434 
    435     public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
    436     {
    437         if (shouldBeMarkedAsUsed(utf8Constant))
    438         {
    439             markAsUsed(utf8Constant);
    440         }
    441     }
    442 
    443 
    444     public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
    445     {
    446         if (shouldBeMarkedAsUsed(invokeDynamicConstant))
    447         {
    448             markAsUsed(invokeDynamicConstant);
    449 
    450             markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
    451 
    452             // Mark the referenced descriptor classes.
    453             invokeDynamicConstant.referencedClassesAccept(this);
    454 
    455             // Mark the bootstrap methods attribute.
    456             clazz.attributesAccept(new MyBootStrapMethodUsageMarker(invokeDynamicConstant.u2bootstrapMethodAttributeIndex));
    457         }
    458     }
    459 
    460 
    461     public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
    462     {
    463         if (shouldBeMarkedAsUsed(methodHandleConstant))
    464         {
    465             markAsUsed(methodHandleConstant);
    466 
    467             markConstant(clazz, methodHandleConstant.u2referenceIndex);
    468         }
    469     }
    470 
    471 
    472     public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
    473     {
    474         if (shouldBeMarkedAsUsed(refConstant))
    475         {
    476             markAsUsed(refConstant);
    477 
    478             markConstant(clazz, refConstant.u2classIndex);
    479             markConstant(clazz, refConstant.u2nameAndTypeIndex);
    480 
    481             // When compiled with "-target 1.2" or higher, the class or
    482             // interface actually containing the referenced class member may
    483             // be higher up the hierarchy. Make sure it's marked, in case it
    484             // isn't used elsewhere.
    485             refConstant.referencedClassAccept(this);
    486 
    487             // Mark the referenced class member itself.
    488             refConstant.referencedMemberAccept(this);
    489         }
    490     }
    491 
    492 
    493     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
    494     {
    495         if (shouldBeMarkedAsUsed(classConstant))
    496         {
    497             markAsUsed(classConstant);
    498 
    499             markConstant(clazz, classConstant.u2nameIndex);
    500 
    501             // Mark the referenced class itself.
    502             classConstant.referencedClassAccept(this);
    503         }
    504     }
    505 
    506 
    507     public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
    508     {
    509         if (shouldBeMarkedAsUsed(methodTypeConstant))
    510         {
    511             markAsUsed(methodTypeConstant);
    512 
    513             markConstant(clazz, methodTypeConstant.u2descriptorIndex);
    514 
    515             // Mark the referenced descriptor classes.
    516             methodTypeConstant.referencedClassesAccept(this);
    517         }
    518     }
    519 
    520 
    521     public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
    522     {
    523         if (shouldBeMarkedAsUsed(nameAndTypeConstant))
    524         {
    525             markAsUsed(nameAndTypeConstant);
    526 
    527             markConstant(clazz, nameAndTypeConstant.u2nameIndex);
    528             markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
    529         }
    530     }
    531 
    532 
    533     /**
    534      * This AttributeVisitor marks the bootstrap methods attributes, their
    535      * method entries, their method handles, and their arguments.
    536      */
    537     private class MyBootStrapMethodUsageMarker
    538     extends       SimplifiedVisitor
    539     implements    AttributeVisitor,
    540                   BootstrapMethodInfoVisitor
    541     {
    542         private int bootstrapMethodIndex;
    543 
    544 
    545         private MyBootStrapMethodUsageMarker(int bootstrapMethodIndex)
    546         {
    547             this.bootstrapMethodIndex = bootstrapMethodIndex;
    548         }
    549 
    550 
    551         // Implementations for AttributeVisitor.
    552 
    553         public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
    554 
    555 
    556         public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
    557         {
    558             if (shouldBeMarkedAsUsed(bootstrapMethodsAttribute))
    559             {
    560                 markAsUsed(bootstrapMethodsAttribute);
    561 
    562                 markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
    563             }
    564 
    565             bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
    566                                                                  bootstrapMethodIndex,
    567                                                                  this);
    568         }
    569 
    570 
    571         // Implementations for BootstrapMethodInfoVisitor.
    572 
    573         public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
    574         {
    575             markAsUsed(bootstrapMethodInfo);
    576 
    577             markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
    578 
    579             // Mark the constant pool entries referenced by the arguments.
    580             bootstrapMethodInfo.methodArgumentsAccept(clazz, UsageMarker.this);
    581         }
    582     }
    583 
    584 
    585     // Implementations for AttributeVisitor.
    586     // Note that attributes are typically only referenced once, so we don't
    587     // test if they have been marked already.
    588 
    589     public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
    590     {
    591         // This is the best we can do for unknown attributes.
    592         markAsUsed(unknownAttribute);
    593 
    594         markConstant(clazz, unknownAttribute.u2attributeNameIndex);
    595     }
    596 
    597 
    598     public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
    599     {
    600         // Don't mark the attribute and its name here. We may mark it in
    601         // MyBootStrapMethodsAttributeUsageMarker.
    602     }
    603 
    604 
    605     public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
    606     {
    607         markAsUsed(sourceFileAttribute);
    608 
    609         markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
    610         markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
    611     }
    612 
    613 
    614     public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
    615     {
    616         markAsUsed(sourceDirAttribute);
    617 
    618         markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
    619         markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
    620     }
    621 
    622 
    623     public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
    624     {
    625         // Don't mark the attribute and its name yet. We may mark it later, in
    626         // InnerUsageMarker.
    627         //markAsUsed(innerClassesAttribute);
    628 
    629         //markConstant(clazz, innerClassesAttribute.u2attrNameIndex);
    630 
    631         // Do mark the outer class entries.
    632         innerClassesAttribute.innerClassEntriesAccept(clazz, this);
    633     }
    634 
    635 
    636     public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
    637     {
    638         markAsUsed(enclosingMethodAttribute);
    639 
    640         markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
    641         markConstant(clazz, enclosingMethodAttribute.u2classIndex);
    642 
    643         if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
    644         {
    645             markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
    646         }
    647     }
    648 
    649 
    650     public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
    651     {
    652         markAsUsed(deprecatedAttribute);
    653 
    654         markConstant(clazz, deprecatedAttribute.u2attributeNameIndex);
    655     }
    656 
    657 
    658     public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
    659     {
    660         markAsUsed(syntheticAttribute);
    661 
    662         markConstant(clazz, syntheticAttribute.u2attributeNameIndex);
    663     }
    664 
    665 
    666     public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
    667     {
    668         markAsUsed(signatureAttribute);
    669 
    670         markConstant(clazz, signatureAttribute.u2attributeNameIndex);
    671         markConstant(clazz, signatureAttribute.u2signatureIndex);
    672 
    673         // Don't mark the referenced classes. We'll clean them up in
    674         // ClassShrinker, if they appear unused.
    675         //// Mark the classes referenced in the descriptor string.
    676         //signatureAttribute.referencedClassesAccept(this);
    677     }
    678 
    679 
    680     public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
    681     {
    682         markAsUsed(constantValueAttribute);
    683 
    684         markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
    685         markConstant(clazz, constantValueAttribute.u2constantValueIndex);
    686     }
    687 
    688 
    689     public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
    690     {
    691         markAsUsed(methodParametersAttribute);
    692 
    693         markConstant(clazz, methodParametersAttribute.u2attributeNameIndex);
    694 
    695         // Mark the constant pool entries referenced by the parameter information.
    696         methodParametersAttribute.parametersAccept(clazz, method, this);
    697     }
    698 
    699 
    700     public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
    701     {
    702         markAsUsed(exceptionsAttribute);
    703 
    704         markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);
    705 
    706         // Mark the constant pool entries referenced by the exceptions.
    707         exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
    708     }
    709 
    710 
    711     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
    712     {
    713         markAsUsed(codeAttribute);
    714 
    715         markConstant(clazz, codeAttribute.u2attributeNameIndex);
    716 
    717         // Mark the constant pool entries referenced by the instructions,
    718         // by the exceptions, and by the attributes.
    719         codeAttribute.instructionsAccept(clazz, method, this);
    720         codeAttribute.exceptionsAccept(clazz, method, this);
    721         codeAttribute.attributesAccept(clazz, method, this);
    722     }
    723 
    724 
    725     public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
    726     {
    727         markAsUsed(stackMapAttribute);
    728 
    729         markConstant(clazz, stackMapAttribute.u2attributeNameIndex);
    730 
    731         // Mark the constant pool entries referenced by the stack map frames.
    732         stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
    733     }
    734 
    735 
    736     public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
    737     {
    738         markAsUsed(stackMapTableAttribute);
    739 
    740         markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);
    741 
    742         // Mark the constant pool entries referenced by the stack map frames.
    743         stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
    744     }
    745 
    746 
    747     public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
    748     {
    749         markAsUsed(lineNumberTableAttribute);
    750 
    751         markConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex);
    752     }
    753 
    754 
    755     public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
    756     {
    757         // Don't mark the attribute and its contents yet. We may mark them later,
    758         // in LocalVariableTypeUsageMarker.
    759         //markAsUsed(localVariableTableAttribute);
    760         //
    761         //markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
    762         //
    763         //// Mark the constant pool entries referenced by the local variables.
    764         //localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
    765     }
    766 
    767 
    768     public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
    769     {
    770         // Don't mark the attribute and its contents yet. We may mark them later,
    771         // in LocalVariableTypeUsageMarker.
    772         //markAsUsed(localVariableTypeTableAttribute);
    773         //
    774         //markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
    775         //
    776         //// Mark the constant pool entries referenced by the local variable types.
    777         //localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
    778     }
    779 
    780 
    781     public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
    782     {
    783         // Don't mark the attribute and its contents yet. We may mark them later,
    784         // in AnnotationUsageMarker.
    785         //markAsUsed(annotationsAttribute);
    786         //
    787         //markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
    788         //
    789         //// Mark the constant pool entries referenced by the annotations.
    790         //annotationsAttribute.annotationsAccept(clazz, this);
    791     }
    792 
    793 
    794     public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
    795     {
    796         // Don't mark the attribute and its contents yet. We may mark them later,
    797         // in AnnotationUsageMarker.
    798         //markAsUsed(parameterAnnotationsAttribute);
    799         //
    800         //markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
    801         //
    802         //// Mark the constant pool entries referenced by the annotations.
    803         //parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
    804     }
    805 
    806 
    807     public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
    808     {
    809         // Don't mark the attribute and its contents yet. We may mark them later,
    810         // in AnnotationUsageMarker.
    811         //markAsUsed(annotationDefaultAttribute);
    812         //
    813         //markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
    814         //
    815         //// Mark the constant pool entries referenced by the element value.
    816         //annotationDefaultAttribute.defaultValueAccept(clazz, this);
    817     }
    818 
    819 
    820     // Implementations for ExceptionInfoVisitor.
    821 
    822     public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
    823     {
    824         markAsUsed(exceptionInfo);
    825 
    826         if (exceptionInfo.u2catchType != 0)
    827         {
    828             markConstant(clazz, exceptionInfo.u2catchType);
    829         }
    830     }
    831 
    832 
    833     // Implementations for InnerClassesInfoVisitor.
    834 
    835     public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
    836     {
    837         // At this point, we only mark outer classes of this class.
    838         // Inner class can be marked later, by InnerUsageMarker.
    839         if (innerClassesInfo.u2innerClassIndex != 0 &&
    840             clazz.getName().equals(clazz.getClassName(innerClassesInfo.u2innerClassIndex)))
    841         {
    842             markAsUsed(innerClassesInfo);
    843 
    844             innerClassesInfo.innerClassConstantAccept(clazz, this);
    845             innerClassesInfo.outerClassConstantAccept(clazz, this);
    846             innerClassesInfo.innerNameConstantAccept(clazz, this);
    847         }
    848     }
    849 
    850 
    851     // Implementations for StackMapFrameVisitor.
    852 
    853     public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
    854 
    855 
    856     public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
    857     {
    858         // Mark the constant pool entries referenced by the verification types.
    859         sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
    860     }
    861 
    862 
    863     public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
    864     {
    865         // Mark the constant pool entries referenced by the verification types.
    866         moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
    867     }
    868 
    869 
    870     public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
    871     {
    872         // Mark the constant pool entries referenced by the verification types.
    873         fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
    874         fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
    875     }
    876 
    877 
    878     // Implementations for VerificationTypeVisitor.
    879 
    880     public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
    881 
    882 
    883     public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
    884     {
    885         markConstant(clazz, objectType.u2classIndex);
    886     }
    887 
    888 
    889     // Implementations for ParameterInfoVisitor.
    890 
    891     public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
    892     {
    893         markConstant(clazz, parameterInfo.u2nameIndex);
    894     }
    895 
    896 
    897     // Implementations for LocalVariableInfoVisitor.
    898 
    899     public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
    900     {
    901         markConstant(clazz, localVariableInfo.u2nameIndex);
    902         markConstant(clazz, localVariableInfo.u2descriptorIndex);
    903     }
    904 
    905 
    906     // Implementations for LocalVariableTypeInfoVisitor.
    907 
    908     public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
    909     {
    910         markConstant(clazz, localVariableTypeInfo.u2nameIndex);
    911         markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
    912     }
    913 
    914 
    915 //    // Implementations for AnnotationVisitor.
    916 //
    917 //    public void visitAnnotation(Clazz clazz, Annotation annotation)
    918 //    {
    919 //        markConstant(clazz, annotation.u2typeIndex);
    920 //
    921 //        // Mark the constant pool entries referenced by the element values.
    922 //        annotation.elementValuesAccept(clazz, this);
    923 //    }
    924 //
    925 //
    926 //    // Implementations for ElementValueVisitor.
    927 //
    928 //    public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
    929 //    {
    930 //        if (constantElementValue.u2elementNameIndex != 0)
    931 //        {
    932 //            markConstant(clazz, constantElementValue.u2elementNameIndex);
    933 //        }
    934 //
    935 //        markConstant(clazz, constantElementValue.u2constantValueIndex);
    936 //    }
    937 //
    938 //
    939 //    public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
    940 //    {
    941 //        if (enumConstantElementValue.u2elementNameIndex != 0)
    942 //        {
    943 //            markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
    944 //        }
    945 //
    946 //        markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
    947 //        markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
    948 //    }
    949 //
    950 //
    951 //    public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
    952 //    {
    953 //        if (classElementValue.u2elementNameIndex != 0)
    954 //        {
    955 //            markConstant(clazz, classElementValue.u2elementNameIndex);
    956 //        }
    957 //
    958 //        // Mark the referenced class constant pool entry.
    959 //        markConstant(clazz, classElementValue.u2classInfoIndex);
    960 //    }
    961 //
    962 //
    963 //    public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
    964 //    {
    965 //        if (annotationElementValue.u2elementNameIndex != 0)
    966 //        {
    967 //            markConstant(clazz, annotationElementValue.u2elementNameIndex);
    968 //        }
    969 //
    970 //        // Mark the constant pool entries referenced by the annotation.
    971 //        annotationElementValue.annotationAccept(clazz, this);
    972 //    }
    973 //
    974 //
    975 //    public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
    976 //    {
    977 //        if (arrayElementValue.u2elementNameIndex != 0)
    978 //        {
    979 //            markConstant(clazz, arrayElementValue.u2elementNameIndex);
    980 //        }
    981 //
    982 //        // Mark the constant pool entries referenced by the element values.
    983 //        arrayElementValue.elementValuesAccept(clazz, annotation, this);
    984 //    }
    985 
    986 
    987     // Implementations for InstructionVisitor.
    988 
    989     public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
    990 
    991 
    992     public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
    993     {
    994         markConstant(clazz, constantInstruction.constantIndex);
    995 
    996         // Also mark the parameterless constructor of the class, in case the
    997         // string constant or class constant is being used in a Class.forName
    998         // or a .class construct.
    999         clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
   1000                                       parameterlessConstructorMarker);
   1001     }
   1002 
   1003 
   1004     // Small utility methods.
   1005 
   1006     /**
   1007      * Marks the given visitor accepter as being used.
   1008      */
   1009     protected void markAsUsed(VisitorAccepter visitorAccepter)
   1010     {
   1011         visitorAccepter.setVisitorInfo(USED);
   1012     }
   1013 
   1014 
   1015     /**
   1016      * Returns whether the given visitor accepter should still be marked as
   1017      * being used.
   1018      */
   1019     protected boolean shouldBeMarkedAsUsed(VisitorAccepter visitorAccepter)
   1020     {
   1021         return visitorAccepter.getVisitorInfo() != USED;
   1022     }
   1023 
   1024 
   1025     /**
   1026      * Returns whether the given visitor accepter has been marked as being used.
   1027      */
   1028     protected boolean isUsed(VisitorAccepter visitorAccepter)
   1029     {
   1030         return visitorAccepter.getVisitorInfo() == USED;
   1031     }
   1032 
   1033 
   1034     /**
   1035      * Marks the given visitor accepter as possibly being used.
   1036      */
   1037     protected void markAsPossiblyUsed(VisitorAccepter visitorAccepter)
   1038     {
   1039         visitorAccepter.setVisitorInfo(POSSIBLY_USED);
   1040     }
   1041 
   1042 
   1043     /**
   1044      * Returns whether the given visitor accepter should still be marked as
   1045      * possibly being used.
   1046      */
   1047     protected boolean shouldBeMarkedAsPossiblyUsed(VisitorAccepter visitorAccepter)
   1048     {
   1049         return visitorAccepter.getVisitorInfo() != USED &&
   1050                visitorAccepter.getVisitorInfo() != POSSIBLY_USED;
   1051     }
   1052 
   1053 
   1054     /**
   1055      * Returns whether the given visitor accepter has been marked as possibly
   1056      * being used.
   1057      */
   1058     protected boolean isPossiblyUsed(VisitorAccepter visitorAccepter)
   1059     {
   1060         return visitorAccepter.getVisitorInfo() == POSSIBLY_USED;
   1061     }
   1062 
   1063 
   1064     /**
   1065      * Clears any usage marks from the given visitor accepter.
   1066      */
   1067     protected void markAsUnused(VisitorAccepter visitorAccepter)
   1068     {
   1069         visitorAccepter.setVisitorInfo(null);
   1070     }
   1071 
   1072 
   1073     /**
   1074      * Marks the given constant pool entry of the given class. This includes
   1075      * visiting any referenced objects.
   1076      */
   1077     private void markConstant(Clazz clazz, int index)
   1078     {
   1079         clazz.constantPoolEntryAccept(index, this);
   1080     }
   1081 }
   1082