public void visitProgramClass(ProgramClass programClass) { int[] interfaces = programClass.u2interfaces; int interfacesCount = programClass.u2interfacesCount; if (interfacesCount > 1) { // Sort the interfaces. Arrays.sort(interfaces, 0, interfacesCount); // Remove any duplicate entries. int newInterfacesCount = 0; int previousInterfaceIndex = 0; for (int index = 0; index < interfacesCount; index++) { int interfaceIndex = interfaces[index]; // Isn't this a duplicate of the previous interface? if (interfaceIndex != previousInterfaceIndex) { interfaces[newInterfacesCount++] = interfaceIndex; // Remember the interface. previousInterfaceIndex = interfaceIndex; } } programClass.u2interfacesCount = newInterfacesCount; // Update the signature, if any programClass.attributesAccept(this); } }
protected void markProgramClassBody(ProgramClass programClass) { // Mark this class's name. markConstant(programClass, programClass.u2thisClass); // Mark the superclass. if (programClass.u2superClass != 0) { markConstant(programClass, programClass.u2superClass); } // Give the interfaces preliminary marks. programClass.hierarchyAccept(false, false, true, false, interfaceUsageMarker); // Explicitly mark the <clinit> method, if it's not empty. programClass.methodAccept( ClassConstants.METHOD_NAME_CLINIT, ClassConstants.METHOD_TYPE_CLINIT, nonEmptyMethodUsageMarker); // Process all class members that have already been marked as possibly used. programClass.fieldsAccept(possiblyUsedMemberUsageMarker); programClass.methodsAccept(possiblyUsedMemberUsageMarker); // Mark the attributes. programClass.attributesAccept(this); }
public void visitProgramClass(ProgramClass programClass) { // Visit the constant pool entries. programClass.constantPoolEntriesAccept(this); // Visit the fields and methods. programClass.fieldsAccept(this); programClass.methodsAccept(this); // Visit the attributes. programClass.attributesAccept(this); }
public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { // Process the generic definitions, superclass, and implemented // interfaces. String signature = clazz.getString(signatureAttribute.u2signatureIndex); // Count the signature types. InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(signature); int count = 0; int interfacesCount = -1; while (internalTypeEnumeration.hasMoreTypes()) { String internalType = internalTypeEnumeration.nextType(); count++; if (ClassUtil.isInternalClassType(internalType)) { interfacesCount++; } } // Put the signature types in an array. internalTypeEnumeration = new InternalTypeEnumeration(signature); String[] internalTypes = new String[count]; for (int index = 0; index < count; index++) { String internalType = internalTypeEnumeration.nextType(); internalTypes[index] = internalType; } // Sort the interface types in the array. Arrays.sort(internalTypes, count - interfacesCount, count); // Recompose the signature types in a string. StringBuffer newSignatureBuffer = new StringBuffer(); for (int index = 0; index < count; index++) { // Is this not an interface type, or an interface type that isn't // a duplicate of the previous interface type? if (index < count - interfacesCount || !internalTypes[index].equals(internalTypes[index - 1])) { newSignatureBuffer.append(internalTypes[index]); } } String newSignature = newSignatureBuffer.toString(); // Did the signature change? if (!newSignature.equals(signature)) { // Update the signature. ((Utf8Constant) ((ProgramClass) clazz).constantPool[signatureAttribute.u2signatureIndex]) .setString(newSignatureBuffer.toString()); // Clear the referenced classes. // TODO: Properly update the referenced classes. signatureAttribute.referencedClasses = null; } }
public void visitProgramClass(ProgramClass programClass) { if (DEBUG) { System.out.println("SimpleEnumClassSimplifier: [" + programClass.getName() + "]"); } // Unmark the class as an enum. programClass.u2accessFlags &= ~ClassConstants.ACC_ENUM; // Remove the valueOf method, if present. Method valueOfMethod = programClass.findMethod(ClassConstants.METHOD_NAME_VALUEOF, null); if (valueOfMethod != null) { new ClassEditor(programClass).removeMethod(valueOfMethod); } // Simplify the static initializer. programClass.methodAccept( ClassConstants.METHOD_NAME_CLINIT, ClassConstants.METHOD_TYPE_CLINIT, initializerSimplifier); }
/** Deletes the specified attribute from the target. */ public void deleteAttribute(String attributeName) { // What's the target? if (targetAttribute != null) { targetAttribute.u2attributesCount = deleteAttribute( targetAttribute.u2attributesCount, targetAttribute.attributes, attributeName); } else if (targetMember != null) { targetMember.u2attributesCount = deleteAttribute(targetMember.u2attributesCount, targetMember.attributes, attributeName); } else { targetClass.u2attributesCount = deleteAttribute(targetClass.u2attributesCount, targetClass.attributes, attributeName); } }
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { // Update the descriptor if it has any unused parameters. String descriptor = programMethod.getDescriptor(programClass); String newDescriptor = shrinkDescriptor(programMethod, descriptor); if (!descriptor.equals(newDescriptor)) { // Shrink the signature and parameter annotations. programMethod.attributesAccept(programClass, this); String name = programMethod.getName(programClass); String newName = name; // Append a code, if the method isn't a class instance initializer. if (!name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) { newName += ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); } if (DEBUG) { System.out.println("MethodDescriptorShrinker:"); System.out.println(" Class file = " + programClass.getName()); System.out.println(" Method name = " + name); System.out.println(" -> " + newName); System.out.println(" Method descriptor = " + descriptor); System.out.println(" -> " + newDescriptor); } ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(programClass); // Update the name, if necessary. if (!newName.equals(name)) { programMethod.u2nameIndex = constantPoolEditor.addUtf8Constant(newName); } // Update the referenced classes. programMethod.referencedClasses = shrinkReferencedClasses(programMethod, descriptor, programMethod.referencedClasses); // Finally, update the descriptor itself. programMethod.u2descriptorIndex = constantPoolEditor.addUtf8Constant(newDescriptor); // Visit the method, if required. if (extraMemberVisitor != null) { extraMemberVisitor.visitProgramMethod(programClass, programMethod); } } }
/** Adds the given attribute to the target. */ public void addAttribute(Attribute attribute) { // What's the target? if (targetAttribute != null) { // Try to replace an existing attribute. if (!replaceAttributes || !replaceAttribute( targetAttribute.u2attributesCount, targetAttribute.attributes, attribute)) { // Otherwise append the attribute. targetAttribute.attributes = addAttribute(targetAttribute.u2attributesCount, targetAttribute.attributes, attribute); targetAttribute.u2attributesCount++; } } else if (targetMember != null) { // Try to replace an existing attribute. if (!replaceAttributes || !replaceAttribute( targetMember.u2attributesCount, targetMember.attributes, attribute)) { // Otherwise append the attribute. targetMember.attributes = addAttribute(targetMember.u2attributesCount, targetMember.attributes, attribute); targetMember.u2attributesCount++; } } else { // Try to replace an existing attribute. if (!replaceAttributes || !replaceAttribute(targetClass.u2attributesCount, targetClass.attributes, attribute)) { // Otherwise append the attribute. targetClass.attributes = addAttribute(targetClass.u2attributesCount, targetClass.attributes, attribute); targetClass.u2attributesCount++; } } }