Пример #1
0
  public void visitLibraryClass(LibraryClass libraryClass) {
    if (shouldBeMarkedAsUsed(libraryClass)) {
      markAsUsed(libraryClass);

      // We're not going to analyze all library code. We're assuming that
      // if this class is being used, all of its methods will be used as
      // well. We'll mark them as such (here and in all subclasses).

      // Mark the superclass.
      Clazz superClass = libraryClass.superClass;
      if (superClass != null) {
        superClass.accept(this);
      }

      // Mark the interfaces.
      Clazz[] interfaceClasses = libraryClass.interfaceClasses;
      if (interfaceClasses != null) {
        for (int index = 0; index < interfaceClasses.length; index++) {
          if (interfaceClasses[index] != null) {
            interfaceClasses[index].accept(this);
          }
        }
      }

      // Mark all methods.
      libraryClass.methodsAccept(this);
    }
  }
Пример #2
0
 /**
  * Lets the given class visitor visit all known direct interfaces.
  *
  * @param classVisitor the <code>ClassVisitor</code> that will visit the interfaces.
  */
 public void interfacesAccept(ClassVisitor classVisitor) {
   if (interfaceClasses != null) {
     for (int index = 0; index < interfaceClasses.length; index++) {
       Clazz interfaceClass = interfaceClasses[index];
       if (interfaceClass != null) {
         interfaceClass.accept(classVisitor);
       }
     }
   }
 }
Пример #3
0
  public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) {
    // At this point, we only mark outer classes of this class.
    // Inner class can be marked later, by InnerUsageMarker.
    if (innerClassesInfo.u2innerClassIndex != 0
        && clazz.getName().equals(clazz.getClassName(innerClassesInfo.u2innerClassIndex))) {
      markAsUsed(innerClassesInfo);

      innerClassesInfo.innerClassConstantAccept(clazz, this);
      innerClassesInfo.outerClassConstantAccept(clazz, this);
      innerClassesInfo.innerNameConstantAccept(clazz, this);
    }
  }
Пример #4
0
  /**
   * Marks the hierarchy of implementing or overriding methods corresponding to the given method, if
   * any.
   */
  protected void markMethodHierarchy(Clazz clazz, Method method) {
    int accessFlags = method.getAccessFlags();
    if ((accessFlags & (ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC)) == 0
        && !ClassUtil.isInitializer(method.getName(clazz))) {
      // We can skip private and static methods in the hierarchy, and
      // also abstract methods, unless they might widen a current
      // non-public access.
      int requiredUnsetAccessFlags =
          ClassConstants.ACC_PRIVATE
              | ClassConstants.ACC_STATIC
              | ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 : ClassConstants.ACC_ABSTRACT);

      clazz.accept(
          new ConcreteClassDownTraveler(
              new ClassHierarchyTraveler(
                  true,
                  true,
                  false,
                  true,
                  new NamedMethodVisitor(
                      method.getName(clazz),
                      method.getDescriptor(clazz),
                      new MemberAccessFilter(0, requiredUnsetAccessFlags, this)))));
    }
  }
Пример #5
0
  public boolean extends_(Clazz clazz) {
    if (this.equals(clazz)) {
      return true;
    }

    return superClass != null && superClass.extends_(clazz);
  }
Пример #6
0
  public boolean extends_(String className) {
    if (getName().equals(className)) {
      return true;
    }

    return superClass != null && superClass.extends_(className);
  }
Пример #7
0
  /**
   * Marks the hierarchy of implementing or overriding methods corresponding to the given method, if
   * any.
   */
  protected void markMethodHierarchy(Clazz clazz, Method method) {
    int accessFlags = method.getAccessFlags();
    if ((accessFlags & (ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC)) == 0
        && !ClassUtil.isInitializer(method.getName(clazz))) {
      // We can skip private and static methods in the hierarchy, and
      // also abstract methods, unless they might widen a current
      // non-public access.
      int requiredUnsetAccessFlags =
          ClassConstants.ACC_PRIVATE
              | ClassConstants.ACC_STATIC
              | ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 : ClassConstants.ACC_ABSTRACT);

      // Mark default implementations in interfaces down the hierarchy.
      // TODO: This may be premature if there aren't any concrete implementing classes.
      clazz.accept(
          new ClassAccessFilter(
              ClassConstants.ACC_ABSTRACT,
              0,
              new ClassHierarchyTraveler(
                  false,
                  false,
                  false,
                  true,
                  new ProgramClassFilter(
                      new ClassAccessFilter(
                          ClassConstants.ACC_ABSTRACT,
                          0,
                          new NamedMethodVisitor(
                              method.getName(clazz),
                              method.getDescriptor(clazz),
                              new MemberAccessFilter(
                                  0, requiredUnsetAccessFlags, defaultMethodUsageMarker)))))));

      // Mark other implementations.
      clazz.accept(
          new ConcreteClassDownTraveler(
              new ClassHierarchyTraveler(
                  true,
                  true,
                  false,
                  true,
                  new NamedMethodVisitor(
                      method.getName(clazz),
                      method.getDescriptor(clazz),
                      new MemberAccessFilter(0, requiredUnsetAccessFlags, this)))));
    }
  }
Пример #8
0
  public void hierarchyAccept(
      boolean visitThisClass,
      boolean visitSuperClass,
      boolean visitInterfaces,
      boolean visitSubclasses,
      ClassVisitor classVisitor) {
    // First visit the current classfile.
    if (visitThisClass) {
      accept(classVisitor);
    }

    // Then visit its superclass, recursively.
    if (visitSuperClass) {
      if (superClass != null) {
        superClass.hierarchyAccept(true, true, visitInterfaces, false, classVisitor);
      }
    }

    // Then visit its interfaces, recursively.
    if (visitInterfaces) {
      // Visit the interfaces of the superclasses, if we haven't done so yet.
      if (!visitSuperClass) {
        if (superClass != null) {
          superClass.hierarchyAccept(false, false, true, false, classVisitor);
        }
      }

      // Visit the interfaces.
      if (interfaceClasses != null) {
        for (int index = 0; index < interfaceClasses.length; index++) {
          Clazz interfaceClass = interfaceClasses[index];
          if (interfaceClass != null) {
            interfaceClass.hierarchyAccept(true, false, true, false, classVisitor);
          }
        }
      }
    }

    // Then visit its subclasses, recursively.
    if (visitSubclasses) {
      if (subClasses != null) {
        for (int index = 0; index < subClasses.length; index++) {
          subClasses[index].hierarchyAccept(true, false, false, true, classVisitor);
        }
      }
    }
  }
Пример #9
0
  public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) {
    if (shouldBeMarkedAsUsed(invokeDynamicConstant)) {
      markAsUsed(invokeDynamicConstant);

      markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);

      // Mark the bootstrap methods attribute.
      clazz.attributesAccept(
          new MyBootStrapMethodUsageMarker(invokeDynamicConstant.u2bootstrapMethodAttributeIndex));
    }
  }
Пример #10
0
  public boolean extendsOrImplements(String className) {
    if (getName().equals(className)) {
      return true;
    }

    if (superClass != null && superClass.extendsOrImplements(className)) {
      return true;
    }

    if (interfaceClasses != null) {
      for (int index = 0; index < interfaceClasses.length; index++) {
        Clazz interfaceClass = interfaceClasses[index];
        if (interfaceClass != null && interfaceClass.extendsOrImplements(className)) {
          return true;
        }
      }
    }

    return false;
  }
Пример #11
0
 public String toString() {
   return "certain="
       + certain
       + ", depth="
       + depth
       + ": "
       + reason
       + (clazz != null ? clazz.getName() : "(none)")
       + ": "
       + (member != null ? member.getName(clazz) : "(none)");
 }
Пример #12
0
  public void visitConstantInstruction(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      ConstantInstruction constantInstruction) {
    markConstant(clazz, constantInstruction.constantIndex);

    // Also mark the parameterless constructor of the class, in case the
    // string constant or class constant is being used in a Class.forName
    // or a .class construct.
    clazz.constantPoolEntryAccept(
        constantInstruction.constantIndex, parameterlessConstructorMarker);
  }
Пример #13
0
 /**
  * Marks the hierarchy of implementing or overriding methods corresponding to the given method, if
  * any.
  */
 protected void markMethodHierarchy(Clazz clazz, Method method) {
   if ((method.getAccessFlags()
           & (ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC))
       == 0) {
     clazz.accept(
         new ConcreteClassDownTraveler(
             new ClassHierarchyTraveler(
                 true,
                 true,
                 false,
                 true,
                 new NamedMethodVisitor(
                     method.getName(clazz),
                     method.getDescriptor(clazz),
                     new MemberAccessFilter(
                         0,
                         ClassConstants.INTERNAL_ACC_PRIVATE
                             | ClassConstants.INTERNAL_ACC_STATIC
                             | ClassConstants.INTERNAL_ACC_ABSTRACT,
                         this)))));
   }
 }
Пример #14
0
  public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) {
    //        DEBUG =
    //            clazz.getName().equals("abc/Def") &&
    //            method.getName(clazz).equals("abc");

    if (DEBUG) {
      method.accept(clazz, new ClassPrinter());
    }

    branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);

    // Don't bother if there aren't any subroutines anyway.
    if (!containsSubroutines(codeAttribute)) {
      return;
    }

    if (DEBUG) {
      System.out.println(
          "SubroutineInliner: processing ["
              + clazz.getName()
              + "."
              + method.getName(clazz)
              + method.getDescriptor(clazz)
              + "]");
    }

    // Append the body of the code.
    codeAttributeComposer.reset();
    codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);

    // Copy the non-subroutine instructions.
    int offset = 0;
    while (offset < codeAttribute.u4codeLength) {
      Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
      int instructionLength = instruction.length(offset);

      // Is this returning subroutine?
      if (branchTargetFinder.isSubroutine(offset)
          && branchTargetFinder.isSubroutineReturning(offset)) {
        // Skip the subroutine.
        if (DEBUG) {
          System.out.println(
              "  Skipping original subroutine instruction " + instruction.toString(offset));
        }

        // Append a label at this offset instead.
        codeAttributeComposer.appendLabel(offset);
      } else {
        // Copy the instruction, inlining any subroutine call recursively.
        instruction.accept(clazz, method, codeAttribute, offset, this);
      }

      offset += instructionLength;
    }

    // Copy the exceptions. Note that exceptions with empty try blocks
    // are automatically removed.
    codeAttribute.exceptionsAccept(clazz, method, subroutineExceptionInliner);

    if (DEBUG) {
      System.out.println("  Appending label after code at [" + offset + "]");
    }

    // Append a label just after the code.
    codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);

    // End and update the code attribute.
    codeAttributeComposer.endCodeFragment();
    codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);

    if (DEBUG) {
      method.accept(clazz, new ClassPrinter());
    }
  }
Пример #15
0
 /**
  * Lets the given class visitor visit the superclass, if it is known.
  *
  * @param classVisitor the <code>ClassVisitor</code> that will visit the superclass.
  */
 public void superClassAccept(ClassVisitor classVisitor) {
   if (superClass != null) {
     superClass.accept(classVisitor);
   }
 }
Пример #16
0
 /**
  * Applies the given class visitor to this mark's class, if any, and if this mark doesn't have a
  * member.
  */
 public void acceptClassVisitor(ClassVisitor classVisitor) {
   if (clazz != null && member == null) {
     clazz.accept(classVisitor);
   }
 }
Пример #17
0
 /** Returns whether this is mark is caused by the given class. */
 public boolean isCausedBy(Clazz clazz) {
   return clazz.equals(this.clazz);
 }
Пример #18
0
 public void referencedClassesAccept(ClassVisitor classVisitor) {
   if (referencedClass != null) {
     referencedClass.accept(classVisitor);
   }
 }
Пример #19
0
 /**
  * Marks the given constant pool entry of the given class. This includes visiting any referenced
  * objects.
  */
 private void markConstant(Clazz clazz, int index) {
   clazz.constantPoolEntryAccept(index, this);
 }