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