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); } }
/** * 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); } } } }
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); } }
/** * 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))))); } }
public boolean extends_(Clazz clazz) { if (this.equals(clazz)) { return true; } return superClass != null && superClass.extends_(clazz); }
public boolean extends_(String className) { if (getName().equals(className)) { return true; } return superClass != null && superClass.extends_(className); }
/** * 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))))); } }
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); } } } }
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)); } }
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; }
public String toString() { return "certain=" + certain + ", depth=" + depth + ": " + reason + (clazz != null ? clazz.getName() : "(none)") + ": " + (member != null ? member.getName(clazz) : "(none)"); }
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); }
/** * 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))))); } }
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()); } }
/** * 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); } }
/** * 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); } }
/** Returns whether this is mark is caused by the given class. */ public boolean isCausedBy(Clazz clazz) { return clazz.equals(this.clazz); }
public void referencedClassesAccept(ClassVisitor classVisitor) { if (referencedClass != null) { referencedClass.accept(classVisitor); } }
/** * 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); }