1 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.ConstantVisitor; 31 import proguard.classfile.instruction.*; 32 import proguard.classfile.instruction.visitor.InstructionVisitor; 33 import proguard.classfile.util.SimplifiedVisitor; 34 import proguard.classfile.visitor.*; 35 36 37 45 class UsageMarker 46 extends SimplifiedVisitor 47 implements ClassVisitor, 48 MemberVisitor, 49 ConstantVisitor, 50 AttributeVisitor, 51 InnerClassesInfoVisitor, 52 ExceptionInfoVisitor, 53 StackMapFrameVisitor, 54 VerificationTypeVisitor, 55 LocalVariableInfoVisitor, 56 LocalVariableTypeInfoVisitor, 57 InstructionVisitor 60 { 61 private static final Object POSSIBLY_USED = new Object (); 64 private static final Object USED = new Object (); 66 67 68 private MyInterfaceUsageMarker interfaceUsageMarker = new MyInterfaceUsageMarker(); 69 private MyPossiblyUsedMethodUsageMarker possiblyUsedMethodUsageMarker = new MyPossiblyUsedMethodUsageMarker(); 70 80 81 83 public void visitProgramClass(ProgramClass programClass) 84 { 85 if (shouldBeMarkedAsUsed(programClass)) 86 { 87 markAsUsed(programClass); 89 90 markProgramClassBody(programClass); 91 } 92 } 93 94 95 protected void markProgramClassBody(ProgramClass programClass) 96 { 97 markConstant(programClass, programClass.u2thisClass); 99 100 if (programClass.u2superClass != 0) 102 { 103 markConstant(programClass, programClass.u2superClass); 104 } 105 106 programClass.hierarchyAccept(false, false, true, false, 108 interfaceUsageMarker); 109 110 programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, 112 ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, 113 this); 114 115 programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT, 117 ClassConstants.INTERNAL_METHOD_TYPE_INIT, 118 this); 119 120 programClass.methodsAccept(possiblyUsedMethodUsageMarker); 122 123 programClass.attributesAccept(this); 125 } 126 127 128 public void visitLibraryClass(LibraryClass libraryClass) 129 { 130 if (shouldBeMarkedAsUsed(libraryClass)) 131 { 132 markAsUsed(libraryClass); 133 134 138 Clazz superClass = libraryClass.superClass; 140 if (superClass != null) 141 { 142 superClass.accept(this); 143 } 144 145 Clazz[] interfaceClasses = libraryClass.interfaceClasses; 147 if (interfaceClasses != null) 148 { 149 for (int index = 0; index < interfaceClasses.length; index++) 150 { 151 if (interfaceClasses[index] != null) 152 { 153 interfaceClasses[index].accept(this); 154 } 155 } 156 } 157 158 libraryClass.methodsAccept(this); 160 } 161 } 162 163 164 168 private class MyInterfaceUsageMarker 169 implements ClassVisitor 170 { 171 public void visitProgramClass(ProgramClass programClass) 172 { 173 if (shouldBeMarkedAsPossiblyUsed(programClass)) 174 { 175 markAsPossiblyUsed(programClass); 178 } 179 } 180 181 public void visitLibraryClass(LibraryClass libraryClass) 182 { 183 UsageMarker.this.visitLibraryClass(libraryClass); 185 } 186 } 187 188 189 private class MyPossiblyUsedMethodUsageMarker 190 extends SimplifiedVisitor 191 implements MemberVisitor 192 { 193 195 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 196 { 197 if (isPossiblyUsed(programMethod)) 199 { 200 markAsUsed(programMethod); 201 202 markProgramMethodBody(programClass, programMethod); 204 205 } 208 } 209 210 211 } 212 213 214 216 public void visitProgramField(ProgramClass programClass, ProgramField programField) 217 { 218 if (shouldBeMarkedAsUsed(programField)) 219 { 220 markAsUsed(programField); 221 222 markConstant(programClass, programField.u2nameIndex); 224 markConstant(programClass, programField.u2descriptorIndex); 225 226 programField.attributesAccept(programClass, this); 228 229 programField.referencedClassesAccept(this); 231 } 232 } 233 234 235 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 236 { 237 if (shouldBeMarkedAsUsed(programMethod)) 238 { 239 if (isUsed(programClass)) 241 { 242 markAsUsed(programMethod); 243 244 markProgramMethodBody(programClass, programMethod); 246 247 markMethodHierarchy(programClass, programMethod); 249 } 250 251 else if (shouldBeMarkedAsPossiblyUsed(programMethod)) 253 { 254 markAsPossiblyUsed(programMethod); 257 258 markMethodHierarchy(programClass, programMethod); 260 } 261 } 262 } 263 264 265 public void visitLibraryField(LibraryClass programClass, LibraryField programField) {} 266 267 268 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 269 { 270 if (shouldBeMarkedAsUsed(libraryMethod)) 271 { 272 markAsUsed(libraryMethod); 273 274 markMethodHierarchy(libraryClass, libraryMethod); 276 } 277 } 278 279 280 protected void markProgramMethodBody(ProgramClass programClass, ProgramMethod programMethod) 281 { 282 markConstant(programClass, programMethod.u2nameIndex); 284 markConstant(programClass, programMethod.u2descriptorIndex); 285 286 programMethod.attributesAccept(programClass, this); 288 289 programMethod.referencedClassesAccept(this); 291 } 292 293 294 298 protected void markMethodHierarchy(Clazz clazz, Method method) 299 { 300 clazz.methodImplementationsAccept(method, false, this); 301 } 302 303 304 306 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 307 { 308 if (shouldBeMarkedAsUsed(integerConstant)) 309 { 310 markAsUsed(integerConstant); 311 } 312 } 313 314 315 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 316 { 317 if (shouldBeMarkedAsUsed(longConstant)) 318 { 319 markAsUsed(longConstant); 320 } 321 } 322 323 324 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 325 { 326 if (shouldBeMarkedAsUsed(floatConstant)) 327 { 328 markAsUsed(floatConstant); 329 } 330 } 331 332 333 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 334 { 335 if (shouldBeMarkedAsUsed(doubleConstant)) 336 { 337 markAsUsed(doubleConstant); 338 } 339 } 340 341 342 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 343 { 344 if (shouldBeMarkedAsUsed(stringConstant)) 345 { 346 markAsUsed(stringConstant); 347 348 markConstant(clazz, stringConstant.u2stringIndex); 349 350 354 stringConstant.referencedClassAccept(this); 356 stringConstant.referencedMemberAccept(this); 357 } 358 } 359 360 361 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 362 { 363 if (shouldBeMarkedAsUsed(utf8Constant)) 364 { 365 markAsUsed(utf8Constant); 366 } 367 } 368 369 370 public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) 371 { 372 visitRefConstant(clazz, fieldrefConstant); 373 } 374 375 376 public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) 377 { 378 visitRefConstant(clazz, interfaceMethodrefConstant); 379 } 380 381 382 public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) 383 { 384 visitRefConstant(clazz, methodrefConstant); 385 } 386 387 388 private void visitRefConstant(Clazz clazz, RefConstant methodrefConstant) 389 { 390 if (shouldBeMarkedAsUsed(methodrefConstant)) 391 { 392 markAsUsed(methodrefConstant); 393 394 markConstant(clazz, methodrefConstant.u2classIndex); 395 markConstant(clazz, methodrefConstant.u2nameAndTypeIndex); 396 397 methodrefConstant.referencedClassAccept(this); 402 403 methodrefConstant.referencedMemberAccept(this); 405 } 406 } 407 408 409 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 410 { 411 if (shouldBeMarkedAsUsed(classConstant)) 412 { 413 markAsUsed(classConstant); 414 415 markConstant(clazz, classConstant.u2nameIndex); 416 417 classConstant.referencedClassAccept(this); 419 } 420 } 421 422 423 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 424 { 425 if (shouldBeMarkedAsUsed(nameAndTypeConstant)) 426 { 427 markAsUsed(nameAndTypeConstant); 428 429 markConstant(clazz, nameAndTypeConstant.u2nameIndex); 430 markConstant(clazz, nameAndTypeConstant.u2descriptorIndex); 431 } 432 } 433 434 435 439 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 440 { 441 markAsUsed(unknownAttribute); 443 444 markConstant(clazz, unknownAttribute.u2attributeNameIndex); 445 } 446 447 448 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 449 { 450 markAsUsed(sourceFileAttribute); 451 452 markConstant(clazz, sourceFileAttribute.u2attributeNameIndex); 453 markConstant(clazz, sourceFileAttribute.u2sourceFileIndex); 454 } 455 456 457 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 458 { 459 markAsUsed(sourceDirAttribute); 460 461 markConstant(clazz, sourceDirAttribute.u2attributeNameIndex); 462 markConstant(clazz, sourceDirAttribute.u2sourceDirIndex); 463 } 464 465 466 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 467 { 468 472 474 innerClassesAttribute.innerClassEntriesAccept(clazz, this); 476 } 477 478 479 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 480 { 481 markAsUsed(enclosingMethodAttribute); 482 483 markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex); 484 markConstant(clazz, enclosingMethodAttribute.u2classIndex); 485 486 if (enclosingMethodAttribute.u2nameAndTypeIndex != 0) 487 { 488 markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex); 489 } 490 } 491 492 493 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 494 { 495 markAsUsed(deprecatedAttribute); 496 497 markConstant(clazz, deprecatedAttribute.u2attributeNameIndex); 498 } 499 500 501 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 502 { 503 markAsUsed(syntheticAttribute); 504 505 markConstant(clazz, syntheticAttribute.u2attributeNameIndex); 506 } 507 508 509 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 510 { 511 markAsUsed(signatureAttribute); 512 513 markConstant(clazz, signatureAttribute.u2attributeNameIndex); 514 markConstant(clazz, signatureAttribute.u2signatureIndex); 515 } 516 517 518 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 519 { 520 markAsUsed(constantValueAttribute); 521 522 markConstant(clazz, constantValueAttribute.u2attributeNameIndex); 523 markConstant(clazz, constantValueAttribute.u2constantValueIndex); 524 } 525 526 527 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 528 { 529 markAsUsed(exceptionsAttribute); 530 531 markConstant(clazz, exceptionsAttribute.u2attributeNameIndex); 532 533 exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this); 535 } 536 537 538 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 539 { 540 markAsUsed(codeAttribute); 541 542 markConstant(clazz, codeAttribute.u2attributeNameIndex); 543 544 codeAttribute.instructionsAccept(clazz, method, this); 547 codeAttribute.exceptionsAccept(clazz, method, this); 548 codeAttribute.attributesAccept(clazz, method, this); 549 } 550 551 552 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 553 { 554 markAsUsed(stackMapAttribute); 555 556 markConstant(clazz, stackMapAttribute.u2attributeNameIndex); 557 558 stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 560 } 561 562 563 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 564 { 565 markAsUsed(stackMapTableAttribute); 566 567 markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex); 568 569 stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 571 } 572 573 574 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 575 { 576 markAsUsed(lineNumberTableAttribute); 577 578 markConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex); 579 } 580 581 582 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 583 { 584 markAsUsed(localVariableTableAttribute); 585 586 markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex); 587 588 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 590 } 591 592 593 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 594 { 595 markAsUsed(localVariableTypeTableAttribute); 596 597 markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex); 598 599 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 601 } 602 603 604 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 605 { 606 } 615 616 617 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 618 { 619 } 628 629 630 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 631 { 632 } 641 642 643 645 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 646 { 647 markAsUsed(exceptionInfo); 648 649 if (exceptionInfo.u2catchType != 0) 650 { 651 markConstant(clazz, exceptionInfo.u2catchType); 652 } 653 } 654 655 656 658 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 659 { 660 if (innerClassesInfo.u2innerClassIndex == 0 && 663 clazz.getName().equals(clazz.getClassName(innerClassesInfo.u2innerClassIndex))) 664 { 665 markAsUsed(innerClassesInfo); 666 667 if (innerClassesInfo.u2innerClassIndex != 0) 668 { 669 markConstant(clazz, innerClassesInfo.u2innerClassIndex); 670 } 671 672 if (innerClassesInfo.u2outerClassIndex != 0) 673 { 674 markConstant(clazz, innerClassesInfo.u2outerClassIndex); 675 } 676 677 if (innerClassesInfo.u2innerNameIndex != 0) 678 { 679 markConstant(clazz, innerClassesInfo.u2innerNameIndex); 680 } 681 } 682 } 683 684 685 687 public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {} 688 689 690 public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 691 { 692 sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); 694 } 695 696 697 public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 698 { 699 moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); 701 } 702 703 704 public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 705 { 706 fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); 708 fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); 709 } 710 711 712 714 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {} 715 716 717 public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) 718 { 719 markConstant(clazz, objectType.u2classIndex); 720 } 721 722 723 725 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 726 { 727 markConstant(clazz, localVariableInfo.u2nameIndex); 728 markConstant(clazz, localVariableInfo.u2descriptorIndex); 729 } 730 731 732 734 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 735 { 736 markConstant(clazz, localVariableTypeInfo.u2nameIndex); 737 markConstant(clazz, localVariableTypeInfo.u2signatureIndex); 738 } 739 740 741 812 813 815 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 816 817 818 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 819 { 820 markConstant(clazz, constantInstruction.constantIndex); 821 } 822 823 824 826 829 protected void markAsUsed(VisitorAccepter visitorAccepter) 830 { 831 visitorAccepter.setVisitorInfo(USED); 832 } 833 834 835 839 protected boolean shouldBeMarkedAsUsed(VisitorAccepter visitorAccepter) 840 { 841 return visitorAccepter.getVisitorInfo() != USED; 842 } 843 844 845 848 protected boolean isUsed(VisitorAccepter visitorAccepter) 849 { 850 return visitorAccepter.getVisitorInfo() == USED; 851 } 852 853 854 857 protected void markAsPossiblyUsed(VisitorAccepter visitorAccepter) 858 { 859 visitorAccepter.setVisitorInfo(POSSIBLY_USED); 860 } 861 862 863 867 protected boolean shouldBeMarkedAsPossiblyUsed(VisitorAccepter visitorAccepter) 868 { 869 return visitorAccepter.getVisitorInfo() != USED && 870 visitorAccepter.getVisitorInfo() != POSSIBLY_USED; 871 } 872 873 874 878 protected boolean isPossiblyUsed(VisitorAccepter visitorAccepter) 879 { 880 return visitorAccepter.getVisitorInfo() == POSSIBLY_USED; 881 } 882 883 884 887 protected void markAsUnused(VisitorAccepter visitorAccepter) 888 { 889 visitorAccepter.setVisitorInfo(null); 890 } 891 892 893 897 private void markConstant(Clazz clazz, int index) 898 { 899 clazz.constantPoolEntryAccept(index, this); 900 } 901 } 902 | Popular Tags |