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 */ 21package proguard.shrink; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.*; 25import proguard.classfile.attribute.annotation.*; 26import proguard.classfile.attribute.preverification.*; 27import proguard.classfile.attribute.preverification.visitor.*; 28import proguard.classfile.attribute.visitor.*; 29import proguard.classfile.constant.*; 30import proguard.classfile.constant.visitor.*; 31import proguard.classfile.instruction.*; 32import proguard.classfile.instruction.visitor.InstructionVisitor; 33import proguard.classfile.util.*; 34import 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 */ 45class UsageMarker 46extends SimplifiedVisitor 47implements 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