/** Returns the ClassMemberSpecification currently represented in this dialog. */ public ClassMemberSpecification getClassMemberSpecification() { String name = nameTextField.getText(); String type = typeTextField.getText(); String arguments = argumentsTextField.getText(); if (name.equals("") || name.equals("*")) { name = null; } if (type.equals("") || type.equals("*")) { type = null; } if (name != null || type != null) { if (isField) { if (type == null) { type = ClassConstants.EXTERNAL_TYPE_INT; } type = ClassUtil.internalType(type); } else { if (type == null) { type = ClassConstants.EXTERNAL_TYPE_VOID; } type = ClassUtil.internalMethodDescriptor(type, ListUtil.commaSeparatedList(arguments)); } } ClassMemberSpecification classMemberSpecification = new ClassMemberSpecification(0, 0, name, type); // Also get the access radio button settings. getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_PRIVATE, privateRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_SYNCHRONIZED, synchronizedRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons); getClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons); return classMemberSpecification; }
public void visitProgramClass(ProgramClass programClass) { String name = programClass.getName(); String newName = ClassObfuscator.newClassName(programClass); ps.println( ClassUtil.externalClassName(name) + " -> " + ClassUtil.externalClassName(newName) + ":"); // Print out the class members. programClass.fieldsAccept(this); programClass.methodsAccept(this); }
/** Returns a shrunk descriptor or signature of the given method. */ private String shrinkDescriptor(Method method, String descriptor) { // All parameters of non-static methods are shifted by one in the local // variable frame. int parameterIndex = (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1; // Go over the parameters. InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor); StringBuffer newDescriptorBuffer = new StringBuffer(); newDescriptorBuffer.append(internalTypeEnumeration.formalTypeParameters()); newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN); while (internalTypeEnumeration.hasMoreTypes()) { String type = internalTypeEnumeration.nextType(); if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) { newDescriptorBuffer.append(type); } else if (DEBUG) { System.out.println(" Deleting parameter #" + parameterIndex + " [" + type + "]"); } parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; } newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); newDescriptorBuffer.append(internalTypeEnumeration.returnType()); return newDescriptorBuffer.toString(); }
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // DEBUG = // clazz.getName().equals("abc/Def") && // method.getName(clazz).equals("abc"); // The minimum variable size is determined by the arguments. codeAttribute.u2maxLocals = ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz), method.getAccessFlags()); if (DEBUG) { System.out.println( "VariableSizeUpdater: " + clazz.getName() + "." + method.getName(clazz) + method.getDescriptor(clazz)); System.out.println(" Max locals: " + codeAttribute.u2maxLocals + " <- parameters"); } // Go over all instructions. codeAttribute.instructionsAccept(clazz, method, this); // Remove the unused variables of the attributes. codeAttribute.attributesAccept(clazz, method, variableCleaner); }
/** * 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 void visitLibraryClass(LibraryClass libraryClass) { notePrinter.print( libraryClass.getName(), "Note: duplicate definition of library class [" + ClassUtil.externalClassName(libraryClass.getName()) + "]"); }
public void visitProgramClass(ProgramClass programClass) { notePrinter.print( programClass.getName(), "Note: duplicate definition of program class [" + ClassUtil.externalClassName(programClass.getName()) + "]"); }
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; } }
/** Shrinks the array of referenced classes of the given method. */ private Clazz[] shrinkReferencedClasses( Method method, String descriptor, Clazz[] referencedClasses) { if (referencedClasses != null) { // All parameters of non-static methods are shifted by one in the local // variable frame. int parameterIndex = (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1; int referencedClassIndex = 0; int newReferencedClassIndex = 0; // Go over the parameters. InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor); // Also look at the formal type parameters. String type = internalTypeEnumeration.formalTypeParameters(); int count = new DescriptorClassEnumeration(type).classCount(); for (int counter = 0; counter < count; counter++) { referencedClasses[newReferencedClassIndex++] = referencedClasses[referencedClassIndex++]; } while (internalTypeEnumeration.hasMoreTypes()) { // Consider the classes referenced by this parameter type. type = internalTypeEnumeration.nextType(); count = new DescriptorClassEnumeration(type).classCount(); if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) { // Copy the referenced classes. for (int counter = 0; counter < count; counter++) { referencedClasses[newReferencedClassIndex++] = referencedClasses[referencedClassIndex++]; } } else { // Skip the referenced classes. referencedClassIndex += count; } parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; } // Also look at the return value. type = internalTypeEnumeration.returnType(); count = new DescriptorClassEnumeration(type).classCount(); for (int counter = 0; counter < count; counter++) { referencedClasses[newReferencedClassIndex++] = referencedClasses[referencedClassIndex++]; } // Clear the unused entries. while (newReferencedClassIndex < referencedClassIndex) { referencedClasses[newReferencedClassIndex++] = null; } } return referencedClasses; }
/** Sets the ClassMemberSpecification to be represented in this dialog. */ public void setClassMemberSpecification(ClassMemberSpecification classMemberSpecification) { String name = classMemberSpecification.name; String descriptor = classMemberSpecification.descriptor; // Set the access radio buttons. setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_PRIVATE, privateRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_SYNCHRONIZED, synchronizedRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons); setClassMemberSpecificationRadioButtons( classMemberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons); // Set the class name text fields. nameTextField.setText(name == null ? "" : name); if (isField) { typeTextField.setText(descriptor == null ? "" : ClassUtil.externalType(descriptor)); } else { typeTextField.setText( descriptor == null ? "" : ClassUtil.externalMethodReturnType(descriptor)); argumentsTextField.setText( descriptor == null ? "" : ClassUtil.externalMethodArguments(descriptor)); } }
public void visitProgramField(ProgramClass programClass, ProgramField programField) { String newName = MemberObfuscator.newMemberName(programField); if (newName != null) { ps.println( " " + // lineNumberRange(programClass, programField) + ClassUtil.externalFullFieldDescription( 0, programField.getName(programClass), programField.getDescriptor(programClass)) + " -> " + newName); } }
public void read(DataEntry dataEntry) throws IOException { try { // Get the input stream. InputStream inputStream = dataEntry.getInputStream(); // Wrap it into a data input stream. DataInputStream dataInputStream = new DataInputStream(inputStream); // Create a Clazz representation. Clazz clazz; if (isLibrary) { clazz = new LibraryClass(); clazz.accept( new LibraryClassReader( dataInputStream, skipNonPublicLibraryClasses, skipNonPublicLibraryClassMembers)); } else { clazz = new ProgramClass(); clazz.accept(new ProgramClassReader(dataInputStream)); } // Apply the visitor, if we have a real class. String className = clazz.getName(); if (className != null) { if (!dataEntry .getName() .replace(File.pathSeparatorChar, ClassConstants.PACKAGE_SEPARATOR) .equals(className + ClassConstants.CLASS_FILE_EXTENSION) && warningPrinter != null) { warningPrinter.print( className, "Warning: class [" + dataEntry.getName() + "] unexpectedly contains class [" + ClassUtil.externalClassName(className) + "]"); } clazz.accept(classVisitor); } dataEntry.closeInputStream(); } catch (Exception ex) { throw (IOException) new IOException( "Can't process class [" + dataEntry.getName() + "] (" + ex.getMessage() + ")") .initCause(ex); } }
/** * 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 visitAnyParameterAnnotationsAttribute( Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) { int[] annotationsCounts = parameterAnnotationsAttribute.u2parameterAnnotationsCount; Annotation[][] annotations = parameterAnnotationsAttribute.parameterAnnotations; // All parameters of non-static methods are shifted by one in the local // variable frame. int parameterIndex = (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1; int annotationIndex = 0; int newAnnotationIndex = 0; // Go over the parameters. String descriptor = method.getDescriptor(clazz); InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor); while (internalTypeEnumeration.hasMoreTypes()) { String type = internalTypeEnumeration.nextType(); if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) { annotationsCounts[newAnnotationIndex] = annotationsCounts[annotationIndex]; annotations[newAnnotationIndex++] = annotations[annotationIndex]; } annotationIndex++; parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; } // Update the number of parameters. parameterAnnotationsAttribute.u2parametersCount = newAnnotationIndex; // Clear the unused entries. while (newAnnotationIndex < annotationIndex) { annotationsCounts[newAnnotationIndex] = 0; annotations[newAnnotationIndex++] = null; } }
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { // Special cases: <clinit> and <init> are always kept unchanged. // We can ignore them here. String name = programMethod.getName(programClass); if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) { return; } String newName = MemberObfuscator.newMemberName(programMethod); if (newName != null) { ps.println( " " + lineNumberRange(programClass, programMethod) + ClassUtil.externalFullMethodDescription( programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) + " -> " + newName); } }
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // Get the original parameter size that was saved. int oldParameterSize = ParameterUsageMarker.getParameterSize(method); // Compute the new parameter size from the shrunk descriptor. int newParameterSize = ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz), method.getAccessFlags()); if (oldParameterSize > newParameterSize) { // Get the total size of the local variable frame. int maxLocals = codeAttribute.u2maxLocals; if (DEBUG) { System.out.println( "ParameterShrinker: " + clazz.getName() + "." + method.getName(clazz) + method.getDescriptor(clazz)); System.out.println(" Old parameter size = " + oldParameterSize); System.out.println(" New parameter size = " + newParameterSize); System.out.println(" Max locals = " + maxLocals); } // Create a variable map. int[] variableMap = new int[maxLocals]; // Move unused parameters right after the parameter block. int usedParameterIndex = 0; int unusedParameterIndex = newParameterSize; for (int parameterIndex = 0; parameterIndex < oldParameterSize; parameterIndex++) { // Is the variable required as a parameter? if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) { // Keep the variable as a parameter. variableMap[parameterIndex] = usedParameterIndex++; } else { if (DEBUG) { System.out.println(" Deleting parameter #" + parameterIndex); } // Shift the variable to the unused parameter block, // in case it is still used as a variable. variableMap[parameterIndex] = unusedParameterIndex++; // Visit the method, if required. if (extraVariableMemberVisitor != null) { method.accept(clazz, extraVariableMemberVisitor); } } } // Fill out the remainder of the map. for (int variableIndex = oldParameterSize; variableIndex < maxLocals; variableIndex++) { variableMap[variableIndex] = variableIndex; } // Set the map. variableRemapper.setVariableMap(variableMap); // Remap the variables. variableRemapper.visitCodeAttribute(clazz, method, codeAttribute); } }