• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@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 
visitProgramClass(ProgramClass programClass)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 
markProgramClassBody(ProgramClass programClass)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 
visitLibraryClass(LibraryClass libraryClass)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     {
visitProgramClass(ProgramClass programClass)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 
visitLibraryClass(LibraryClass libraryClass)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 
visitProgramField(ProgramClass programClass, ProgramField programField)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 
visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)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 
visitAnyAttribute(Clazz clazz, Attribute attribute)239         public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
240 
241 
visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)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 
visitProgramField(ProgramClass programClass, ProgramField programField)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 
visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)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 
visitLibraryField(LibraryClass programClass, LibraryField programField)308     public void visitLibraryField(LibraryClass programClass, LibraryField programField) {}
309 
310 
visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)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 
markProgramFieldBody(ProgramClass programClass, ProgramField programField)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 
markProgramMethodBody(ProgramClass programClass, ProgramMethod programMethod)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      */
markMethodHierarchy(Clazz clazz, Method method)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 
visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)384     public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
385     {
386         if (shouldBeMarkedAsUsed(integerConstant))
387         {
388             markAsUsed(integerConstant);
389         }
390     }
391 
392 
visitLongConstant(Clazz clazz, LongConstant longConstant)393     public void visitLongConstant(Clazz clazz, LongConstant longConstant)
394     {
395         if (shouldBeMarkedAsUsed(longConstant))
396         {
397             markAsUsed(longConstant);
398         }
399     }
400 
401 
visitFloatConstant(Clazz clazz, FloatConstant floatConstant)402     public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
403     {
404         if (shouldBeMarkedAsUsed(floatConstant))
405         {
406             markAsUsed(floatConstant);
407         }
408     }
409 
410 
visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)411     public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
412     {
413         if (shouldBeMarkedAsUsed(doubleConstant))
414         {
415             markAsUsed(doubleConstant);
416         }
417     }
418 
419 
visitStringConstant(Clazz clazz, StringConstant stringConstant)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 
visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)435     public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
436     {
437         if (shouldBeMarkedAsUsed(utf8Constant))
438         {
439             markAsUsed(utf8Constant);
440         }
441     }
442 
443 
visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)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 
visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)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 
visitAnyRefConstant(Clazz clazz, RefConstant refConstant)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 
visitClassConstant(Clazz clazz, ClassConstant classConstant)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 
visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)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 
visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)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 
MyBootStrapMethodUsageMarker(int bootstrapMethodIndex)545         private MyBootStrapMethodUsageMarker(int bootstrapMethodIndex)
546         {
547             this.bootstrapMethodIndex = bootstrapMethodIndex;
548         }
549 
550 
551         // Implementations for AttributeVisitor.
552 
visitAnyAttribute(Clazz clazz, Attribute attribute)553         public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
554 
555 
visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)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 
visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)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 
visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)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 
visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)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 
visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)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 
visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)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 
visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)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 
visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)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 
visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)650     public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
651     {
652         markAsUsed(deprecatedAttribute);
653 
654         markConstant(clazz, deprecatedAttribute.u2attributeNameIndex);
655     }
656 
657 
visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)658     public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
659     {
660         markAsUsed(syntheticAttribute);
661 
662         markConstant(clazz, syntheticAttribute.u2attributeNameIndex);
663     }
664 
665 
visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)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 
visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)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 
visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)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 
visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)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 
visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)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 
visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)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 
visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)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 
visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)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 
visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)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 
visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)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 
visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)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 
visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)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 
visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)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 
visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)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 
visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)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 
visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)853     public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
854 
855 
visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)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 
visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)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 
visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)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 
visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)880     public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
881 
882 
visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)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 
visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)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 
visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)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 
visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)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 
visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)989     public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
990 
991 
visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)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      */
markAsUsed(VisitorAccepter visitorAccepter)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      */
shouldBeMarkedAsUsed(VisitorAccepter visitorAccepter)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      */
isUsed(VisitorAccepter visitorAccepter)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      */
markAsPossiblyUsed(VisitorAccepter visitorAccepter)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      */
shouldBeMarkedAsPossiblyUsed(VisitorAccepter visitorAccepter)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      */
isPossiblyUsed(VisitorAccepter visitorAccepter)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      */
markAsUnused(VisitorAccepter visitorAccepter)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      */
markConstant(Clazz clazz, int index)1077     private void markConstant(Clazz clazz, int index)
1078     {
1079         clazz.constantPoolEntryAccept(index, this);
1080     }
1081 }
1082