aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/proguard/ArgumentWordReader.java7
-rw-r--r--src/proguard/ClassPath.java2
-rw-r--r--src/proguard/ClassPathEntry.java137
-rw-r--r--src/proguard/ClassSpecification.java2
-rw-r--r--src/proguard/ClassSpecificationVisitorFactory.java5
-rw-r--r--src/proguard/Configuration.java16
-rw-r--r--src/proguard/ConfigurationConstants.java4
-rw-r--r--src/proguard/ConfigurationParser.java300
-rw-r--r--src/proguard/ConfigurationWriter.java44
-rw-r--r--src/proguard/DataEntryReaderFactory.java24
-rw-r--r--src/proguard/DataEntryWriterFactory.java26
-rw-r--r--src/proguard/DescriptorKeepChecker.java62
-rw-r--r--src/proguard/DuplicateClassPrinter.java2
-rw-r--r--src/proguard/FileWordReader.java52
-rw-r--r--src/proguard/FullyQualifiedClassNameChecker.java9
-rw-r--r--src/proguard/GPL.java18
-rw-r--r--src/proguard/Initializer.java109
-rw-r--r--src/proguard/InputReader.java6
-rw-r--r--src/proguard/KeepClassMemberChecker.java88
-rw-r--r--src/proguard/KeepClassSpecification.java2
-rw-r--r--src/proguard/LineWordReader.java74
-rw-r--r--src/proguard/MemberSpecification.java2
-rw-r--r--src/proguard/OutputWriter.java66
-rw-r--r--src/proguard/ParseException.java2
-rw-r--r--src/proguard/ProGuard.java73
-rw-r--r--src/proguard/SeedPrinter.java97
-rw-r--r--src/proguard/SubclassedClassFilter.java2
-rw-r--r--src/proguard/Targeter.java2
-rw-r--r--src/proguard/UpToDateChecker.java219
-rw-r--r--src/proguard/WordReader.java127
-rw-r--r--src/proguard/ant/ClassPathElement.java2
-rw-r--r--src/proguard/ant/ClassSpecificationElement.java3
-rw-r--r--src/proguard/ant/ConfigurationElement.java101
-rw-r--r--src/proguard/ant/ConfigurationTask.java18
-rw-r--r--src/proguard/ant/FilterElement.java2
-rw-r--r--src/proguard/ant/KeepSpecificationElement.java20
-rw-r--r--src/proguard/ant/MemberSpecificationElement.java7
-rw-r--r--src/proguard/ant/ProGuardTask.java49
-rw-r--r--src/proguard/ant/task.properties4
-rw-r--r--src/proguard/classfile/ClassConstants.java126
-rw-r--r--src/proguard/classfile/ClassPool.java30
-rw-r--r--src/proguard/classfile/Clazz.java31
-rw-r--r--src/proguard/classfile/Field.java2
-rw-r--r--src/proguard/classfile/LibraryClass.java61
-rw-r--r--src/proguard/classfile/LibraryField.java2
-rw-r--r--src/proguard/classfile/LibraryMember.java2
-rw-r--r--src/proguard/classfile/LibraryMethod.java2
-rw-r--r--src/proguard/classfile/Member.java2
-rw-r--r--src/proguard/classfile/Method.java2
-rw-r--r--src/proguard/classfile/ProgramClass.java92
-rw-r--r--src/proguard/classfile/ProgramField.java2
-rw-r--r--src/proguard/classfile/ProgramMember.java32
-rw-r--r--src/proguard/classfile/ProgramMethod.java2
-rw-r--r--src/proguard/classfile/VisitorAccepter.java2
-rw-r--r--src/proguard/classfile/attribute/Attribute.java2
-rwxr-xr-xsrc/proguard/classfile/attribute/BootstrapMethodInfo.java89
-rwxr-xr-xsrc/proguard/classfile/attribute/BootstrapMethodsAttribute.java95
-rw-r--r--src/proguard/classfile/attribute/CodeAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/ConstantValueAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/DeprecatedAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/EnclosingMethodAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/ExceptionInfo.java2
-rw-r--r--src/proguard/classfile/attribute/ExceptionsAttribute.java8
-rw-r--r--src/proguard/classfile/attribute/InnerClassesAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/InnerClassesInfo.java11
-rw-r--r--src/proguard/classfile/attribute/LineNumberInfo.java2
-rw-r--r--src/proguard/classfile/attribute/LineNumberTableAttribute.java52
-rw-r--r--src/proguard/classfile/attribute/LocalVariableInfo.java40
-rw-r--r--src/proguard/classfile/attribute/LocalVariableTableAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/LocalVariableTypeInfo.java40
-rw-r--r--src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SignatureAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SourceDirAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SourceFileAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SyntheticAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/UnknownAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/Annotation.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/AnnotationElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/ArrayElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/ClassElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/ConstantElementValue.java16
-rw-r--r--src/proguard/classfile/attribute/annotation/ElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java45
-rw-r--r--src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java7
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java201
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java3
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/DoubleType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/FloatType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/FullFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/IntegerType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/LessZeroFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/LongType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/MoreZeroFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/NullType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/ObjectType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/SameOneFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/SameZeroFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/StackMapAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/StackMapFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/TopType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/UninitializedThisType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/UninitializedType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/VerificationType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java55
-rw-r--r--src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java55
-rw-r--r--src/proguard/classfile/attribute/visitor/AttributeNameFilter.java67
-rw-r--r--src/proguard/classfile/attribute/visitor/AttributeVisitor.java13
-rwxr-xr-xsrc/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java40
-rw-r--r--src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java11
-rw-r--r--src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java293
-rw-r--r--src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java17
-rw-r--r--src/proguard/classfile/attribute/visitor/StackSizeComputer.java9
-rw-r--r--src/proguard/classfile/constant/ClassConstant.java2
-rw-r--r--src/proguard/classfile/constant/Constant.java2
-rw-r--r--src/proguard/classfile/constant/DoubleConstant.java2
-rw-r--r--src/proguard/classfile/constant/FieldrefConstant.java2
-rw-r--r--src/proguard/classfile/constant/FloatConstant.java2
-rw-r--r--src/proguard/classfile/constant/IntegerConstant.java2
-rw-r--r--src/proguard/classfile/constant/InterfaceMethodrefConstant.java2
-rwxr-xr-xsrc/proguard/classfile/constant/InvokeDynamicConstant.java148
-rw-r--r--src/proguard/classfile/constant/LongConstant.java2
-rwxr-xr-xsrc/proguard/classfile/constant/MethodHandleConstant.java124
-rw-r--r--src/proguard/classfile/constant/MethodTypeConstant.java93
-rw-r--r--src/proguard/classfile/constant/MethodrefConstant.java2
-rw-r--r--src/proguard/classfile/constant/NameAndTypeConstant.java2
-rw-r--r--src/proguard/classfile/constant/RefConstant.java2
-rw-r--r--src/proguard/classfile/constant/StringConstant.java2
-rw-r--r--src/proguard/classfile/constant/Utf8Constant.java2
-rw-r--r--src/proguard/classfile/constant/visitor/AllConstantVisitor.java2
-rw-r--r--src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java100
-rw-r--r--src/proguard/classfile/constant/visitor/ConstantTagFilter.java86
-rw-r--r--src/proguard/classfile/constant/visitor/ConstantVisitor.java5
-rw-r--r--src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java12
-rw-r--r--src/proguard/classfile/constant/visitor/MethodrefTraveler.java (renamed from src/proguard/classfile/visitor/ClassForNameClassVisitor.java)32
-rw-r--r--src/proguard/classfile/editor/AccessFixer.java28
-rw-r--r--src/proguard/classfile/editor/AnnotationAdder.java2
-rw-r--r--src/proguard/classfile/editor/AnnotationsAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/AttributeAdder.java22
-rw-r--r--src/proguard/classfile/editor/AttributeSorter.java2
-rw-r--r--src/proguard/classfile/editor/AttributesEditor.java2
-rw-r--r--src/proguard/classfile/editor/BridgeMethodFixer.java117
-rw-r--r--src/proguard/classfile/editor/ClassEditor.java2
-rw-r--r--src/proguard/classfile/editor/ClassElementSorter.java2
-rw-r--r--src/proguard/classfile/editor/ClassMemberSorter.java2
-rw-r--r--src/proguard/classfile/editor/ClassReferenceFixer.java2
-rw-r--r--src/proguard/classfile/editor/CodeAttributeComposer.java269
-rw-r--r--src/proguard/classfile/editor/CodeAttributeEditor.java400
-rw-r--r--src/proguard/classfile/editor/CodeAttributeEditorResetter.java2
-rw-r--r--src/proguard/classfile/editor/ComparableConstant.java83
-rw-r--r--src/proguard/classfile/editor/ConstantAdder.java47
-rw-r--r--src/proguard/classfile/editor/ConstantPoolEditor.java119
-rw-r--r--src/proguard/classfile/editor/ConstantPoolRemapper.java107
-rw-r--r--src/proguard/classfile/editor/ConstantPoolShrinker.java578
-rw-r--r--src/proguard/classfile/editor/ConstantPoolSorter.java7
-rw-r--r--src/proguard/classfile/editor/ElementValueAdder.java2
-rw-r--r--src/proguard/classfile/editor/ElementValuesEditor.java2
-rw-r--r--src/proguard/classfile/editor/ExceptionAdder.java2
-rw-r--r--src/proguard/classfile/editor/ExceptionInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/ExceptionsAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/InnerClassesAccessFixer.java83
-rw-r--r--src/proguard/classfile/editor/InstructionAdder.java4
-rw-r--r--src/proguard/classfile/editor/InstructionWriter.java60
-rw-r--r--src/proguard/classfile/editor/InterfaceAdder.java2
-rw-r--r--src/proguard/classfile/editor/InterfaceSorter.java119
-rw-r--r--src/proguard/classfile/editor/InterfacesEditor.java2
-rw-r--r--src/proguard/classfile/editor/LineNumberInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/LineNumberTableAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/MemberAdder.java147
-rw-r--r--src/proguard/classfile/editor/MemberReferenceFixer.java39
-rw-r--r--src/proguard/classfile/editor/MethodInvocationFixer.java65
-rw-r--r--src/proguard/classfile/editor/NameAndTypeShrinker.java (renamed from src/proguard/obfuscate/NameAndTypeUsageMarker.java)101
-rw-r--r--src/proguard/classfile/editor/NamedAttributeDeleter.java2
-rw-r--r--src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/StackSizeUpdater.java2
-rw-r--r--src/proguard/classfile/editor/SubclassAdder.java2
-rw-r--r--src/proguard/classfile/editor/SubclassToAdder.java2
-rw-r--r--src/proguard/classfile/editor/Utf8Shrinker.java (renamed from src/proguard/obfuscate/Utf8UsageMarker.java)81
-rw-r--r--src/proguard/classfile/editor/VariableCleaner.java208
-rw-r--r--src/proguard/classfile/editor/VariableEditor.java11
-rw-r--r--src/proguard/classfile/editor/VariableRemapper.java77
-rw-r--r--src/proguard/classfile/editor/VariableSizeUpdater.java13
-rw-r--r--src/proguard/classfile/instruction/BranchInstruction.java5
-rw-r--r--src/proguard/classfile/instruction/ConstantInstruction.java36
-rw-r--r--src/proguard/classfile/instruction/Instruction.java12
-rw-r--r--src/proguard/classfile/instruction/InstructionConstants.java36
-rw-r--r--src/proguard/classfile/instruction/InstructionFactory.java3
-rw-r--r--src/proguard/classfile/instruction/InstructionUtil.java2
-rw-r--r--src/proguard/classfile/instruction/LookUpSwitchInstruction.java2
-rw-r--r--src/proguard/classfile/instruction/SimpleInstruction.java6
-rw-r--r--src/proguard/classfile/instruction/SwitchInstruction.java2
-rw-r--r--src/proguard/classfile/instruction/TableSwitchInstruction.java2
-rw-r--r--src/proguard/classfile/instruction/VariableInstruction.java6
-rw-r--r--src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java2
-rw-r--r--src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java65
-rw-r--r--src/proguard/classfile/instruction/visitor/InstructionCounter.java2
-rw-r--r--src/proguard/classfile/instruction/visitor/InstructionVisitor.java2
-rw-r--r--src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java2
-rw-r--r--src/proguard/classfile/io/LibraryClassReader.java25
-rw-r--r--src/proguard/classfile/io/ProgramClassReader.java81
-rw-r--r--src/proguard/classfile/io/ProgramClassWriter.java53
-rw-r--r--src/proguard/classfile/io/RuntimeDataInput.java2
-rw-r--r--src/proguard/classfile/io/RuntimeDataOutput.java2
-rw-r--r--src/proguard/classfile/util/AccessUtil.java2
-rw-r--r--src/proguard/classfile/util/ClassReferenceInitializer.java137
-rw-r--r--src/proguard/classfile/util/ClassSubHierarchyInitializer.java2
-rw-r--r--src/proguard/classfile/util/ClassSuperHierarchyInitializer.java7
-rw-r--r--src/proguard/classfile/util/ClassUtil.java85
-rw-r--r--src/proguard/classfile/util/DescriptorClassEnumeration.java2
-rw-r--r--src/proguard/classfile/util/DynamicClassReferenceInitializer.java21
-rw-r--r--src/proguard/classfile/util/DynamicMemberReferenceInitializer.java485
-rw-r--r--src/proguard/classfile/util/EnumFieldReferenceInitializer.java150
-rw-r--r--src/proguard/classfile/util/ExternalTypeEnumeration.java2
-rw-r--r--src/proguard/classfile/util/InstructionSequenceMatcher.java182
-rw-r--r--src/proguard/classfile/util/InternalTypeEnumeration.java4
-rw-r--r--src/proguard/classfile/util/MemberFinder.java2
-rw-r--r--src/proguard/classfile/util/MethodLinker.java19
-rw-r--r--src/proguard/classfile/util/SimplifiedVisitor.java28
-rw-r--r--src/proguard/classfile/util/StringReferenceInitializer.java5
-rw-r--r--src/proguard/classfile/util/StringSharer.java21
-rw-r--r--src/proguard/classfile/util/WarningPrinter.java2
-rw-r--r--src/proguard/classfile/visitor/AllClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/AllFieldVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/AllMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/AllMethodVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/BottomClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassAccessFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassCleaner.java2
-rw-r--r--src/proguard/classfile/visitor/ClassCollector.java2
-rw-r--r--src/proguard/classfile/visitor/ClassCounter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassHierarchyTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/ClassNameFilter.java4
-rw-r--r--src/proguard/classfile/visitor/ClassPoolFiller.java2
-rw-r--r--src/proguard/classfile/visitor/ClassPoolVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ClassPresenceFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassPrinter.java70
-rw-r--r--src/proguard/classfile/visitor/ClassVersionFilter.java15
-rw-r--r--src/proguard/classfile/visitor/ClassVersionSetter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ConcreteClassDownTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/DotClassClassVisitor.java4
-rw-r--r--src/proguard/classfile/visitor/ExceptClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptClassesFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionCounter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionHandlerFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionOffsetFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionRangeFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ImplementedClassConstantFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ImplementedClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ImplementingClassConstantFilter.java2
-rw-r--r--src/proguard/classfile/visitor/LibraryClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/LibraryMemberFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberAccessFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberClassAccessFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberCollector.java2
-rw-r--r--src/proguard/classfile/visitor/MemberCounter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberDescriptorFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberNameFilter.java5
-rw-r--r--src/proguard/classfile/visitor/MemberToClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MethodImplementationFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MethodImplementationTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/MultiClassPoolVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MultiClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MultiMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/NamedClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/NamedFieldVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/NamedMethodVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ProgramClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ProgramMemberFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ReferencedClassVisitor.java9
-rw-r--r--src/proguard/classfile/visitor/ReferencedMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/SimilarMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/SimpleClassPrinter.java2
-rw-r--r--src/proguard/classfile/visitor/SubclassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/SubclassTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/VariableClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/VariableMemberVisitor.java2
-rw-r--r--src/proguard/evaluation/BasicBranchUnit.java2
-rw-r--r--src/proguard/evaluation/BasicInvocationUnit.java47
-rw-r--r--src/proguard/evaluation/BranchUnit.java2
-rw-r--r--src/proguard/evaluation/ClassConstantValueFactory.java53
-rw-r--r--src/proguard/evaluation/ConstantValueFactory.java113
-rw-r--r--src/proguard/evaluation/InvocationUnit.java2
-rw-r--r--src/proguard/evaluation/Processor.java101
-rw-r--r--src/proguard/evaluation/Stack.java9
-rw-r--r--src/proguard/evaluation/TracedStack.java2
-rw-r--r--src/proguard/evaluation/TracedVariables.java32
-rw-r--r--src/proguard/evaluation/Variables.java9
-rw-r--r--src/proguard/evaluation/value/Category1Value.java2
-rw-r--r--src/proguard/evaluation/value/Category2Value.java2
-rw-r--r--src/proguard/evaluation/value/ComparisonValue.java10
-rw-r--r--src/proguard/evaluation/value/CompositeDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/CompositeFloatValue.java10
-rw-r--r--src/proguard/evaluation/value/CompositeIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/CompositeLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedByteValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedCharacterValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedFloatValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedShortValue.java2
-rw-r--r--src/proguard/evaluation/value/DoubleValue.java7
-rw-r--r--src/proguard/evaluation/value/FloatValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedFloatValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedLongValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedReferenceValue.java13
-rw-r--r--src/proguard/evaluation/value/IdentifiedValueFactory.java2
-rw-r--r--src/proguard/evaluation/value/InstructionOffsetValue.java2
-rw-r--r--src/proguard/evaluation/value/IntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/LongValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedFloatValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ParticularDoubleValue.java25
-rw-r--r--src/proguard/evaluation/value/ParticularFloatValue.java23
-rw-r--r--src/proguard/evaluation/value/ParticularIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/ParticularLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ReferenceValue.java40
-rw-r--r--src/proguard/evaluation/value/SpecificDoubleValue.java11
-rw-r--r--src/proguard/evaluation/value/SpecificFloatValue.java11
-rw-r--r--src/proguard/evaluation/value/SpecificIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/SpecificLongValue.java2
-rw-r--r--src/proguard/evaluation/value/SpecificValueFactory.java14
-rw-r--r--src/proguard/evaluation/value/TopValue.java2
-rw-r--r--src/proguard/evaluation/value/UnknownDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/UnknownFloatValue.java4
-rw-r--r--src/proguard/evaluation/value/UnknownIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/UnknownLongValue.java2
-rw-r--r--src/proguard/evaluation/value/Value.java2
-rw-r--r--src/proguard/evaluation/value/ValueFactory.java2
-rw-r--r--src/proguard/gradle/ProGuardTask.java1532
-rw-r--r--src/proguard/gui/ClassPathPanel.java8
-rw-r--r--src/proguard/gui/ClassSpecificationDialog.java22
-rw-r--r--src/proguard/gui/ClassSpecificationsPanel.java2
-rw-r--r--src/proguard/gui/ExtensionFileFilter.java2
-rw-r--r--src/proguard/gui/FilterBuilder.java2
-rw-r--r--src/proguard/gui/FilterDialog.java12
-rw-r--r--src/proguard/gui/GUIResources.java2
-rw-r--r--src/proguard/gui/GUIResources.properties48
-rw-r--r--src/proguard/gui/KeepSpecificationsPanel.java2
-rw-r--r--src/proguard/gui/ListPanel.java2
-rw-r--r--src/proguard/gui/MemberSpecificationDialog.java14
-rw-r--r--src/proguard/gui/MemberSpecificationsPanel.java2
-rw-r--r--src/proguard/gui/MessageDialogRunnable.java2
-rw-r--r--src/proguard/gui/OptimizationsDialog.java2
-rw-r--r--src/proguard/gui/ProGuardGUI.java179
-rw-r--r--src/proguard/gui/ProGuardRunnable.java2
-rw-r--r--src/proguard/gui/ReTraceRunnable.java2
-rw-r--r--src/proguard/gui/SwingUtil.java2
-rw-r--r--src/proguard/gui/TabbedPane.java2
-rw-r--r--src/proguard/gui/TextAreaOutputStream.java2
-rw-r--r--src/proguard/gui/boilerplate.pro26
-rw-r--r--src/proguard/gui/default.pro26
-rw-r--r--src/proguard/gui/splash/BufferedSprite.java2
-rw-r--r--src/proguard/gui/splash/CircleSprite.java2
-rw-r--r--src/proguard/gui/splash/ClipSprite.java2
-rw-r--r--src/proguard/gui/splash/ColorSprite.java2
-rw-r--r--src/proguard/gui/splash/CompositeSprite.java2
-rw-r--r--src/proguard/gui/splash/ConstantColor.java2
-rw-r--r--src/proguard/gui/splash/ConstantDouble.java2
-rw-r--r--src/proguard/gui/splash/ConstantFont.java2
-rw-r--r--src/proguard/gui/splash/ConstantInt.java2
-rw-r--r--src/proguard/gui/splash/ConstantString.java2
-rw-r--r--src/proguard/gui/splash/ConstantTiming.java2
-rw-r--r--src/proguard/gui/splash/FontSprite.java2
-rw-r--r--src/proguard/gui/splash/ImageSprite.java2
-rw-r--r--src/proguard/gui/splash/LinearColor.java2
-rw-r--r--src/proguard/gui/splash/LinearDouble.java2
-rw-r--r--src/proguard/gui/splash/LinearInt.java2
-rw-r--r--src/proguard/gui/splash/LinearTiming.java2
-rw-r--r--src/proguard/gui/splash/OverrideGraphics2D.java2
-rw-r--r--src/proguard/gui/splash/RectangleSprite.java2
-rw-r--r--src/proguard/gui/splash/SawToothTiming.java2
-rw-r--r--src/proguard/gui/splash/ShadowedSprite.java2
-rw-r--r--src/proguard/gui/splash/SineTiming.java2
-rw-r--r--src/proguard/gui/splash/SmoothTiming.java2
-rw-r--r--src/proguard/gui/splash/SplashPanel.java2
-rw-r--r--src/proguard/gui/splash/Sprite.java2
-rw-r--r--src/proguard/gui/splash/TextSprite.java2
-rw-r--r--src/proguard/gui/splash/TimeSwitchSprite.java2
-rw-r--r--src/proguard/gui/splash/Timing.java2
-rw-r--r--src/proguard/gui/splash/TypeWriterString.java2
-rw-r--r--src/proguard/gui/splash/VariableColor.java2
-rw-r--r--src/proguard/gui/splash/VariableDouble.java2
-rw-r--r--src/proguard/gui/splash/VariableFont.java2
-rw-r--r--src/proguard/gui/splash/VariableInt.java2
-rw-r--r--src/proguard/gui/splash/VariableSizeFont.java2
-rw-r--r--src/proguard/gui/splash/VariableString.java2
-rw-r--r--src/proguard/io/CascadingDataEntryWriter.java2
-rw-r--r--src/proguard/io/ClassFilter.java2
-rw-r--r--src/proguard/io/ClassReader.java4
-rw-r--r--src/proguard/io/ClassRewriter.java2
-rw-r--r--src/proguard/io/DataEntry.java2
-rw-r--r--src/proguard/io/DataEntryClassWriter.java85
-rw-r--r--src/proguard/io/DataEntryCopier.java21
-rw-r--r--src/proguard/io/DataEntryDirectoryFilter.java2
-rw-r--r--src/proguard/io/DataEntryFilter.java2
-rw-r--r--src/proguard/io/DataEntryNameFilter.java2
-rw-r--r--src/proguard/io/DataEntryObfuscator.java47
-rw-r--r--src/proguard/io/DataEntryParentFilter.java2
-rw-r--r--src/proguard/io/DataEntryPump.java2
-rw-r--r--src/proguard/io/DataEntryReader.java2
-rw-r--r--src/proguard/io/DataEntryRenamer.java6
-rw-r--r--src/proguard/io/DataEntryRewriter.java2
-rw-r--r--src/proguard/io/DataEntryWriter.java2
-rw-r--r--src/proguard/io/DirectoryFilter.java2
-rw-r--r--src/proguard/io/DirectoryPump.java2
-rw-r--r--src/proguard/io/DirectoryWriter.java2
-rw-r--r--src/proguard/io/FileDataEntry.java2
-rw-r--r--src/proguard/io/FilteredDataEntryReader.java2
-rw-r--r--src/proguard/io/FilteredDataEntryWriter.java2
-rw-r--r--src/proguard/io/Finisher.java2
-rw-r--r--src/proguard/io/JarReader.java2
-rw-r--r--src/proguard/io/JarWriter.java2
-rw-r--r--src/proguard/io/ManifestRewriter.java57
-rw-r--r--src/proguard/io/NameFilter.java2
-rw-r--r--src/proguard/io/ParentDataEntryWriter.java2
-rw-r--r--src/proguard/io/RenamedDataEntry.java2
-rw-r--r--src/proguard/io/ZipDataEntry.java2
-rw-r--r--src/proguard/obfuscate/AttributeShrinker.java9
-rw-r--r--src/proguard/obfuscate/AttributeUsageMarker.java4
-rw-r--r--src/proguard/obfuscate/ClassObfuscator.java24
-rw-r--r--src/proguard/obfuscate/ClassRenamer.java2
-rw-r--r--src/proguard/obfuscate/DictionaryNameFactory.java2
-rw-r--r--src/proguard/obfuscate/MapCleaner.java2
-rw-r--r--src/proguard/obfuscate/MappingKeeper.java2
-rw-r--r--src/proguard/obfuscate/MappingPrinter.java42
-rw-r--r--src/proguard/obfuscate/MappingProcessor.java2
-rw-r--r--src/proguard/obfuscate/MappingReader.java2
-rw-r--r--src/proguard/obfuscate/MemberNameCleaner.java2
-rw-r--r--src/proguard/obfuscate/MemberNameCollector.java2
-rw-r--r--src/proguard/obfuscate/MemberNameConflictFixer.java2
-rw-r--r--src/proguard/obfuscate/MemberNameFilter.java120
-rw-r--r--src/proguard/obfuscate/MemberObfuscator.java2
-rw-r--r--src/proguard/obfuscate/MemberSpecialNameFilter.java12
-rw-r--r--src/proguard/obfuscate/MultiMappingProcessor.java2
-rw-r--r--src/proguard/obfuscate/NameAndTypeShrinker.java112
-rw-r--r--src/proguard/obfuscate/NameFactory.java2
-rw-r--r--src/proguard/obfuscate/NameFactoryResetter.java2
-rw-r--r--src/proguard/obfuscate/NameMarker.java2
-rw-r--r--src/proguard/obfuscate/NumericNameFactory.java2
-rw-r--r--src/proguard/obfuscate/Obfuscator.java105
-rw-r--r--src/proguard/obfuscate/ParameterNameMarker.java128
-rw-r--r--src/proguard/obfuscate/SimpleNameFactory.java2
-rw-r--r--src/proguard/obfuscate/SourceFileRenamer.java2
-rw-r--r--src/proguard/obfuscate/SpecialNameFactory.java2
-rw-r--r--src/proguard/obfuscate/Utf8Shrinker.java110
-rw-r--r--src/proguard/optimize/BootstrapMethodArgumentShrinker.java103
-rw-r--r--src/proguard/optimize/ChangedCodePrinter.java8
-rw-r--r--src/proguard/optimize/ConstantMemberFilter.java2
-rw-r--r--src/proguard/optimize/ConstantParameterFilter.java2
-rw-r--r--src/proguard/optimize/DuplicateInitializerFixer.java34
-rw-r--r--src/proguard/optimize/DuplicateInitializerInvocationFixer.java37
-rw-r--r--src/proguard/optimize/KeepMarker.java12
-rw-r--r--src/proguard/optimize/KeptClassFilter.java69
-rw-r--r--src/proguard/optimize/KeptMemberFilter.java87
-rw-r--r--src/proguard/optimize/MemberDescriptorSpecializer.java4
-rw-r--r--src/proguard/optimize/MethodDescriptorShrinker.java12
-rw-r--r--src/proguard/optimize/MethodStaticizer.java2
-rw-r--r--src/proguard/optimize/OptimizationInfoMemberFilter.java2
-rw-r--r--src/proguard/optimize/Optimizer.java197
-rw-r--r--src/proguard/optimize/ParameterShrinker.java4
-rw-r--r--src/proguard/optimize/TailRecursionSimplifier.java109
-rw-r--r--src/proguard/optimize/WriteOnlyFieldFilter.java2
-rw-r--r--src/proguard/optimize/evaluation/EvaluationShrinker.java1260
-rw-r--r--src/proguard/optimize/evaluation/EvaluationSimplifier.java58
-rw-r--r--src/proguard/optimize/evaluation/LivenessAnalyzer.java12
-rw-r--r--src/proguard/optimize/evaluation/LoadingInvocationUnit.java20
-rw-r--r--src/proguard/optimize/evaluation/PartialEvaluator.java166
-rw-r--r--src/proguard/optimize/evaluation/StoringInvocationUnit.java2
-rw-r--r--src/proguard/optimize/evaluation/TracedBranchUnit.java2
-rw-r--r--src/proguard/optimize/evaluation/VariableOptimizer.java139
-rw-r--r--src/proguard/optimize/info/AccessMethodMarker.java19
-rw-r--r--src/proguard/optimize/info/BackwardBranchMarker.java2
-rw-r--r--src/proguard/optimize/info/CatchExceptionMarker.java2
-rw-r--r--src/proguard/optimize/info/CaughtClassFilter.java2
-rw-r--r--src/proguard/optimize/info/CaughtClassMarker.java7
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfo.java16
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfoSetter.java2
-rw-r--r--src/proguard/optimize/info/DotClassFilter.java2
-rw-r--r--src/proguard/optimize/info/DotClassMarker.java2
-rw-r--r--src/proguard/optimize/info/ExceptionInstructionChecker.java104
-rw-r--r--src/proguard/optimize/info/FieldOptimizationInfo.java56
-rw-r--r--src/proguard/optimize/info/InstanceofClassFilter.java2
-rw-r--r--src/proguard/optimize/info/InstanceofClassMarker.java2
-rw-r--r--src/proguard/optimize/info/InstantiationClassFilter.java2
-rw-r--r--src/proguard/optimize/info/InstantiationClassMarker.java2
-rw-r--r--src/proguard/optimize/info/MemberOptimizationInfoSetter.java18
-rw-r--r--src/proguard/optimize/info/MethodInvocationMarker.java2
-rw-r--r--src/proguard/optimize/info/MethodOptimizationInfo.java6
-rw-r--r--src/proguard/optimize/info/NoSideEffectMethodMarker.java4
-rw-r--r--src/proguard/optimize/info/NonPrivateMemberMarker.java16
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java28
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java72
-rw-r--r--src/proguard/optimize/info/ParameterUsageMarker.java8
-rw-r--r--src/proguard/optimize/info/ReadWriteFieldMarker.java2
-rw-r--r--src/proguard/optimize/info/SideEffectInstructionChecker.java239
-rw-r--r--src/proguard/optimize/info/SideEffectMethodFilter.java73
-rw-r--r--src/proguard/optimize/info/SideEffectMethodMarker.java22
-rw-r--r--src/proguard/optimize/info/StaticInitializerContainingClassFilter.java62
-rw-r--r--src/proguard/optimize/info/StaticInitializerContainingClassMarker.java65
-rw-r--r--src/proguard/optimize/info/SuperInvocationMarker.java2
-rw-r--r--src/proguard/optimize/info/VariableUsageMarker.java11
-rw-r--r--src/proguard/optimize/peephole/BranchTargetFinder.java279
-rw-r--r--src/proguard/optimize/peephole/ClassFinalizer.java2
-rw-r--r--src/proguard/optimize/peephole/ClassMerger.java160
-rw-r--r--src/proguard/optimize/peephole/GotoCommonCodeReplacer.java11
-rw-r--r--src/proguard/optimize/peephole/GotoGotoReplacer.java7
-rw-r--r--src/proguard/optimize/peephole/GotoReturnReplacer.java2
-rw-r--r--src/proguard/optimize/peephole/HorizontalClassMerger.java2
-rw-r--r--src/proguard/optimize/peephole/InstructionSequenceConstants.java1899
-rw-r--r--src/proguard/optimize/peephole/InstructionSequenceReplacer.java166
-rw-r--r--src/proguard/optimize/peephole/InstructionSequencesReplacer.java2
-rw-r--r--src/proguard/optimize/peephole/MemberPrivatizer.java2
-rw-r--r--src/proguard/optimize/peephole/MethodFinalizer.java2
-rw-r--r--src/proguard/optimize/peephole/MethodInliner.java142
-rw-r--r--src/proguard/optimize/peephole/NopRemover.java2
-rw-r--r--src/proguard/optimize/peephole/PeepholeOptimizer.java2
-rw-r--r--src/proguard/optimize/peephole/ReachableCodeMarker.java9
-rw-r--r--src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java46
-rw-r--r--src/proguard/optimize/peephole/TargetClassChanger.java62
-rw-r--r--src/proguard/optimize/peephole/UnreachableCodeRemover.java2
-rw-r--r--src/proguard/optimize/peephole/UnreachableExceptionRemover.java2
-rw-r--r--src/proguard/optimize/peephole/VariableShrinker.java2
-rw-r--r--src/proguard/optimize/peephole/VerticalClassMerger.java2
-rw-r--r--src/proguard/preverify/CodePreverifier.java30
-rw-r--r--src/proguard/preverify/CodeSubroutineInliner.java32
-rw-r--r--src/proguard/preverify/Preverifier.java7
-rw-r--r--src/proguard/preverify/SubroutineInliner.java3
-rw-r--r--src/proguard/retrace/ReTrace.java9
-rw-r--r--src/proguard/shrink/AnnotationUsageMarker.java76
-rw-r--r--src/proguard/shrink/ClassShrinker.java73
-rw-r--r--src/proguard/shrink/InnerUsageMarker.java2
-rw-r--r--src/proguard/shrink/InterfaceUsageMarker.java2
-rw-r--r--src/proguard/shrink/LocalVariableTypeUsageMarker.java178
-rw-r--r--src/proguard/shrink/ShortestUsageMark.java2
-rw-r--r--src/proguard/shrink/ShortestUsageMarker.java2
-rw-r--r--src/proguard/shrink/ShortestUsagePrinter.java56
-rw-r--r--src/proguard/shrink/Shrinker.java43
-rw-r--r--src/proguard/shrink/SignatureUsageMarker.java117
-rw-r--r--src/proguard/shrink/UsageMarker.java250
-rw-r--r--src/proguard/shrink/UsagePrinter.java46
-rw-r--r--src/proguard/shrink/UsedClassFilter.java2
-rw-r--r--src/proguard/shrink/UsedMemberFilter.java4
-rw-r--r--src/proguard/util/AndMatcher.java2
-rw-r--r--src/proguard/util/ArrayUtil.java960
-rw-r--r--src/proguard/util/ClassNameParser.java2
-rw-r--r--src/proguard/util/ConstantMatcher.java2
-rw-r--r--src/proguard/util/EmptyStringMatcher.java2
-rw-r--r--src/proguard/util/ExtensionMatcher.java2
-rw-r--r--src/proguard/util/FileNameParser.java2
-rw-r--r--src/proguard/util/FixedStringMatcher.java2
-rw-r--r--src/proguard/util/ListMatcher.java2
-rw-r--r--src/proguard/util/ListParser.java4
-rw-r--r--src/proguard/util/ListUtil.java15
-rw-r--r--src/proguard/util/NameParser.java2
-rw-r--r--src/proguard/util/NotMatcher.java2
-rw-r--r--src/proguard/util/ObjectUtil.java67
-rw-r--r--src/proguard/util/OrMatcher.java2
-rw-r--r--src/proguard/util/SettableMatcher.java2
-rw-r--r--src/proguard/util/StringMatcher.java2
-rw-r--r--src/proguard/util/StringParser.java2
-rw-r--r--src/proguard/util/VariableStringMatcher.java2
-rw-r--r--src/proguard/wtk/ProGuardObfuscator.java5
596 files changed, 16075 insertions, 4141 deletions
diff --git a/src/proguard/ArgumentWordReader.java b/src/proguard/ArgumentWordReader.java
index 89f3824..efe8e6e 100644
--- a/src/proguard/ArgumentWordReader.java
+++ b/src/proguard/ArgumentWordReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -32,7 +32,8 @@ import java.io.*;
public class ArgumentWordReader extends WordReader
{
private final String[] arguments;
- private int index = 0;
+
+ private int index = 0;
// /**
@@ -86,7 +87,7 @@ public class ArgumentWordReader extends WordReader
{
while (true)
{
- String word = reader.nextWord();
+ String word = reader.nextWord(false);
if (word == null)
System.exit(-1);
diff --git a/src/proguard/ClassPath.java b/src/proguard/ClassPath.java
index f4eeaad..3d7d119 100644
--- a/src/proguard/ClassPath.java
+++ b/src/proguard/ClassPath.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassPathEntry.java b/src/proguard/ClassPathEntry.java
index 28483be..7051955 100644
--- a/src/proguard/ClassPathEntry.java
+++ b/src/proguard/ClassPathEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,6 +20,8 @@
*/
package proguard;
+import proguard.util.ListUtil;
+
import java.io.*;
import java.util.List;
@@ -44,7 +46,7 @@ public class ClassPathEntry
/**
- * Creates a new ClassPathEntry with the given name and type.
+ * Creates a new ClassPathEntry with the given file and output flag.
*/
public ClassPathEntry(File file, boolean isOutput)
{
@@ -69,81 +71,212 @@ public class ClassPathEntry
}
+ /**
+ * Returns the file.
+ */
public File getFile()
{
return file;
}
+ /**
+ * Sets the file.
+ */
public void setFile(File file)
{
this.file = file;
}
+ /**
+ * Returns whether this data entry is an output entry.
+ */
public boolean isOutput()
{
return output;
}
+ /**
+ * Specifies whether this data entry is an output entry.
+ */
public void setOutput(boolean output)
{
this.output = output;
}
+ /**
+ * Returns whether this data entry is a jar file.
+ */
+ public boolean isJar()
+ {
+ return hasExtension(".jar");
+ }
+
+
+ /**
+ * Returns whether this data entry is a war file.
+ */
+ public boolean isWar()
+ {
+ return hasExtension(".war");
+ }
+
+
+ /**
+ * Returns whether this data entry is a ear file.
+ */
+ public boolean isEar()
+ {
+ return hasExtension(".ear");
+ }
+
+
+ /**
+ * Returns whether this data entry is a zip file.
+ */
+ public boolean isZip()
+ {
+ return hasExtension(".zip");
+ }
+
+
+ /**
+ * Returns whether this data entry has the given extension.
+ */
+ private boolean hasExtension(String extension)
+ {
+ return endsWithIgnoreCase(file.getPath(), extension);
+ }
+
+
+ /**
+ * Returns whether the given string ends with the given suffix, ignoring
+ * its case.
+ */
+ private static boolean endsWithIgnoreCase(String string, String suffix)
+ {
+ int stringLength = string.length();
+ int suffixLength = suffix.length();
+
+ return string.regionMatches(true, stringLength -
+ suffixLength, suffix, 0, suffixLength);
+ }
+
+
+ /**
+ * Returns the name filter that is applied to bottom-level files in this entry.
+ */
public List getFilter()
{
return filter;
}
+ /**
+ * Sets the name filter that is applied to bottom-level files in this entry.
+ */
public void setFilter(List filter)
{
this.filter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to jar files in this entry, if any.
+ */
public List getJarFilter()
{
return jarFilter;
}
+ /**
+ * Sets the name filter that is applied to jar files in this entry, if any.
+ */
public void setJarFilter(List filter)
{
this.jarFilter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to war files in this entry, if any.
+ */
public List getWarFilter()
{
return warFilter;
}
+ /**
+ * Sets the name filter that is applied to war files in this entry, if any.
+ */
public void setWarFilter(List filter)
{
this.warFilter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to ear files in this entry, if any.
+ */
public List getEarFilter()
{
return earFilter;
}
+ /**
+ * Sets the name filter that is applied to ear files in this entry, if any.
+ */
public void setEarFilter(List filter)
{
this.earFilter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to zip files in this entry, if any.
+ */
public List getZipFilter()
{
return zipFilter;
}
+ /**
+ * Sets the name filter that is applied to zip files in this entry, if any.
+ */
public void setZipFilter(List filter)
{
this.zipFilter = filter == null || filter.size() == 0 ? null : filter;
}
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ String string = getName();
+
+ if (filter != null ||
+ jarFilter != null ||
+ warFilter != null ||
+ earFilter != null ||
+ zipFilter != null)
+ {
+ string +=
+ ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
+ (zipFilter != null ? ListUtil.commaSeparatedString(zipFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (earFilter != null ? ListUtil.commaSeparatedString(earFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (warFilter != null ? ListUtil.commaSeparatedString(warFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (jarFilter != null ? ListUtil.commaSeparatedString(jarFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (filter != null ? ListUtil.commaSeparatedString(filter, true) : "") +
+ ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD;
+ }
+
+ return string;
+ }
}
diff --git a/src/proguard/ClassSpecification.java b/src/proguard/ClassSpecification.java
index a84e0c8..485c0b0 100644
--- a/src/proguard/ClassSpecification.java
+++ b/src/proguard/ClassSpecification.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassSpecificationVisitorFactory.java b/src/proguard/ClassSpecificationVisitorFactory.java
index c99ab2c..dc5d71f 100644
--- a/src/proguard/ClassSpecificationVisitorFactory.java
+++ b/src/proguard/ClassSpecificationVisitorFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -493,7 +493,8 @@ public class ClassSpecificationVisitorFactory
private static boolean containsWildCards(String string)
{
return string != null &&
- (string.indexOf('*') >= 0 ||
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
string.indexOf('?') >= 0 ||
string.indexOf('%') >= 0 ||
string.indexOf(',') >= 0 ||
diff --git a/src/proguard/Configuration.java b/src/proguard/Configuration.java
index d513e2c..4711260 100644
--- a/src/proguard/Configuration.java
+++ b/src/proguard/Configuration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -32,6 +32,9 @@ import java.util.List;
*/
public class Configuration
{
+ public static final File STD_OUT = new File("");
+
+
///////////////////////////////////////////////////////////////////////////
// Input and output options.
///////////////////////////////////////////////////////////////////////////
@@ -50,7 +53,7 @@ public class Configuration
* Specifies whether to skip non-public library classes while reading
* library jars.
*/
- public boolean skipNonPublicLibraryClasses = true;
+ public boolean skipNonPublicLibraryClasses = false;
/**
* Specifies whether to skip non-public library class members while reading
@@ -237,12 +240,19 @@ public class Configuration
public List keepAttributes;
/**
+ * Specifies whether method parameter names and types should be kept for
+ * methods that are not obfuscated. This is achieved by keeping partial
+ * "LocalVariableTable" and "LocalVariableTypeTable" attributes.
+ */
+ public boolean keepParameterNames = false;
+
+ /**
* An optional replacement for all SourceFile attributes.
*/
public String newSourceFileAttribute;
/**
- * A list of <code>String</code>s specifying a filter for clases whose
+ * A list of <code>String</code>s specifying a filter for classes whose
* string constants are to be adapted, based on corresponding obfuscated
* class names.
*/
diff --git a/src/proguard/ConfigurationConstants.java b/src/proguard/ConfigurationConstants.java
index 694e006..14c5654 100644
--- a/src/proguard/ConfigurationConstants.java
+++ b/src/proguard/ConfigurationConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -73,6 +73,7 @@ class ConfigurationConstants
public static final String REPACKAGE_CLASSES_OPTION = "-repackageclasses";
public static final String DEFAULT_PACKAGE_OPTION = "-defaultpackage";
public static final String KEEP_ATTRIBUTES_OPTION = "-keepattributes";
+ public static final String KEEP_PARAMETER_NAMES_OPTION = "-keepparameternames";
public static final String RENAME_SOURCE_FILE_ATTRIBUTE_OPTION = "-renamesourcefileattribute";
public static final String ADAPT_CLASS_STRINGS_OPTION = "-adaptclassstrings";
public static final String ADAPT_RESOURCE_FILE_NAMES_OPTION = "-adaptresourcefilenames";
@@ -87,6 +88,7 @@ class ConfigurationConstants
public static final String IGNORE_WARNINGS_OPTION = "-ignorewarnings";
public static final String PRINT_CONFIGURATION_OPTION = "-printconfiguration";
public static final String DUMP_OPTION = "-dump";
+ public static final String SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION = "-skipnonpubliclibraryclasses";
public static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION = "-dontskipnonpubliclibraryclasses";
public static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION = "-dontskipnonpubliclibraryclassmembers";
public static final String TARGET_OPTION = "-target";
diff --git a/src/proguard/ConfigurationParser.java b/src/proguard/ConfigurationParser.java
index e01809e..a38e9ed 100644
--- a/src/proguard/ConfigurationParser.java
+++ b/src/proguard/ConfigurationParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,56 +31,101 @@ import java.util.*;
/**
* This class parses ProGuard configurations. Configurations can be read from an
- * array of arguments or from a configuration file or URL.
+ * array of arguments or from a configuration file or URL. External references
+ * in file names ('<...>') can be resolved against a given set of properties.
*
* @author Eric Lafortune
*/
public class ConfigurationParser
{
- private WordReader reader;
+ private final WordReader reader;
+ private final Properties properties;
+
private String nextWord;
private String lastComments;
/**
- * Creates a new ConfigurationParser for the given String arguments.
+ * Creates a new ConfigurationParser for the given String arguments and
+ * the given Properties.
*/
- public ConfigurationParser(String[] args) throws IOException
+ public ConfigurationParser(String[] args,
+ Properties properties) throws IOException
{
- this(args, null);
+ this(args, null, properties);
}
/**
* Creates a new ConfigurationParser for the given String arguments,
- * with the given base directory.
+ * with the given base directory and the given Properties.
*/
- public ConfigurationParser(String[] args,
- File baseDir) throws IOException
+ public ConfigurationParser(String[] args,
+ File baseDir,
+ Properties properties) throws IOException
{
- reader = new ArgumentWordReader(args, baseDir);
+ this(new ArgumentWordReader(args, baseDir), properties);
+ }
- readNextWord();
+
+ /**
+ * Creates a new ConfigurationParser for the given lines,
+ * with the given base directory and the given Properties.
+ */
+ public ConfigurationParser(String lines,
+ String description,
+ File baseDir,
+ Properties properties) throws IOException
+ {
+ this(new LineWordReader(new LineNumberReader(new StringReader(lines)),
+ description,
+ baseDir),
+ properties);
}
/**
- * Creates a new ConfigurationParser for the given file.
+ * Creates a new ConfigurationParser for the given file, with the system
+ * Properties.
+ * @deprecated Temporary code for backward compatibility in Obclipse.
*/
public ConfigurationParser(File file) throws IOException
{
- reader = new FileWordReader(file);
+ this(file, System.getProperties());
+ }
- readNextWord();
+
+ /**
+ * Creates a new ConfigurationParser for the given file and the given
+ * Properties.
+ */
+ public ConfigurationParser(File file,
+ Properties properties) throws IOException
+ {
+ this(new FileWordReader(file), properties);
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given URL and the given
+ * Properties.
+ */
+ public ConfigurationParser(URL url,
+ Properties properties) throws IOException
+ {
+ this(new FileWordReader(url), properties);
}
/**
- * Creates a new ConfigurationParser for the given URL.
+ * Creates a new ConfigurationParser for the given word reader and the
+ * given Properties.
*/
- public ConfigurationParser(URL url) throws IOException
+ public ConfigurationParser(WordReader reader,
+ Properties properties) throws IOException
{
- reader = new FileWordReader(url);
+ this.reader = reader;
+ this.properties = properties;
readNextWord();
}
@@ -110,6 +155,7 @@ public class ConfigurationParser
else if (ConfigurationConstants.OUTJARS_OPTION .startsWith(nextWord)) configuration.programJars = parseClassPathArgument(configuration.programJars, true);
else if (ConfigurationConstants.LIBRARYJARS_OPTION .startsWith(nextWord)) configuration.libraryJars = parseClassPathArgument(configuration.libraryJars, false);
else if (ConfigurationConstants.RESOURCEJARS_OPTION .startsWith(nextWord)) throw new ParseException("The '-resourcejars' option is no longer supported. Please use the '-injars' option for all input");
+ else if (ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(true);
else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(false);
else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION.startsWith(nextWord)) configuration.skipNonPublicLibraryClassMembers = parseNoArgument(false);
else if (ConfigurationConstants.TARGET_OPTION .startsWith(nextWord)) configuration.targetClassVersion = parseClassVersion();
@@ -124,7 +170,7 @@ public class ConfigurationParser
else if (ConfigurationConstants.PRINT_SEEDS_OPTION .startsWith(nextWord)) configuration.printSeeds = parseOptionalFile();
// After '-keep'.
- else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION .startsWith(nextWord)) configuration.keepDirectories = parseCommaSeparatedList("directory name", true, true, false, false, true, false, false, configuration.keepDirectories);
+ else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION .startsWith(nextWord)) configuration.keepDirectories = parseCommaSeparatedList("directory name", true, true, false, true, false, true, false, false, configuration.keepDirectories);
else if (ConfigurationConstants.DONT_SHRINK_OPTION .startsWith(nextWord)) configuration.shrink = parseNoArgument(false);
else if (ConfigurationConstants.PRINT_USAGE_OPTION .startsWith(nextWord)) configuration.printUsage = parseOptionalFile();
@@ -132,7 +178,7 @@ public class ConfigurationParser
else if (ConfigurationConstants.DONT_OPTIMIZE_OPTION .startsWith(nextWord)) configuration.optimize = parseNoArgument(false);
else if (ConfigurationConstants.OPTIMIZATION_PASSES .startsWith(nextWord)) configuration.optimizationPasses = parseIntegerArgument();
- else if (ConfigurationConstants.OPTIMIZATIONS .startsWith(nextWord)) configuration.optimizations = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, configuration.optimizations);
+ else if (ConfigurationConstants.OPTIMIZATIONS .startsWith(nextWord)) configuration.optimizations = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, false, configuration.optimizations);
else if (ConfigurationConstants.ASSUME_NO_SIDE_EFFECTS_OPTION .startsWith(nextWord)) configuration.assumeNoSideEffects = parseClassSpecificationArguments(configuration.assumeNoSideEffects);
else if (ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION .startsWith(nextWord)) configuration.allowAccessModification = parseNoArgument(true);
else if (ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.mergeInterfacesAggressively = parseNoArgument(true);
@@ -146,22 +192,23 @@ public class ConfigurationParser
else if (ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.overloadAggressively = parseNoArgument(true);
else if (ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.useUniqueClassMemberNames = parseNoArgument(true);
else if (ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION .startsWith(nextWord)) configuration.useMixedCaseClassNames = parseNoArgument(false);
- else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION .startsWith(nextWord)) configuration.keepPackageNames = parseCommaSeparatedList("package name", true, true, false, true, false, true, false, configuration.keepPackageNames);
+ else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION .startsWith(nextWord)) configuration.keepPackageNames = parseCommaSeparatedList("package name", true, true, false, false, true, false, true, false, configuration.keepPackageNames);
else if (ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION .startsWith(nextWord)) configuration.flattenPackageHierarchy = ClassUtil.internalClassName(parseOptionalArgument());
else if (ConfigurationConstants.REPACKAGE_CLASSES_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument());
else if (ConfigurationConstants.DEFAULT_PACKAGE_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument());
- else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION .startsWith(nextWord)) configuration.keepAttributes = parseCommaSeparatedList("attribute name", true, true, false, true, false, false, false, configuration.keepAttributes);
+ else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION .startsWith(nextWord)) configuration.keepAttributes = parseCommaSeparatedList("attribute name", true, true, false, false, true, false, false, false, configuration.keepAttributes);
+ else if (ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION .startsWith(nextWord)) configuration.keepParameterNames = parseNoArgument(true);
else if (ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION .startsWith(nextWord)) configuration.newSourceFileAttribute = parseOptionalArgument();
- else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION .startsWith(nextWord)) configuration.adaptClassStrings = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.adaptClassStrings);
- else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, false, false, false, false, false, configuration.adaptResourceFileNames);
- else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION .startsWith(nextWord)) configuration.adaptResourceFileContents = parseCommaSeparatedList("resource file name", true, true, false, false, false, false, false, configuration.adaptResourceFileContents);
+ else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION .startsWith(nextWord)) configuration.adaptClassStrings = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.adaptClassStrings);
+ else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileNames);
+ else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION .startsWith(nextWord)) configuration.adaptResourceFileContents = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileContents);
else if (ConfigurationConstants.DONT_PREVERIFY_OPTION .startsWith(nextWord)) configuration.preverify = parseNoArgument(false);
else if (ConfigurationConstants.MICRO_EDITION_OPTION .startsWith(nextWord)) configuration.microEdition = parseNoArgument(true);
else if (ConfigurationConstants.VERBOSE_OPTION .startsWith(nextWord)) configuration.verbose = parseNoArgument(true);
- else if (ConfigurationConstants.DONT_NOTE_OPTION .startsWith(nextWord)) configuration.note = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.note);
- else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.warn);
+ else if (ConfigurationConstants.DONT_NOTE_OPTION .startsWith(nextWord)) configuration.note = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.note);
+ else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.warn);
else if (ConfigurationConstants.IGNORE_WARNINGS_OPTION .startsWith(nextWord)) configuration.ignoreWarnings = parseNoArgument(true);
else if (ConfigurationConstants.PRINT_CONFIGURATION_OPTION .startsWith(nextWord)) configuration.printConfiguration = parseOptionalFile();
else if (ConfigurationConstants.DUMP_OPTION .startsWith(nextWord)) configuration.dump = parseOptionalFile();
@@ -190,7 +237,7 @@ public class ConfigurationParser
private long parseIncludeArgument(long lastModified) throws ParseException, IOException
{
// Read the configuation file name.
- readNextWord("configuration file name");
+ readNextWord("configuration file name", true, false);
File file = file(nextWord);
reader.includeWordReader(new FileWordReader(file));
@@ -204,7 +251,7 @@ public class ConfigurationParser
private void parseBaseDirectoryArgument() throws ParseException, IOException
{
// Read the base directory name.
- readNextWord("base directory name");
+ readNextWord("base directory name", true, false);
reader.setBaseDir(file(nextWord));
@@ -225,7 +272,7 @@ public class ConfigurationParser
while (true)
{
// Read the next jar name.
- readNextWord("jar or directory name");
+ readNextWord("jar or directory name", true, false);
// Create a new class path entry.
ClassPathEntry entry = new ClassPathEntry(file(nextWord), isOutput);
@@ -245,7 +292,7 @@ public class ConfigurationParser
{
// Read the filter.
filters[counter++] =
- parseCommaSeparatedList("filter", true, false, true, false, true, false, false, null);
+ parseCommaSeparatedList("filter", true, true, true, true, false, true, false, false, null);
}
while (counter < filters.length &&
ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord));
@@ -343,7 +390,7 @@ public class ConfigurationParser
throws ParseException, IOException
{
// Read the obligatory file name.
- readNextWord("file name");
+ readNextWord("file name", true, false);
// Make sure the file is properly resolved.
File file = file(nextWord);
@@ -358,12 +405,12 @@ public class ConfigurationParser
throws ParseException, IOException
{
// Read the optional file name.
- readNextWord();
+ readNextWord(true);
// Didn't the user specify a file name?
if (configurationEnd())
{
- return new File("");
+ return Configuration.STD_OUT;
}
// Make sure the file is properly resolved.
@@ -386,11 +433,11 @@ public class ConfigurationParser
return "";
}
- String fileName = nextWord;
+ String argument = nextWord;
readNextWord();
- return fileName;
+ return argument;
}
@@ -431,7 +478,8 @@ public class ConfigurationParser
{
readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
"', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
- "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
+ "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'",
+ false, true);
if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
{
@@ -491,7 +539,8 @@ public class ConfigurationParser
// Read and add the class configuration.
readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
"', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
- "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
+ "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'",
+ false, true);
classSpecifications.add(parseClassSpecificationArguments());
@@ -499,7 +548,13 @@ public class ConfigurationParser
}
- private ClassSpecification parseClassSpecificationArguments()
+ /**
+ * Parses and returns a class specification.
+ * @throws ParseException if the class specification contains a syntax error.
+ * @throws IOException if an IO error occurs while reading the class
+ * specification.
+ */
+ public ClassSpecification parseClassSpecificationArguments()
throws ParseException, IOException
{
// Clear the annotation type.
@@ -512,30 +567,21 @@ public class ConfigurationParser
// Parse the class annotations and access modifiers until the class keyword.
while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord))
{
- // Parse the annotation type, if any.
-// if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
-// {
-// annotationType =
-// ClassUtil.internalType(
-// ListUtil.commaSeparatedString(
-// parseCommaSeparatedList("annotation type",
-// true, false, false, true, false, null)));
-//
-// continue;
-// }
-
// Strip the negating sign, if any.
- String strippedWord = nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD) ?
+ boolean negated =
+ nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD);
+
+ String strippedWord = negated ?
nextWord.substring(1) :
nextWord;
// Parse the class access modifiers.
- // TODO: Distinguish annotation from annotation modifier.
int accessFlag =
strippedWord.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ENUM) ? ClassConstants.INTERNAL_ACC_ENUM :
unknownAccessFlag();
@@ -543,9 +589,11 @@ public class ConfigurationParser
// Is it an annotation modifier?
if (accessFlag == ClassConstants.INTERNAL_ACC_ANNOTATTION)
{
- // Is the next word actually an annotation type?
- readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", false);
+ // Already read the next word.
+ readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'",
+ false, false);
+ // Is the next word actually an annotation type?
if (!nextWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) &&
!nextWord.equals(ClassConstants.EXTERNAL_ACC_ENUM) &&
!nextWord.equals(ConfigurationConstants.CLASS_KEYWORD))
@@ -554,13 +602,17 @@ public class ConfigurationParser
annotationType =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- false, false, false, true, false, false, true, null));
+ false, false, false, false, true, false, false, true, null), false);
+ // Continue parsing the access modifier that we just read
+ // in the next cycle.
continue;
}
+
+ // Otherwise just handle the annotation modifier.
}
- if (strippedWord.equals(nextWord))
+ if (!negated)
{
requiredSetClassAccessFlags |= accessFlag;
}
@@ -569,7 +621,6 @@ public class ConfigurationParser
requiredUnsetClassAccessFlags |= accessFlag;
}
-
if ((requiredSetClassAccessFlags &
requiredUnsetClassAccessFlags) != 0)
{
@@ -585,16 +636,21 @@ public class ConfigurationParser
break;
}
- readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
- "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
- "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
+ // Should we read the next word?
+ if (accessFlag != ClassConstants.INTERNAL_ACC_ANNOTATTION)
+ {
+ readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
+ "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
+ "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'",
+ false, true);
+ }
}
// Parse the class name part.
String externalClassName =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("class name or interface name",
- true, false, false, true, false, false, false, null));
+ true, false, false, false, true, false, false, false, null), false);
// For backward compatibility, allow a single "*" wildcard to match any
// class.
@@ -612,7 +668,7 @@ public class ConfigurationParser
if (ConfigurationConstants.IMPLEMENTS_KEYWORD.equals(nextWord) ||
ConfigurationConstants.EXTENDS_KEYWORD.equals(nextWord))
{
- readNextWord("class name or interface name", true);
+ readNextWord("class name or interface name", false, true);
// Parse the annotation type, if any.
if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
@@ -620,13 +676,13 @@ public class ConfigurationParser
extendsAnnotationType =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- true, false, false, true, false, false, true, null));
+ true, false, false, false, true, false, false, true, null), false);
}
String externalExtendsClassName =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("class name or interface name",
- false, false, false, true, false, false, false, null));
+ false, false, false, false, true, false, false, false, null), false);
extendsClassName = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalExtendsClassName) ?
null :
@@ -659,7 +715,8 @@ public class ConfigurationParser
while (true)
{
readNextWord("class member description" +
- " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'", true);
+ " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'",
+ false, true);
if (nextWord.equals(ConfigurationConstants.CLOSE_KEYWORD))
{
@@ -697,8 +754,7 @@ public class ConfigurationParser
annotationType =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- true, false, false, true, false, false, true, null));
-
+ true, false, false, false, true, false, false, true, null), false);
continue;
}
@@ -716,9 +772,12 @@ public class ConfigurationParser
strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
0;
if (accessFlag == 0)
{
@@ -875,7 +934,7 @@ public class ConfigurationParser
// Parse the method arguments.
String descriptor =
ClassUtil.internalMethodDescriptor(type,
- parseCommaSeparatedList("argument", true, true, true, true, false, false, false, null));
+ parseCommaSeparatedList("argument", true, true, true, false, true, false, false, false, null));
if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord))
{
@@ -913,14 +972,30 @@ public class ConfigurationParser
/**
- * Reads a comma-separated list of java identifiers or of file names. If an
- * empty list is allowed, the reading will end after a closing parenthesis
- * or semi-colon.
+ * Reads a comma-separated list of java identifiers or of file names.
+ * Examples of invocation arguments:
+ * ("directory n", true, true, false, true, false, true, false, false, ...)
+ * ("optimizatio", true, false, false, false, false, false, false, false, ...)
+ * ("package nam", true, true, false, false, true, false, true, false, ...)
+ * ("attribute n", true, true, false, false, true, false, false, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("resource fi", true, true, false, true, false, false, false, false, ...)
+ * ("resource fi", true, true, false, true, false, false, false, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("filter", true, true, true, true, false, true, false, false, ...)
+ * ("annotation ", false, false, false, false, true, false, false, true, ...)
+ * ("class name ", true, false, false, false, true, false, false, false, ...)
+ * ("annotation ", true, false, false, false, true, false, false, true, ...)
+ * ("class name ", false, false, false, false, true, false, false, false, ...)
+ * ("annotation ", true, false, false, false, true, false, false, true, ...)
+ * ("argument", true, true, true, false, true, false, false, false, ...)
*/
private List parseCommaSeparatedList(String expectedDescription,
boolean readFirstWord,
boolean allowEmptyList,
boolean expectClosingParenthesis,
+ boolean isFileName,
boolean checkJavaIdentifiers,
boolean replaceSystemProperties,
boolean replaceExternalClassNames,
@@ -935,19 +1010,38 @@ public class ConfigurationParser
if (readFirstWord)
{
- if (expectClosingParenthesis || !allowEmptyList)
+ if (!allowEmptyList)
{
// Read the first list entry.
- readNextWord(expectedDescription);
+ readNextWord(expectedDescription, isFileName, false);
+ }
+ else if (expectClosingParenthesis)
+ {
+ // Read the first list entry.
+ readNextWord(expectedDescription, isFileName, false);
+
+ // Return if the entry is actually empty (an empty file name or
+ // a closing parenthesis).
+ if (nextWord.length() == 0)
+ {
+ // Read the closing parenthesis
+ readNextWord("closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
+ "'");
+
+ return list;
+ }
+ else if (nextWord.equals(ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD))
+ {
+ return list;
+ }
}
else
{
// Read the first list entry, if there is any.
- readNextWord();
+ readNextWord(isFileName);
// Check if the list is empty.
- if (configurationEnd() ||
- nextWord.equals(ConfigurationConstants.ANY_ATTRIBUTE_KEYWORD))
+ if (configurationEnd())
{
return list;
}
@@ -956,14 +1050,6 @@ public class ConfigurationParser
while (true)
{
- if (expectClosingParenthesis &&
- list.size() == 0 &&
- (ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord) ||
- ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord)))
- {
- break;
- }
-
if (checkJavaIdentifiers)
{
checkJavaIdentifier("java type");
@@ -1001,14 +1087,12 @@ public class ConfigurationParser
if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
{
- break;
+ return list;
}
// Read the next list entry.
- readNextWord(expectedDescription);
+ readNextWord(expectedDescription, isFileName, false);
}
-
- return list;
}
@@ -1035,23 +1119,13 @@ public class ConfigurationParser
file = new File(reader.getBaseDir(), fileName);
}
- // Try to get a canonical representation.
- try
- {
- file = file.getCanonicalFile();
- }
- catch (IOException ex)
- {
- // Just keep the original representation.
- }
-
return file;
}
/**
- * Replaces any system properties in the given word by their values
- * (e.g. the substring "<java.home>" is replaced by its value).
+ * Replaces any properties in the given word by their values.
+ * For instance, the substring "<java.home>" is replaced by its value.
*/
private String replaceSystemProperties(String word) throws ParseException
{
@@ -1073,7 +1147,7 @@ public class ConfigurationParser
}
String propertyName = word.substring(fromIndex+1, toIndex);
- String propertyValue = System.getProperty(propertyName);
+ String propertyValue = properties.getProperty(propertyName);
if (propertyValue == null)
{
throw new ParseException("Value of system property '" + propertyName +
@@ -1096,7 +1170,7 @@ public class ConfigurationParser
private void readNextWord(String expectedDescription)
throws ParseException, IOException
{
- readNextWord(expectedDescription, false);
+ readNextWord(expectedDescription, false, false);
}
@@ -1105,10 +1179,11 @@ public class ConfigurationParser
* throwing an exception if there is no next word.
*/
private void readNextWord(String expectedDescription,
+ boolean isFileName,
boolean expectingAtCharacter)
throws ParseException, IOException
{
- readNextWord();
+ readNextWord(isFileName);
if (configurationEnd(expectingAtCharacter))
{
throw new ParseException("Expecting " + expectedDescription +
@@ -1122,7 +1197,16 @@ public class ConfigurationParser
*/
private void readNextWord() throws IOException
{
- nextWord = reader.nextWord();
+ readNextWord(false);
+ }
+
+
+ /**
+ * Reads the next word of the configuration in the 'nextWord' field.
+ */
+ private void readNextWord(boolean isFileName) throws IOException
+ {
+ nextWord = reader.nextWord(isFileName);
}
@@ -1168,6 +1252,11 @@ public class ConfigurationParser
*/
private boolean isJavaIdentifier(String aWord)
{
+ if (aWord.length() == 0)
+ {
+ return false;
+ }
+
for (int index = 0; index < aWord.length(); index++)
{
char c = aWord.charAt(index);
@@ -1234,7 +1323,8 @@ public class ConfigurationParser
{
try
{
- ConfigurationParser parser = new ConfigurationParser(args);
+ ConfigurationParser parser =
+ new ConfigurationParser(args, System.getProperties());
try
{
diff --git a/src/proguard/ConfigurationWriter.java b/src/proguard/ConfigurationWriter.java
index 5d112d6..00dfa9e 100644
--- a/src/proguard/ConfigurationWriter.java
+++ b/src/proguard/ConfigurationWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,7 +25,7 @@ import proguard.classfile.util.ClassUtil;
import proguard.util.ListUtil;
import java.io.*;
-import java.util.List;
+import java.util.*;
/**
@@ -44,7 +44,7 @@ public class ConfigurationWriter
private final PrintWriter writer;
- private File baseDir;
+ private File baseDir;
/**
@@ -105,7 +105,7 @@ public class ConfigurationWriter
writer.println();
// Write the other options.
- writeOption(ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION, !configuration.skipNonPublicLibraryClasses);
+ writeOption(ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION, configuration.skipNonPublicLibraryClasses);
writeOption(ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION, !configuration.skipNonPublicLibraryClassMembers);
writeOption(ConfigurationConstants.KEEP_DIRECTORIES_OPTION, configuration.keepDirectories);
writeOption(ConfigurationConstants.TARGET_OPTION, ClassUtil.externalClassVersion(configuration.targetClassVersion));
@@ -115,7 +115,7 @@ public class ConfigurationWriter
writeOption(ConfigurationConstants.PRINT_USAGE_OPTION, configuration.printUsage);
writeOption(ConfigurationConstants.DONT_OPTIMIZE_OPTION, !configuration.optimize);
- writeOption(ConfigurationConstants.OPTIMIZATIONS, configuration.optimize ? ListUtil.commaSeparatedString(configuration.optimizations) : null);
+ writeOption(ConfigurationConstants.OPTIMIZATIONS, configuration.optimizations);
writeOption(ConfigurationConstants.OPTIMIZATION_PASSES, configuration.optimizationPasses);
writeOption(ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION, configuration.allowAccessModification);
writeOption(ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION, configuration.mergeInterfacesAggressively);
@@ -133,6 +133,7 @@ public class ConfigurationWriter
writeOption(ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION, configuration.flattenPackageHierarchy, true);
writeOption(ConfigurationConstants.REPACKAGE_CLASSES_OPTION, configuration.repackageClasses, true);
writeOption(ConfigurationConstants.KEEP_ATTRIBUTES_OPTION, configuration.keepAttributes);
+ writeOption(ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION, configuration.keepParameterNames);
writeOption(ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION, configuration.newSourceFileAttribute);
writeOption(ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION, configuration.adaptClassStrings, true);
writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION, configuration.adaptResourceFileNames);
@@ -218,15 +219,7 @@ public class ConfigurationWriter
writer.print(ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD);
}
- for (int index = 0; index < filter.size(); index++)
- {
- if (index > 0)
- {
- writer.print(ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD);
- }
-
- writer.print(quotedString((String)filter.get(index)));
- }
+ writer.print(ListUtil.commaSeparatedString(filter, true));
filtered = true;
}
@@ -273,16 +266,14 @@ public class ConfigurationWriter
}
else
{
- String argumentString = ListUtil.commaSeparatedString(arguments);
-
if (replaceInternalClassNames)
{
- argumentString = ClassUtil.externalClassName(argumentString);
+ arguments = externalClassNames(arguments);
}
writer.print(optionName);
writer.print(' ');
- writer.println(quotedString(argumentString));
+ writer.println(ListUtil.commaSeparatedString(arguments, true));
}
}
}
@@ -585,6 +576,23 @@ public class ConfigurationWriter
/**
+ * Returns a list with external versions of the given list of internal
+ * class names.
+ */
+ private List externalClassNames(List internalClassNames)
+ {
+ List externalClassNames = new ArrayList(internalClassNames.size());
+
+ for (int index = 0; index < internalClassNames.size(); index++)
+ {
+ externalClassNames.add(ClassUtil.externalClassName((String)internalClassNames.get(index)));
+ }
+
+ return externalClassNames;
+ }
+
+
+ /**
* Returns a relative file name of the given file, if possible.
* The file name is also quoted, if necessary.
*/
diff --git a/src/proguard/DataEntryReaderFactory.java b/src/proguard/DataEntryReaderFactory.java
index a9724b5..3bf6f56 100644
--- a/src/proguard/DataEntryReaderFactory.java
+++ b/src/proguard/DataEntryReaderFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -48,11 +48,10 @@ public class DataEntryReaderFactory
ClassPathEntry classPathEntry,
DataEntryReader reader)
{
- String entryName = classPathEntry.getName();
- boolean isJar = endsWithIgnoreCase(entryName, ".jar");
- boolean isWar = endsWithIgnoreCase(entryName, ".war");
- boolean isEar = endsWithIgnoreCase(entryName, ".ear");
- boolean isZip = endsWithIgnoreCase(entryName, ".zip");
+ boolean isJar = classPathEntry.isJar();
+ boolean isWar = classPathEntry.isWar();
+ boolean isEar = classPathEntry.isEar();
+ boolean isZip = classPathEntry.isZip();
List filter = classPathEntry.getFilter();
List jarFilter = classPathEntry.getJarFilter();
@@ -139,17 +138,4 @@ public class DataEntryReaderFactory
reader);
}
}
-
-
- /**
- * Returns whether the given string ends with the given suffix, ignoring its
- * case.
- */
- private static boolean endsWithIgnoreCase(String string, String suffix)
- {
- int stringLength = string.length();
- int suffixLength = suffix.length();
-
- return string.regionMatches(true, stringLength - suffixLength, suffix, 0, suffixLength);
- }
}
diff --git a/src/proguard/DataEntryWriterFactory.java b/src/proguard/DataEntryWriterFactory.java
index 9fbc6d0..ca33a35 100644
--- a/src/proguard/DataEntryWriterFactory.java
+++ b/src/proguard/DataEntryWriterFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -65,11 +65,10 @@ public class DataEntryWriterFactory
private static DataEntryWriter createClassPathEntryWriter(ClassPathEntry classPathEntry,
DataEntryWriter alternativeWriter)
{
- String entryName = classPathEntry.getName();
- boolean isJar = endsWithIgnoreCase(entryName, ".jar");
- boolean isWar = endsWithIgnoreCase(entryName, ".war");
- boolean isEar = endsWithIgnoreCase(entryName, ".ear");
- boolean isZip = endsWithIgnoreCase(entryName, ".zip");
+ boolean isJar = classPathEntry.isJar();
+ boolean isWar = classPathEntry.isWar();
+ boolean isEar = classPathEntry.isEar();
+ boolean isZip = classPathEntry.isZip();
List filter = classPathEntry.getFilter();
List jarFilter = classPathEntry.getJarFilter();
@@ -83,7 +82,7 @@ public class DataEntryWriterFactory
isEar ? "ear" :
isZip ? "zip" :
"directory") +
- " [" + entryName + "]" +
+ " [" + classPathEntry.getName() + "]" +
(filter != null ||
jarFilter != null ||
warFilter != null ||
@@ -148,17 +147,4 @@ public class DataEntryWriterFactory
filteredJarWriter,
isJar ? jarWriter : writer);
}
-
-
- /**
- * Returns whether the given string ends with the given suffix, ignoring its
- * case.
- */
- private static boolean endsWithIgnoreCase(String string, String suffix)
- {
- int stringLength = string.length();
- int suffixLength = suffix.length();
-
- return string.regionMatches(true, stringLength - suffixLength, suffix, 0, suffixLength);
- }
}
diff --git a/src/proguard/DescriptorKeepChecker.java b/src/proguard/DescriptorKeepChecker.java
index 1dfaf1a..fcd80b2 100644
--- a/src/proguard/DescriptorKeepChecker.java
+++ b/src/proguard/DescriptorKeepChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,7 @@ package proguard;
import proguard.classfile.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
-import proguard.optimize.KeepMarker;
+import proguard.optimize.*;
import java.util.List;
@@ -64,7 +64,7 @@ implements MemberVisitor,
/**
* Checks the classes mentioned in the given keep specifications, printing
- * notes if necessary. Returns the number of notes printed.
+ * notes if necessary.
*/
public void checkClassSpecifications(List keepSpecifications)
{
@@ -85,8 +85,11 @@ implements MemberVisitor,
programClassPool.accept(classPoolvisitor);
libraryClassPool.accept(classPoolvisitor);
- // Print out notes about argument types that are not being kept.
- programClassPool.classesAccept(new AllMemberVisitor(this));
+ // Print out notes about argument types that are not being kept in
+ // class members that are being kept.
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new KeptMemberFilter(this)));
}
@@ -94,39 +97,42 @@ implements MemberVisitor,
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- if (KeepMarker.isKept(programField))
- {
- referencingClass = programClass;
- referencingMember = programField;
- isField = true;
-
- // Don't check the type, because it is not required for introspection.
- //programField.referencedClassesAccept(this);
- }
+ //referencingClass = programClass;
+ //referencingMember = programField;
+ //isField = true;
+ //
+ // Don't check the type, because it is not required for introspection.
+ //programField.referencedClassesAccept(this);
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- if (KeepMarker.isKept(programMethod))
+ referencingClass = programClass;
+ referencingMember = programMethod;
+ isField = false;
+
+ // Don't check the return type, because it is not required for
+ // introspection (e.g. the return type of the special Enum methods).
+ //programMethod.referencedClassesAccept(this);
+
+ Clazz[] referencedClasses = programMethod.referencedClasses;
+ if (referencedClasses != null)
{
- referencingClass = programClass;
- referencingMember = programMethod;
- isField = false;
+ int count = referencedClasses.length;
- // Don't check the return type, because it is not required for
- // introspection (e.g. the return type of the special Enum methods).
- //programMethod.referencedClassesAccept(this);
+ // Adapt the count if the return type is a class type (not so
+ // pretty; assuming test just checks for final ';').
+ if (ClassUtil.isInternalClassType(programMethod.getDescriptor(programClass)))
+ {
+ count--;
+ }
- Clazz[] referencedClasses = programMethod.referencedClasses;
- if (referencedClasses != null)
+ for (int index = 0; index < count; index++)
{
- for (int index = 0; index < referencedClasses.length-1; index++)
+ if (referencedClasses[index] != null)
{
- if (referencedClasses[index] != null)
- {
- referencedClasses[index].accept(this);
- }
+ referencedClasses[index].accept(this);
}
}
}
diff --git a/src/proguard/DuplicateClassPrinter.java b/src/proguard/DuplicateClassPrinter.java
index 21b6aa0..7a071ce 100644
--- a/src/proguard/DuplicateClassPrinter.java
+++ b/src/proguard/DuplicateClassPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/FileWordReader.java b/src/proguard/FileWordReader.java
index fb9fa50..7309843 100644
--- a/src/proguard/FileWordReader.java
+++ b/src/proguard/FileWordReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,23 +29,17 @@ import java.net.URL;
*
* @author Eric Lafortune
*/
-public class FileWordReader extends WordReader
+public class FileWordReader extends LineWordReader
{
- private final String name;
- private LineNumberReader reader;
-
-
/**
* Creates a new FileWordReader for the given file.
*/
public FileWordReader(File file) throws IOException
{
- super(file.getParentFile());
-
- this.name = file.getPath();
- this.reader = new LineNumberReader(
- new BufferedReader(
- new FileReader(file)));
+ super(new LineNumberReader(new BufferedReader(new FileReader(file))),
+ "file '" + file.getPath() + "'",
+ file.getParentFile()
+ );
}
@@ -54,36 +48,8 @@ public class FileWordReader extends WordReader
*/
public FileWordReader(URL url) throws IOException
{
- super(null);
-
- this.name = url.toString();
- this.reader = new LineNumberReader(
- new BufferedReader(
- new InputStreamReader(url.openStream())));
- }
-
-
- // Implementations for WordReader.
-
- protected String nextLine() throws IOException
- {
- return reader.readLine();
- }
-
-
- protected String lineLocationDescription()
- {
- return "line " + reader.getLineNumber() + " of file '" + name + "'";
- }
-
-
- public void close() throws IOException
- {
- super.close();
-
- if (reader != null)
- {
- reader.close();
- }
+ super(new LineNumberReader(new BufferedReader(new InputStreamReader(url.openStream()))),
+ "file '" + url.toString() + "'",
+ null);
}
}
diff --git a/src/proguard/FullyQualifiedClassNameChecker.java b/src/proguard/FullyQualifiedClassNameChecker.java
index 06949b5..eb1865a 100644
--- a/src/proguard/FullyQualifiedClassNameChecker.java
+++ b/src/proguard/FullyQualifiedClassNameChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -42,7 +42,7 @@ implements ClassVisitor
/**
- * Creates a new DescriptorKeepChecker.
+ * Creates a new FullyQualifiedClassNameChecker.
*/
public FullyQualifiedClassNameChecker(ClassPool programClassPool,
ClassPool libraryClassPool,
@@ -56,7 +56,7 @@ implements ClassVisitor
/**
* Checks the classes mentioned in the given class specifications, printing
- * notes if necessary. Returns the number of notes printed.
+ * notes if necessary.
*/
public void checkClassSpecifications(List classSpecifications)
{
@@ -173,7 +173,8 @@ implements ClassVisitor
private static boolean containsWildCards(String string)
{
return string != null &&
- (string.indexOf('*') >= 0 ||
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
string.indexOf('?') >= 0 ||
string.indexOf(',') >= 0 ||
string.indexOf("///") >= 0);
diff --git a/src/proguard/GPL.java b/src/proguard/GPL.java
index 272a837..51220b8 100644
--- a/src/proguard/GPL.java
+++ b/src/proguard/GPL.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -48,9 +48,10 @@ public class GPL
{
String uniquePackageNames = uniquePackageNames(unknownPackageNames);
- System.out.println("ProGuard is released under the GNU General Public License. The authors of all");
- System.out.println("programs or plugins that link to it ("+uniquePackageNames+"...) therefore");
- System.out.println("must ensure that these programs carry the GNU General Public License as well.");
+ System.out.println("ProGuard is released under the GNU General Public License. You therefore");
+ System.out.println("must ensure that programs that link to it ("+uniquePackageNames+"...)");
+ System.out.println("carry the GNU General Public License as well. Alternatively, you can");
+ System.out.println("apply for an exception with the author of ProGuard.");
}
}
@@ -163,11 +164,20 @@ public class GPL
packageName.startsWith("proguard") ||
packageName.startsWith("org.apache.tools.ant") ||
packageName.startsWith("org.apache.tools.maven") ||
+ packageName.startsWith("org.gradle") ||
+ packageName.startsWith("org.codehaus.groovy") ||
packageName.startsWith("org.eclipse") ||
packageName.startsWith("org.netbeans") ||
+ packageName.startsWith("com.android") ||
packageName.startsWith("com.sun.kvem") ||
+ packageName.startsWith("com.intel") ||
packageName.startsWith("net.certiv.proguarddt") ||
+ packageName.startsWith("groovy") ||
+ packageName.startsWith("scala") ||
+ packageName.startsWith("sbt") ||
+ packageName.startsWith("xsbt") ||
packageName.startsWith("eclipseme") ||
+ packageName.startsWith("com.neomades") ||
packageName.startsWith("jg.j2me") ||
packageName.startsWith("jg.common") ||
packageName.startsWith("jg.buildengine");
diff --git a/src/proguard/Initializer.java b/src/proguard/Initializer.java
index 41cf971..405c06d 100644
--- a/src/proguard/Initializer.java
+++ b/src/proguard/Initializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,7 @@
package proguard;
import proguard.classfile.ClassPool;
+import proguard.classfile.attribute.annotation.visitor.*;
import proguard.classfile.attribute.visitor.AllAttributeVisitor;
import proguard.classfile.constant.visitor.*;
import proguard.classfile.instruction.visitor.AllInstructionVisitor;
@@ -60,6 +61,16 @@ public class Initializer
{
int originalLibraryClassPoolSize = libraryClassPool.size();
+ // Perform basic checks on the configuration.
+ WarningPrinter fullyQualifiedClassNameNotePrinter = new WarningPrinter(System.out, configuration.note);
+ WarningPrinter keepClassMemberNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ new FullyQualifiedClassNameChecker(programClassPool,
+ libraryClassPool,
+ fullyQualifiedClassNameNotePrinter).checkClassSpecifications(configuration.keep);
+
+ new KeepClassMemberChecker(keepClassMemberNotePrinter).checkClassSpecifications(configuration.keep);
+
// Construct a reduced library class pool with only those library
// classes whose hierarchies are referenced by the program classes.
// We can't do this if we later have to come up with the obfuscated
@@ -88,13 +99,15 @@ public class Initializer
// Initialize the class references of program class members and
// attributes. Note that all superclass hierarchies have to be
// initialized for this purpose.
- WarningPrinter memberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter programMemberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter libraryMemberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
programClassPool.classesAccept(
new ClassReferenceInitializer(programClassPool,
libraryClassPool,
classReferenceWarningPrinter,
- memberReferenceWarningPrinter,
+ programMemberReferenceWarningPrinter,
+ libraryMemberReferenceWarningPrinter,
null));
if (reducedLibraryClassPool != null)
@@ -115,7 +128,13 @@ public class Initializer
null));
}
- // Initialize the Class.forName references.
+ // Initialize the enum annotation references.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(true,
+ new AllElementValueVisitor(true,
+ new EnumFieldReferenceInitializer())));
+
+ // Initialize the Class.forName references.
WarningPrinter dynamicClassReferenceNotePrinter = new WarningPrinter(System.out, configuration.note);
WarningPrinter classForNameNotePrinter = new WarningPrinter(System.out, configuration.note);
@@ -153,13 +172,8 @@ public class Initializer
libraryClassPool))));
}
- // Print various notes, if specified.
- WarningPrinter fullyQualifiedClassNameNotePrinter = new WarningPrinter(System.out, configuration.note);
- WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note);
-
- new FullyQualifiedClassNameChecker(programClassPool,
- libraryClassPool,
- fullyQualifiedClassNameNotePrinter).checkClassSpecifications(configuration.keep);
+ // Check for unkept descriptor classes of kept class members.
+ WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note);
new DescriptorKeepChecker(programClassPool,
libraryClassPool,
@@ -184,6 +198,7 @@ public class Initializer
libraryClassPool,
null,
null,
+ null,
dependencyWarningPrinter));
// Reset the library class pool.
@@ -214,6 +229,7 @@ public class Initializer
libraryClassPool,
null,
null,
+ null,
dependencyWarningPrinter));
}
@@ -232,6 +248,18 @@ public class Initializer
System.out.println("Note: there were " + fullyQualifiedNoteCount +
" references to unknown classes.");
System.out.println(" You should check your configuration for typos.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unknownclass)");
+ }
+
+ // Print out a summary of the notes, if necessary.
+ int keepClassMemberNoteCount = keepClassMemberNotePrinter.getWarningCount();
+ if (keepClassMemberNoteCount > 0)
+ {
+ System.out.println("Note: there were " + keepClassMemberNoteCount +
+ " '-keepclassmembers' options that didn't specify class");
+ System.out.println(" members. You should specify at least some class members or consider");
+ System.out.println(" if you just need '-keep'.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#classmembers)");
}
int descriptorNoteCount = descriptorKeepNotePrinter.getWarningCount();
@@ -241,6 +269,7 @@ public class Initializer
" unkept descriptor classes in kept class members.");
System.out.println(" You should consider explicitly keeping the mentioned classes");
System.out.println(" (using '-keep').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#descriptorclass)");
}
int dynamicClassReferenceNoteCount = dynamicClassReferenceNotePrinter.getWarningCount();
@@ -248,7 +277,8 @@ public class Initializer
{
System.out.println("Note: there were " + dynamicClassReferenceNoteCount +
" unresolved dynamic references to classes or interfaces.");
- System.err.println(" You should check if you need to specify additional program jars.");
+ System.out.println(" You should check if you need to specify additional program jars.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclass)");
}
int classForNameNoteCount = classForNameNotePrinter.getWarningCount();
@@ -258,6 +288,7 @@ public class Initializer
" class casts of dynamically created class instances.");
System.out.println(" You might consider explicitly keeping the mentioned classes and/or");
System.out.println(" their implementations (using '-keep').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclasscast)");
}
int getmemberNoteCount = getMemberNotePrinter.getWarningCount();
@@ -267,6 +298,7 @@ public class Initializer
" accesses to class members by means of introspection.");
System.out.println(" You should consider explicitly keeping the mentioned class members");
System.out.println(" (using '-keep' or '-keepclassmembers').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclassmember)");
}
// Print out a summary of the warnings, if necessary.
@@ -275,8 +307,16 @@ public class Initializer
{
System.err.println("Warning: there were " + classReferenceWarningCount +
" unresolved references to classes or interfaces.");
- System.err.println(" You may need to specify additional library jars (using '-libraryjars'),");
- System.err.println(" or perhaps the '-dontskipnonpubliclibraryclasses' option.");
+ System.err.println(" You may need to add missing library jars or update their versions.");
+ System.err.println(" If your code works fine without the missing classes, you can suppress");
+ System.err.println(" the warnings with '-dontwarn' options.");
+
+ if (configuration.skipNonPublicLibraryClasses)
+ {
+ System.err.println(" You may also have to remove the option '-skipnonpubliclibraryclasses'.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)");
}
int dependencyWarningCount = dependencyWarningPrinter.getWarningCount();
@@ -286,23 +326,44 @@ public class Initializer
" instances of library classes depending on program classes.");
System.err.println(" You must avoid such dependencies, since the program classes will");
System.err.println(" be processed, while the library classes will remain unchanged.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dependency)");
}
- int memberReferenceWarningCount = memberReferenceWarningPrinter.getWarningCount();
- if (memberReferenceWarningCount > 0)
+ int programMemberReferenceWarningCount = programMemberReferenceWarningPrinter.getWarningCount();
+ if (programMemberReferenceWarningCount > 0)
{
- System.err.println("Warning: there were " + memberReferenceWarningCount +
+ System.err.println("Warning: there were " + programMemberReferenceWarningCount +
" unresolved references to program class members.");
System.err.println(" Your input classes appear to be inconsistent.");
- System.err.println(" You may need to recompile them and try again.");
- System.err.println(" Alternatively, you may have to specify the options ");
- System.err.println(" '-dontskipnonpubliclibraryclasses' and/or");
- System.err.println(" '-dontskipnonpubliclibraryclassmembers'.");
+ System.err.println(" You may need to recompile the code.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)");
+ }
+
+ int libraryMemberReferenceWarningCount = libraryMemberReferenceWarningPrinter.getWarningCount();
+ if (libraryMemberReferenceWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + libraryMemberReferenceWarningCount +
+ " unresolved references to library class members.");
+ System.err.println(" You probably need to update the library versions.");
+
+ if (!configuration.skipNonPublicLibraryClassMembers)
+ {
+ System.err.println(" Alternatively, you may have to specify the option ");
+ System.err.println(" '-dontskipnonpubliclibraryclassmembers'.");
+ }
+
+ if (configuration.skipNonPublicLibraryClasses)
+ {
+ System.err.println(" You may also have to remove the option '-skipnonpubliclibraryclasses'.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)");
}
- if ((classReferenceWarningCount > 0 ||
- dependencyWarningCount > 0 ||
- memberReferenceWarningCount > 0) &&
+ if ((classReferenceWarningCount > 0 ||
+ dependencyWarningCount > 0 ||
+ programMemberReferenceWarningCount > 0 ||
+ libraryMemberReferenceWarningCount > 0) &&
!configuration.ignoreWarnings)
{
throw new IOException("Please correct the above warnings first.");
diff --git a/src/proguard/InputReader.java b/src/proguard/InputReader.java
index c088324..707774e 100644
--- a/src/proguard/InputReader.java
+++ b/src/proguard/InputReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -115,6 +115,7 @@ public class InputReader
{
System.err.println("Note: there were " + noteCount +
" duplicate class definitions.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#duplicateclass)");
}
// Print out a summary of the warnings, if necessary.
@@ -125,6 +126,7 @@ public class InputReader
" classes in incorrectly named files.");
System.err.println(" You should make sure all file names correspond to their class names.");
System.err.println(" The directory hierarchies must correspond to the package hierarchies.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unexpectedclass)");
if (!configuration.ignoreWarnings)
{
@@ -227,7 +229,7 @@ public class InputReader
}
catch (IOException ex)
{
- throw new IOException("Can't read [" + classPathEntry + "] (" + ex.getMessage() + ")");
+ throw (IOException)new IOException("Can't read [" + classPathEntry + "] (" + ex.getMessage() + ")").initCause(ex);
}
}
}
diff --git a/src/proguard/KeepClassMemberChecker.java b/src/proguard/KeepClassMemberChecker.java
new file mode 100644
index 0000000..3ea518e
--- /dev/null
+++ b/src/proguard/KeepClassMemberChecker.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.List;
+
+/**
+ * This class checks if the user has forgotten to specify class members in
+ * some keep options in the configuration.
+ *
+ * @author Eric Lafortune
+ */
+public class KeepClassMemberChecker
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new KeepClassMemberChecker.
+ */
+ public KeepClassMemberChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks if the given class specifications try to keep class members
+ * without actually specifying any, printing notes if necessary. Returns
+ * the number of notes printed.
+ */
+ public void checkClassSpecifications(List keepClassSpecifications)
+ {
+ if (keepClassSpecifications != null)
+ {
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepClassSpecifications.get(index);
+
+ if (!keepClassSpecification.markClasses &&
+ (keepClassSpecification.fieldSpecifications == null ||
+ keepClassSpecification.fieldSpecifications.size() == 0) &&
+ (keepClassSpecification.methodSpecifications == null ||
+ keepClassSpecification.methodSpecifications.size() == 0))
+ {
+ String className = keepClassSpecification.className;
+ if (className == null)
+ {
+ className = keepClassSpecification.extendsClassName;
+ }
+
+ if (notePrinter.accepts(className))
+ {
+ notePrinter.print(className,
+ "Note: the configuration doesn't specify which class members to keep for class '" +
+ (className == null ?
+ ConfigurationConstants.ANY_CLASS_KEYWORD :
+ ClassUtil.externalClassName(className)) + "'");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/proguard/KeepClassSpecification.java b/src/proguard/KeepClassSpecification.java
index 29c0d3c..a6215c5 100644
--- a/src/proguard/KeepClassSpecification.java
+++ b/src/proguard/KeepClassSpecification.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/LineWordReader.java b/src/proguard/LineWordReader.java
new file mode 100644
index 0000000..64a228c
--- /dev/null
+++ b/src/proguard/LineWordReader.java
@@ -0,0 +1,74 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+
+
+/**
+ * A <code>WordReader</code> that returns words from a line number reader.
+ *
+ * @author Eric Lafortune
+ */
+public class LineWordReader extends WordReader
+{
+ private final LineNumberReader reader;
+ private final String description;
+
+
+ /**
+ * Creates a new LineWordReader for the given input.
+ */
+ public LineWordReader(LineNumberReader lineNumberReader,
+ String description,
+ File baseDir) throws IOException
+ {
+ super(baseDir);
+
+ this.reader = lineNumberReader;
+ this.description = description;
+ }
+
+
+ // Implementations for WordReader.
+
+ protected String nextLine() throws IOException
+ {
+ return reader.readLine();
+ }
+
+
+ protected String lineLocationDescription()
+ {
+ return "line " + reader.getLineNumber() + " of " + description;
+ }
+
+
+ public void close() throws IOException
+ {
+ super.close();
+
+ if (reader != null)
+ {
+ reader.close();
+ }
+ }
+}
diff --git a/src/proguard/MemberSpecification.java b/src/proguard/MemberSpecification.java
index 1cfa962..e771fde 100644
--- a/src/proguard/MemberSpecification.java
+++ b/src/proguard/MemberSpecification.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/OutputWriter.java b/src/proguard/OutputWriter.java
index 10c18fb..c4467cf 100644
--- a/src/proguard/OutputWriter.java
+++ b/src/proguard/OutputWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,13 +63,12 @@ public class OutputWriter
"] must be specified after an input jar, or it will be empty.");
}
- // Perform some checks on the output jars.
+ // Check if the first of two subsequent the output jars has a filter.
for (int index = 0; index < programJars.size() - 1; index++)
{
ClassPathEntry entry = programJars.get(index);
if (entry.isOutput())
{
- // Check if all but the last output jars have filters.
if (entry.getFilter() == null &&
entry.getJarFilter() == null &&
entry.getWarFilter() == null &&
@@ -78,10 +77,17 @@ public class OutputWriter
programJars.get(index + 1).isOutput())
{
throw new IOException("The output jar [" + entry.getName() +
- "] must have a filter, or all subsequent jars will be empty.");
+ "] must have a filter, or all subsequent output jars will be empty.");
}
+ }
+ }
- // Check if the output jar name is different from the input jar names.
+ // Check if the output jar names are different from the input jar names.
+ for (int outIndex = 0; outIndex < programJars.size() - 1; outIndex++)
+ {
+ ClassPathEntry entry = programJars.get(outIndex);
+ if (entry.isOutput())
+ {
for (int inIndex = 0; inIndex < programJars.size(); inIndex++)
{
ClassPathEntry otherEntry = programJars.get(inIndex);
@@ -96,6 +102,40 @@ public class OutputWriter
}
}
+ // Check for potential problems with mixed-case class names on
+ // case-insensitive file systems.
+ if (configuration.obfuscate &&
+ configuration.useMixedCaseClassNames &&
+ configuration.classObfuscationDictionary == null &&
+ (configuration.note == null ||
+ !configuration.note.isEmpty()))
+ {
+ String os = System.getProperty("os.name").toLowerCase();
+ if (os.startsWith("windows") ||
+ os.startsWith("mac os"))
+ {
+ // Go over all program class path entries.
+ for (int index = 0; index < programJars.size(); index++)
+ {
+ // Is it an output directory?
+ ClassPathEntry entry = programJars.get(index);
+ if (entry.isOutput() &&
+ !entry.isJar() &&
+ !entry.isWar() &&
+ !entry.isEar() &&
+ !entry.isZip())
+ {
+ System.out.println("Note: you're writing the processed class files to a directory [" + entry.getName() +"].");
+ System.out.println(" This will likely cause problems with obfuscated mixed-case class names.");
+ System.out.println(" You should consider writing the output to a jar file, or otherwise");
+ System.out.println(" specify '-dontusemixedcaseclassnames'.");
+
+ break;
+ }
+ }
+ }
+ }
+
int firstInputIndex = 0;
int lastInputIndex = 0;
@@ -166,7 +206,7 @@ public class OutputWriter
{
resourceRewriter =
new NameFilter(configuration.adaptResourceFileContents,
- new NameFilter("META-INF/**",
+ new NameFilter("META-INF/MANIFEST.MF,META-INF/*.SF",
new ManifestRewriter(programClassPool, writer),
new DataEntryRewriter(programClassPool, writer)),
resourceRewriter);
@@ -221,7 +261,7 @@ public class OutputWriter
}
catch (IOException ex)
{
- throw new IOException("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")");
+ throw (IOException)new IOException("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")").initCause(ex);
}
}
@@ -232,25 +272,25 @@ public class OutputWriter
*/
private static Map createPackagePrefixMap(ClassPool classPool)
{
- Map PackagePrefixMap = new HashMap();
+ Map packagePrefixMap = new HashMap();
Iterator iterator = classPool.classNames();
while (iterator.hasNext())
{
String className = (String)iterator.next();
- String PackagePrefix = ClassUtil.internalPackagePrefix(className);
+ String packagePrefix = ClassUtil.internalPackagePrefix(className);
- String mappedNewPackagePrefix = (String)PackagePrefixMap.get(PackagePrefix);
+ String mappedNewPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
if (mappedNewPackagePrefix == null ||
- !mappedNewPackagePrefix.equals(PackagePrefix))
+ !mappedNewPackagePrefix.equals(packagePrefix))
{
String newClassName = classPool.getClass(className).getName();
String newPackagePrefix = ClassUtil.internalPackagePrefix(newClassName);
- PackagePrefixMap.put(PackagePrefix, newPackagePrefix);
+ packagePrefixMap.put(packagePrefix, newPackagePrefix);
}
}
- return PackagePrefixMap;
+ return packagePrefixMap;
}
}
diff --git a/src/proguard/ParseException.java b/src/proguard/ParseException.java
index 9294200..b4af6c2 100644
--- a/src/proguard/ParseException.java
+++ b/src/proguard/ParseException.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ProGuard.java b/src/proguard/ProGuard.java
index 8c30e10..f9dbf54 100644
--- a/src/proguard/ProGuard.java
+++ b/src/proguard/ProGuard.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,11 +24,12 @@ import proguard.classfile.ClassPool;
import proguard.classfile.editor.ClassElementSorter;
import proguard.classfile.visitor.*;
import proguard.obfuscate.Obfuscator;
-import proguard.optimize.Optimizer;
+import proguard.optimize.*;
import proguard.preverify.*;
import proguard.shrink.Shrinker;
import java.io.*;
+import java.util.Properties;
/**
* Tool for shrinking, optimizing, obfuscating, and preverifying Java classes.
@@ -37,7 +38,7 @@ import java.io.*;
*/
public class ProGuard
{
- public static final String VERSION = "ProGuard, version 4.4";
+ public static final String VERSION = "ProGuard, version 4.10";
private final Configuration configuration;
private ClassPool programClassPool = new ClassPool();
@@ -77,7 +78,8 @@ public class ProGuard
readInput();
- if (configuration.shrink ||
+ if (configuration.printSeeds != null ||
+ configuration.shrink ||
configuration.optimize ||
configuration.obfuscate ||
configuration.preverify)
@@ -236,30 +238,10 @@ public class ProGuard
System.out.println("Printing kept classes, fields, and methods...");
}
- // Check if we have at least some keep commands.
- if (configuration.keep == null)
- {
- throw new IOException("You have to specify '-keep' options for the shrinking step.");
- }
-
PrintStream ps = createPrintStream(configuration.printSeeds);
try
{
- // Create a visitor for printing out the seeds. We're printing out
- // the program elements that are preserved against shrinking,
- // optimization, or obfuscation.
- SimpleClassPrinter printer = new SimpleClassPrinter(false, ps);
- ClassPoolVisitor classPoolvisitor =
- ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
- new ProgramClassFilter(printer),
- new ProgramMemberFilter(printer),
- true,
- true,
- true);
-
- // Print out the seeds.
- programClassPool.accept(classPoolvisitor);
- libraryClassPool.accept(classPoolvisitor);
+ new SeedPrinter(ps).write(configuration, programClassPool, libraryClassPool);
}
finally
{
@@ -421,9 +403,10 @@ public class ProGuard
private PrintStream createPrintStream(File file)
throws FileNotFoundException
{
- return isFile(file) ?
- new PrintStream(new BufferedOutputStream(new FileOutputStream(file))) :
- System.out;
+ return file == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(file)));
}
@@ -445,24 +428,26 @@ public class ProGuard
/**
- * Returns the absolute file name for the given file, or the standard output
+ * Returns the canonical file name for the given file, or "standard output"
* if the file name is empty.
*/
private String fileName(File file)
{
- return isFile(file) ?
- file.getAbsolutePath() :
- "standard output";
- }
-
-
- /**
- * Returns whether the given file is actually a file, or just a placeholder
- * for the standard output.
- */
- private boolean isFile(File file)
- {
- return file.getPath().length() > 0;
+ if (file == Configuration.STD_OUT)
+ {
+ return "standard output";
+ }
+ else
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
}
@@ -484,8 +469,8 @@ public class ProGuard
try
{
// Parse the options specified in the command line arguments.
- ConfigurationParser parser = new ConfigurationParser(args);
-
+ ConfigurationParser parser = new ConfigurationParser(args,
+ System.getProperties());
try
{
parser.parse(configuration);
diff --git a/src/proguard/SeedPrinter.java b/src/proguard/SeedPrinter.java
new file mode 100644
index 0000000..8ed74b6
--- /dev/null
+++ b/src/proguard/SeedPrinter.java
@@ -0,0 +1,97 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassPool;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.constant.visitor.AllConstantVisitor;
+import proguard.classfile.instruction.visitor.AllInstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.*;
+import proguard.util.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class prints out the seeds specified by keep options.
+ *
+ * @author Eric Lafortune
+ */
+public class SeedPrinter
+{
+ private final PrintStream ps;
+
+
+ /**
+ * Creates a new ConfigurationWriter for the given PrintStream.
+ */
+ public SeedPrinter(PrintStream ps) throws IOException
+ {
+ this.ps = ps;
+ }
+
+
+ /**
+ * Prints out the seeds for the classes in the given program class pool.
+ * @param configuration the configuration containing the keep options.
+ * @throws IOException if an IO error occurs while writing the configuration.
+ */
+ public void write(Configuration configuration,
+ ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ // Check if we have at least some keep commands.
+ if (configuration.keep == null)
+ {
+ throw new IOException("You have to specify '-keep' options for the shrinking step.");
+ }
+
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+ libraryClassPool.classesAccept(new ClassCleaner());
+
+ // Create a visitor for printing out the seeds. We're printing out
+ // the program elements that are preserved against shrinking,
+ // optimization, or obfuscation.
+ KeepMarker keepMarker = new KeepMarker();
+ ClassPoolVisitor classPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
+ keepMarker,
+ keepMarker,
+ true,
+ true,
+ true);
+ // Mark the seeds.
+ programClassPool.accept(classPoolvisitor);
+ libraryClassPool.accept(classPoolvisitor);
+
+ // Print out the seeds.
+ SimpleClassPrinter printer = new SimpleClassPrinter(false, ps);
+ programClassPool.classesAcceptAlphabetically(new MultiClassVisitor(
+ new ClassVisitor[]
+ {
+ new KeptClassFilter(printer),
+ new AllMemberVisitor(new KeptMemberFilter(printer))
+ }));
+ }
+} \ No newline at end of file
diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/SubclassedClassFilter.java
index 27cac11..1b9c1fe 100644
--- a/src/proguard/SubclassedClassFilter.java
+++ b/src/proguard/SubclassedClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/Targeter.java b/src/proguard/Targeter.java
index 5067205..675f0df 100644
--- a/src/proguard/Targeter.java
+++ b/src/proguard/Targeter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/UpToDateChecker.java b/src/proguard/UpToDateChecker.java
index 9fa5d16..7f5e7a6 100644
--- a/src/proguard/UpToDateChecker.java
+++ b/src/proguard/UpToDateChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -47,107 +47,186 @@ public class UpToDateChecker
*/
public boolean check()
{
- long inputLastModified = configuration.lastModified;
- long outputLastModified = Long.MAX_VALUE;
+ try
+ {
+ ModificationTimeChecker checker = new ModificationTimeChecker();
- ClassPath programJars = configuration.programJars;
- ClassPath libraryJars = configuration.libraryJars;
+ checker.updateInputModificationTime(configuration.lastModified);
- // Check the dates of the program jars, if any.
- if (programJars != null)
- {
- for (int index = 0; index < programJars.size(); index++)
+ ClassPath programJars = configuration.programJars;
+ ClassPath libraryJars = configuration.libraryJars;
+
+ // Check the dates of the program jars, if any.
+ if (programJars != null)
{
- // Break early, if possible.
- if (inputLastModified >= outputLastModified)
+ for (int index = 0; index < programJars.size(); index++)
{
- break;
- }
+ // Update the input and output modification times.
+ ClassPathEntry classPathEntry = programJars.get(index);
- // Update the input and output modification times.
- ClassPathEntry classPathEntry = programJars.get(index);
- if (classPathEntry.isOutput())
- {
- long lastModified = lastModified(classPathEntry.getFile(), true);
- if (outputLastModified > lastModified)
- {
- outputLastModified = lastModified;
- }
- }
- else
- {
- long lastModified = lastModified(classPathEntry.getFile(), false);
- if (inputLastModified < lastModified)
- {
- inputLastModified = lastModified;
- }
+ checker.updateModificationTime(classPathEntry.getFile(),
+ classPathEntry.isOutput());
}
}
- }
- // Check the dates of the library jars, if any.
- if (libraryJars != null)
- {
- for (int index = 0; index < libraryJars.size(); index++)
+ // Check the dates of the library jars, if any.
+ if (libraryJars != null)
{
- // Break early, if possible.
- if (inputLastModified >= outputLastModified)
+ for (int index = 0; index < libraryJars.size(); index++)
{
- break;
- }
+ // Update the input modification time.
+ ClassPathEntry classPathEntry = libraryJars.get(index);
- // Update the input modification time.
- ClassPathEntry classPathEntry = libraryJars.get(index);
- long lastModified = lastModified(classPathEntry.getFile(), false);
- if (inputLastModified < lastModified)
- {
- inputLastModified = lastModified;
+ checker.updateModificationTime(classPathEntry.getFile(),
+ false);
}
}
- }
- boolean outputUpToDate = inputLastModified < outputLastModified;
- if (outputUpToDate)
+ // Check the dates of the auxiliary input files.
+ checker.updateInputModificationTime(configuration.applyMapping);
+ checker.updateInputModificationTime(configuration.obfuscationDictionary);
+ checker.updateInputModificationTime(configuration.classObfuscationDictionary);
+ checker.updateInputModificationTime(configuration.packageObfuscationDictionary);
+
+ // Check the dates of the auxiliary output files.
+ checker.updateOutputModificationTime(configuration.printSeeds);
+ checker.updateOutputModificationTime(configuration.printUsage);
+ checker.updateOutputModificationTime(configuration.printMapping);
+ checker.updateOutputModificationTime(configuration.printConfiguration);
+ checker.updateOutputModificationTime(configuration.dump);
+ }
+ catch (IllegalStateException e)
{
- System.out.println("The output is up to date");
+ // The output is outdated.
+ return false;
}
- return outputUpToDate;
+ System.out.println("The output seems up to date");
+
+ return true;
}
/**
- * Returns the minimum or maximum modification time of the given file or
- * of the files in the given directory (recursively).
+ * This class maintains the modification times of input and output.
+ * The methods throw an IllegalStateException if the output appears
+ * outdated.
*/
- private long lastModified(File file, boolean minimum)
- {
- // Is it a directory?
- if (file.isDirectory())
+ private static class ModificationTimeChecker {
+
+ private long inputModificationTime = Long.MIN_VALUE;
+ private long outputModificationTime = Long.MAX_VALUE;
+
+
+ /**
+ * Updates the input modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateInputModificationTime(File file)
{
- // Ignore the directory's modification time; just recurse on its files.
- File[] files = file.listFiles();
+ if (file != null)
+ {
+ updateModificationTime(file, false);
+ }
+ }
- // Still, an empty output directory is probably a sign that it is
- // not up to date.
- long lastModified = files.length != 0 && minimum ?
- Long.MAX_VALUE : 0L;
- for (int index = 0; index < files.length; index++)
+ /**
+ * Updates the input modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateOutputModificationTime(File file)
+ {
+ if (file != null && file.getName().length() > 0)
{
- long fileLastModified = lastModified(files[index], minimum);
- if ((lastModified < fileLastModified) ^ minimum)
+ updateModificationTime(file, true);
+ }
+ }
+
+
+ /**
+ * Updates the specified modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateModificationTime(File file, boolean isOutput)
+ {
+ // Is it a directory?
+ if (file.isDirectory())
+ {
+ // Ignore the directory's modification time; just recurse on
+ // its files.
+ File[] files = file.listFiles();
+
+ // Still, an empty output directory is probably a sign that it
+ // is not up to date.
+ if (files.length == 0 && isOutput)
{
- lastModified = fileLastModified;
+ updateOutputModificationTime(Long.MIN_VALUE);
}
+
+ for (int index = 0; index < files.length; index++)
+ {
+ updateModificationTime(files[index], isOutput);
+ }
+ }
+ else
+ {
+ // Update with the file's modification time.
+ updateModificationTime(file.lastModified(), isOutput);
}
+ }
+
- return lastModified;
+ /**
+ * Updates the specified modification time.
+ */
+ public void updateModificationTime(long time, boolean isOutput)
+ {
+ if (isOutput)
+ {
+ updateOutputModificationTime(time);
+ }
+ else
+ {
+ updateInputModificationTime(time);
+ }
}
- else
+
+
+ /**
+ * Updates the input modification time.
+ */
+ public void updateInputModificationTime(long time)
{
- // Return the file's modification time.
- return file.lastModified();
+ if (inputModificationTime < time)
+ {
+ inputModificationTime = time;
+
+ checkModificationTimes();
+ }
+ }
+
+
+ /**
+ * Updates the output modification time.
+ */
+ public void updateOutputModificationTime(long time)
+ {
+ if (outputModificationTime > time)
+ {
+ outputModificationTime = time;
+
+ checkModificationTimes();
+ }
+ }
+
+
+ private void checkModificationTimes()
+ {
+ if (inputModificationTime > outputModificationTime)
+ {
+ throw new IllegalStateException("The output is outdated");
+ }
}
}
}
diff --git a/src/proguard/WordReader.java b/src/proguard/WordReader.java
index d73505a..110fce3 100644
--- a/src/proguard/WordReader.java
+++ b/src/proguard/WordReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -105,9 +105,11 @@ public abstract class WordReader
* Reads a word from this WordReader, or from one of its active included
* WordReader objects.
*
+ * @param isFileName return a complete line (or argument), if the word
+ * isn't an option (it doesn't start with '-').
* @return the read word.
*/
- public String nextWord() throws IOException
+ public String nextWord(boolean isFileName) throws IOException
{
currentWord = null;
@@ -115,7 +117,7 @@ public abstract class WordReader
if (includeWordReader != null)
{
// Does the included word reader still produce a word?
- currentWord = includeWordReader.nextWord();
+ currentWord = includeWordReader.nextWord(isFileName);
if (currentWord != null)
{
// Return it if so.
@@ -129,12 +131,22 @@ public abstract class WordReader
// Get a word from this reader.
- // Skip leading whitespace.
- while (currentLine != null &&
- currentIndex < currentLineLength &&
- Character.isWhitespace(currentLine.charAt(currentIndex)))
+ // Skip any whitespace and comments left on the current line.
+ if (currentLine != null)
{
- currentIndex++;
+ // Skip any leading whitespace.
+ while (currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
+ {
+ currentIndex++;
+ }
+
+ // Skip any comments.
+ if (currentIndex < currentLineLength &&
+ isComment(currentLine.charAt(currentIndex)))
+ {
+ currentIndex = currentLineLength;
+ }
}
// Make sure we have a non-blank line.
@@ -146,29 +158,28 @@ public abstract class WordReader
return null;
}
- // Trim off any comments.
- int comments_start = currentLine.indexOf(COMMENT_CHARACTER);
- if (comments_start >= 0)
+ currentLineLength = currentLine.length();
+
+ // Skip any leading whitespace.
+ currentIndex = 0;
+ while (currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
{
- currentLineLength = comments_start;
+ currentIndex++;
+ }
+ // Remember any leading comments.
+ if (currentIndex < currentLineLength &&
+ isComment(currentLine.charAt(currentIndex)))
+ {
// Remember the comments.
- String comment = currentLine.substring(comments_start + 1);
+ String comment = currentLine.substring(currentIndex + 1);
currentComments = currentComments == null ?
comment :
currentComments + '\n' + comment;
- }
- else
- {
- currentLineLength = currentLine.length();
- }
- // Skip leading whitespace.
- currentIndex = 0;
- while (currentIndex < currentLineLength &&
- Character.isWhitespace(currentLine.charAt(currentIndex)))
- {
- currentIndex++;
+ // Skip the comments.
+ currentIndex = currentLineLength;
}
}
@@ -178,12 +189,7 @@ public abstract class WordReader
char startChar = currentLine.charAt(startIndex);
- if (isDelimiter(startChar))
- {
- // The next word is a single delimiting character.
- endIndex = ++currentIndex;
- }
- else if (isQuote(startChar))
+ if (isQuote(startChar))
{
// The next word is starting with a quote character.
// Skip the opening quote.
@@ -205,6 +211,39 @@ public abstract class WordReader
endIndex = currentIndex++;
}
+ else if (isFileName &&
+ !isOption(startChar))
+ {
+ // The next word is a (possibly optional) file name.
+ // Find the end of the line, the first path separator, the first
+ // option, or the first comment.
+ while (currentIndex < currentLineLength)
+ {
+ char currentCharacter = currentLine.charAt(currentIndex);
+ if (isFileDelimiter(currentCharacter) ||
+ ((isOption(currentCharacter) ||
+ isComment(currentCharacter)) &&
+ Character.isWhitespace(currentLine.charAt(currentIndex-1)))) {
+ break;
+ }
+
+ currentIndex++;
+ }
+
+ endIndex = currentIndex;
+
+ // Trim any trailing whitespace.
+ while (endIndex > startIndex &&
+ Character.isWhitespace(currentLine.charAt(endIndex-1)))
+ {
+ endIndex--;
+ }
+ }
+ else if (isDelimiter(startChar))
+ {
+ // The next word is a single delimiting character.
+ endIndex = ++currentIndex;
+ }
else
{
// The next word is a simple character string.
@@ -213,9 +252,9 @@ public abstract class WordReader
while (currentIndex < currentLineLength)
{
char currentCharacter = currentLine.charAt(currentIndex);
- if (isDelimiter(currentCharacter) ||
- Character.isWhitespace(currentCharacter))
- {
+ if (isDelimiter(currentCharacter) ||
+ Character.isWhitespace(currentCharacter) ||
+ isComment(currentCharacter)) {
break;
}
@@ -305,6 +344,18 @@ public abstract class WordReader
// Small utility methods.
+ private boolean isOption(char character)
+ {
+ return character == '-';
+ }
+
+
+ private boolean isComment(char character)
+ {
+ return character == COMMENT_CHARACTER;
+ }
+
+
private boolean isDelimiter(char character)
{
return character == '@' ||
@@ -318,6 +369,16 @@ public abstract class WordReader
}
+ private boolean isFileDelimiter(char character)
+ {
+ return character == '(' ||
+ character == ')' ||
+ character == ',' ||
+ character == ';' ||
+ character == File.pathSeparatorChar;
+ }
+
+
private boolean isQuote(char character)
{
return character == '\'' ||
diff --git a/src/proguard/ant/ClassPathElement.java b/src/proguard/ant/ClassPathElement.java
index b5c2df4..b496123 100644
--- a/src/proguard/ant/ClassPathElement.java
+++ b/src/proguard/ant/ClassPathElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/ClassSpecificationElement.java b/src/proguard/ant/ClassSpecificationElement.java
index f4ea2ff..c07e101 100644
--- a/src/proguard/ant/ClassSpecificationElement.java
+++ b/src/proguard/ant/ClassSpecificationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -222,6 +222,7 @@ public class ClassSpecificationElement extends DataType
strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
0;
diff --git a/src/proguard/ant/ConfigurationElement.java b/src/proguard/ant/ConfigurationElement.java
index 76e9418..d184aef 100644
--- a/src/proguard/ant/ConfigurationElement.java
+++ b/src/proguard/ant/ConfigurationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,34 +20,105 @@
*/
package proguard.ant;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.DataType;
-import proguard.Configuration;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.*;
+import proguard.*;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.Properties;
/**
- * This DataType represents a reference to a ProGuard configuration in Ant.
+ * This DataType represents a reference to an XML-style ProGuard configuration
+ * in Ant, or a file set of ProGuard-style configuration files.
*
* @author Eric Lafortune
*/
-public class ConfigurationElement extends DataType
+public class ConfigurationElement extends FileSet
{
/**
- * Adds the contents of this configuration task to the given configuration.
+ * Adds the contents of this configuration element to the given
+ * configuration.
* @param configuration the configuration to be extended.
*/
public void appendTo(Configuration configuration)
{
- // Get the referenced element.
- if (!isReference())
+ File baseDir;
+ String[] fileNames;
+
+ if (isReference())
{
- throw new BuildException("Nested element <configuration> must have a refid attribute");
+ // Get the referenced path or file set.
+ Object referencedObject = getCheckedRef(Object.class,
+ Object.class.getName());
+
+ if (referencedObject instanceof ConfigurationTask)
+ {
+ // The reference doesn't point to a file set, but to a
+ // configuration task.
+ ConfigurationTask configurationTask =
+ (ConfigurationTask)referencedObject;
+
+ // Append the contents of the referenced configuration to the
+ // current configuration.
+ configurationTask.appendTo(configuration);
+
+ return;
+ }
+ else if (referencedObject instanceof AbstractFileSet)
+ {
+ AbstractFileSet fileSet = (AbstractFileSet)referencedObject;
+
+ // Get the names of the existing input files in the referenced file set.
+ DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
+ baseDir = scanner.getBasedir();
+ fileNames = scanner.getIncludedFiles();
+ }
+ else
+ {
+ throw new BuildException("The refid attribute doesn't point to a <proguardconfiguration> element or a <fileset> element");
+ }
}
+ else
+ {
+ // Get the names of the existing input files in the referenced file set.
+ DirectoryScanner scanner = getDirectoryScanner(getProject());
+ baseDir = scanner.getBasedir();
+ fileNames = scanner.getIncludedFiles();
+ }
+
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(getProject().getProperties());
- ConfigurationTask configurationTask =
- (ConfigurationTask)getCheckedRef(ConfigurationTask.class,
- ConfigurationTask.class.getName());
+ try
+ {
+ // Append the contents of the configuration files to the current
+ // configuration.
+ for (int index = 0; index < fileNames.length; index++)
+ {
+ File configurationFile = new File(baseDir, fileNames[index]);
- // Append the referenced configuration entries to the given configuration.
- configurationTask.appendTo(configuration);
+ ConfigurationParser parser =
+ new ConfigurationParser(configurationFile, properties);
+ try
+ {
+ parser.parse(configuration);
+ }
+ catch (ParseException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
}
}
diff --git a/src/proguard/ant/ConfigurationTask.java b/src/proguard/ant/ConfigurationTask.java
index 0d2f04f..376a1a1 100644
--- a/src/proguard/ant/ConfigurationTask.java
+++ b/src/proguard/ant/ConfigurationTask.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -291,10 +291,20 @@ public class ConfigurationTask extends Task
{
try
{
- String arg = getProject().replaceProperties(text);
+ Project project = getProject();
- ConfigurationParser parser = new ConfigurationParser(new String[] { arg },
- getProject().getBaseDir());
+ // Replace Ant-style properties ('${...}').
+ String arg = project.replaceProperties(text);
+
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(project.getProperties());
+
+ ConfigurationParser parser = new ConfigurationParser(arg,
+ "embedded configuration",
+ project.getBaseDir(),
+ properties);
try
{
diff --git a/src/proguard/ant/FilterElement.java b/src/proguard/ant/FilterElement.java
index d792c5d..ab3364a 100644
--- a/src/proguard/ant/FilterElement.java
+++ b/src/proguard/ant/FilterElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/KeepSpecificationElement.java b/src/proguard/ant/KeepSpecificationElement.java
index e36b744..feabc18 100644
--- a/src/proguard/ant/KeepSpecificationElement.java
+++ b/src/proguard/ant/KeepSpecificationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,9 +39,9 @@ public class KeepSpecificationElement extends ClassSpecificationElement
/**
* Adds the contents of this class specification element to the given list.
* @param keepSpecifications the class specifications to be extended.
- * @param markClasses specifies whether to mark the classes.
- * @param markConditionally specifies whether to mark the classes
- * and class members conditionally.
+ * @param markClasses specifies whether to mark the classes.
+ * @param markConditionally specifies whether to mark the classes
+ * and class members conditionally.
*/
public void appendTo(List keepSpecifications,
boolean markClasses,
@@ -50,16 +50,16 @@ public class KeepSpecificationElement extends ClassSpecificationElement
// Get the referenced file set, or else this one.
KeepSpecificationElement keepSpecificationElement = isReference() ?
(KeepSpecificationElement)getCheckedRef(this.getClass(),
- this.getClass().getName()) :
+ this.getClass().getName()) :
this;
KeepClassSpecification keepClassSpecification =
new KeepClassSpecification(markClasses,
- markConditionally,
- allowShrinking,
- allowOptimization,
- allowObfuscation,
- createClassSpecification(keepSpecificationElement));
+ markConditionally,
+ allowShrinking,
+ allowOptimization,
+ allowObfuscation,
+ createClassSpecification(keepSpecificationElement));
// Add it to the list.
keepSpecifications.add(keepClassSpecification);
diff --git a/src/proguard/ant/MemberSpecificationElement.java b/src/proguard/ant/MemberSpecificationElement.java
index d4bb4a9..9762009 100644
--- a/src/proguard/ant/MemberSpecificationElement.java
+++ b/src/proguard/ant/MemberSpecificationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,7 +63,7 @@ public class MemberSpecificationElement extends DataType
this.getClass().getName()) :
this;
- // Create a new class specification.
+ // Create a new class member specification.
String access = memberSpecificationElement.access;
String type = memberSpecificationElement.type;
String annotation = memberSpecificationElement.annotation;
@@ -195,9 +195,12 @@ public class MemberSpecificationElement extends DataType
strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
0;
if (accessFlag == 0)
diff --git a/src/proguard/ant/ProGuardTask.java b/src/proguard/ant/ProGuardTask.java
index b7fc361..7ab1cdf 100644
--- a/src/proguard/ant/ProGuardTask.java
+++ b/src/proguard/ant/ProGuardTask.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,7 +25,7 @@ import proguard.*;
import proguard.classfile.util.ClassUtil;
import java.io.*;
-import java.util.ArrayList;
+import java.util.*;
/**
* This Task allows to configure and run ProGuard from Ant.
@@ -40,8 +40,13 @@ public class ProGuardTask extends ConfigurationTask
{
try
{
- ConfigurationParser parser = new ConfigurationParser(configurationFile);
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(getProject().getProperties());
+ ConfigurationParser parser = new ConfigurationParser(configurationFile,
+ properties);
try
{
parser.parse(configuration);
@@ -215,6 +220,12 @@ public class ProGuardTask extends ConfigurationTask
}
+ public void setKeepparameternames(boolean keepParameterNames)
+ {
+ configuration.keepParameterNames = keepParameterNames;
+ }
+
+
public void setRenamesourcefileattribute(String newSourceFileAttribute)
{
configuration.newSourceFileAttribute = newSourceFileAttribute;
@@ -241,13 +252,39 @@ public class ProGuardTask extends ConfigurationTask
public void setNote(boolean note)
{
- configuration.note = note ? null : new ArrayList();
+ if (note)
+ {
+ // Switch on notes if they were completely disabled.
+ if (configuration.note != null &&
+ configuration.note.isEmpty())
+ {
+ configuration.note = null;
+ }
+ }
+ else
+ {
+ // Switch off notes.
+ configuration.note = new ArrayList();
+ }
}
public void setWarn(boolean warn)
{
- configuration.warn = warn ? null : new ArrayList();
+ if (warn)
+ {
+ // Switch on warnings if they were completely disabled.
+ if (configuration.warn != null &&
+ configuration.warn.isEmpty())
+ {
+ configuration.warn = null;
+ }
+ }
+ else
+ {
+ // Switch off warnings.
+ configuration.warn = new ArrayList();
+ }
}
@@ -302,7 +339,7 @@ public class ProGuardTask extends ConfigurationTask
fileName.equalsIgnoreCase("off") ? null :
fileName.equalsIgnoreCase("true") ||
fileName.equalsIgnoreCase("yes") ||
- fileName.equalsIgnoreCase("on") ? new File("") :
+ fileName.equalsIgnoreCase("on") ? Configuration.STD_OUT :
resolvedFile(file);
}
diff --git a/src/proguard/ant/task.properties b/src/proguard/ant/task.properties
index b676db7..82d0f3f 100644
--- a/src/proguard/ant/task.properties
+++ b/src/proguard/ant/task.properties
@@ -1,2 +1,2 @@
-proguard = proguard.ant.ProGuardTask
-proguardconfiguration = proguard.ant.ConfigurationTask
+proguard = proguard.ant.ProGuardTask
+proguardconfiguration = proguard.ant.ConfigurationTask
diff --git a/src/proguard/classfile/ClassConstants.java b/src/proguard/classfile/ClassConstants.java
index 3b243e0..59580c5 100644
--- a/src/proguard/classfile/ClassConstants.java
+++ b/src/proguard/classfile/ClassConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -43,6 +43,8 @@ public interface ClassConstants
public static final int INTERNAL_CLASS_VERSION_1_5_MINOR = 0;
public static final int INTERNAL_CLASS_VERSION_1_6_MAJOR = 50;
public static final int INTERNAL_CLASS_VERSION_1_6_MINOR = 0;
+ public static final int INTERNAL_CLASS_VERSION_1_7_MAJOR = 51;
+ public static final int INTERNAL_CLASS_VERSION_1_7_MINOR = 0;
public static final int INTERNAL_CLASS_VERSION_1_0 = (INTERNAL_CLASS_VERSION_1_0_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_0_MINOR;
public static final int INTERNAL_CLASS_VERSION_1_2 = (INTERNAL_CLASS_VERSION_1_2_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_2_MINOR;
@@ -50,6 +52,7 @@ public interface ClassConstants
public static final int INTERNAL_CLASS_VERSION_1_4 = (INTERNAL_CLASS_VERSION_1_4_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_4_MINOR;
public static final int INTERNAL_CLASS_VERSION_1_5 = (INTERNAL_CLASS_VERSION_1_5_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_5_MINOR;
public static final int INTERNAL_CLASS_VERSION_1_6 = (INTERNAL_CLASS_VERSION_1_6_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_6_MINOR;
+ public static final int INTERNAL_CLASS_VERSION_1_7 = (INTERNAL_CLASS_VERSION_1_7_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_7_MINOR;
public static final String EXTERNAL_CLASS_VERSION_1_0 = "1.0";
public static final String EXTERNAL_CLASS_VERSION_1_1 = "1.1";
@@ -58,8 +61,10 @@ public interface ClassConstants
public static final String EXTERNAL_CLASS_VERSION_1_4 = "1.4";
public static final String EXTERNAL_CLASS_VERSION_1_5 = "1.5";
public static final String EXTERNAL_CLASS_VERSION_1_6 = "1.6";
+ public static final String EXTERNAL_CLASS_VERSION_1_7 = "1.7";
public static final String EXTERNAL_CLASS_VERSION_1_5_ALIAS = "5";
public static final String EXTERNAL_CLASS_VERSION_1_6_ALIAS = "6";
+ public static final String EXTERNAL_CLASS_VERSION_1_7_ALIAS = "7";
public static final int INTERNAL_ACC_PUBLIC = 0x0001;
public static final int INTERNAL_ACC_PRIVATE = 0x0002;
@@ -119,10 +124,13 @@ public interface ClassConstants
public static final String EXTERNAL_ACC_SYNCHRONIZED = "synchronized";
public static final String EXTERNAL_ACC_VOLATILE = "volatile";
public static final String EXTERNAL_ACC_TRANSIENT = "transient";
+ public static final String EXTERNAL_ACC_BRIDGE = "bridge";
+ public static final String EXTERNAL_ACC_VARARGS = "varargs";
public static final String EXTERNAL_ACC_NATIVE = "native";
public static final String EXTERNAL_ACC_INTERFACE = "interface";
public static final String EXTERNAL_ACC_ABSTRACT = "abstract";
public static final String EXTERNAL_ACC_STRICT = "strictfp";
+ public static final String EXTERNAL_ACC_SYNTHETIC = "synthetic";
public static final String EXTERNAL_ACC_ANNOTATION = "@";
public static final String EXTERNAL_ACC_ENUM = "enum";
@@ -137,7 +145,21 @@ public interface ClassConstants
public static final int CONSTANT_Methodref = 10;
public static final int CONSTANT_InterfaceMethodref = 11;
public static final int CONSTANT_NameAndType = 12;
+ public static final int CONSTANT_MethodHandle = 15;
+ public static final int CONSTANT_MethodType = 16;
+ public static final int CONSTANT_InvokeDynamic = 18;
+ public static final int REF_getField = 1;
+ public static final int REF_getStatic = 2;
+ public static final int REF_putField = 3;
+ public static final int REF_putStatic = 4;
+ public static final int REF_invokeVirtual = 5;
+ public static final int REF_invokeStatic = 6;
+ public static final int REF_invokeSpecial = 7;
+ public static final int REF_newInvokeSpecial = 8;
+ public static final int REF_invokeInterface = 9;
+
+ public static final String ATTR_BootstrapMethods = "BootstrapMethods";
public static final String ATTR_SourceFile = "SourceFile";
public static final String ATTR_SourceDir = "SourceDir";
public static final String ATTR_InnerClasses = "InnerClasses";
@@ -159,11 +181,11 @@ public interface ClassConstants
public static final String ATTR_RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations";
public static final String ATTR_AnnotationDefault = "AnnotationDefault";
- public static final int ELEMENT_VALUE_STRING_CONSTANT = 's';
- public static final int ELEMENT_VALUE_ENUM_CONSTANT = 'e';
- public static final int ELEMENT_VALUE_CLASS = 'c';
- public static final int ELEMENT_VALUE_ANNOTATION = '@';
- public static final int ELEMENT_VALUE_ARRAY = '[';
+ public static final char ELEMENT_VALUE_STRING_CONSTANT = 's';
+ public static final char ELEMENT_VALUE_ENUM_CONSTANT = 'e';
+ public static final char ELEMENT_VALUE_CLASS = 'c';
+ public static final char ELEMENT_VALUE_ANNOTATION = '@';
+ public static final char ELEMENT_VALUE_ARRAY = '[';
public static final char EXTERNAL_PACKAGE_SEPARATOR = '.';
public static final char EXTERNAL_INNER_CLASS_SEPARATOR = '.';
@@ -179,41 +201,93 @@ public interface ClassConstants
public static final char INTERNAL_METHOD_ARGUMENTS_OPEN = '(';
public static final char INTERNAL_METHOD_ARGUMENTS_CLOSE = ')';
- public static final String INTERNAL_PACKAGE_JAVA_LANG = "java/lang/";
- public static final String INTERNAL_NAME_JAVA_LANG_OBJECT = "java/lang/Object";
- public static final String INTERNAL_TYPE_JAVA_LANG_OBJECT = "Ljava/lang/Object;";
- public static final String INTERNAL_NAME_JAVA_LANG_CLONEABLE = "java/lang/Cloneable";
- public static final String INTERNAL_NAME_JAVA_LANG_THROWABLE = "java/lang/Throwable";
- public static final String INTERNAL_NAME_JAVA_LANG_CLASS = "java/lang/Class";
- public static final String INTERNAL_NAME_JAVA_LANG_STRING = "java/lang/String";
- public static final String INTERNAL_NAME_JAVA_IO_SERIALIZABLE = "java/io/Serializable";
+ public static final String INTERNAL_PACKAGE_JAVA_LANG = "java/lang/";
+ public static final String INTERNAL_NAME_JAVA_LANG_OBJECT = "java/lang/Object";
+ public static final String INTERNAL_TYPE_JAVA_LANG_OBJECT = "Ljava/lang/Object;";
+ public static final String INTERNAL_NAME_JAVA_LANG_CLONEABLE = "java/lang/Cloneable";
+ public static final String INTERNAL_NAME_JAVA_LANG_THROWABLE = "java/lang/Throwable";
+ public static final String INTERNAL_NAME_JAVA_LANG_CLASS = "java/lang/Class";
+ public static final String INTERNAL_NAME_JAVA_LANG_STRING = "java/lang/String";
+ public static final String INTERNAL_NAME_JAVA_LANG_STRING_BUFFER = "java/lang/StringBuffer";
+ public static final String INTERNAL_NAME_JAVA_LANG_STRING_BUILDER = "java/lang/StringBuilder";
+ public static final String INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE = "java/lang/invoke/MethodHandle";
+ public static final String INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE = "java/lang/invoke/MethodType";
+ public static final String INTERNAL_NAME_JAVA_IO_SERIALIZABLE = "java/io/Serializable";
+
+ public static final String INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicIntegerFieldUpdater";
+ public static final String INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicLongFieldUpdater";
+ public static final String INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicReferenceFieldUpdater";
public static final String INTERNAL_METHOD_NAME_INIT = "<init>";
public static final String INTERNAL_METHOD_TYPE_INIT = "()V";
public static final String INTERNAL_METHOD_NAME_CLINIT = "<clinit>";
public static final String INTERNAL_METHOD_TYPE_CLINIT = "()V";
- public static final String INTERNAL_METHOD_NAME_CLASS_FOR_NAME = "forName";
- public static final String INTERNAL_METHOD_TYPE_CLASS_FOR_NAME = "(Ljava/lang/String;)Ljava/lang/Class;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_COMPONENT_TYPE = "getComponentType";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_COMPONENT_TYPE = "()Ljava/lang/Class;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_FIELD = "getField";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_FIELD = "getDeclaredField";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_METHOD = "getMethod";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_METHOD = "getDeclaredMethod";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_FOR_NAME = "forName";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_FOR_NAME = "(Ljava/lang/String;)Ljava/lang/Class;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_COMPONENT_TYPE = "getComponentType";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_COMPONENT_TYPE = "()Ljava/lang/Class;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_FIELD = "getField";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_FIELD = "getDeclaredField";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
+ public static final String INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR = "getConstructor";
+ public static final String INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;";
+ public static final String INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR = "getDeclaredConstructor";
+ public static final String INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_METHOD = "getMethod";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_METHOD = "getDeclaredMethod";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String INTERNAL_METHOD_NAME_NEW_UPDATER = "newUpdater";
+ public static final String INTERNAL_METHOD_TYPE_NEW_INTEGER_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;";
+ public static final String INTERNAL_METHOD_TYPE_NEW_LONG_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicLongFieldUpdater;";
+ public static final String INTERNAL_METHOD_TYPE_NEW_REFERENCE_UPDATER = "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;";
public static final String INTERNAL_METHOD_NAME_DOT_CLASS_JAVAC = "class$";
public static final String INTERNAL_METHOD_TYPE_DOT_CLASS_JAVAC = "(Ljava/lang/String;)Ljava/lang/Class;";
public static final String INTERNAL_METHOD_NAME_DOT_CLASS_JIKES = "class";
public static final String INTERNAL_METHOD_TYPE_DOT_CLASS_JIKES = "(Ljava/lang/String;Z)Ljava/lang/Class;";
+ public static final String INTERNAL_METHOD_TYPE_INIT_ENUM = "(Ljava/lang/String;I)V";
+
public static final String INTERNAL_METHOD_NAME_NEW_INSTANCE = "newInstance";
public static final String INTERNAL_METHOD_TYPE_NEW_INSTANCE = "()Ljava/lang/Object;";
+ public static final String INTERNAL_METHOD_NAME_EQUALS = "equals";
+ public static final String INTERNAL_METHOD_TYPE_EQUALS = "(Ljava/lang/Object;)Z";
+ public static final String INTERNAL_METHOD_NAME_LENGTH = "length";
+ public static final String INTERNAL_METHOD_NAME_VALUEOF = "valueOf";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_BOOLEAN = "(Z)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_CHAR = "(C)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_INT = "(I)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_LONG = "(J)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_FLOAT = "(F)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_DOUBLE = "(D)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_OBJECT = "(Ljava/lang/Object;)Ljava/lang/String;";
+
+ public static final String INTERNAL_METHOD_TYPE_LENGTH = "()I";
+ public static final String INTERNAL_METHOD_NAME_APPEND = "append";
+ public static final String INTERNAL_METHOD_TYPE_STRING_VOID = "(Ljava/lang/String;)V";
+ public static final String INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUFFER = "(Z)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_CHAR_STRING_BUFFER = "(C)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_INT_STRING_BUFFER = "(I)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_LONG_STRING_BUFFER = "(J)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_FLOAT_STRING_BUFFER = "(F)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUFFER = "(D)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_STRING_STRING_BUFFER = "(Ljava/lang/String;)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_OBJECT_STRING_BUFFER = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUILDER = "(Z)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_CHAR_STRING_BUILDER = "(C)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_INT_STRING_BUILDER = "(I)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_LONG_STRING_BUILDER = "(J)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_FLOAT_STRING_BUILDER = "(F)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUILDER = "(D)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_STRING_STRING_BUILDER = "(Ljava/lang/String;)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_OBJECT_STRING_BUILDER = "(Ljava/lang/Object;)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_NAME_TOSTRING = "toString";
+ public static final String INTERNAL_METHOD_TYPE_TOSTRING = "()Ljava/lang/String;";
+
public static final char INTERNAL_TYPE_VOID = 'V';
public static final char INTERNAL_TYPE_BOOLEAN = 'Z';
public static final char INTERNAL_TYPE_BYTE = 'B';
diff --git a/src/proguard/classfile/ClassPool.java b/src/proguard/classfile/ClassPool.java
index 57728a5..5439c6f 100644
--- a/src/proguard/classfile/ClassPool.java
+++ b/src/proguard/classfile/ClassPool.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,14 +26,16 @@ import proguard.classfile.visitor.*;
import java.util.*;
/**
- * This is a set of representations of classes. They can be enumerated or
+ * This is a set of representations of classes. They can be enumerated or
* retrieved by name. They can also be accessed by means of class visitors.
*
* @author Eric Lafortune
*/
public class ClassPool
{
- private final Map classes = new HashMap();
+ // We're using a sorted tree map instead of a hash map to store the classes,
+ // in order to make the processing more deterministic.
+ private final Map classes = new TreeMap();
/**
@@ -59,18 +61,27 @@ public class ClassPool
*/
public void removeClass(Clazz clazz)
{
- classes.remove(clazz.getName());
+ removeClass(clazz.getName());
+ }
+
+
+ /**
+ * Removes the specified Clazz from the class pool.
+ */
+ public void removeClass(String className)
+ {
+ classes.remove(className);
}
/**
* Returns a Clazz from the class pool based on its name. Returns
* <code>null</code> if the class with the given name is not in the class
- * pool. Returns the base class if the class name is an array type.
+ * pool.
*/
public Clazz getClass(String className)
{
- return (Clazz)classes.get(ClassUtil.internalClassNameFromClassType(className));
+ return (Clazz)classes.get(className);
}
@@ -122,8 +133,11 @@ public class ClassPool
*/
public void classesAcceptAlphabetically(ClassVisitor classVisitor)
{
- TreeMap sortedClasses = new TreeMap(classes);
- Iterator iterator = sortedClasses.values().iterator();
+ // We're already using a tree map.
+ //TreeMap sortedClasses = new TreeMap(classes);
+ //Iterator iterator = sortedClasses.values().iterator();
+
+ Iterator iterator = classes.values().iterator();
while (iterator.hasNext())
{
Clazz clazz = (Clazz)iterator.next();
diff --git a/src/proguard/classfile/Clazz.java b/src/proguard/classfile/Clazz.java
index da37d9a..35f8a1c 100644
--- a/src/proguard/classfile/Clazz.java
+++ b/src/proguard/classfile/Clazz.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -90,6 +90,16 @@ public interface Clazz extends VisitorAccepter
*/
public String getType(int constantIndex);
+ /**
+ * Returns the name of the RefConstant at the specified index.
+ */
+ public String getRefName(int constantIndex);
+
+ /**
+ * Returns the type of the RefConstant at the specified index.
+ */
+ public String getRefType(int constantIndex);
+
// Methods pertaining to related classes.
@@ -116,12 +126,26 @@ public interface Clazz extends VisitorAccepter
public boolean extends_(Clazz clazz);
/**
+ * Returns whether this class extends the specified class.
+ * A class is always considered to extend itself.
+ * Interfaces are considered to only extend the root Object class.
+ */
+ public boolean extends_(String className);
+
+ /**
* Returns whether this class implements the given class.
* A class is always considered to implement itself.
* Interfaces are considered to implement all their superinterfaces.
*/
public boolean extendsOrImplements(Clazz clazz);
+ /**
+ * Returns whether this class implements the specified class.
+ * A class is always considered to implement itself.
+ * Interfaces are considered to implement all their superinterfaces.
+ */
+ public boolean extendsOrImplements(String className);
+
// Methods for getting specific class members.
@@ -229,4 +253,9 @@ public interface Clazz extends VisitorAccepter
* Lets the given attribute info visitor visit all attributes of this class.
*/
public void attributesAccept(AttributeVisitor attributeVisitor);
+
+ /**
+ * Lets the given attribute info visitor visit the specified attribute.
+ */
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor);
}
diff --git a/src/proguard/classfile/Field.java b/src/proguard/classfile/Field.java
index ba1315a..61bf2da 100644
--- a/src/proguard/classfile/Field.java
+++ b/src/proguard/classfile/Field.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/LibraryClass.java b/src/proguard/classfile/LibraryClass.java
index 0a27593..151a32a 100644
--- a/src/proguard/classfile/LibraryClass.java
+++ b/src/proguard/classfile/LibraryClass.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -137,6 +137,17 @@ public class LibraryClass implements Clazz
}
+ public String getRefName(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getRefType(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+
public void addSubClass(Clazz clazz)
{
if (subClasses == null)
@@ -179,6 +190,18 @@ public class LibraryClass implements Clazz
}
+ public boolean extends_(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ return superClass != null &&
+ superClass.extends_(className);
+ }
+
+
public boolean extendsOrImplements(Clazz clazz)
{
if (this.equals(clazz))
@@ -209,6 +232,36 @@ public class LibraryClass implements Clazz
}
+ 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 Field findField(String name, String descriptor)
{
for (int index = 0; index < fields.length; index++)
@@ -467,6 +520,12 @@ public class LibraryClass implements Clazz
}
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store attributes");
+ }
+
+
// Implementations for VisitorAccepter.
public Object getVisitorInfo()
diff --git a/src/proguard/classfile/LibraryField.java b/src/proguard/classfile/LibraryField.java
index 2908c37..1c1c427 100644
--- a/src/proguard/classfile/LibraryField.java
+++ b/src/proguard/classfile/LibraryField.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/LibraryMember.java b/src/proguard/classfile/LibraryMember.java
index 41ccb60..8d8d00e 100644
--- a/src/proguard/classfile/LibraryMember.java
+++ b/src/proguard/classfile/LibraryMember.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/LibraryMethod.java b/src/proguard/classfile/LibraryMethod.java
index a49a5f1..ac07857 100644
--- a/src/proguard/classfile/LibraryMethod.java
+++ b/src/proguard/classfile/LibraryMethod.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/Member.java b/src/proguard/classfile/Member.java
index 1400b9c..ee2cf19 100644
--- a/src/proguard/classfile/Member.java
+++ b/src/proguard/classfile/Member.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/Method.java b/src/proguard/classfile/Method.java
index ebcae2b..64ff50a 100644
--- a/src/proguard/classfile/Method.java
+++ b/src/proguard/classfile/Method.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/ProgramClass.java b/src/proguard/classfile/ProgramClass.java
index 9d0fc0c..54bb8b1 100644
--- a/src/proguard/classfile/ProgramClass.java
+++ b/src/proguard/classfile/ProgramClass.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -117,8 +117,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- new ClassPrinter().visitProgramClass(this);
- throw new ClassCastException("Expected Utf8Constant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected Utf8Constant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -130,7 +129,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected StringConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected StringConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -142,7 +141,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected ClassConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected ClassConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -154,7 +153,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -166,7 +165,32 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+
+ public String getRefName(int constantIndex)
+ {
+ try
+ {
+ return ((RefConstant)constantPool[constantIndex]).getName(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+ public String getRefType(int constantIndex)
+ {
+ try
+ {
+ return ((RefConstant)constantPool[constantIndex]).getType(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -216,6 +240,19 @@ public class ProgramClass implements Clazz
}
+ public boolean extends_(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ return superClass != null &&
+ superClass.extends_(className);
+ }
+
+
public boolean extendsOrImplements(Clazz clazz)
{
if (this.equals(clazz))
@@ -244,6 +281,34 @@ public class ProgramClass implements Clazz
}
+ public boolean extendsOrImplements(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ if (superClass != null &&
+ superClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+
+ for (int index = 0; index < u2interfacesCount; index++)
+ {
+ Clazz interfaceClass = getInterface(index);
+ if (interfaceClass != null &&
+ interfaceClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
public Field findField(String name, String descriptor)
{
for (int index = 0; index < u2fieldsCount; index++)
@@ -472,6 +537,19 @@ public class ProgramClass implements Clazz
}
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+ if (attribute.getAttributeName(this).equals(name))
+ {
+ attribute.accept(this, attributeVisitor);
+ }
+ }
+ }
+
+
// Implementations for VisitorAccepter.
public Object getVisitorInfo()
diff --git a/src/proguard/classfile/ProgramField.java b/src/proguard/classfile/ProgramField.java
index 5991b00..3bdfd85 100644
--- a/src/proguard/classfile/ProgramField.java
+++ b/src/proguard/classfile/ProgramField.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/ProgramMember.java b/src/proguard/classfile/ProgramMember.java
index ea6f46d..240d344 100644
--- a/src/proguard/classfile/ProgramMember.java
+++ b/src/proguard/classfile/ProgramMember.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -53,7 +53,7 @@ public abstract class ProgramMember implements Member
/**
- * Creates an initialized ProgramMember.
+ * Creates an initialized ProgramMember.
*/
protected ProgramMember(int u2accessFlags,
int u2nameIndex,
@@ -70,34 +70,6 @@ public abstract class ProgramMember implements Member
/**
- * Returns the line number range of the given class member as "m:n",
- * if it can find it, or <code>null</code> otherwise.
- */
- public String getLineNumberRange(Clazz clazz)
- {
- CodeAttribute codeAttribute =
- (CodeAttribute)getAttribute(clazz, ClassConstants.ATTR_Code);
- if (codeAttribute == null)
- {
- return null;
- }
-
- LineNumberTableAttribute lineNumberTableAttribute =
- (LineNumberTableAttribute)codeAttribute.getAttribute(clazz,
- ClassConstants.ATTR_LineNumberTable);
- if (lineNumberTableAttribute == null)
- {
- return null;
- }
-
- return "" +
- lineNumberTableAttribute.getLineNumber(0) +
- ":" +
- lineNumberTableAttribute.getLineNumber(Integer.MAX_VALUE);
- }
-
-
- /**
* Returns the (first) attribute with the given name.
*/
private Attribute getAttribute(Clazz clazz, String name)
diff --git a/src/proguard/classfile/ProgramMethod.java b/src/proguard/classfile/ProgramMethod.java
index 943c3d6..26f793f 100644
--- a/src/proguard/classfile/ProgramMethod.java
+++ b/src/proguard/classfile/ProgramMethod.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/VisitorAccepter.java b/src/proguard/classfile/VisitorAccepter.java
index e38f888..9c7a062 100644
--- a/src/proguard/classfile/VisitorAccepter.java
+++ b/src/proguard/classfile/VisitorAccepter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/Attribute.java b/src/proguard/classfile/attribute/Attribute.java
index 2e16e22..f34a0ee 100644
--- a/src/proguard/classfile/attribute/Attribute.java
+++ b/src/proguard/classfile/attribute/Attribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/BootstrapMethodInfo.java b/src/proguard/classfile/attribute/BootstrapMethodInfo.java
new file mode 100755
index 0000000..f246766
--- /dev/null
+++ b/src/proguard/classfile/attribute/BootstrapMethodInfo.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * Representation of a bootstrap method.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodInfo implements VisitorAccepter
+{
+ public int u2methodHandleIndex;
+ public int u2methodArgumentCount;
+ public int[] u2methodArguments;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized BootstrapMethodInfo.
+ */
+ public BootstrapMethodInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized BootstrapMethodInfo.
+ */
+ public BootstrapMethodInfo(int u2methodHandleIndex,
+ int u2methodArgumentCount,
+ int[] u2methodArguments)
+ {
+ this.u2methodHandleIndex = u2methodHandleIndex;
+ this.u2methodArgumentCount = u2methodArgumentCount;
+ this.u2methodArguments = u2methodArguments;
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the argument constants of the
+ * bootstrap method.
+ */
+ public void methodArgumentsAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ for (int index = 0; index < u2methodArgumentCount; index++)
+ {
+ clazz.constantPoolEntryAccept(u2methodArguments[index],
+ constantVisitor);
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java b/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java
new file mode 100755
index 0000000..4471a75
--- /dev/null
+++ b/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java
@@ -0,0 +1,95 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Attribute represents a bootstrap methods attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodsAttribute extends Attribute
+{
+ public int u2bootstrapMethodsCount;
+ public BootstrapMethodInfo[] bootstrapMethods;
+
+
+ /**
+ * Creates an uninitialized BootstrapMethodsAttribute.
+ */
+ public BootstrapMethodsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized BootstrapMethodsAttribute.
+ */
+ public BootstrapMethodsAttribute(int u2attributeNameIndex,
+ int u2bootstrapMethodsCount,
+ BootstrapMethodInfo[] bootstrapMethods)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2bootstrapMethodsCount = u2bootstrapMethodsCount;
+ this.bootstrapMethods = bootstrapMethods;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, this);
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to all bootstrap method info
+ * entries.
+ */
+ public void bootstrapMethodEntriesAccept(Clazz clazz, BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ for (int index = 0; index < u2bootstrapMethodsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of BootstrapMethodInfo.
+ bootstrapMethodInfoVisitor.visitBootstrapMethodInfo(clazz, bootstrapMethods[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the specified bootstrap method
+ * info entry.
+ */
+ public void bootstrapMethodEntryAccept(Clazz clazz,
+ int bootstrapMethodIndex,
+ BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of BootstrapMethodInfo.
+ bootstrapMethodInfoVisitor.visitBootstrapMethodInfo(clazz, bootstrapMethods[bootstrapMethodIndex]);
+ }
+}
diff --git a/src/proguard/classfile/attribute/CodeAttribute.java b/src/proguard/classfile/attribute/CodeAttribute.java
index 92ff9ea..b3d4f4c 100644
--- a/src/proguard/classfile/attribute/CodeAttribute.java
+++ b/src/proguard/classfile/attribute/CodeAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/ConstantValueAttribute.java b/src/proguard/classfile/attribute/ConstantValueAttribute.java
index 3ae991e..056e377 100644
--- a/src/proguard/classfile/attribute/ConstantValueAttribute.java
+++ b/src/proguard/classfile/attribute/ConstantValueAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/DeprecatedAttribute.java b/src/proguard/classfile/attribute/DeprecatedAttribute.java
index 4180950..f668063 100644
--- a/src/proguard/classfile/attribute/DeprecatedAttribute.java
+++ b/src/proguard/classfile/attribute/DeprecatedAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/EnclosingMethodAttribute.java b/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
index 9275b3a..1c2ecc4 100644
--- a/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
+++ b/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/ExceptionInfo.java b/src/proguard/classfile/attribute/ExceptionInfo.java
index 082efab..31512e5 100644
--- a/src/proguard/classfile/attribute/ExceptionInfo.java
+++ b/src/proguard/classfile/attribute/ExceptionInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/ExceptionsAttribute.java b/src/proguard/classfile/attribute/ExceptionsAttribute.java
index d22c4a6..ff7b84a 100644
--- a/src/proguard/classfile/attribute/ExceptionsAttribute.java
+++ b/src/proguard/classfile/attribute/ExceptionsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -69,12 +69,12 @@ public class ExceptionsAttribute extends Attribute
* Applies the given constant pool visitor to all exception class pool info
* entries.
*/
- public void exceptionEntriesAccept(ProgramClass programClass, ConstantVisitor constantVisitor)
+ public void exceptionEntriesAccept(Clazz clazz, ConstantVisitor constantVisitor)
{
for (int index = 0; index < u2exceptionIndexTableLength; index++)
{
- programClass.constantPoolEntryAccept(u2exceptionIndexTable[index],
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2exceptionIndexTable[index],
+ constantVisitor);
}
}
}
diff --git a/src/proguard/classfile/attribute/InnerClassesAttribute.java b/src/proguard/classfile/attribute/InnerClassesAttribute.java
index 2f7e310..b08d104 100644
--- a/src/proguard/classfile/attribute/InnerClassesAttribute.java
+++ b/src/proguard/classfile/attribute/InnerClassesAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/InnerClassesInfo.java b/src/proguard/classfile/attribute/InnerClassesInfo.java
index 1bdd6c3..87b9de4 100644
--- a/src/proguard/classfile/attribute/InnerClassesInfo.java
+++ b/src/proguard/classfile/attribute/InnerClassesInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -74,8 +74,7 @@ public class InnerClassesInfo implements VisitorAccepter
{
if (u2innerClassIndex != 0)
{
- clazz.constantPoolEntryAccept(u2innerClassIndex,
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2innerClassIndex, constantVisitor);
}
}
@@ -88,8 +87,7 @@ public class InnerClassesInfo implements VisitorAccepter
{
if (u2outerClassIndex != 0)
{
- clazz.constantPoolEntryAccept(u2outerClassIndex,
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2outerClassIndex, constantVisitor);
}
}
@@ -102,8 +100,7 @@ public class InnerClassesInfo implements VisitorAccepter
{
if (u2innerNameIndex != 0)
{
- clazz.constantPoolEntryAccept(u2innerNameIndex,
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2innerNameIndex, constantVisitor);
}
}
diff --git a/src/proguard/classfile/attribute/LineNumberInfo.java b/src/proguard/classfile/attribute/LineNumberInfo.java
index f58083a..1bcacef 100644
--- a/src/proguard/classfile/attribute/LineNumberInfo.java
+++ b/src/proguard/classfile/attribute/LineNumberInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/LineNumberTableAttribute.java b/src/proguard/classfile/attribute/LineNumberTableAttribute.java
index 4d507d9..c217119 100644
--- a/src/proguard/classfile/attribute/LineNumberTableAttribute.java
+++ b/src/proguard/classfile/attribute/LineNumberTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -77,6 +77,56 @@ public class LineNumberTableAttribute extends Attribute
}
+ /**
+ * Returns the lowest line number, or 0 if there aren't any line numbers.
+ */
+ public int getLowestLineNumber()
+ {
+ if (u2lineNumberTableLength == 0)
+ {
+ return 0;
+ }
+
+ int lowestLineNumber = Integer.MAX_VALUE;
+
+ for (int index = 0; index < u2lineNumberTableLength; index++)
+ {
+ int lineNumber = lineNumberTable[index].u2lineNumber;
+ if (lineNumber < lowestLineNumber)
+ {
+ lowestLineNumber = lineNumber;
+ }
+ }
+
+ return lowestLineNumber;
+ }
+
+
+ /**
+ * Returns the highest line number, or 0 if there aren't any line numbers.
+ */
+ public int getHighestLineNumber()
+ {
+ if (u2lineNumberTableLength == 0)
+ {
+ return 0;
+ }
+
+ int highestLineNumber = Integer.MIN_VALUE;
+
+ for (int index = 0; index < u2lineNumberTableLength; index++)
+ {
+ int lineNumber = lineNumberTable[index].u2lineNumber;
+ if (lineNumber > highestLineNumber)
+ {
+ highestLineNumber = lineNumber;
+ }
+ }
+
+ return highestLineNumber;
+ }
+
+
// Implementations for Attribute.
public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
diff --git a/src/proguard/classfile/attribute/LocalVariableInfo.java b/src/proguard/classfile/attribute/LocalVariableInfo.java
index 4e54c22..00bbd50 100644
--- a/src/proguard/classfile/attribute/LocalVariableInfo.java
+++ b/src/proguard/classfile/attribute/LocalVariableInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,7 +20,7 @@
*/
package proguard.classfile.attribute;
-import proguard.classfile.Clazz;
+import proguard.classfile.*;
import proguard.classfile.visitor.ClassVisitor;
/**
@@ -28,7 +28,7 @@ import proguard.classfile.visitor.ClassVisitor;
*
* @author Eric Lafortune
*/
-public class LocalVariableInfo
+public class LocalVariableInfo implements VisitorAccepter, Comparable
{
public int u2startPC;
public int u2length;
@@ -44,6 +44,11 @@ public class LocalVariableInfo
*/
public Clazz referencedClass;
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
/**
* Creates an uninitialized LocalVariableInfo.
@@ -80,4 +85,33 @@ public class LocalVariableInfo
referencedClass.accept(classVisitor);
}
}
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Comparable.
+
+ public int compareTo(Object object)
+ {
+ LocalVariableInfo other = (LocalVariableInfo)object;
+
+ return
+ this.u2startPC < other.u2startPC ? -1 : this.u2startPC > other.u2startPC ? 1 :
+ this.u2index < other.u2index ? -1 : this.u2index > other.u2index ? 1 :
+ this.u2length < other.u2length ? -1 : this.u2length > other.u2length ? 1 :
+ this.u2descriptorIndex < other.u2descriptorIndex ? -1 : this.u2descriptorIndex > other.u2descriptorIndex ? 1 :
+ this.u2nameIndex < other.u2nameIndex ? -1 : this.u2nameIndex > other.u2nameIndex ? 1 :
+ 0;
+ }
}
diff --git a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
index 9c3f115..9e081c0 100644
--- a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
+++ b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/LocalVariableTypeInfo.java b/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
index 1b71f35..15b9d24 100644
--- a/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
+++ b/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,7 +20,7 @@
*/
package proguard.classfile.attribute;
-import proguard.classfile.Clazz;
+import proguard.classfile.*;
import proguard.classfile.visitor.ClassVisitor;
/**
@@ -28,7 +28,7 @@ import proguard.classfile.visitor.ClassVisitor;
*
* @author Eric Lafortune
*/
-public class LocalVariableTypeInfo
+public class LocalVariableTypeInfo implements VisitorAccepter, Comparable
{
public int u2startPC;
public int u2length;
@@ -45,6 +45,11 @@ public class LocalVariableTypeInfo
*/
public Clazz[] referencedClasses;
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
/**
* Creates an uninitialized LocalVariableTypeInfo.
@@ -88,4 +93,33 @@ public class LocalVariableTypeInfo
}
}
}
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Comparable.
+
+ public int compareTo(Object object)
+ {
+ LocalVariableTypeInfo other = (LocalVariableTypeInfo)object;
+
+ return
+ this.u2startPC < other.u2startPC ? -1 : this.u2startPC > other.u2startPC ? 1 :
+ this.u2length < other.u2length ? -1 : this.u2length > other.u2length ? 1 :
+ this.u2index < other.u2index ? -1 : this.u2index > other.u2index ? 1 :
+ this.u2signatureIndex < other.u2signatureIndex ? -1 : this.u2signatureIndex > other.u2signatureIndex ? 1 :
+ this.u2nameIndex < other.u2nameIndex ? -1 : this.u2nameIndex > other.u2nameIndex ? 1 :
+ 0;
+ }
}
diff --git a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
index fd856fe..dda24fb 100644
--- a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
+++ b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SignatureAttribute.java b/src/proguard/classfile/attribute/SignatureAttribute.java
index c7585fe..86f95b8 100644
--- a/src/proguard/classfile/attribute/SignatureAttribute.java
+++ b/src/proguard/classfile/attribute/SignatureAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SourceDirAttribute.java b/src/proguard/classfile/attribute/SourceDirAttribute.java
index a26e8b1..faa1c79 100644
--- a/src/proguard/classfile/attribute/SourceDirAttribute.java
+++ b/src/proguard/classfile/attribute/SourceDirAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SourceFileAttribute.java b/src/proguard/classfile/attribute/SourceFileAttribute.java
index 24269b7..4abac17 100644
--- a/src/proguard/classfile/attribute/SourceFileAttribute.java
+++ b/src/proguard/classfile/attribute/SourceFileAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SyntheticAttribute.java b/src/proguard/classfile/attribute/SyntheticAttribute.java
index 6ccb1b5..0135330 100644
--- a/src/proguard/classfile/attribute/SyntheticAttribute.java
+++ b/src/proguard/classfile/attribute/SyntheticAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/UnknownAttribute.java b/src/proguard/classfile/attribute/UnknownAttribute.java
index 2f138bd..182a9e8 100644
--- a/src/proguard/classfile/attribute/UnknownAttribute.java
+++ b/src/proguard/classfile/attribute/UnknownAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/Annotation.java b/src/proguard/classfile/attribute/annotation/Annotation.java
index 41bb8e3..b2f18d5 100644
--- a/src/proguard/classfile/attribute/annotation/Annotation.java
+++ b/src/proguard/classfile/attribute/annotation/Annotation.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
index b378cd2..b8f29cc 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java b/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
index 29129d0..8354f5d 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,7 +64,7 @@ public class AnnotationElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_ANNOTATION;
}
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
index 8117077..a936ff4 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/ArrayElementValue.java b/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
index 25b8b9f..0aab49b 100644
--- a/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -58,7 +58,7 @@ public class ArrayElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_ARRAY;
}
diff --git a/src/proguard/classfile/attribute/annotation/ClassElementValue.java b/src/proguard/classfile/attribute/annotation/ClassElementValue.java
index ba51641..ffeaf71 100644
--- a/src/proguard/classfile/attribute/annotation/ClassElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ClassElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -83,7 +83,7 @@ public class ClassElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_CLASS;
}
diff --git a/src/proguard/classfile/attribute/annotation/ConstantElementValue.java b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
index 3ebe5e5..8be4329 100644
--- a/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -30,14 +30,14 @@ import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
*/
public class ConstantElementValue extends ElementValue
{
- public final int u1tag;
- public int u2constantValueIndex;
+ public final char u1tag;
+ public int u2constantValueIndex;
/**
* Creates an uninitialized ConstantElementValue.
*/
- public ConstantElementValue(int u1tag)
+ public ConstantElementValue(char u1tag)
{
this.u1tag = u1tag;
}
@@ -46,9 +46,9 @@ public class ConstantElementValue extends ElementValue
/**
* Creates an initialized ConstantElementValue.
*/
- public ConstantElementValue(int u1tag,
- int u2elementNameIndex,
- int u2constantValueIndex)
+ public ConstantElementValue(char u1tag,
+ int u2elementNameIndex,
+ int u2constantValueIndex)
{
super(u2elementNameIndex);
@@ -59,7 +59,7 @@ public class ConstantElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return u1tag;
}
diff --git a/src/proguard/classfile/attribute/annotation/ElementValue.java b/src/proguard/classfile/attribute/annotation/ElementValue.java
index 39f8953..19a7198 100644
--- a/src/proguard/classfile/attribute/annotation/ElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -90,7 +90,7 @@ public abstract class ElementValue implements VisitorAccepter
/**
* Returns the tag of this element value.
*/
- public abstract int getTag();
+ public abstract char getTag();
/**
diff --git a/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
index d46bb7f..cd0f2f9 100644
--- a/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,7 +22,7 @@ package proguard.classfile.attribute.annotation;
import proguard.classfile.*;
import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
-import proguard.classfile.visitor.ClassVisitor;
+import proguard.classfile.visitor.*;
/**
* This ElementValue represents an enumeration constant element value.
@@ -43,6 +43,14 @@ public class EnumConstantElementValue extends ElementValue
*/
public Clazz[] referencedClasses;
+ /**
+ * An extra field optionally pointing to the referenced enum Field object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Field referencedField;
+
/**
* Creates an uninitialized EnumConstantElementValue.
@@ -67,6 +75,24 @@ public class EnumConstantElementValue extends ElementValue
/**
+ * Returns the enumeration type name.
+ */
+ public String getTypeName(Clazz clazz)
+ {
+ return clazz.getString(u2typeNameIndex);
+ }
+
+
+ /**
+ * Returns the constant name.
+ */
+ public String getConstantName(Clazz clazz)
+ {
+ return clazz.getString(u2constantNameIndex);
+ }
+
+
+ /**
* Applies the given visitor to all referenced classes.
*/
public void referencedClassesAccept(ClassVisitor classVisitor)
@@ -85,9 +111,22 @@ public class EnumConstantElementValue extends ElementValue
}
+ /**
+ * Applies the given visitor to the referenced field.
+ */
+ public void referencedFieldAccept(MemberVisitor memberVisitor)
+ {
+ if (referencedField != null)
+ {
+ referencedField.accept(referencedClasses[0],
+ memberVisitor);
+ }
+ }
+
+
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT;
}
diff --git a/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
index 3c700c8..ddaa3a6 100644
--- a/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
index 9c8180c..deda8a5 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
index 7e41656..2fcae88 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
index 380c52e..da94f0c 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
index 626fbda..caa6830 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
index bce7170..0aadfe3 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,6 +39,11 @@ implements AttributeVisitor
private final AnnotationVisitor annotationVisitor;
+ /**
+ * Creates a new AllAnnotationVisitor.
+ * @param annotationVisitor the AnnotationVisitor to which visits will be
+ * delegated.
+ */
public AllAnnotationVisitor(AnnotationVisitor annotationVisitor)
{
this.annotationVisitor = annotationVisitor;
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java
new file mode 100644
index 0000000..b728b8b
--- /dev/null
+++ b/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java
@@ -0,0 +1,201 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.util.*;
+
+/**
+ * This AttributeVisitor and AnnotationVisitor lets a given ElementValueVisitor
+ * visit all ElementValue objects of the attributes or annotations that it
+ * visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllElementValueVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private final boolean deep;
+ private final ElementValueVisitor elementValueVisitor;
+
+
+ /**
+ * Creates a new AllElementValueVisitor.
+ * @param elementValueVisitor the AllElementValueVisitor to which visits
+ * will be delegated.
+ */
+ public AllElementValueVisitor(ElementValueVisitor elementValueVisitor)
+ {
+ this(false, elementValueVisitor);
+ }
+
+
+ /**
+ * Creates a new AllElementValueVisitor.
+ * @param deep specifies whether the element values
+ * further down the hierarchy should be
+ * visited too.
+ * @param elementValueVisitor the AllElementValueVisitor to which visits
+ * will be delegated.
+ */
+ public AllElementValueVisitor(boolean deep,
+ ElementValueVisitor elementValueVisitor)
+ {
+ this.deep = deep;
+ this.elementValueVisitor = elementValueVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, field, this);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, field, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Visit the default element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Field field, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ elementValueVisitor.visitConstantElementValue(clazz, annotation, constantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ elementValueVisitor.visitEnumConstantElementValue(clazz, annotation, enumConstantElementValue);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ elementValueVisitor.visitClassElementValue(clazz, annotation, classElementValue);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ elementValueVisitor.visitAnnotationElementValue(clazz, annotation, annotationElementValue);
+
+ if (deep)
+ {
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ elementValueVisitor.visitArrayElementValue(clazz, annotation, arrayElementValue);
+
+ if (deep)
+ {
+ arrayElementValue.elementValuesAccept(clazz, annotation, elementValueVisitor);
+ }
+ }
+}
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
index 7a1d7c6..305928e 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
index c206c16..7833f7e 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
index d869fd2..d6ec3ca 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -33,7 +33,6 @@ import proguard.util.*;
* @author Eric Lafortune
*/
public class AnnotationTypeFilter
-extends SimplifiedVisitor
implements AnnotationVisitor
{
private final StringMatcher regularExpressionMatcher;
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
index 16b2a56..8d207af 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
index 112084a..2d3a20d 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/DoubleType.java b/src/proguard/classfile/attribute/preverification/DoubleType.java
index d574dcb..1bc3e5d 100644
--- a/src/proguard/classfile/attribute/preverification/DoubleType.java
+++ b/src/proguard/classfile/attribute/preverification/DoubleType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/FloatType.java b/src/proguard/classfile/attribute/preverification/FloatType.java
index 2f24720..c58cd0a 100644
--- a/src/proguard/classfile/attribute/preverification/FloatType.java
+++ b/src/proguard/classfile/attribute/preverification/FloatType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/FullFrame.java b/src/proguard/classfile/attribute/preverification/FullFrame.java
index adf5684..4f0d72e 100644
--- a/src/proguard/classfile/attribute/preverification/FullFrame.java
+++ b/src/proguard/classfile/attribute/preverification/FullFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/IntegerType.java b/src/proguard/classfile/attribute/preverification/IntegerType.java
index 55e3abe..9c43cae 100644
--- a/src/proguard/classfile/attribute/preverification/IntegerType.java
+++ b/src/proguard/classfile/attribute/preverification/IntegerType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/LessZeroFrame.java b/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
index fcc8e0a..f722d73 100644
--- a/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/LongType.java b/src/proguard/classfile/attribute/preverification/LongType.java
index 9b14dd6..c986165 100644
--- a/src/proguard/classfile/attribute/preverification/LongType.java
+++ b/src/proguard/classfile/attribute/preverification/LongType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java b/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
index 881f188..be74df0 100644
--- a/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/NullType.java b/src/proguard/classfile/attribute/preverification/NullType.java
index f35cefd..fe0d85f 100644
--- a/src/proguard/classfile/attribute/preverification/NullType.java
+++ b/src/proguard/classfile/attribute/preverification/NullType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/ObjectType.java b/src/proguard/classfile/attribute/preverification/ObjectType.java
index fbdeec7..4ea370a 100644
--- a/src/proguard/classfile/attribute/preverification/ObjectType.java
+++ b/src/proguard/classfile/attribute/preverification/ObjectType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/SameOneFrame.java b/src/proguard/classfile/attribute/preverification/SameOneFrame.java
index db6747b..4384aae 100644
--- a/src/proguard/classfile/attribute/preverification/SameOneFrame.java
+++ b/src/proguard/classfile/attribute/preverification/SameOneFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/SameZeroFrame.java b/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
index 64b17f5..a3bd824 100644
--- a/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/StackMapAttribute.java b/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
index db53ff1..51e69fb 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/StackMapFrame.java b/src/proguard/classfile/attribute/preverification/StackMapFrame.java
index aa3e1f2..01890f3 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapFrame.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java b/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
index 0cddf70..3de059f 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/TopType.java b/src/proguard/classfile/attribute/preverification/TopType.java
index bde8dda..02dd1a2 100644
--- a/src/proguard/classfile/attribute/preverification/TopType.java
+++ b/src/proguard/classfile/attribute/preverification/TopType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/UninitializedThisType.java b/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
index dc4654f..7b2bfa9 100644
--- a/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
+++ b/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/UninitializedType.java b/src/proguard/classfile/attribute/preverification/UninitializedType.java
index a495f1f..7e4a0fd 100644
--- a/src/proguard/classfile/attribute/preverification/UninitializedType.java
+++ b/src/proguard/classfile/attribute/preverification/UninitializedType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/VerificationType.java b/src/proguard/classfile/attribute/preverification/VerificationType.java
index f33d511..02c3872 100644
--- a/src/proguard/classfile/attribute/preverification/VerificationType.java
+++ b/src/proguard/classfile/attribute/preverification/VerificationType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java b/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
index f8ef7e0..ada9ce8 100644
--- a/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
+++ b/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java b/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
index 7db246c..5e4cf88 100644
--- a/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
+++ b/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java b/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
index e9931f8..2a3e9e7 100644
--- a/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
+++ b/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
index 61b0f1a..9d8801c 100644
--- a/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java b/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java
new file mode 100644
index 0000000..d70803c
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given BootstrapMethodInfoVisitor visit all
+ * bootstrap method objects of the BootstrapMethodsAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllBootstrapMethodInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor;
+
+
+ public AllBootstrapMethodInfoVisitor(BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ this.bootstrapMethodInfoVisitor = bootstrapMethodInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, bootstrapMethodInfoVisitor);
+ }
+}
diff --git a/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
index 839e104..927bfd9 100644
--- a/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java b/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java
new file mode 100644
index 0000000..2422218
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given InnerClassesInfoVisitor visit all
+ * InnerClassessInfo objects of the InnerClassesAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllInnerClassesInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final InnerClassesInfoVisitor innerClassesInfoVisitor;
+
+
+ public AllInnerClassesInfoVisitor(InnerClassesInfoVisitor innerClassesInfoVisitor)
+ {
+ this.innerClassesInfoVisitor = innerClassesInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ innerClassesAttribute.innerClassEntriesAccept(clazz, innerClassesInfoVisitor);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
index aa81ce0..0db77d5 100644
--- a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
+++ b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,34 +24,66 @@ import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
import proguard.classfile.attribute.preverification.*;
-import proguard.util.StringMatcher;
+import proguard.util.*;
+
+import java.util.List;
/**
* This AttributeVisitor delegates its visits another AttributeVisitor, but
- * only when the visited attribute has a name that passes a given string
- * matcher.
+ * only when the visited attribute has a name that that matches a given regular
+ * expression.
*
* @author Eric Lafortune
*/
public class AttributeNameFilter
implements AttributeVisitor
{
- private final StringMatcher stringMatcher;
+ private final StringMatcher regularExpressionMatcher;
private final AttributeVisitor attributeVisitor;
/**
* Creates a new AttributeNameFilter.
- * @param stringMatcher the string matcher that will check the attribute
- * names.
- * @param attributeVisitor the <code>AttributeVisitor</code> to which
- * visits will be delegated.
+ * @param regularExpression the regular expression against which attribute
+ * names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
+ */
+ public AttributeNameFilter(String regularExpression,
+ AttributeVisitor attributeVisitor)
+ {
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ attributeVisitor);
+ }
+
+
+ /**
+ * Creates a new AttributeNameFilter.
+ * @param regularExpression the regular expression against which attribute
+ * names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
*/
- public AttributeNameFilter(StringMatcher stringMatcher,
+ public AttributeNameFilter(List regularExpression,
AttributeVisitor attributeVisitor)
{
- this.stringMatcher = stringMatcher;
- this.attributeVisitor = attributeVisitor;
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ attributeVisitor);
+ }
+
+
+ /**
+ * Creates a new AttributeNameFilter.
+ * @param regularExpressionMatcher the string matcher against which
+ * attribute names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to
+ * which visits will be delegated.
+ */
+ public AttributeNameFilter(StringMatcher regularExpressionMatcher,
+ AttributeVisitor attributeVisitor)
+ {
+ this.regularExpressionMatcher = regularExpressionMatcher;
+ this.attributeVisitor = attributeVisitor;
}
@@ -66,6 +98,15 @@ implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (accepted(clazz, bootstrapMethodsAttribute))
+ {
+ bootstrapMethodsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
if (accepted(clazz, sourceFileAttribute))
@@ -340,6 +381,6 @@ implements AttributeVisitor
private boolean accepted(Clazz clazz, Attribute attribute)
{
- return stringMatcher.matches(attribute.getAttributeName(clazz));
+ return regularExpressionMatcher.matches(attribute.getAttributeName(clazz));
}
}
diff --git a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
index e8f226b..76c1ab9 100644
--- a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -35,11 +35,12 @@ public interface AttributeVisitor
{
// Attributes that are attached to classes.
- public void visitUnknownAttribute( Clazz clazz, UnknownAttribute unknownAttribute);
- public void visitSourceFileAttribute( Clazz clazz, SourceFileAttribute sourceFileAttribute);
- public void visitSourceDirAttribute( Clazz clazz, SourceDirAttribute sourceDirAttribute);
- public void visitInnerClassesAttribute( Clazz clazz, InnerClassesAttribute innerClassesAttribute);
- public void visitEnclosingMethodAttribute( Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute);
+ public void visitUnknownAttribute( Clazz clazz, UnknownAttribute unknownAttribute);
+ public void visitBootstrapMethodsAttribute( Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute);
+ public void visitSourceFileAttribute( Clazz clazz, SourceFileAttribute sourceFileAttribute);
+ public void visitSourceDirAttribute( Clazz clazz, SourceDirAttribute sourceDirAttribute);
+ public void visitInnerClassesAttribute( Clazz clazz, InnerClassesAttribute innerClassesAttribute);
+ public void visitEnclosingMethodAttribute( Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute);
// Attributes that are attached to classes, fields, and methods.
diff --git a/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java b/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java
new file mode 100755
index 0000000..9aab92e
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java
@@ -0,0 +1,40 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+import java.beans.MethodDescriptor;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>BootstrapMethodInfo</code> objects. Note that there is only a single
+ * implementation of <code>BootstrapMethodInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface BootstrapMethodInfoVisitor
+{
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo);
+}
diff --git a/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
index 7c85e53..4a765f2 100644
--- a/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java b/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
index 91267b0..b373493 100644
--- a/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
index e59ed7b..189b3d0 100644
--- a/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
index 8647cb3..c888d63 100644
--- a/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
index 9ad38e0..f992e6d 100644
--- a/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java b/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
index 870ba94..37c0639 100644
--- a/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -85,6 +85,15 @@ public class MultiAttributeVisitor implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
for (int index = 0; index < attributeVisitors.length; index++)
diff --git a/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java b/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java
new file mode 100644
index 0000000..2ccc09c
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java
@@ -0,0 +1,293 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.util.StringMatcher;
+
+/**
+ * This AttributeVisitor delegates its visits another AttributeVisitor, but
+ * only when the visited attribute is not empty. For instance, a local variable
+ * table without variables is empty.
+ *
+ * @author Eric Lafortune
+ */
+public class NonEmptyAttributeFilter
+implements AttributeVisitor
+{
+ private final AttributeVisitor attributeVisitor;
+
+
+ /**
+ * Creates a new NonEmptyAttributeFilter.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
+ */
+ public NonEmptyAttributeFilter(AttributeVisitor attributeVisitor)
+ {
+ this.attributeVisitor = attributeVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ unknownAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (bootstrapMethodsAttribute.u2bootstrapMethodsCount > 0)
+ {
+ bootstrapMethodsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ sourceFileAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ sourceDirAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ if (innerClassesAttribute.u2classesCount > 0)
+ {
+ innerClassesAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ enclosingMethodAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ deprecatedAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ deprecatedAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ deprecatedAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ syntheticAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ syntheticAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ syntheticAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ constantValueAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ if (exceptionsAttribute.u2exceptionIndexTableLength > 0)
+ {
+ exceptionsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ if (stackMapAttribute.u2stackMapFramesCount > 0)
+ {
+ stackMapAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ if (stackMapTableAttribute.u2stackMapFramesCount > 0)
+ {
+ stackMapTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ if (lineNumberTableAttribute.u2lineNumberTableLength > 0)
+ {
+ lineNumberTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (localVariableTableAttribute.u2localVariableTableLength > 0)
+ {
+ localVariableTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (localVariableTypeTableAttribute.u2localVariableTypeTableLength > 0)
+ {
+ localVariableTypeTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeVisibleAnnotationsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeVisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeVisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeInvisibleAnnotationsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeInvisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeInvisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ if (runtimeVisibleParameterAnnotationsAttribute.u2parametersCount > 0)
+ {
+ runtimeVisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ if (runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount > 0)
+ {
+ runtimeInvisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ annotationDefaultAttribute.accept(clazz, method, attributeVisitor);
+ }
+}
diff --git a/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
index 92099f9..58e4e40 100644
--- a/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
+++ b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,6 +31,8 @@ import proguard.obfuscate.AttributeShrinker;
* AttributeVisitor instances, depending on whether the visited attribute
* is strictly required or not.
*
+ * Stack map attributes and stack map table attributes are treated as optional.
+ *
* @see AttributeShrinker
*
* @author Eric Lafortune
@@ -80,6 +82,15 @@ implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (requiredAttributeVisitor != null)
+ {
+ bootstrapMethodsAttribute.accept(clazz, requiredAttributeVisitor);
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
if (optionalAttributeVisitor != null)
@@ -235,9 +246,9 @@ implements AttributeVisitor
public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
{
- if (requiredAttributeVisitor != null)
+ if (optionalAttributeVisitor != null)
{
- stackMapTableAttribute.accept(clazz, method, codeAttribute, requiredAttributeVisitor);
+ stackMapTableAttribute.accept(clazz, method, codeAttribute, optionalAttributeVisitor);
}
}
diff --git a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
index 401f188..b5e02e2 100644
--- a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
+++ b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor computes the stack sizes at all instruction offsets
* of the code attributes that it visits.
@@ -140,10 +142,7 @@ implements AttributeVisitor,
}
else
{
- for (int index = 0; index < codeLength; index++)
- {
- evaluated[index] = false;
- }
+ Arrays.fill(evaluated, 0, codeLength, false);
}
// The initial stack is always empty.
diff --git a/src/proguard/classfile/constant/ClassConstant.java b/src/proguard/classfile/constant/ClassConstant.java
index d217bf6..bbd9b31 100644
--- a/src/proguard/classfile/constant/ClassConstant.java
+++ b/src/proguard/classfile/constant/ClassConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/Constant.java b/src/proguard/classfile/constant/Constant.java
index 30ce5df..b4168ce 100644
--- a/src/proguard/classfile/constant/Constant.java
+++ b/src/proguard/classfile/constant/Constant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/DoubleConstant.java b/src/proguard/classfile/constant/DoubleConstant.java
index 61779b5..a4c64cf 100644
--- a/src/proguard/classfile/constant/DoubleConstant.java
+++ b/src/proguard/classfile/constant/DoubleConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/FieldrefConstant.java b/src/proguard/classfile/constant/FieldrefConstant.java
index d4afce5..d552d47 100644
--- a/src/proguard/classfile/constant/FieldrefConstant.java
+++ b/src/proguard/classfile/constant/FieldrefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/FloatConstant.java b/src/proguard/classfile/constant/FloatConstant.java
index 578f567..1709fcb 100644
--- a/src/proguard/classfile/constant/FloatConstant.java
+++ b/src/proguard/classfile/constant/FloatConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/IntegerConstant.java b/src/proguard/classfile/constant/IntegerConstant.java
index 8a476c6..5f0d7f9 100644
--- a/src/proguard/classfile/constant/IntegerConstant.java
+++ b/src/proguard/classfile/constant/IntegerConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/InterfaceMethodrefConstant.java b/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
index ddee42f..52f1852 100644
--- a/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
+++ b/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/InvokeDynamicConstant.java b/src/proguard/classfile/constant/InvokeDynamicConstant.java
new file mode 100755
index 0000000..57474aa
--- /dev/null
+++ b/src/proguard/classfile/constant/InvokeDynamicConstant.java
@@ -0,0 +1,148 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This Constant represents an invoke dynamic constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class InvokeDynamicConstant extends Constant
+{
+ public int u2bootstrapMethodAttributeIndex;
+ public int u2nameAndTypeIndex;
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * descriptor string. This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized InvokeDynamicConstant.
+ */
+ public InvokeDynamicConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new InvokeDynamicConstant with the given bootstrap method
+ * and name-and-type indices.
+ * @param u2bootstrapMethodAttributeIndex the index of the bootstrap method
+ * entry in the bootstrap methods
+ * attribute.
+ * @param u2nameAndTypeIndex the index of the name and type
+ * entry in the constant pool.
+ * @param referencedClasses the classes referenced by the
+ * type.
+ */
+ public InvokeDynamicConstant(int u2bootstrapMethodAttributeIndex,
+ int u2nameAndTypeIndex,
+ Clazz[] referencedClasses)
+ {
+ this.u2bootstrapMethodAttributeIndex = u2bootstrapMethodAttributeIndex;
+ this.u2nameAndTypeIndex = u2nameAndTypeIndex;
+ this.referencedClasses = referencedClasses;
+ }
+
+
+ /**
+ * Returns the index of the bootstrap method in the bootstrap methods
+ * attribute of the class.
+ */
+ public int getBootstrapMethodAttributeIndex()
+ {
+ return u2bootstrapMethodAttributeIndex;
+ }
+
+ /**
+ * Returns the name-and-type index.
+ */
+ public int getNameAndTypeIndex()
+ {
+ return u2nameAndTypeIndex;
+ }
+
+ /**
+ * Returns the method name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getName(u2nameAndTypeIndex);
+ }
+
+ /**
+ * Returns the method type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getType(u2nameAndTypeIndex);
+ }
+
+
+ /**
+ * Lets the Clazz objects referenced in the descriptor string
+ * accept the given visitor.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Lets the bootstrap method handle constant accept the given visitor.
+ */
+ public void bootstrapMethodHandleAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ new BootstrapMethodHandleTraveler(constantVisitor).visitInvokeDynamicConstant(clazz, this);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_InvokeDynamic;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitInvokeDynamicConstant(clazz, this);
+ }
+}
diff --git a/src/proguard/classfile/constant/LongConstant.java b/src/proguard/classfile/constant/LongConstant.java
index ea66e07..2416f01 100644
--- a/src/proguard/classfile/constant/LongConstant.java
+++ b/src/proguard/classfile/constant/LongConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/MethodHandleConstant.java b/src/proguard/classfile/constant/MethodHandleConstant.java
new file mode 100755
index 0000000..6cffd9a
--- /dev/null
+++ b/src/proguard/classfile/constant/MethodHandleConstant.java
@@ -0,0 +1,124 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a method handle constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodHandleConstant extends Constant
+{
+ public int u1referenceKind;
+ public int u2referenceIndex;
+
+
+ /**
+ * An extra field pointing to the java.lang.invoke.MethodHandle Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>..
+ */
+ public Clazz javaLangInvokeMethodHandleClass;
+
+
+ /**
+ * Creates an uninitialized MethodHandleConstant.
+ */
+ public MethodHandleConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new MethodHandleConstant with the given type and method ref
+ * index.
+ * @param u1referenceKind the reference kind.
+ * @param u2referenceIndex the index of the field ref constant, interface
+ * method ref constant, or method ref constant in
+ * the constant pool.
+ */
+ public MethodHandleConstant(int u1referenceKind, int u2referenceIndex)
+ {
+ this.u1referenceKind = u1referenceKind;
+ this.u2referenceIndex = u2referenceIndex;
+ }
+
+
+ /**
+ * Returns the kind of reference to which this constant is pointing.
+ * @return One of
+ * {@link ClassConstants#REF_getField },
+ * {@link ClassConstants#REF_getStatic },
+ * {@link ClassConstants#REF_putField },
+ * {@link ClassConstants#REF_putStatic },
+ * {@link ClassConstants#REF_invokeVirtual },
+ * {@link ClassConstants#REF_invokeStatic },
+ * {@link ClassConstants#REF_invokeSpecial },
+ * {@link ClassConstants#REF_newInvokeSpecial}, or
+ * {@link ClassConstants#REF_invokeInterface }.
+ */
+ public int getReferenceKind()
+ {
+ return u1referenceKind;
+ }
+
+ /**
+ * Returns the field ref, interface method ref, or method ref index.
+ */
+ public int getReferenceIndex()
+ {
+ return u2referenceIndex;
+ }
+
+
+ /**
+ * Returns the method/field name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getRefName(u2referenceIndex);
+ }
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getRefType(u2referenceIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_MethodHandle;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitMethodHandleConstant(clazz, this);
+ }
+}
diff --git a/src/proguard/classfile/constant/MethodTypeConstant.java b/src/proguard/classfile/constant/MethodTypeConstant.java
new file mode 100644
index 0000000..96c136f
--- /dev/null
+++ b/src/proguard/classfile/constant/MethodTypeConstant.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a method handle constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodTypeConstant extends Constant
+{
+ public int u2descriptorIndex;
+
+
+ /**
+ * An extra field pointing to the java.lang.invoke.MethodType Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>..
+ */
+ public Clazz javaLangInvokeMethodTypeClass;
+
+
+ /**
+ * Creates an uninitialized MethodTypeConstant.
+ */
+ public MethodTypeConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new MethodTypeConstant with the given descriptor index.
+ * @param u2descriptorIndex the index of the descriptor in the constant
+ * pool.
+ */
+ public MethodTypeConstant(int u2descriptorIndex)
+ {
+ this.u2descriptorIndex = u2descriptorIndex;
+ }
+
+
+ /**
+ * Returns the descriptor index.
+ */
+ public int getDescriptorIndex()
+ {
+ return u2descriptorIndex;
+ }
+
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getString(u2descriptorIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_MethodType;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitMethodTypeConstant(clazz, this);
+ }
+}
diff --git a/src/proguard/classfile/constant/MethodrefConstant.java b/src/proguard/classfile/constant/MethodrefConstant.java
index 858eec9..1ffa236 100644
--- a/src/proguard/classfile/constant/MethodrefConstant.java
+++ b/src/proguard/classfile/constant/MethodrefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/NameAndTypeConstant.java b/src/proguard/classfile/constant/NameAndTypeConstant.java
index e83d2f1..2a4dd66 100644
--- a/src/proguard/classfile/constant/NameAndTypeConstant.java
+++ b/src/proguard/classfile/constant/NameAndTypeConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/RefConstant.java b/src/proguard/classfile/constant/RefConstant.java
index 4e4d019..0a8fb78 100644
--- a/src/proguard/classfile/constant/RefConstant.java
+++ b/src/proguard/classfile/constant/RefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/StringConstant.java b/src/proguard/classfile/constant/StringConstant.java
index 9a8d453..9b83745 100644
--- a/src/proguard/classfile/constant/StringConstant.java
+++ b/src/proguard/classfile/constant/StringConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/Utf8Constant.java b/src/proguard/classfile/constant/Utf8Constant.java
index ae419c9..3707ba9 100644
--- a/src/proguard/classfile/constant/Utf8Constant.java
+++ b/src/proguard/classfile/constant/Utf8Constant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java b/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
index d2d3c2c..3c36609 100644
--- a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
+++ b/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java b/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java
new file mode 100644
index 0000000..6dce6c5
--- /dev/null
+++ b/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java
@@ -0,0 +1,100 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+import proguard.optimize.info.MethodOptimizationInfo;
+
+/**
+ * This ConstantVisitor and BootstrapMethodInfoVisitor travels from any invoke
+ * dynamic constants or bootstrap method info entries that it visits to their
+ * bootstrap method handle constants, and applies a given constant visitor.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodHandleTraveler
+extends SimplifiedVisitor
+implements ConstantVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor
+{
+ private ConstantVisitor bootstrapMethodHandleVisitor;
+
+ // Field serving as a method argument.
+ int bootstrapMethodAttributeIndex;
+
+
+ /**
+ * Creates a new BootstrapMethodHandleVisitor that will delegate to the
+ * given constant visitor.
+ */
+ public BootstrapMethodHandleTraveler(ConstantVisitor bootstrapMethodHandleVisitor)
+ {
+ this.bootstrapMethodHandleVisitor = bootstrapMethodHandleVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Pass the method index.
+ bootstrapMethodAttributeIndex =
+ invokeDynamicConstant.u2bootstrapMethodAttributeIndex;
+
+ // Delegate to the bootstrap method.
+ clazz.attributesAccept(this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Check bootstrap methods.
+ bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
+ bootstrapMethodAttributeIndex,
+ this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Check bootstrap method.
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex,
+ bootstrapMethodHandleVisitor);
+ }
+}
diff --git a/src/proguard/classfile/constant/visitor/ConstantTagFilter.java b/src/proguard/classfile/constant/visitor/ConstantTagFilter.java
new file mode 100644
index 0000000..a3fcc8a
--- /dev/null
+++ b/src/proguard/classfile/constant/visitor/ConstantTagFilter.java
@@ -0,0 +1,86 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>ConstantVisitor</code> delegates its visits to one or more
+ * specified types of constants.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantTagFilter
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final int constantTagMask;
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new ConstantTagFilter.
+ * @param constantTag the type of constants for which visits will be
+ * delegated.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ConstantTagFilter(int constantTag,
+ ConstantVisitor constantVisitor)
+ {
+ this.constantTagMask = 1 << constantTag;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ /**
+ * Creates a new ConstantTagFilter.
+ * @param constantTags the types of constants for which visits will be
+ * delegated.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ConstantTagFilter(int[] constantTags,
+ ConstantVisitor constantVisitor)
+ {
+ int constantTagMask = 0;
+ for (int index = 0; index < constantTags.length; index++)
+ {
+ constantTagMask |= 1 << constantTags[index];
+ }
+
+ this.constantTagMask = constantTagMask;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ if (((1 << constant.getTag()) & constantTagMask) != 0)
+ {
+ constant.accept(clazz, constantVisitor);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/constant/visitor/ConstantVisitor.java b/src/proguard/classfile/constant/visitor/ConstantVisitor.java
index 6cae352..362d54d 100644
--- a/src/proguard/classfile/constant/visitor/ConstantVisitor.java
+++ b/src/proguard/classfile/constant/visitor/ConstantVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -38,9 +38,12 @@ public interface ConstantVisitor
public void visitDoubleConstant( Clazz clazz, DoubleConstant doubleConstant);
public void visitStringConstant( Clazz clazz, StringConstant stringConstant);
public void visitUtf8Constant( Clazz clazz, Utf8Constant utf8Constant);
+ public void visitInvokeDynamicConstant( Clazz clazz, InvokeDynamicConstant invokeDynamicConstant);
+ public void visitMethodHandleConstant( Clazz clazz, MethodHandleConstant methodHandleConstant);
public void visitFieldrefConstant( Clazz clazz, FieldrefConstant fieldrefConstant);
public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant);
public void visitMethodrefConstant( Clazz clazz, MethodrefConstant methodrefConstant);
public void visitClassConstant( Clazz clazz, ClassConstant classConstant);
+ public void visitMethodTypeConstant( Clazz clazz, MethodTypeConstant methodTypeConstant);
public void visitNameAndTypeConstant( Clazz clazz, NameAndTypeConstant nameAndTypeConstant);
}
diff --git a/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
index fbb3e52..bff4d1e 100644
--- a/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
+++ b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -44,16 +44,16 @@ implements ConstantVisitor
/**
- * Creates a new ClassNameFilter.
+ * Creates a new ExceptClassConstantFilter.
* @param exceptClassName the name of the class that will not be visited.
* @param constantVisitor the <code>ConstantVisitor</code> to which visits
* will be delegated.
*/
- public ExceptClassConstantFilter(String exceptClassName,
- ConstantVisitor constantVisitor)
+ public ExceptClassConstantFilter(String exceptClassName,
+ ConstantVisitor constantVisitor)
{
- this.exceptClassName = exceptClassName;
- this.constantVisitor = constantVisitor;
+ this.exceptClassName = exceptClassName;
+ this.constantVisitor = constantVisitor;
}
diff --git a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java b/src/proguard/classfile/constant/visitor/MethodrefTraveler.java
index ee028f8..acd1bc8 100644
--- a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java
+++ b/src/proguard/classfile/constant/visitor/MethodrefTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,38 +18,32 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package proguard.classfile.visitor;
+package proguard.classfile.constant.visitor;
import proguard.classfile.Clazz;
+import proguard.classfile.attribute.*;
import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.SimplifiedVisitor;
-
/**
- * This ConstantVisitor lets a given <code>ClassVisitor</code> visit all
- * constant classes involved in any <code>Class.forName</code> constructs that
- * it visits.
- *
- * @see DotClassClassVisitor
+ * This ConstantVisitor travels from any method handle constants that it visits
+ * to their methodref constants, and applies a given constant visitor.
*
* @author Eric Lafortune
*/
-public class ClassForNameClassVisitor
+public class MethodrefTraveler
extends SimplifiedVisitor
implements ConstantVisitor
{
- private final ClassVisitor classVisitor;
+ private ConstantVisitor methodrefConstantVisitor;
/**
- * Creates a new ClassHierarchyTraveler.
- * @param classVisitor the <code>ClassVisitor</code> to which visits will
- * be delegated.
+ * Creates a new v that will delegate to the given constant visitor.
*/
- public ClassForNameClassVisitor(ClassVisitor classVisitor)
+ public MethodrefTraveler(ConstantVisitor methodrefConstantVisitor)
{
- this.classVisitor = classVisitor;
+ this.methodrefConstantVisitor = methodrefConstantVisitor;
}
@@ -58,9 +52,9 @@ implements ConstantVisitor
public void visitAnyConstant(Clazz clazz, Constant constant) {}
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
{
- // Visit the referenced class from the Class.forName construct, if any.
- stringConstant.referencedClassAccept(classVisitor);
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex,
+ methodrefConstantVisitor);
}
}
diff --git a/src/proguard/classfile/editor/AccessFixer.java b/src/proguard/classfile/editor/AccessFixer.java
index 7d6274e..d770531 100644
--- a/src/proguard/classfile/editor/AccessFixer.java
+++ b/src/proguard/classfile/editor/AccessFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,8 @@
package proguard.classfile.editor;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.*;
@@ -61,12 +63,26 @@ implements ConstantVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Check the bootstrap method.
+ invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the method reference.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
referencingClass = clazz;
// Remember the specified class, since it might be different from
- // the referenced class that acutally contains the class member.
+ // the referenced class that actually contains the class member.
clazz.constantPoolEntryAccept(refConstant.u2classIndex, referencedClassFinder);
// Make sure the access flags of the referenced class member are
@@ -91,8 +107,8 @@ implements ConstantVisitor,
public void visitProgramClass(ProgramClass programClass)
{
- int currentAccessFlags = programClass.getAccessFlags();
- int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
+ int currentAccessFlags = programClass.getAccessFlags();
+ int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
// Compute the required access level.
Clazz referencingClass = this.referencingClass;
@@ -117,8 +133,8 @@ implements ConstantVisitor,
public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
{
- int currentAccessFlags = programMember.getAccessFlags();
- int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
+ int currentAccessFlags = programMember.getAccessFlags();
+ int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
// Compute the required access level.
int requiredAccessLevel =
diff --git a/src/proguard/classfile/editor/AnnotationAdder.java b/src/proguard/classfile/editor/AnnotationAdder.java
index 359164a..0389ab1 100644
--- a/src/proguard/classfile/editor/AnnotationAdder.java
+++ b/src/proguard/classfile/editor/AnnotationAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
index bf8852c..a175c33 100644
--- a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
+++ b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/AttributeAdder.java b/src/proguard/classfile/editor/AttributeAdder.java
index 2b610b7..ad4ecc0 100644
--- a/src/proguard/classfile/editor/AttributeAdder.java
+++ b/src/proguard/classfile/editor/AttributeAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -138,16 +138,14 @@ implements AttributeVisitor
public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
{
- // TODO: Implement method.
- // Note that the attribute may already be present.
-// // Create a copy of the attribute.
-// InnerClassesAttribute newInnerClassesAttribute =
-// new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex),
-// 0,
-// null);
-//
-// // Add it to the target class.
-// attributesEditor.addClassAttribute(newInnerClassesAttribute);
+ // Create a copy of the attribute.
+ InnerClassesAttribute newInnerClassesAttribute =
+ new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex),
+ 0,
+ null);
+
+ // Add it to the target class.
+ attributesEditor.addAttribute(newInnerClassesAttribute);
}
@@ -256,7 +254,7 @@ implements AttributeVisitor
CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength + 32);
// Add the instructions.
codeAttribute.instructionsAccept(clazz,
diff --git a/src/proguard/classfile/editor/AttributeSorter.java b/src/proguard/classfile/editor/AttributeSorter.java
index d8e3367..23fe027 100644
--- a/src/proguard/classfile/editor/AttributeSorter.java
+++ b/src/proguard/classfile/editor/AttributeSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/AttributesEditor.java b/src/proguard/classfile/editor/AttributesEditor.java
index 10846cc..f50b8f1 100644
--- a/src/proguard/classfile/editor/AttributesEditor.java
+++ b/src/proguard/classfile/editor/AttributesEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/BridgeMethodFixer.java b/src/proguard/classfile/editor/BridgeMethodFixer.java
new file mode 100644
index 0000000..2f1120d
--- /dev/null
+++ b/src/proguard/classfile/editor/BridgeMethodFixer.java
@@ -0,0 +1,117 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This MemberVisitor fixes all inappropriate bridge access flags of the
+ * program methods that it visits, checking whether the methods to which they
+ * bridge have the same name. Some compilers, like in Eclipse and in later
+ * versions of JDK 1.6, complain if they can't find the method with the same
+ * name.
+ *
+ * @author Eric Lafortune
+ */
+public class BridgeMethodFixer
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ // Return values for the visitor methods.
+ private String bridgedMethodName;
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_BRIDGE) != 0)
+ {
+ programMethod.attributesAccept(programClass, this);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Go over the instructions of the bridge method.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ // Get the name of the bridged method.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+
+ // Check if the name is different.
+ if (!method.getName(clazz).equals(bridgedMethodName))
+ {
+ if (DEBUG)
+ {
+ System.out.println("BridgeMethodFixer: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] does not bridge to ["+bridgedMethodName+"]");
+ }
+
+ // Clear the bridge flag.
+ ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.INTERNAL_ACC_BRIDGE;
+ }
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ bridgedMethodName = refConstant.getName(clazz);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/editor/ClassEditor.java b/src/proguard/classfile/editor/ClassEditor.java
index e503ea3..7703c9d 100644
--- a/src/proguard/classfile/editor/ClassEditor.java
+++ b/src/proguard/classfile/editor/ClassEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ClassElementSorter.java b/src/proguard/classfile/editor/ClassElementSorter.java
index 3256c88..9875a29 100644
--- a/src/proguard/classfile/editor/ClassElementSorter.java
+++ b/src/proguard/classfile/editor/ClassElementSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ClassMemberSorter.java b/src/proguard/classfile/editor/ClassMemberSorter.java
index f31fcd0..ed0b5b1 100644
--- a/src/proguard/classfile/editor/ClassMemberSorter.java
+++ b/src/proguard/classfile/editor/ClassMemberSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ClassReferenceFixer.java b/src/proguard/classfile/editor/ClassReferenceFixer.java
index 9857903..1f8b396 100644
--- a/src/proguard/classfile/editor/ClassReferenceFixer.java
+++ b/src/proguard/classfile/editor/ClassReferenceFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/CodeAttributeComposer.java b/src/proguard/classfile/editor/CodeAttributeComposer.java
index e783203..c59b712 100644
--- a/src/proguard/classfile/editor/CodeAttributeComposer.java
+++ b/src/proguard/classfile/editor/CodeAttributeComposer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,6 +28,9 @@ import proguard.classfile.attribute.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import proguard.util.ArrayUtil;
+
+import java.util.Arrays;
/**
* This AttributeVisitor accumulates instructions and exceptions, and then
@@ -49,7 +52,7 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- public static boolean DEBUG = true;
+ public static boolean DEBUG = false;
//*/
@@ -57,7 +60,8 @@ implements AttributeVisitor,
private static final int INVALID = -1;
- private boolean allowExternalExceptionHandlers;
+ private final boolean allowExternalExceptionHandlers;
+ private final boolean shrinkInstructions;
private int maximumCodeLength;
private int codeLength;
@@ -77,26 +81,34 @@ implements AttributeVisitor,
private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater();
private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();
-// private final InstructionWriter instructionWriter = new InstructionWriter();
+ private final InstructionWriter instructionWriter = new InstructionWriter();
/**
* Creates a new CodeAttributeComposer that doesn't allow external exception
- * handlers.
+ * handlers and that automatically shrinks instructions.
*/
public CodeAttributeComposer()
{
- this(false);
+ this(false, true);
}
/**
- * Creates a new CodeAttributeComposer that optionally allows external
- * exception handlers.
+ * Creates a new CodeAttributeComposer.
+ * @param allowExternalExceptionHandlers specifies whether exception
+ * handlers can lie outside the code
+ * fragment in which exceptions are
+ * defined.
+ * @param shrinkInstructions specifies whether instructions
+ * should automatically be shrunk
+ * before being written.
*/
- public CodeAttributeComposer(boolean allowExternalExceptionHandlers)
+ public CodeAttributeComposer(boolean allowExternalExceptionHandlers,
+ boolean shrinkInstructions)
{
this.allowExternalExceptionHandlers = allowExternalExceptionHandlers;
+ this.shrinkInstructions = shrinkInstructions;
}
@@ -109,6 +121,8 @@ implements AttributeVisitor,
codeLength = 0;
exceptionTableLength = 0;
level = -1;
+
+ instructionWriter.reset(ClassConstants.TYPICAL_CODE_LENGTH);
}
@@ -116,7 +130,10 @@ implements AttributeVisitor,
* Starts a new code fragment. Branch instructions that are added are
* assumed to be relative within such code fragments.
* @param maximumCodeFragmentLength the maximum length of the code that will
- * be added as part of this fragment.
+ * be added as part of this fragment (more
+ * precisely, the maximum old instruction
+ * offset or label that is specified, plus
+ * one).
*/
public void beginCodeFragment(int maximumCodeFragmentLength)
{
@@ -127,14 +144,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Maximum number of code fragment levels exceeded ["+level+"]");
}
-// // TODO: Figure out some length.
-// if (level == 0)
-// {
-// // Prepare for possible widening of instructions.
-// instructionWriter.reset(2 * maximumCodeFragmentLength);
-// }
-
// Make sure there is sufficient space for adding the code fragment.
+ // It's only a rough initial estimate for the code length, not even
+ // necessarily a length expressed in bytes.
maximumCodeLength += maximumCodeFragmentLength;
ensureCodeLength(maximumCodeLength);
@@ -159,6 +171,8 @@ implements AttributeVisitor,
/**
* Appends the given instruction with the given old offset.
+ * Branch instructions must fit, for instance by enabling automatic
+ * shrinking of instructions.
* @param oldInstructionOffset the old offset of the instruction, to which
* branches and other references in the current
* code fragment are pointing.
@@ -167,12 +181,17 @@ implements AttributeVisitor,
public void appendInstruction(int oldInstructionOffset,
Instruction instruction)
{
+ if (shrinkInstructions)
+ {
+ instruction = instruction.shrink();
+ }
+
if (DEBUG)
{
println("["+codeLength+"] <- ", instruction.toString(oldInstructionOffset));
}
- // Make sure the code array is large enough.
+ // Make sure the code and offset arrays are large enough.
int newCodeLength = codeLength + instruction.length(codeLength);
ensureCodeLength(newCodeLength);
@@ -180,17 +199,18 @@ implements AttributeVisitor,
// Remember the old offset of the appended instruction.
oldInstructionOffsets[codeLength] = oldInstructionOffset;
- // Write the instruction.
-// instruction.accept(null,
-// null,
-// new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
-// codeLength,
-// instructionWriter);
- instruction.write(code, codeLength);
-
// Fill out the new offset of the appended instruction.
instructionOffsetMap[level][oldInstructionOffset] = codeLength;
+ // Write the instruction. The instruction writer may widen it later on,
+ // if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ codeLength,
+ instructionWriter);
+ //instruction.write(code, codeLength);
+
// Continue appending at the next instruction offset.
codeLength = newCodeLength;
}
@@ -209,12 +229,70 @@ implements AttributeVisitor,
println("["+codeLength+"] <- ", "[" + oldInstructionOffset + "] (label)");
}
- // Fill out the new offset of the appended instruction.
+ // Make sure the code and offset arrays are large enough.
+ ensureCodeLength(codeLength + 1);
+
+ // Remember the old offset of the following instruction.
+ oldInstructionOffsets[codeLength] = oldInstructionOffset;
+
+ // Fill out the new offset of the following instruction.
instructionOffsetMap[level][oldInstructionOffset] = codeLength;
}
/**
+ * Appends the given instruction without defined offsets.
+ * @param instructions the instructions to be appended.
+ */
+ public void appendInstructions(Instruction[] instructions)
+ {
+ for (int index = 0; index < instructions.length; index++)
+ {
+ appendInstruction(instructions[index]);
+ }
+ }
+
+
+ /**
+ * Appends the given instruction without a defined offset.
+ * Branch instructions should have a label, to allow computing the
+ * new relative offset.
+ * Branch instructions must fit, for instance by enabling automatic
+ * shrinking of instructions.
+ * @param instruction the instruction to be appended.
+ */
+ public void appendInstruction(Instruction instruction)
+ {
+ if (shrinkInstructions)
+ {
+ instruction = instruction.shrink();
+ }
+
+ if (DEBUG)
+ {
+ println("["+codeLength+"] <- ", instruction.toString());
+ }
+
+ // Make sure the code array is large enough.
+ int newCodeLength = codeLength + instruction.length(codeLength);
+
+ ensureCodeLength(newCodeLength);
+
+ // Write the instruction. The instruction writer may widen it later on,
+ // if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ codeLength,
+ instructionWriter);
+ //instruction.write(code, codeLength);
+
+ // Continue appending at the next instruction offset.
+ codeLength = newCodeLength;
+ }
+
+
+ /**
* Appends the given exception to the exception table.
* @param exceptionInfo the exception to be appended.
*/
@@ -244,16 +322,11 @@ implements AttributeVisitor,
return;
}
- // Make sure there is sufficient space in the exception table.
- if (exceptionTable.length <= exceptionTableLength)
- {
- ExceptionInfo[] newExceptionTable = new ExceptionInfo[exceptionTableLength+1];
- System.arraycopy(exceptionTable, 0, newExceptionTable, 0, exceptionTableLength);
- exceptionTable = newExceptionTable;
- }
-
// Add the exception.
- exceptionTable[exceptionTableLength++] = exceptionInfo;
+ exceptionTable =
+ (ExceptionInfo[])ArrayUtil.add(exceptionTable,
+ exceptionTableLength++,
+ exceptionInfo);
}
@@ -281,13 +354,14 @@ implements AttributeVisitor,
// Adapt the instruction for its new offset.
instruction.accept(null, null, null, instructionOffset, this);
- // Write the instruction back.
-// instruction.accept(null,
-// null,
-// new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
-// instructionOffset,
-// instructionWriter);
- instruction.write(code, instructionOffset);
+ // Write the instruction back. The instruction writer may still
+ // widen it later on, if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ instructionOffset,
+ instructionWriter);
+ //instruction.write(code, codeLength);
// Don't remap this instruction again.
oldInstructionOffsets[instructionOffset] = -1;
@@ -313,9 +387,9 @@ implements AttributeVisitor,
int handlerPC = -exceptionInfo.u2handlerPC;
if (handlerPC > 0)
{
- if (remappableInstructionOffset(handlerPC))
+ if (remappableExceptionHandler(handlerPC))
{
- exceptionInfo.u2handlerPC = remapInstructionOffset(handlerPC);
+ exceptionInfo.u2handlerPC = newInstructionOffset(handlerPC);
}
else if (level == 0)
{
@@ -381,7 +455,7 @@ implements AttributeVisitor,
// Remap the line number table and the local variable table.
codeAttribute.attributesAccept(clazz, method, this);
- // Remap the exception table.
+ // Remap the exception table (done before).
//codeAttribute.exceptionsAccept(clazz, method, this);
// Remove exceptions with empty code blocks (done before).
@@ -389,8 +463,8 @@ implements AttributeVisitor,
// removeEmptyExceptions(codeAttribute.exceptionTable,
// codeAttribute.u2exceptionTableLength);
-// // Make sure instructions are widened if necessary.
-// instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
+ // Make sure instructions are widened if necessary.
+ instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
level--;
}
@@ -459,20 +533,20 @@ implements AttributeVisitor,
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
{
// Adjust the branch offset.
- branchInstruction.branchOffset = remapBranchOffset(offset,
- branchInstruction.branchOffset);
+ branchInstruction.branchOffset = newBranchOffset(offset,
+ branchInstruction.branchOffset);
}
public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
{
// Adjust the default jump offset.
- switchInstruction.defaultOffset = remapBranchOffset(offset,
- switchInstruction.defaultOffset);
+ switchInstruction.defaultOffset = newBranchOffset(offset,
+ switchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
- switchInstruction.jumpOffsets);
+ updateJumpOffsets(offset,
+ switchInstruction.jumpOffsets);
}
@@ -482,16 +556,16 @@ implements AttributeVisitor,
{
// Remap the code offsets. Note that the instruction offset map also has
// an entry for the first offset after the code, for u2endPC.
- exceptionInfo.u2startPC = remapInstructionOffset(exceptionInfo.u2startPC);
- exceptionInfo.u2endPC = remapInstructionOffset(exceptionInfo.u2endPC);
+ exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC);
+ exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC);
// See if we can remap the handler right away. Unmapped exception
// handlers are negated, in order to mark them as external.
int handlerPC = exceptionInfo.u2handlerPC;
exceptionInfo.u2handlerPC =
!allowExternalExceptionHandlers ||
- remappableInstructionOffset(handlerPC) ?
- remapInstructionOffset(handlerPC) :
+ remappableExceptionHandler(handlerPC) ?
+ newInstructionOffset(handlerPC) :
-handlerPC;
}
@@ -501,7 +575,7 @@ implements AttributeVisitor,
public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
{
// Remap the stack map frame offset.
- int stackMapFrameOffset = remapInstructionOffset(offset);
+ int stackMapFrameOffset = newInstructionOffset(offset);
int offsetDelta = stackMapFrameOffset;
@@ -557,7 +631,7 @@ implements AttributeVisitor,
public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
{
// Remap the offset of the 'new' instruction.
- uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset);
+ uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset);
}
@@ -566,7 +640,7 @@ implements AttributeVisitor,
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
{
// Remap the code offset.
- lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC);
+ lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC);
}
@@ -576,8 +650,9 @@ implements AttributeVisitor,
{
// Remap the code offset and length.
// TODO: The local variable frame might not be strictly preserved.
- int startPC = remapInstructionOffset(localVariableInfo.u2startPC);
- int endPC = remapInstructionOffset(localVariableInfo.u2startPC + localVariableInfo.u2length);
+ int startPC = newInstructionOffset(localVariableInfo.u2startPC);
+ int endPC = newInstructionOffset(localVariableInfo.u2startPC +
+ localVariableInfo.u2length);
localVariableInfo.u2startPC = startPC;
localVariableInfo.u2length = endPC - startPC;
@@ -589,8 +664,9 @@ implements AttributeVisitor,
{
// Remap the code offset and length.
// TODO: The local variable frame might not be strictly preserved.
- int startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC);
- int endPC = remapInstructionOffset(localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length);
+ int startPC = newInstructionOffset(localVariableTypeInfo.u2startPC);
+ int endPC = newInstructionOffset(localVariableTypeInfo.u2startPC +
+ localVariableTypeInfo.u2length);
localVariableTypeInfo.u2startPC = startPC;
localVariableTypeInfo.u2length = endPC - startPC;
@@ -609,13 +685,10 @@ implements AttributeVisitor,
// Add 20% to avoid extending the arrays too often.
newCodeLength = newCodeLength * 6 / 5;
- byte[] newCode = new byte[newCodeLength];
- System.arraycopy(code, 0, newCode, 0, codeLength);
- code = newCode;
+ code = ArrayUtil.extendArray(code, newCodeLength);
+ oldInstructionOffsets = ArrayUtil.extendArray(oldInstructionOffsets, newCodeLength);
- int[] newOldInstructionOffsets = new int[newCodeLength];
- System.arraycopy(oldInstructionOffsets, 0, newOldInstructionOffsets, 0, codeLength);
- oldInstructionOffsets = newOldInstructionOffsets;
+ instructionWriter.extend(newCodeLength);
}
}
@@ -623,11 +696,11 @@ implements AttributeVisitor,
/**
* Adjusts the given jump offsets for the instruction at the given offset.
*/
- private void remapJumpOffsets(int offset, int[] jumpOffsets)
+ private void updateJumpOffsets(int offset, int[] jumpOffsets)
{
for (int index = 0; index < jumpOffsets.length; index++)
{
- jumpOffsets[index] = remapBranchOffset(offset, jumpOffsets[index]);
+ jumpOffsets[index] = newBranchOffset(offset, jumpOffsets[index]);
}
}
@@ -636,7 +709,7 @@ implements AttributeVisitor,
* Computes the new branch offset for the instruction at the given new offset
* with the given old branch offset.
*/
- private int remapBranchOffset(int newInstructionOffset, int branchOffset)
+ private int newBranchOffset(int newInstructionOffset, int oldBranchOffset)
{
if (newInstructionOffset < 0 ||
newInstructionOffset > codeLength)
@@ -646,8 +719,8 @@ implements AttributeVisitor,
int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset];
- return remapInstructionOffset(oldInstructionOffset + branchOffset) -
- remapInstructionOffset(oldInstructionOffset);
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) -
+ newInstructionOffset(oldInstructionOffset);
}
@@ -655,7 +728,7 @@ implements AttributeVisitor,
* Computes the new instruction offset for the instruction at the given old
* offset.
*/
- private int remapInstructionOffset(int oldInstructionOffset)
+ private int newInstructionOffset(int oldInstructionOffset)
{
if (oldInstructionOffset < 0 ||
oldInstructionOffset > codeFragmentLengths[level])
@@ -674,13 +747,25 @@ implements AttributeVisitor,
/**
- * Returns whether the given old instruction offset can be remapped at the
+ * Returns whether the given old exception handler can be remapped in the
+ * current code fragment.
*/
- private boolean remappableInstructionOffset(int oldInstructionOffset)
+ private boolean remappableExceptionHandler(int oldInstructionOffset)
{
- return
- oldInstructionOffset <= codeFragmentLengths[level] &&
- instructionOffsetMap[level][oldInstructionOffset] > INVALID;
+ // Can we index in the array?
+ if (oldInstructionOffset > codeFragmentLengths[level])
+ {
+ return false;
+ }
+
+ // Do we have a valid new instruction offset, but not yet right after
+ // the code? That offset is only labeled for mapping try blocks, not
+ // for mapping handlers.
+ int newInstructionOffset =
+ instructionOffsetMap[level][oldInstructionOffset];
+
+ return newInstructionOffset > INVALID &&
+ newInstructionOffset < codeLength;
}
@@ -703,10 +788,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < exceptionInfoCount; index++)
- {
- exceptionInfos[index] = null;
- }
+ Arrays.fill(exceptionInfos, newIndex, exceptionInfoCount, null);
return newIndex;
}
@@ -734,10 +816,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < lineNumberInfoCount; index++)
- {
- lineNumberInfos[index] = null;
- }
+ Arrays.fill(lineNumberInfos, newIndex, lineNumberInfoCount, null);
return newIndex;
}
@@ -764,10 +843,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < localVariableInfoCount; index++)
- {
- localVariableInfos[index] = null;
- }
+ Arrays.fill(localVariableInfos, newIndex, localVariableInfoCount, null);
return newIndex;
}
@@ -794,10 +870,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < localVariableTypeInfoCount; index++)
- {
- localVariableTypeInfos[index] = null;
- }
+ Arrays.fill(localVariableTypeInfos, newIndex, localVariableTypeInfoCount, null);
return newIndex;
}
diff --git a/src/proguard/classfile/editor/CodeAttributeEditor.java b/src/proguard/classfile/editor/CodeAttributeEditor.java
index 9658c98..337e0d4 100644
--- a/src/proguard/classfile/editor/CodeAttributeEditor.java
+++ b/src/proguard/classfile/editor/CodeAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,9 @@ import proguard.classfile.attribute.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.ClassPrinter;
+import proguard.util.ArrayUtil;
+
+import java.util.Arrays;
/**
* This AttributeVisitor accumulates specified changes to code, and then applies
@@ -50,10 +52,12 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ public static boolean DEBUG = false;
//*/
- private boolean updateFrameSizes;
+
+ private final boolean updateFrameSizes;
+ private final boolean shrinkInstructions;
private int codeLength;
private boolean modified;
@@ -64,7 +68,7 @@ implements AttributeVisitor,
/*private*/public Instruction[] postInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];
/*private*/public boolean[] deleted = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
- private int[] instructionOffsetMap = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] newInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int newOffset;
private boolean lengthIncreased;
@@ -75,15 +79,28 @@ implements AttributeVisitor,
private final InstructionWriter instructionWriter = new InstructionWriter();
+ /**
+ * Creates a new CodeAttributeEditor that automatically updates frame
+ * sizes and shrinks instructions.
+ */
public CodeAttributeEditor()
{
- this(true);
+ this(true, true);
}
- public CodeAttributeEditor(boolean updateFrameSizes)
+ /**
+ * Creates a new CodeAttributeEditor.
+ * @param updateFrameSizes specifies whether frame sizes of edited code
+ * should be updated.
+ * @param shrinkInstructions specifies whether added instructions should
+ * automatically be shrunk before being written.
+ */
+ public CodeAttributeEditor(boolean updateFrameSizes,
+ boolean shrinkInstructions)
{
- this.updateFrameSizes = updateFrameSizes;
+ this.updateFrameSizes = updateFrameSizes;
+ this.shrinkInstructions = shrinkInstructions;
}
@@ -93,8 +110,6 @@ implements AttributeVisitor,
*/
public void reset(int codeLength)
{
- this.codeLength = codeLength;
-
// Try to reuse the previous arrays.
if (preInsertions.length < codeLength)
{
@@ -105,18 +120,42 @@ implements AttributeVisitor,
}
else
{
- for (int index = 0; index < codeLength; index++)
- {
- preInsertions[index] = null;
- replacements[index] = null;
- postInsertions[index] = null;
- deleted[index] = false;
- }
+ Arrays.fill(preInsertions, 0, codeLength, null);
+ Arrays.fill(replacements, 0, codeLength, null);
+ Arrays.fill(postInsertions, 0, codeLength, null);
+ Arrays.fill(deleted, 0, codeLength, false);
}
+ this.codeLength = codeLength;
+
modified = false;
simple = true;
+ }
+
+
+ /**
+ * Extends the size of the accumulated code changes.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void extend(int codeLength)
+ {
+ // Try to reuse the previous arrays.
+ if (preInsertions.length < codeLength)
+ {
+ preInsertions = (Instruction[])ArrayUtil.extendArray(preInsertions, codeLength);
+ replacements = (Instruction[])ArrayUtil.extendArray(replacements, codeLength);
+ postInsertions = (Instruction[])ArrayUtil.extendArray(postInsertions, codeLength);
+ deleted = ArrayUtil.extendArray(deleted, codeLength);
+ }
+ else
+ {
+ Arrays.fill(preInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(replacements, this.codeLength, codeLength, null);
+ Arrays.fill(postInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(deleted, this.codeLength, codeLength, false);
+ }
+ this.codeLength = codeLength;
}
@@ -134,7 +173,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- preInsertions[instructionOffset] = instruction;
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -156,7 +197,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- preInsertions[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -178,7 +224,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- replacements[instructionOffset] = instruction;
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
}
@@ -198,7 +246,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- replacements[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
}
@@ -218,7 +271,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- postInsertions[instructionOffset] = instruction;
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -239,7 +294,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- postInsertions[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -282,6 +342,34 @@ implements AttributeVisitor,
/**
+ * Clears all modifications of the instruction at the given offset.
+ * @param instructionOffset the offset of the instruction to be deleted.
+ */
+ public void clearModifications(int instructionOffset)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ preInsertions[instructionOffset] = null;
+ replacements[instructionOffset] = null;
+ postInsertions[instructionOffset] = null;
+ deleted[instructionOffset] = false;
+ }
+
+
+ /**
+ * Returns whether the code has been modified in any way.
+ */
+ public boolean isModified()
+ {
+ return modified;
+ }
+
+
+ /**
* Returns whether the instruction at the given offset has been modified
* in any way.
*/
@@ -326,54 +414,53 @@ implements AttributeVisitor,
public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
- if (DEBUG)
- {
- System.out.println("CodeAttributeEditor: ["+clazz.getName()+"."+method.getName(clazz)+"]");
- }
-
- // Avoid doing any work if nothing is changing anyway.
- if (!modified)
+ // Do we have to update the code?
+ if (modified)
{
- return;
- }
+ if (DEBUG)
+ {
+ System.out.println("CodeAttributeEditor: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
- // Check if we can perform a faster simple replacement of instructions.
- if (canPerformSimpleReplacements(codeAttribute))
- {
- // Simply overwrite the instructions.
- performSimpleReplacements(codeAttribute);
+ // Can we perform a faster simple replacement of instructions?
+ if (canPerformSimpleReplacements(codeAttribute))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Simple editing");
+ }
- // Update the maximum stack size and local variable frame size.
- updateFrameSizes(clazz, method, codeAttribute);
- }
- else
- {
- // Move and remap the instructions.
- codeAttribute.u4codeLength =
- updateInstructions(clazz, method, codeAttribute);
+ // Simply overwrite the instructions.
+ performSimpleReplacements(codeAttribute);
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Full editing");
+ }
- // Remap the exception table.
- codeAttribute.exceptionsAccept(clazz, method, this);
+ // Move and remap the instructions.
+ codeAttribute.u4codeLength =
+ updateInstructions(clazz, method, codeAttribute);
- // Remove exceptions with empty code blocks.
- codeAttribute.u2exceptionTableLength =
- removeEmptyExceptions(codeAttribute.exceptionTable,
- codeAttribute.u2exceptionTableLength);
+ // Update the exception table.
+ codeAttribute.exceptionsAccept(clazz, method, this);
- // Update the maximum stack size and local variable frame size.
- updateFrameSizes(clazz, method, codeAttribute);
+ // Remove exceptions with empty code blocks.
+ codeAttribute.u2exceptionTableLength =
+ removeEmptyExceptions(codeAttribute.exceptionTable,
+ codeAttribute.u2exceptionTableLength);
- // Remap the line number table and the local variable table.
- codeAttribute.attributesAccept(clazz, method, this);
+ // Update the line number table and the local variable tables.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
// Make sure instructions are widened if necessary.
instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
}
- }
-
- private void updateFrameSizes(Clazz clazz, Method method, CodeAttribute codeAttribute)
- {
+ // Update the maximum stack size and local variable frame size.
if (updateFrameSizes)
{
stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
@@ -384,7 +471,7 @@ implements AttributeVisitor,
public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
{
- // Remap all stack map entries.
+ // Update all stack map entries.
expectedStackMapFrameOffset = -1;
stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
}
@@ -392,7 +479,7 @@ implements AttributeVisitor,
public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
{
- // Remap all stack map table entries.
+ // Update all stack map table entries.
expectedStackMapFrameOffset = 0;
stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
}
@@ -400,7 +487,7 @@ implements AttributeVisitor,
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
- // Remap all line number table entries.
+ // Update all line number table entries.
lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
// Remove line numbers with empty code blocks.
@@ -413,27 +500,15 @@ implements AttributeVisitor,
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
{
- // Remap all local variable table entries.
+ // Update all local variable table entries.
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables with empty code blocks.
- localVariableTableAttribute.u2localVariableTableLength =
- removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
- localVariableTableAttribute.u2localVariableTableLength,
- codeAttribute.u2maxLocals);
}
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
{
- // Remap all local variable table entries.
+ // Update all local variable table entries.
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables with empty code blocks.
- localVariableTypeTableAttribute.u2localVariableTypeTableLength =
- removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
- localVariableTypeTableAttribute.u2localVariableTypeTableLength,
- codeAttribute.u2maxLocals);
}
@@ -491,7 +566,7 @@ implements AttributeVisitor,
if (DEBUG)
{
- System.out.println(" Replaced "+replacementInstruction.toString(newOffset));
+ System.out.println(" Replaced "+replacementInstruction.toString(offset));
}
}
}
@@ -513,9 +588,9 @@ implements AttributeVisitor,
int oldLength = codeAttribute.u4codeLength;
// Make sure there is a sufficiently large instruction offset map.
- if (instructionOffsetMap.length < oldLength + 1)
+ if (newInstructionOffsets.length < oldLength + 1)
{
- instructionOffsetMap = new int[oldLength + 1];
+ newInstructionOffsets = new int[oldLength + 1];
}
// Fill out the instruction offset map.
@@ -574,7 +649,7 @@ implements AttributeVisitor,
while (oldOffset < oldLength);
// Also add an entry for the first offset after the code.
- instructionOffsetMap[oldOffset] = newOffset;
+ newInstructionOffsets[oldOffset] = newOffset;
return newOffset;
}
@@ -588,7 +663,7 @@ implements AttributeVisitor,
private void mapInstruction(int oldOffset,
Instruction instruction)
{
- instructionOffsetMap[oldOffset] = newOffset;
+ newInstructionOffsets[oldOffset] = newOffset;
// Account for the pre-inserted instruction, if any.
Instruction preInstruction = preInsertions[oldOffset];
@@ -670,52 +745,53 @@ implements AttributeVisitor,
int oldOffset,
Instruction instruction)
{
- // Remap and insert the pre-inserted instruction, if any.
+ // Update and insert the pre-inserted instruction, if any.
Instruction preInstruction = preInsertions[oldOffset];
if (preInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Pre-inserted "+preInstruction.toString(newOffset));
+ System.out.println(" Pre-inserted ["+oldOffset+"] -> "+preInstruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
preInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
- // Remap and insert the replacement instruction, or the current
+ // Update and insert the replacement instruction, or the current
// instruction, if it shouldn't be deleted.
Instruction replacementInstruction = replacements[oldOffset];
if (replacementInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Replaced "+replacementInstruction.toString(newOffset));
+ System.out.println(" Replaced ["+oldOffset+"] -> "+replacementInstruction.toString(newOffset));
}
- // Remap the instruction.
+
+ // Update the instruction.
replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
else if (!deleted[oldOffset])
{
if (DEBUG)
{
- System.out.println(" Copied "+instruction.toString(newOffset));
+ System.out.println(" Copied ["+oldOffset+"] -> "+instruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
instruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
- // Remap and insert the post-inserted instruction, if any.
+ // Update and insert the post-inserted instruction, if any.
Instruction postInstruction = postInsertions[oldOffset];
if (postInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Post-inserted "+postInstruction.toString(newOffset));
+ System.out.println(" Post-inserted ["+oldOffset+"] -> "+postInstruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
postInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
}
@@ -765,8 +841,8 @@ implements AttributeVisitor,
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
{
// Adjust the branch offset.
- branchInstruction.branchOffset = remapBranchOffset(offset,
- branchInstruction.branchOffset);
+ branchInstruction.branchOffset = newBranchOffset(offset,
+ branchInstruction.branchOffset);
// Write out the instruction.
instructionWriter.visitBranchInstruction(clazz,
@@ -782,11 +858,11 @@ implements AttributeVisitor,
public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
{
// Adjust the default jump offset.
- tableSwitchInstruction.defaultOffset = remapBranchOffset(offset,
- tableSwitchInstruction.defaultOffset);
+ tableSwitchInstruction.defaultOffset = newBranchOffset(offset,
+ tableSwitchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
+ newJumpOffsets(offset,
tableSwitchInstruction.jumpOffsets);
// Write out the instruction.
@@ -803,11 +879,11 @@ implements AttributeVisitor,
public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
{
// Adjust the default jump offset.
- lookUpSwitchInstruction.defaultOffset = remapBranchOffset(offset,
- lookUpSwitchInstruction.defaultOffset);
+ lookUpSwitchInstruction.defaultOffset = newBranchOffset(offset,
+ lookUpSwitchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
+ newJumpOffsets(offset,
lookUpSwitchInstruction.jumpOffsets);
// Write out the instruction.
@@ -825,11 +901,11 @@ implements AttributeVisitor,
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- // Remap the code offsets. Note that the instruction offset map also has
+ // Update the code offsets. Note that the instruction offset map also has
// an entry for the first offset after the code, for u2endPC.
- exceptionInfo.u2startPC = remapInstructionOffset(exceptionInfo.u2startPC);
- exceptionInfo.u2endPC = remapInstructionOffset(exceptionInfo.u2endPC);
- exceptionInfo.u2handlerPC = remapInstructionOffset(exceptionInfo.u2handlerPC);
+ exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC);
+ exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC);
+ exceptionInfo.u2handlerPC = newInstructionOffset(exceptionInfo.u2handlerPC);
}
@@ -837,8 +913,8 @@ implements AttributeVisitor,
public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
{
- // Remap the stack map frame offset.
- int stackMapFrameOffset = remapInstructionOffset(offset);
+ // Update the stack map frame offset.
+ int stackMapFrameOffset = newInstructionOffset(offset);
int offsetDelta = stackMapFrameOffset;
@@ -857,30 +933,30 @@ implements AttributeVisitor,
public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame);
- // Remap the verification type offset.
+ // Update the verification type offset.
sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
}
public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame);
- // Remap the verification type offsets.
+ // Update the verification type offsets.
moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
}
public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame);
- // Remap the verification type offsets.
+ // Update the verification type offsets.
fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
}
@@ -893,8 +969,8 @@ implements AttributeVisitor,
public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
{
- // Remap the offset of the 'new' instruction.
- uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset);
+ // Update the offset of the 'new' instruction.
+ uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset);
}
@@ -902,8 +978,8 @@ implements AttributeVisitor,
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
{
- // Remap the code offset.
- lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC);
+ // Update the code offset.
+ lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC);
}
@@ -911,11 +987,13 @@ implements AttributeVisitor,
public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
{
- // Remap the code offset and length.
- // TODO: The local variable frame might not be strictly preserved.
- localVariableInfo.u2length = remapBranchOffset(localVariableInfo.u2startPC,
- localVariableInfo.u2length);
- localVariableInfo.u2startPC = remapInstructionOffset(localVariableInfo.u2startPC);
+ // Update the code offset and length.
+ int newStartPC = newInstructionOffset(localVariableInfo.u2startPC);
+ int newEndPC = newInstructionOffset(localVariableInfo.u2startPC +
+ localVariableInfo.u2length);
+
+ localVariableInfo.u2length = newEndPC - newStartPC;
+ localVariableInfo.u2startPC = newStartPC;
}
@@ -923,11 +1001,13 @@ implements AttributeVisitor,
public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
{
- // Remap the code offset and length.
- // TODO: The local variable frame might not be strictly preserved.
- localVariableTypeInfo.u2length = remapBranchOffset(localVariableTypeInfo.u2startPC,
- localVariableTypeInfo.u2length);
- localVariableTypeInfo.u2startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC);
+ // Update the code offset and length.
+ int newStartPC = newInstructionOffset(localVariableTypeInfo.u2startPC);
+ int newEndPC = newInstructionOffset(localVariableTypeInfo.u2startPC +
+ localVariableTypeInfo.u2length);
+
+ localVariableTypeInfo.u2length = newEndPC - newStartPC;
+ localVariableTypeInfo.u2startPC = newStartPC;
}
@@ -936,11 +1016,11 @@ implements AttributeVisitor,
/**
* Adjusts the given jump offsets for the instruction at the given offset.
*/
- private void remapJumpOffsets(int offset, int[] jumpOffsets)
+ private void newJumpOffsets(int oldInstructionOffset, int[] oldJumpOffsets)
{
- for (int index = 0; index < jumpOffsets.length; index++)
+ for (int index = 0; index < oldJumpOffsets.length; index++)
{
- jumpOffsets[index] = remapBranchOffset(offset, jumpOffsets[index]);
+ oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, oldJumpOffsets[index]);
}
}
@@ -949,24 +1029,24 @@ implements AttributeVisitor,
* Computes the new branch offset for the instruction at the given offset
* with the given branch offset.
*/
- private int remapBranchOffset(int offset, int branchOffset)
+ private int newBranchOffset(int oldInstructionOffset, int oldBranchOffset)
{
- return remapInstructionOffset(offset + branchOffset) - newOffset;
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - newOffset;
}
/**
* Computes the new instruction offset for the instruction at the given offset.
*/
- private int remapInstructionOffset(int offset)
+ private int newInstructionOffset(int oldInstructionOffset)
{
- if (offset < 0 ||
- offset > codeLength)
+ if (oldInstructionOffset < 0 ||
+ oldInstructionOffset > codeLength)
{
- throw new IllegalArgumentException("Invalid instruction offset ["+offset+"] in code with length ["+codeLength+"]");
+ throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset+"] in code with length ["+codeLength+"]");
}
- return instructionOffsetMap[offset];
+ return newInstructionOffsets[oldInstructionOffset];
}
@@ -1018,53 +1098,9 @@ implements AttributeVisitor,
/**
- * Returns the given list of local variables, without the ones that have empty
- * code blocks or that exceed the actual number of local variables.
+ * This instruction is a composite of other instructions, for local use
+ * inside the editor class only.
*/
- private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
- int localVariableInfoCount,
- int maxLocals)
- {
- // Overwrite all empty local variable entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableInfoCount; index++)
- {
- LocalVariableInfo localVariableInfo = localVariableInfos[index];
- if (localVariableInfo.u2length > 0 &&
- localVariableInfo.u2index < maxLocals)
- {
- localVariableInfos[newIndex++] = localVariableInfo;
- }
- }
-
- return newIndex;
- }
-
-
- /**
- * Returns the given list of local variable types, without the ones that
- * have empty code blocks or that exceed the actual number of local variables.
- */
- private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
- int localVariableTypeInfoCount,
- int maxLocals)
- {
- // Overwrite all empty local variable type entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableTypeInfoCount; index++)
- {
- LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
- if (localVariableTypeInfo.u2length > 0 &&
- localVariableTypeInfo.u2index < maxLocals)
- {
- localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
- }
- }
-
- return newIndex;
- }
-
-
private class CompositeInstruction
extends Instruction
{
diff --git a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
index 9962ea5..8f767c7 100644
--- a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
+++ b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ComparableConstant.java b/src/proguard/classfile/editor/ComparableConstant.java
index bb81221..476edd6 100644
--- a/src/proguard/classfile/editor/ComparableConstant.java
+++ b/src/proguard/classfile/editor/ComparableConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,7 +39,7 @@ class ComparableConstant
extends SimplifiedVisitor
implements Comparable, ConstantVisitor
{
- private static final int[] PRIORITIES = new int[13];
+ private static final int[] PRIORITIES = new int[19];
static
{
PRIORITIES[ClassConstants.CONSTANT_Integer] = 0; // Possibly byte index (ldc).
@@ -47,12 +47,15 @@ implements Comparable, ConstantVisitor
PRIORITIES[ClassConstants.CONSTANT_String] = 2;
PRIORITIES[ClassConstants.CONSTANT_Class] = 3;
PRIORITIES[ClassConstants.CONSTANT_Long] = 4; // Always wide index (ldc2_w).
- PRIORITIES[ClassConstants.CONSTANT_Double] = 5;
- PRIORITIES[ClassConstants.CONSTANT_Fieldref] = 6; // Always wide index.
- PRIORITIES[ClassConstants.CONSTANT_Methodref] = 7;
- PRIORITIES[ClassConstants.CONSTANT_InterfaceMethodref] = 8;
- PRIORITIES[ClassConstants.CONSTANT_NameAndType] = 9;
- PRIORITIES[ClassConstants.CONSTANT_Utf8] = 10;
+ PRIORITIES[ClassConstants.CONSTANT_Double] = 5; // Always wide index (ldc2_w).
+ PRIORITIES[ClassConstants.CONSTANT_Fieldref] = 6; // Always wide index (getfield,...).
+ PRIORITIES[ClassConstants.CONSTANT_Methodref] = 7; // Always wide index (invokespecial,...).
+ PRIORITIES[ClassConstants.CONSTANT_InterfaceMethodref] = 8; // Always wide index (invokeinterface).
+ PRIORITIES[ClassConstants.CONSTANT_InvokeDynamic] = 9; // Always wide index (invokedynamic).
+ PRIORITIES[ClassConstants.CONSTANT_MethodHandle] = 10;
+ PRIORITIES[ClassConstants.CONSTANT_NameAndType] = 11;
+ PRIORITIES[ClassConstants.CONSTANT_MethodType] = 12;
+ PRIORITIES[ClassConstants.CONSTANT_Utf8] = 13;
}
private final Clazz clazz;
@@ -122,26 +125,32 @@ implements Comparable, ConstantVisitor
public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
{
- // In JDK 1.4, we can use Integer.compare(a,b).
- result = new Integer(integerConstant.getValue()).compareTo(new Integer(((IntegerConstant)otherConstant).getValue()));
+ int value = integerConstant.getValue();
+ int otherValue = ((IntegerConstant)otherConstant).getValue();
+ result = value < otherValue ? -1 :
+ value == otherValue ? 0 :
+ 1;
}
public void visitLongConstant(Clazz clazz, LongConstant longConstant)
{
- // In JDK 1.4, we can use Long.compare(a,b).
- result = new Long(longConstant.getValue()).compareTo(new Long(((LongConstant)otherConstant).getValue()));
+ long value = longConstant.getValue();
+ long otherValue = ((LongConstant)otherConstant).getValue();
+ result = value < otherValue ? -1 :
+ value == otherValue ? 0 :
+ 1;
}
public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
{
- // In JDK 1.4, we can use Float.compare(a,b).
- result = new Float(floatConstant.getValue()).compareTo(new Float(((FloatConstant)otherConstant).getValue()));
+ result = Float.compare(floatConstant.getValue(),
+ ((FloatConstant)otherConstant).getValue());
}
public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
- {
- // In JDK 1.4, we can use Double.compare(a,b).
- result = new Double(doubleConstant.getValue()).compareTo(new Double(((DoubleConstant)otherConstant).getValue()));
+ {
+ result = Double.compare(doubleConstant.getValue(),
+ ((DoubleConstant)otherConstant).getValue());
}
public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
@@ -154,6 +163,38 @@ implements Comparable, ConstantVisitor
result = utf8Constant.getString().compareTo(((Utf8Constant)otherConstant).getString());
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ InvokeDynamicConstant otherInvokeDynamicConstant = (InvokeDynamicConstant)otherConstant;
+
+ int index = invokeDynamicConstant.getBootstrapMethodAttributeIndex();
+ int otherIndex = otherInvokeDynamicConstant.getBootstrapMethodAttributeIndex();
+
+ result = index < otherIndex ? -1 :
+ index > otherIndex ? 1 :
+ (invokeDynamicConstant.getName(clazz) + ' ' +
+ invokeDynamicConstant.getType(clazz))
+ .compareTo
+ (otherInvokeDynamicConstant.getName(clazz) + ' ' +
+ otherInvokeDynamicConstant.getType(clazz));
+ }
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ MethodHandleConstant otherMethodHandleConstant = (MethodHandleConstant)otherConstant;
+
+ int kind = methodHandleConstant.getReferenceKind();
+ int otherKind = methodHandleConstant.getReferenceKind();
+
+ result = kind < otherKind ? -1 :
+ kind > otherKind ? 1 :
+ (methodHandleConstant.getName(clazz) + ' ' +
+ methodHandleConstant.getType(clazz))
+ .compareTo
+ (otherMethodHandleConstant.getName(clazz) + ' ' +
+ otherMethodHandleConstant.getType(clazz));
+ }
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
RefConstant otherRefConstant = (RefConstant)otherConstant;
@@ -171,6 +212,14 @@ implements Comparable, ConstantVisitor
result = classConstant.getName(clazz).compareTo(((ClassConstant)otherConstant).getName(clazz));
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant MethodTypeConstant)
+ {
+ MethodTypeConstant otherMethodTypeConstant = (MethodTypeConstant)otherConstant;
+ result = MethodTypeConstant.getType(clazz)
+ .compareTo
+ (otherMethodTypeConstant.getType(clazz));
+ }
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
NameAndTypeConstant otherNameAndTypeConstant = (NameAndTypeConstant)otherConstant;
diff --git a/src/proguard/classfile/editor/ConstantAdder.java b/src/proguard/classfile/editor/ConstantAdder.java
index 2b74f5f..9d20199 100644
--- a/src/proguard/classfile/editor/ConstantAdder.java
+++ b/src/proguard/classfile/editor/ConstantAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,6 +23,7 @@ package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.util.ListUtil;
/**
* This ConstantVisitor adds all constants that it visits to the constant pool
@@ -128,6 +129,43 @@ implements ConstantVisitor
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // First add the name and type constant.
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+
+ // Copy the referenced classes.
+ Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses;
+ Clazz[] referencedClassesCopy = null;
+ if (referencedClasses != null)
+ {
+ referencedClassesCopy = new Clazz[referencedClasses.length];
+ System.arraycopy(referencedClasses, 0,
+ referencedClassesCopy, 0,
+ referencedClasses.length);
+ }
+
+ // Then add the actual invoke dynamic constant.
+ constantIndex =
+ constantPoolEditor.addInvokeDynamicConstant(invokeDynamicConstant.getBootstrapMethodAttributeIndex(),
+ constantIndex,
+ referencedClassesCopy);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // First add the field ref, interface method ref, or method ref
+ // constant.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+
+ // Then add the actual method handle constant.
+ constantIndex =
+ constantPoolEditor.addMethodHandleConstant(methodHandleConstant.getReferenceKind(),
+ constantIndex);
+ }
+
+
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
// First add the referenced class constant, with its own referenced class.
@@ -185,6 +223,13 @@ implements ConstantVisitor
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addMethodTypeConstant(methodTypeConstant.getType(clazz));
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
constantIndex =
diff --git a/src/proguard/classfile/editor/ConstantPoolEditor.java b/src/proguard/classfile/editor/ConstantPoolEditor.java
index 8663dee..7adbc44 100644
--- a/src/proguard/classfile/editor/ConstantPoolEditor.java
+++ b/src/proguard/classfile/editor/ConstantPoolEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -199,6 +199,93 @@ public class ConstantPoolEditor
/**
+ * Finds or creates a InvokeDynamicConstant constant pool entry with the
+ * given bootstrap method constant pool entry index, method name, and
+ * descriptor.
+ * @return the constant pool index of the InvokeDynamicConstant.
+ */
+ public int addInvokeDynamicConstant(int bootstrapMethodIndex,
+ String name,
+ String descriptor,
+ Clazz[] referencedClasses)
+ {
+ return addInvokeDynamicConstant(bootstrapMethodIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClasses);
+ }
+
+
+ /**
+ * Finds or creates a InvokeDynamicConstant constant pool entry with the given
+ * class constant pool entry index and name and type constant pool entry
+ * index.
+ * @return the constant pool index of the InvokeDynamicConstant.
+ */
+ public int addInvokeDynamicConstant(int bootstrapMethodIndex,
+ int nameAndTypeIndex,
+ Clazz[] referencedClasses)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_InvokeDynamic)
+ {
+ InvokeDynamicConstant invokeDynamicConstant = (InvokeDynamicConstant)constant;
+ if (invokeDynamicConstant.u2bootstrapMethodAttributeIndex == bootstrapMethodIndex &&
+ invokeDynamicConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new InvokeDynamicConstant(bootstrapMethodIndex,
+ nameAndTypeIndex,
+ referencedClasses));
+ }
+
+
+ /**
+ * Finds or creates a MethodHandleConstant constant pool entry of the
+ * specified kind and with the given field ref, interface method ref,
+ * or method ref constant pool entry index.
+ * @return the constant pool index of the MethodHandleConstant.
+ */
+ public int addMethodHandleConstant(int referenceKind,
+ int referenceIndex)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_MethodHandle)
+ {
+ MethodHandleConstant methodHandleConstant = (MethodHandleConstant)constant;
+ if (methodHandleConstant.u1referenceKind == referenceKind &&
+ methodHandleConstant.u2referenceIndex == referenceIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodHandleConstant(referenceKind,
+ referenceIndex));
+ }
+
+
+ /**
* Finds or creates a FieldrefConstant constant pool entry for the given
* class and field.
* @return the constant pool index of the FieldrefConstant.
@@ -563,6 +650,36 @@ public class ConstantPoolEditor
/**
+ * Finds or creates a MethodTypeConstant constant pool entry with the given
+ * type.
+ * @return the constant pool index of the MethodTypeConstant.
+ */
+ public int addMethodTypeConstant(String type)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_MethodType)
+ {
+ MethodTypeConstant methodTypeConstant = (MethodTypeConstant)constant;
+ if (methodTypeConstant.getType(targetClass).equals(type))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodTypeConstant(addUtf8Constant(type)));
+ }
+
+
+ /**
* Finds or creates a NameAndTypeConstant constant pool entry with the given
* name and type.
* @return the constant pool index of the NameAndTypeConstant.
diff --git a/src/proguard/classfile/editor/ConstantPoolRemapper.java b/src/proguard/classfile/editor/ConstantPoolRemapper.java
index 7430d3d..eaf7653 100644
--- a/src/proguard/classfile/editor/ConstantPoolRemapper.java
+++ b/src/proguard/classfile/editor/ConstantPoolRemapper.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -47,9 +47,10 @@ implements ClassVisitor,
ConstantVisitor,
MemberVisitor,
AttributeVisitor,
- InstructionVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
ExceptionInfoVisitor,
+ InstructionVisitor,
StackMapFrameVisitor,
VerificationTypeVisitor,
LocalVariableInfoVisitor,
@@ -57,7 +58,7 @@ implements ClassVisitor,
AnnotationVisitor,
ElementValueVisitor
{
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true);
private int[] constantIndexMap;
@@ -100,40 +101,66 @@ implements ClassVisitor,
// Implementations for ConstantVisitor.
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
{
- classConstant.u2nameIndex =
- remapConstantIndex(classConstant.u2nameIndex);
+ // Nothing to do.
}
- public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
{
// Nothing to do.
}
- public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
{
- fieldrefConstant.u2classIndex =
- remapConstantIndex(fieldrefConstant.u2classIndex);
- fieldrefConstant.u2nameAndTypeIndex =
- remapConstantIndex(fieldrefConstant.u2nameAndTypeIndex);
+ // Nothing to do.
}
- public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
{
// Nothing to do.
}
- public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ stringConstant.u2stringIndex =
+ remapConstantIndex(stringConstant.u2stringIndex);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
{
// Nothing to do.
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.u2nameAndTypeIndex =
+ remapConstantIndex(invokeDynamicConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ methodHandleConstant.u2referenceIndex =
+ remapConstantIndex(methodHandleConstant.u2referenceIndex);
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ fieldrefConstant.u2classIndex =
+ remapConstantIndex(fieldrefConstant.u2classIndex);
+ fieldrefConstant.u2nameAndTypeIndex =
+ remapConstantIndex(fieldrefConstant.u2nameAndTypeIndex);
+ }
+
+
public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
{
interfaceMethodrefConstant.u2classIndex =
@@ -143,12 +170,6 @@ implements ClassVisitor,
}
- public void visitLongConstant(Clazz clazz, LongConstant longConstant)
- {
- // Nothing to do.
- }
-
-
public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
{
methodrefConstant.u2classIndex =
@@ -158,25 +179,26 @@ implements ClassVisitor,
}
- public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
- nameAndTypeConstant.u2nameIndex =
- remapConstantIndex(nameAndTypeConstant.u2nameIndex);
- nameAndTypeConstant.u2descriptorIndex =
- remapConstantIndex(nameAndTypeConstant.u2descriptorIndex);
+ classConstant.u2nameIndex =
+ remapConstantIndex(classConstant.u2nameIndex);
}
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
{
- stringConstant.u2stringIndex =
- remapConstantIndex(stringConstant.u2stringIndex);
+ methodTypeConstant.u2descriptorIndex =
+ remapConstantIndex(methodTypeConstant.u2descriptorIndex);
}
- public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
- // Nothing to do.
+ nameAndTypeConstant.u2nameIndex =
+ remapConstantIndex(nameAndTypeConstant.u2nameIndex);
+ nameAndTypeConstant.u2descriptorIndex =
+ remapConstantIndex(nameAndTypeConstant.u2descriptorIndex);
}
@@ -230,6 +252,16 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ bootstrapMethodsAttribute.u2attributeNameIndex =
+ remapConstantIndex(bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the bootstrap method entries.
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
sourceFileAttribute.u2attributeNameIndex =
@@ -410,6 +442,19 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ bootstrapMethodInfo.u2methodHandleIndex =
+ remapConstantIndex(bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Remap the constant pool references of the bootstrap methods..
+ remapConstantIndexArray(bootstrapMethodInfo.u2methodArguments,
+ bootstrapMethodInfo.u2methodArgumentCount);
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
@@ -461,7 +506,7 @@ implements ClassVisitor,
Instruction replacementInstruction =
new ConstantInstruction(constantInstruction.opcode,
newConstantIndex,
- constantInstruction.constant).shrink();
+ constantInstruction.constant);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
}
diff --git a/src/proguard/classfile/editor/ConstantPoolShrinker.java b/src/proguard/classfile/editor/ConstantPoolShrinker.java
new file mode 100644
index 0000000..ee309a0
--- /dev/null
+++ b/src/proguard/classfile/editor/ConstantPoolShrinker.java
@@ -0,0 +1,578 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor removes all unused entries from the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantPoolShrinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor,
+ InstructionVisitor
+{
+ // A visitor info flag to indicate the constant is being used.
+ private static final Object USED = new Object();
+
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Mark this class's name.
+ markConstant(programClass, programClass.u2thisClass);
+
+ // Mark the superclass class constant.
+ programClass.superClassConstantAccept(this);
+
+ // Mark the interface class constants.
+ programClass.interfaceConstantsAccept(this);
+
+ // Mark the constants referenced by the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Mark the attributes.
+ programClass.attributesAccept(this);
+
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Mark the name and descriptor.
+ markConstant(programClass, programMember.u2nameIndex);
+ markConstant(programClass, programMember.u2descriptorIndex);
+
+ // Mark the attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ markAsUsed(constant);
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ markAsUsed(stringConstant);
+
+ markConstant(clazz, stringConstant.u2stringIndex);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ markAsUsed(invokeDynamicConstant);
+
+ markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
+
+ // Mark the bootstrap methods attribute.
+ clazz.attributesAccept(this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ markAsUsed(methodHandleConstant);
+
+ markConstant(clazz, methodHandleConstant.u2referenceIndex);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ markAsUsed(refConstant);
+
+ markConstant(clazz, refConstant.u2classIndex);
+ markConstant(clazz, refConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ markAsUsed(classConstant);
+
+ markConstant(clazz, classConstant.u2nameIndex);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ markAsUsed(methodTypeConstant);
+
+ markConstant(clazz, methodTypeConstant.u2descriptorIndex);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ markAsUsed(nameAndTypeConstant);
+
+ markConstant(clazz, nameAndTypeConstant.u2nameIndex);
+ markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ markConstant(clazz, attribute.u2attributeNameIndex);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ // Mark the bootstrap method entries.
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ markConstant(clazz, innerClassesAttribute.u2attributeNameIndex);
+
+ // Mark the outer class entries.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
+ markConstant(clazz, enclosingMethodAttribute.u2classIndex);
+
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ markConstant(clazz, signatureAttribute.u2signatureIndex);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
+ markConstant(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the exceptions.
+ exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ markConstant(clazz, codeAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the instructions,
+ // by the exceptions, and by the attributes.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ markConstant(clazz, stackMapAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Mark the constant pool entries referenced by the arguments.
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+ innerClassesInfo.outerClassConstantAccept(clazz, this);
+ innerClassesInfo.innerNameConstantAccept(clazz, this);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (exceptionInfo.u2catchType != 0)
+ {
+ markConstant(clazz, exceptionInfo.u2catchType);
+ }
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ markConstant(clazz, objectType.u2classIndex);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ markConstant(clazz, localVariableInfo.u2nameIndex);
+ markConstant(clazz, localVariableInfo.u2descriptorIndex);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ markConstant(clazz, localVariableTypeInfo.u2nameIndex);
+ markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ markConstant(clazz, annotation.u2typeIndex);
+
+ // Mark the constant pool entries referenced by the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ if (constantElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, constantElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, constantElementValue.u2constantValueIndex);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ if (enumConstantElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
+ markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ if (classElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, classElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, classElementValue.u2classInfoIndex);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ if (annotationElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, annotationElementValue.u2elementNameIndex);
+ }
+
+ // Mark the constant pool entries referenced by the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ if (arrayElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, arrayElementValue.u2elementNameIndex);
+ }
+
+ // Mark the constant pool entries referenced by the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ markConstant(clazz, constantInstruction.constantIndex);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * 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);
+ }
+
+
+ /**
+ * Marks the given visitor accepter as being used.
+ */
+ private void markAsUsed(Constant constant)
+ {
+ constant.setVisitorInfo(USED);
+ }
+
+
+ /**
+ * Returns whether the given visitor accepter has been marked as being used.
+ */
+ private boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == USED;
+ }
+
+
+ /**
+ * Removes all constants that are not marked as being used from the given
+ * constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ constantIndexMap[index] = counter;
+
+ Constant constant = constantPool[index];
+
+ // Don't update the flag if this is the second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ constantPool[counter++] = constant;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
+}
diff --git a/src/proguard/classfile/editor/ConstantPoolSorter.java b/src/proguard/classfile/editor/ConstantPoolSorter.java
index faae318..b578624 100644
--- a/src/proguard/classfile/editor/ConstantPoolSorter.java
+++ b/src/proguard/classfile/editor/ConstantPoolSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -112,10 +112,7 @@ implements ClassVisitor
System.arraycopy(newConstantPool, 0, programClass.constantPool, 0, newLength);
// Clear any remaining entries.
- for (int index = newLength; index < constantPoolCount; index++)
- {
- programClass.constantPool[index] = null;
- }
+ Arrays.fill(programClass.constantPool, newLength, constantPoolCount, null);
programClass.u2constantPoolCount = newLength;
diff --git a/src/proguard/classfile/editor/ElementValueAdder.java b/src/proguard/classfile/editor/ElementValueAdder.java
index 8cbd11d..9c8b3f9 100644
--- a/src/proguard/classfile/editor/ElementValueAdder.java
+++ b/src/proguard/classfile/editor/ElementValueAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ElementValuesEditor.java b/src/proguard/classfile/editor/ElementValuesEditor.java
index bfc4e9f..57671e6 100644
--- a/src/proguard/classfile/editor/ElementValuesEditor.java
+++ b/src/proguard/classfile/editor/ElementValuesEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/editor/ExceptionAdder.java
index 1ccb1a6..152a065 100644
--- a/src/proguard/classfile/editor/ExceptionAdder.java
+++ b/src/proguard/classfile/editor/ExceptionAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ExceptionInfoAdder.java b/src/proguard/classfile/editor/ExceptionInfoAdder.java
index e0cc9c5..c1c20fa 100644
--- a/src/proguard/classfile/editor/ExceptionInfoAdder.java
+++ b/src/proguard/classfile/editor/ExceptionInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ExceptionsAttributeEditor.java b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
index 4509a9a..98bb79e 100644
--- a/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
+++ b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/InnerClassesAccessFixer.java b/src/proguard/classfile/editor/InnerClassesAccessFixer.java
new file mode 100644
index 0000000..5a5e8a5
--- /dev/null
+++ b/src/proguard/classfile/editor/InnerClassesAccessFixer.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.InnerClassesInfoVisitor;
+import proguard.classfile.attribute.InnerClassesInfo;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This InnerClassesInfoVisitor fixes the inner class access flags of the
+ * inner classes information that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InnerClassesAccessFixer
+extends SimplifiedVisitor
+implements InnerClassesInfoVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ private int innerClassAccessFlags;
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // The current access flags are the default.
+ innerClassAccessFlags = innerClassesInfo.u2innerClassAccessFlags;
+
+ // See if we can find new access flags.
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+
+ // Update the access flags.
+ innerClassesInfo.u2innerClassAccessFlags = innerClassAccessFlags;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ innerClassAccessFlags =
+ AccessUtil.replaceAccessFlags(innerClassAccessFlags,
+ programClass.u2accessFlags);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/editor/InstructionAdder.java b/src/proguard/classfile/editor/InstructionAdder.java
index 60fde6d..422a348 100644
--- a/src/proguard/classfile/editor/InstructionAdder.java
+++ b/src/proguard/classfile/editor/InstructionAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -68,7 +68,7 @@ implements InstructionVisitor
Instruction newConstantInstruction =
new ConstantInstruction(constantInstruction.opcode,
constantAdder.addConstant(clazz, constantInstruction.constantIndex),
- constantInstruction.constant).shrink();
+ constantInstruction.constant);
// Add the instruction.
codeAttributeComposer.appendInstruction(offset, newConstantInstruction);
diff --git a/src/proguard/classfile/editor/InstructionWriter.java b/src/proguard/classfile/editor/InstructionWriter.java
index d842358..c4a9b09 100644
--- a/src/proguard/classfile/editor/InstructionWriter.java
+++ b/src/proguard/classfile/editor/InstructionWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,7 +31,7 @@ import proguard.classfile.util.SimplifiedVisitor;
* This InstructionVisitor writes out the instructions that it visits,
* collecting instructions that have to be widened. As an AttributeVisitor,
* it then applies the collected changes. The process will be repeated
- * recursively, if necessary.
+ * recursively, if necessary. The caller still has to update the frame sizes.
*
* @author Eric Lafortune
*/
@@ -40,20 +40,26 @@ extends SimplifiedVisitor
implements InstructionVisitor,
AttributeVisitor
{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = false;
+ //*/
+
+
private int codeLength;
private CodeAttributeEditor codeAttributeEditor;
/**
- * Resets the accumulated code changes.
+ * Resets the accumulated code.
* @param codeLength the length of the code that will be edited next.
*/
public void reset(int codeLength)
{
this.codeLength = codeLength;
- // The code attribute editor has to be created lazily.
if (codeAttributeEditor != null)
{
codeAttributeEditor.reset(codeLength);
@@ -61,6 +67,21 @@ implements InstructionVisitor,
}
+ /**
+ * Extends the size of the accumulated code.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void extend(int codeLength)
+ {
+ this.codeLength = codeLength;
+
+ if (codeAttributeEditor != null)
+ {
+ codeAttributeEditor.extend(codeLength);
+ }
+ }
+
+
// Implementations for InstructionVisitor.
public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
@@ -84,7 +105,12 @@ implements InstructionVisitor,
Instruction replacementInstruction =
new ConstantInstruction(constantInstruction.opcode,
constantInstruction.constantIndex,
- constantInstruction.constant).shrink();
+ constantInstruction.constant);
+
+ if (DEBUG)
+ {
+ System.out.println(" "+constantInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
replaceInstruction(offset, replacementInstruction);
@@ -109,10 +135,15 @@ implements InstructionVisitor,
Instruction replacementInstruction =
new VariableInstruction(variableInstruction.opcode,
variableInstruction.variableIndex,
- variableInstruction.constant).shrink();
+ variableInstruction.constant);
replaceInstruction(offset, replacementInstruction);
+ if (DEBUG)
+ {
+ System.out.println(" "+variableInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
+
// Write out a dummy variable instruction for now.
variableInstruction.variableIndex = 0;
variableInstruction.constant = 0;
@@ -143,7 +174,7 @@ implements InstructionVisitor,
// Create a new branch instruction that will fit.
replacementInstruction =
new BranchInstruction(branchInstruction.opcode,
- branchInstruction.branchOffset).shrink();
+ branchInstruction.branchOffset);
break;
}
@@ -190,6 +221,11 @@ implements InstructionVisitor,
}
}
+ if (DEBUG)
+ {
+ System.out.println(" "+branchInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
+
replaceInstruction(offset, replacementInstruction);
// Write out a dummy branch instruction for now.
@@ -214,10 +250,16 @@ implements InstructionVisitor,
// Avoid doing any work if nothing is changing anyway.
if (codeAttributeEditor != null)
{
+ if (DEBUG)
+ {
+ System.out.println("InstructionWriter: widening instructions in "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
// Apply the collected expansions.
codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
- // Clear the modifications for the next run.
+ // Don't keep the editor around. We're assuming it won't be needed
+ // very often, so we don't want to be resetting it all the time.
codeAttributeEditor = null;
}
}
@@ -271,7 +313,7 @@ implements InstructionVisitor,
{
if (codeAttributeEditor == null)
{
- codeAttributeEditor = new CodeAttributeEditor();
+ codeAttributeEditor = new CodeAttributeEditor(false, true);
codeAttributeEditor.reset(codeLength);
}
}
diff --git a/src/proguard/classfile/editor/InterfaceAdder.java b/src/proguard/classfile/editor/InterfaceAdder.java
index e095af6..1ad67dc 100644
--- a/src/proguard/classfile/editor/InterfaceAdder.java
+++ b/src/proguard/classfile/editor/InterfaceAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/InterfaceSorter.java b/src/proguard/classfile/editor/InterfaceSorter.java
index 6521369..0d1f28c 100644
--- a/src/proguard/classfile/editor/InterfaceSorter.java
+++ b/src/proguard/classfile/editor/InterfaceSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,10 +21,14 @@
package proguard.classfile.editor;
import proguard.classfile.*;
-import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.ClassVisitor;
-import java.util.Arrays;
+import java.util.*;
/**
* This ClassVisitor sorts the interfaces of the program classes that it visits.
@@ -33,7 +37,8 @@ import java.util.Arrays;
*/
public class InterfaceSorter
extends SimplifiedVisitor
-implements ClassVisitor
+implements ClassVisitor,
+ AttributeVisitor
{
// Implementations for ClassVisitor.
@@ -42,26 +47,106 @@ implements ClassVisitor
int[] interfaces = programClass.u2interfaces;
int interfacesCount = programClass.u2interfacesCount;
- // Sort the interfaces.
- Arrays.sort(interfaces, 0, interfacesCount);
+ 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);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ 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);
- // Remove any duplicate entries.
- int newInterfacesCount = 0;
- int previousInterfaceIndex = 0;
- for (int index = 0; index < interfacesCount; index++)
+ int count = 0;
+ int interfacesCount = -1;
+ while (internalTypeEnumeration.hasMoreTypes())
{
- int interfaceIndex = interfaces[index];
+ String internalType = internalTypeEnumeration.nextType();
- // Isn't this a duplicate of the previous interface?
- if (interfaceIndex != previousInterfaceIndex)
+ count++;
+
+ if (ClassUtil.isInternalClassType(internalType))
{
- interfaces[newInterfacesCount++] = interfaceIndex;
+ 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;
+ }
- // Remember the interface.
- previousInterfaceIndex = interfaceIndex;
+ // 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]);
}
}
- programClass.u2interfacesCount = newInterfacesCount;
+ 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;
+ }
}
}
diff --git a/src/proguard/classfile/editor/InterfacesEditor.java b/src/proguard/classfile/editor/InterfacesEditor.java
index d3170e1..8765e36 100644
--- a/src/proguard/classfile/editor/InterfacesEditor.java
+++ b/src/proguard/classfile/editor/InterfacesEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LineNumberInfoAdder.java b/src/proguard/classfile/editor/LineNumberInfoAdder.java
index aa8c0c4..e1bd14a 100644
--- a/src/proguard/classfile/editor/LineNumberInfoAdder.java
+++ b/src/proguard/classfile/editor/LineNumberInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
index ab96b38..f712d46 100644
--- a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
+++ b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableInfoAdder.java b/src/proguard/classfile/editor/LocalVariableInfoAdder.java
index f285e4f..a270fcf 100644
--- a/src/proguard/classfile/editor/LocalVariableInfoAdder.java
+++ b/src/proguard/classfile/editor/LocalVariableInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
index 053b628..b9e601f 100644
--- a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
+++ b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
index ca50f3f..bed1366 100644
--- a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
+++ b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
index fe5a64d..00f7ef3 100644
--- a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
+++ b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java
index 5f939bb..811acae 100644
--- a/src/proguard/classfile/editor/MemberAdder.java
+++ b/src/proguard/classfile/editor/MemberAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,8 +26,9 @@ import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.MemberVisitor;
/**
- * This ConstantVisitor adds all class members that it visits to the given
- * target class.
+ * This MemberVisitor copies all class members that it visits to the given
+ * target class. Their visitor info is set to the class members from which they
+ * were copied.
*
* @author Eric Lafortune
*/
@@ -45,8 +46,9 @@ implements MemberVisitor
private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0];
- private final ProgramClass targetClass;
-// private final boolean addFields;
+ private final ProgramClass targetClass;
+// private final boolean addFields;
+ private final MemberVisitor extraMemberVisitor;
private final ConstantAdder constantAdder;
private final ClassEditor classEditor;
@@ -59,13 +61,30 @@ implements MemberVisitor
* @param targetClass the class to which all visited class members will be
* added.
*/
+ public MemberAdder(ProgramClass targetClass)
+ {
+ this(targetClass, null);
+ }
+
+
+ /**
+ * Creates a new MemberAdder that will copy methods into the given target
+ * class.
+ * @param targetClass the class to which all visited class members
+ * will be added.
+ * @param extraMemberVisitor an optional member visitor that visits each
+ * new member right after it has been added. This
+ * allows changing the visitor info, for instance.
+ */
// * @param addFields specifies whether fields should be added, or fused
// * with the present fields.
- public MemberAdder(ProgramClass targetClass)//),
-// boolean addFields)
+ public MemberAdder(ProgramClass targetClass,
+// boolean addFields,
+ MemberVisitor extraMemberVisitor)
{
- this.targetClass = targetClass;
-// this.addFields = addFields;
+ this.targetClass = targetClass;
+// this.addFields = addFields;
+ this.extraMemberVisitor = extraMemberVisitor;
constantAdder = new ConstantAdder(targetClass);
classEditor = new ClassEditor(targetClass);
@@ -77,51 +96,54 @@ implements MemberVisitor
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- String name = programField.getName(programClass);
- String descriptor = programField.getDescriptor(programClass);
+ //String name = programField.getName(programClass);
+ //String descriptor = programField.getDescriptor(programClass);
int accessFlags = programField.getAccessFlags();
- // Does the target class already have such a field?
- ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
- if (targetField != null)
- {
- // Is the field private or static?
- int targetAccessFlags = targetField.getAccessFlags();
- if ((targetAccessFlags &
- (ClassConstants.INTERNAL_ACC_PRIVATE |
- ClassConstants.INTERNAL_ACC_STATIC)) != 0)
- {
- if (DEBUG)
- {
- System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]");
- }
-
- // Rename the private or static field.
- targetField.u2nameIndex =
- constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName()));
- }
-// else
-// {
-// // Keep the non-private and non-static field, but update its
-// // contents, in order to keep any references to it valid.
-// if (DEBUG)
-// {
-// System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
-// }
-//
-// // Combine the access flags.
-// targetField.u2accessFlags = accessFlags | targetAccessFlags;
-//
-// // Add and replace any attributes.
-// programField.attributesAccept(programClass,
-// new AttributeAdder(targetClass,
-// targetField,
-// true));
-//
-// // Don't add a new field.
-// return;
-// }
- }
+ // TODO: Handle field with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical field
+ // still causes confused field references.
+ //// Does the target class already have such a field?
+ //ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
+ //if (targetField != null)
+ //{
+ // // Is the field private or static?
+ // int targetAccessFlags = targetField.getAccessFlags();
+ // if ((targetAccessFlags &
+ // (ClassConstants.INTERNAL_ACC_PRIVATE |
+ // ClassConstants.INTERNAL_ACC_STATIC)) != 0)
+ // {
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]");
+ // }
+ //
+ // // Rename the private or static field.
+ // targetField.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName()));
+ // }
+ // else
+ // {
+ // // Keep the non-private and non-static field, but update its
+ // // contents, in order to keep any references to it valid.
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ // }
+ //
+ // // Combine the access flags.
+ // targetField.u2accessFlags = accessFlags | targetAccessFlags;
+ //
+ // // Add and replace any attributes.
+ // programField.attributesAccept(programClass,
+ // new AttributeAdder(targetClass,
+ // targetField,
+ // true));
+ //
+ // // Don't add a new field.
+ // return;
+ // }
+ //}
if (DEBUG)
{
@@ -150,6 +172,12 @@ implements MemberVisitor
// Add the completed field.
classEditor.addField(newProgramField);
+
+ // Visit the newly added field, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramField(targetClass, newProgramField);
+ }
}
@@ -206,9 +234,12 @@ implements MemberVisitor
System.out.println("MemberAdder: renaming method ["+targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
}
- // Rename the private (non-abstract) or static method.
- targetMethod.u2nameIndex =
- constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
+ // TODO: Handle non-abstract method with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical method
+ // still causes confused method references.
+ //// Rename the private (non-abstract) or static method.
+ //targetMethod.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
}
if (DEBUG)
@@ -240,6 +271,12 @@ implements MemberVisitor
// Add the completed method.
classEditor.addMethod(newProgramMethod);
+
+ // Visit the newly added method, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramMethod(targetClass, newProgramMethod);
+ }
}
diff --git a/src/proguard/classfile/editor/MemberReferenceFixer.java b/src/proguard/classfile/editor/MemberReferenceFixer.java
index 4bd8af5..b623047 100644
--- a/src/proguard/classfile/editor/MemberReferenceFixer.java
+++ b/src/proguard/classfile/editor/MemberReferenceFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -298,22 +298,17 @@ implements ClassVisitor,
{
Clazz referencedClass = enclosingMethodAttribute.referencedClass;
- // Does it have a new class?
- if (!enclosingMethodAttribute.getClassName(clazz).equals(referencedClass.getName()))
- {
- // Update the class index.
- enclosingMethodAttribute.u2classIndex =
- new ConstantPoolEditor((ProgramClass)clazz).addClassConstant(referencedClass);
- }
-
// Does it have a new name or type?
- if (!enclosingMethodAttribute.getName(clazz).equals(referencedMember.getName(referencedClass)) ||
- !enclosingMethodAttribute.getType(clazz).equals(referencedMember.getDescriptor(referencedClass)))
+ String newName = referencedMember.getName(referencedClass);
+ String newType = referencedMember.getDescriptor(referencedClass);
+
+ if (!enclosingMethodAttribute.getName(clazz).equals(newName) ||
+ !enclosingMethodAttribute.getType(clazz).equals(newType))
{
// Update the name and type index.
enclosingMethodAttribute.u2nameAndTypeIndex =
- new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(referencedMember.getName(referencedClass),
- referencedMember.getDescriptor(referencedClass));
+ new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName,
+ newType);
}
}
}
@@ -324,7 +319,7 @@ implements ClassVisitor,
// Recompute the maximum stack size if necessary.
if (stackSizesMayHaveChanged)
{
- stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+ stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
}
// Fix the nested attributes.
@@ -433,10 +428,9 @@ implements ClassVisitor,
Member referencedMember)
{
System.out.println("MemberReferenceFixer:");
- System.out.println(" Class file = "+clazz.getName());
- System.out.println(" Ref class = "+referencedClass.getName());
- System.out.println(" Ref member name = "+stringConstant.getString(clazz));
- System.out.println(" -> "+referencedMember.getName(referencedClass));
+ System.out.println(" ["+clazz.getName()+"]: String ["+
+ stringConstant.getString(clazz)+"] -> ["+
+ referencedClass.getName()+"."+referencedMember.getName(referencedClass)+" "+referencedMember.getDescriptor(referencedClass)+"]");
}
@@ -446,11 +440,8 @@ implements ClassVisitor,
Member referencedMember)
{
System.out.println("MemberReferenceFixer:");
- System.out.println(" Class file = "+clazz.getName());
- System.out.println(" Ref class = "+referencedClass.getName());
- System.out.println(" Ref member name = "+refConstant.getName(clazz));
- System.out.println(" -> "+referencedMember.getName(referencedClass));
- System.out.println(" Ref descriptor = "+refConstant.getType(clazz));
- System.out.println(" -> "+referencedMember.getDescriptor(referencedClass));
+ System.out.println(" ["+clazz.getName()+"]: ["+
+ refConstant.getClassName(clazz)+"."+refConstant.getName(clazz)+" "+refConstant.getType(clazz)+"] -> ["+
+ referencedClass.getName()+"."+referencedMember.getName(referencedClass)+" "+referencedMember.getDescriptor(referencedClass)+"]");
}
}
diff --git a/src/proguard/classfile/editor/MethodInvocationFixer.java b/src/proguard/classfile/editor/MethodInvocationFixer.java
index ef76012..e457e63 100644
--- a/src/proguard/classfile/editor/MethodInvocationFixer.java
+++ b/src/proguard/classfile/editor/MethodInvocationFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,6 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
-import proguard.classfile.visitor.*;
/**
* This AttributeVisitor fixes all inappropriate special/virtual/static/interface
@@ -40,9 +39,7 @@ public class MethodInvocationFixer
extends SimplifiedVisitor
implements AttributeVisitor,
InstructionVisitor,
- ConstantVisitor,
- ClassVisitor,
- MemberVisitor
+ ConstantVisitor
{
private static final boolean DEBUG = false;
@@ -88,7 +85,8 @@ implements AttributeVisitor,
clazz.constantPoolEntryAccept(constantIndex, this);
// Did we find the called class and method?
- if (referencedMethod != null)
+ if (referencedClass != null &&
+ referencedMethod != null)
{
// Do we need to update the opcode?
byte opcode = constantInstruction.opcode;
@@ -102,7 +100,7 @@ implements AttributeVisitor,
// Replace the invocation by an invokestatic instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
- constantIndex).shrink();
+ constantIndex);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -123,7 +121,7 @@ implements AttributeVisitor,
// Replace the invocation by an invokespecial instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL,
- constantIndex).shrink();
+ constantIndex);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -149,7 +147,7 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKEINTERFACE,
constantIndex,
- invokeinterfaceConstant).shrink();
+ invokeinterfaceConstant);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -168,12 +166,13 @@ implements AttributeVisitor,
// but not a super call)?
if (opcode != InstructionConstants.OP_INVOKEVIRTUAL &&
(opcode != InstructionConstants.OP_INVOKESPECIAL ||
+ clazz.equals(referencedClass) ||
!clazz.extends_(referencedClass)))
{
// Replace the invocation by an invokevirtual instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL,
- constantIndex).shrink();
+ constantIndex);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -194,40 +193,30 @@ implements AttributeVisitor,
public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
{
- // Check if this is an interface method. Note that we're interested in
- // the class of the method reference, not in the class in which the
- // method was actually found.
- //refConstant.referencedClassAccept(this);
- clazz.constantPoolEntryAccept(refConstant.u2classIndex, this);
-
- // Get the referenced access flags and names.
- refConstant.referencedMemberAccept(this);
- }
-
+ // Remember the referenced class. Note that we're interested in the
+ // class of the method reference, not in the class in which the
+ // method was actually found, unless it is an array type.
+ //
+ if (ClassUtil.isInternalArrayType(refConstant.getClassName(clazz)))
+ {
+ // For an array type, the class will be java.lang.Object.
+ referencedClass = refConstant.referencedClass;
+ }
+ else
+ {
+ clazz.constantPoolEntryAccept(refConstant.u2classIndex, this);
+ }
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
- {
- // Check if this is an interface class.
- classConstant.referencedClassAccept(this);
+ // Remember the referenced method.
+ referencedMethodClass = refConstant.referencedClass;
+ referencedMethod = refConstant.referencedMember;
}
- // Implementations for ClassVisitor.
-
- public void visitAnyClass(Clazz clazz)
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
// Remember the referenced class.
- referencedClass = clazz;
- }
-
-
- // Implementations for MemberVisitor.
-
- public void visitAnyMember(Clazz clazz, Member member)
- {
- // Remember the referenced method.
- referencedMethodClass = clazz;
- referencedMethod = member;
+ referencedClass = classConstant.referencedClass;
}
diff --git a/src/proguard/obfuscate/NameAndTypeUsageMarker.java b/src/proguard/classfile/editor/NameAndTypeShrinker.java
index cc779f0..650f9ba 100644
--- a/src/proguard/obfuscate/NameAndTypeUsageMarker.java
+++ b/src/proguard/classfile/editor/NameAndTypeShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,25 +18,27 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package proguard.obfuscate;
+package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.ConstantPoolRemapper;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
+import java.util.Arrays;
+
+
/**
- * This ClassVisitor marks all NameAndType constant pool entries that are
- * being used in the program classes it visits.
- *
- * @see NameAndTypeShrinker
+ * This ClassVisitor removes NameAndType constant pool entries that are not
+ * used.
*
* @author Eric Lafortune
*/
-public class NameAndTypeUsageMarker
+public class NameAndTypeShrinker
extends SimplifiedVisitor
implements ClassVisitor,
ConstantVisitor,
@@ -45,6 +47,9 @@ implements ClassVisitor,
// A visitor info flag to indicate the NameAndType constant pool entry is being used.
private static final Object USED = new Object();
+ private int[] constantIndexMap;
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
// Implementations for ClassVisitor.
@@ -57,33 +62,37 @@ implements ClassVisitor,
// Mark the NameAndType entries referenced by all EnclosingMethod
// attributes.
programClass.attributesAccept(this);
- }
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
- // Implementations for ConstantVisitor.
-
- public void visitAnyConstant(Clazz clazz, Constant constant) {}
-
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
- public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
- {
- visitRefConstant(clazz, fieldrefConstant);
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
}
- public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
- {
- visitRefConstant(clazz, interfaceMethodrefConstant);
- }
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
- public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
{
- visitRefConstant(clazz, methodrefConstant);
+ markNameAndTypeConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
}
- private void visitRefConstant(Clazz clazz, RefConstant refConstant)
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
markNameAndTypeConstant(clazz, refConstant.u2nameAndTypeIndex);
}
@@ -118,7 +127,7 @@ implements ClassVisitor,
* Marks the given VisitorAccepter as being used.
* In this context, the VisitorAccepter will be a NameAndTypeConstant object.
*/
- private static void markAsUsed(VisitorAccepter visitorAccepter)
+ private void markAsUsed(VisitorAccepter visitorAccepter)
{
visitorAccepter.setVisitorInfo(USED);
}
@@ -128,8 +137,52 @@ implements ClassVisitor,
* Returns whether the given VisitorAccepter has been marked as being used.
* In this context, the VisitorAccepter will be a NameAndTypeConstant object.
*/
- static boolean isUsed(VisitorAccepter visitorAccepter)
+ private boolean isUsed(VisitorAccepter visitorAccepter)
{
return visitorAccepter.getVisitorInfo() == USED;
}
+
+
+ /**
+ * Removes all NameAndType entries that are not marked as being used
+ * from the given constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap == null ||
+ constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ constantIndexMap[index] = counter;
+
+ Constant constant = constantPool[index];
+
+ // Don't update the flag if this is the second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType ||
+ isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ constantPool[counter++] = constant;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
}
diff --git a/src/proguard/classfile/editor/NamedAttributeDeleter.java b/src/proguard/classfile/editor/NamedAttributeDeleter.java
index 0c4d339..6aa5cdf 100644
--- a/src/proguard/classfile/editor/NamedAttributeDeleter.java
+++ b/src/proguard/classfile/editor/NamedAttributeDeleter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
index 4cad6b8..232747f 100644
--- a/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
+++ b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/StackSizeUpdater.java b/src/proguard/classfile/editor/StackSizeUpdater.java
index 94e0519..d90b3d0 100644
--- a/src/proguard/classfile/editor/StackSizeUpdater.java
+++ b/src/proguard/classfile/editor/StackSizeUpdater.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/SubclassAdder.java b/src/proguard/classfile/editor/SubclassAdder.java
index 6b9fd64..717bb1c 100644
--- a/src/proguard/classfile/editor/SubclassAdder.java
+++ b/src/proguard/classfile/editor/SubclassAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/SubclassToAdder.java b/src/proguard/classfile/editor/SubclassToAdder.java
index deb242f..109152b 100644
--- a/src/proguard/classfile/editor/SubclassToAdder.java
+++ b/src/proguard/classfile/editor/SubclassToAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Utf8UsageMarker.java b/src/proguard/classfile/editor/Utf8Shrinker.java
index c59ebb8..eda5826 100644
--- a/src/proguard/obfuscate/Utf8UsageMarker.java
+++ b/src/proguard/classfile/editor/Utf8Shrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,7 +18,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package proguard.obfuscate;
+package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
@@ -28,18 +28,19 @@ import proguard.classfile.attribute.preverification.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.ConstantPoolRemapper;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.*;
+import java.util.Arrays;
+
+
/**
- * This ClassVisitor marks all UTF-8 constant pool entries that are
- * being used in the program classes it visits.
- *
- * @see Utf8Shrinker
+ * This ClassVisitor removes UTF-8 constant pool entries that are not used.
*
* @author Eric Lafortune
*/
-public class Utf8UsageMarker
+public class Utf8Shrinker
extends SimplifiedVisitor
implements ClassVisitor,
MemberVisitor,
@@ -54,6 +55,9 @@ implements ClassVisitor,
// A visitor info flag to indicate the UTF-8 constant pool entry is being used.
private static final Object USED = new Object();
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
// Implementations for ClassVisitor.
@@ -68,6 +72,22 @@ implements ClassVisitor,
// Mark the UTF-8 entries referenced by the attributes.
programClass.attributesAccept(this);
+
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
}
@@ -375,7 +395,7 @@ implements ClassVisitor,
* Marks the given VisitorAccepter as being used.
* In this context, the VisitorAccepter will be a Utf8Constant object.
*/
- private static void markAsUsed(VisitorAccepter visitorAccepter)
+ private void markAsUsed(VisitorAccepter visitorAccepter)
{
visitorAccepter.setVisitorInfo(USED);
}
@@ -385,8 +405,51 @@ implements ClassVisitor,
* Returns whether the given VisitorAccepter has been marked as being used.
* In this context, the VisitorAccepter will be a Utf8Constant object.
*/
- static boolean isUsed(VisitorAccepter visitorAccepter)
+ private boolean isUsed(VisitorAccepter visitorAccepter)
{
return visitorAccepter.getVisitorInfo() == USED;
}
+
+
+ /**
+ * Removes all UTF-8 entries that are not marked as being used
+ * from the given constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ constantIndexMap[index] = counter;
+
+ Constant constant = constantPool[index];
+
+ // Don't update the flag if this is the second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 ||
+ isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ constantPool[counter++] = constant;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
}
diff --git a/src/proguard/classfile/editor/VariableCleaner.java b/src/proguard/classfile/editor/VariableCleaner.java
index 1e93c15..63b7d4a 100644
--- a/src/proguard/classfile/editor/VariableCleaner.java
+++ b/src/proguard/classfile/editor/VariableCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,15 +22,15 @@ package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
-import proguard.classfile.attribute.visitor.*;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.optimize.info.VariableUsageMarker;
+
+import java.util.Arrays;
/**
- * This AttributeVisitor cleans up unused variables in all attributes that it
- * visits.
+ * This AttributeVisitor cleans up variable tables in all code attributes that
+ * it visits. It trims overlapping local variables. It removes empty local
+ * variables and empty local variable tables.
*
* @author Eric Lafortune
*/
@@ -38,7 +38,8 @@ public class VariableCleaner
extends SimplifiedVisitor
implements AttributeVisitor
{
- private final VariableUsageMarker variableUsageMarker = new VariableUsageMarker();
+ private boolean deleteLocalVariableTableAttribute;
+ private boolean deleteLocalVariableTypeTableAttribute;
// Implementations for AttributeVisitor.
@@ -48,11 +49,35 @@ implements AttributeVisitor
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
- // Figure out the local variables that are used by the code.
- variableUsageMarker.visitCodeAttribute(clazz, method, codeAttribute);
+ deleteLocalVariableTableAttribute = false;
+ deleteLocalVariableTypeTableAttribute = false;
- // Clean up the variables of the attributes.
+ // Trim the local variable table and the local variable type table.
codeAttribute.attributesAccept(clazz, method, this);
+
+ // Delete the local variable table if it ended up empty.
+ if (deleteLocalVariableTableAttribute)
+ {
+ AttributesEditor editor =
+ new AttributesEditor((ProgramClass)clazz,
+ (ProgramMember)method,
+ codeAttribute,
+ true);
+
+ editor.deleteAttribute(ClassConstants.ATTR_LocalVariableTable);
+ }
+
+ // Delete the local variable type table if it ended up empty.
+ if (deleteLocalVariableTypeTableAttribute)
+ {
+ AttributesEditor editor =
+ new AttributesEditor((ProgramClass)clazz,
+ (ProgramMember)method,
+ codeAttribute,
+ true);
+
+ editor.deleteAttribute(ClassConstants.ATTR_LocalVariableTypeTable);
+ }
}
@@ -60,9 +85,20 @@ implements AttributeVisitor
{
// Clean up local variables that aren't used.
localVariableTableAttribute.u2localVariableTableLength =
- removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
- localVariableTableAttribute.u2localVariableTableLength,
- codeAttribute.u2maxLocals);
+ removeUnusedLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Trim the code blocks of the local variables.
+ trimLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Delete the attribute in a moment, if it is empty.
+ if (localVariableTableAttribute.u2localVariableTableLength == 0)
+ {
+ deleteLocalVariableTableAttribute = true;
+ }
}
@@ -70,9 +106,20 @@ implements AttributeVisitor
{
// Clean up local variables that aren't used.
localVariableTypeTableAttribute.u2localVariableTypeTableLength =
- removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
- localVariableTypeTableAttribute.u2localVariableTypeTableLength,
- codeAttribute.u2maxLocals);
+ removeUnusedLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Trim the code blocks of the local variables.
+ trimLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Delete the attribute in a moment, if it is empty.
+ if (localVariableTypeTableAttribute.u2localVariableTypeTableLength == 0)
+ {
+ deleteLocalVariableTypeTableAttribute = true;
+ }
}
@@ -80,27 +127,30 @@ implements AttributeVisitor
/**
* Returns the given list of local variables, without the ones that aren't
- * used
+ * used.
*/
- private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
- int localVariableInfoCount,
- int maxLocals)
+ private int removeUnusedLocalVariables(LocalVariableInfo[] localVariableInfos,
+ int localVariableInfoCount,
+ int maxLocals)
{
// Overwrite all empty local variable entries.
+ // Do keep parameter entries.
int newIndex = 0;
- for (int index = 0; index < localVariableInfoCount && index < maxLocals; index++)
+ for (int index = 0; index < localVariableInfoCount; index++)
{
- if (variableUsageMarker.isVariableUsed(index))
+ LocalVariableInfo localVariableInfo = localVariableInfos[index];
+
+ if (localVariableInfo.u2index >= 0 &&
+ localVariableInfo.u2index < maxLocals &&
+ (localVariableInfo.u2startPC == 0 ||
+ localVariableInfo.u2length > 0))
{
localVariableInfos[newIndex++] = localVariableInfos[index];
}
}
// Clean up any remaining array elements.
- for (int index = newIndex; index < localVariableInfoCount; index++)
- {
- localVariableInfos[index] = null;
- }
+ Arrays.fill(localVariableInfos, newIndex, localVariableInfoCount, null);
return newIndex;
}
@@ -108,28 +158,114 @@ implements AttributeVisitor
/**
* Returns the given list of local variable types, without the ones that
- * aren't used
+ * aren't used.
*/
- private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
- int localVariableTypeInfoCount,
- int maxLocals)
+ private int removeUnusedLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
+ int localVariableTypeInfoCount,
+ int maxLocals)
{
// Overwrite all empty local variable type entries.
+ // Do keep parameter entries.
int newIndex = 0;
- for (int index = 0; index < localVariableTypeInfoCount && index < maxLocals; index++)
+ for (int index = 0; index < localVariableTypeInfoCount; index++)
{
- if (variableUsageMarker.isVariableUsed(index))
+ LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
+
+ if (localVariableTypeInfo.u2index >= 0 &&
+ localVariableTypeInfo.u2index < maxLocals &&
+ (localVariableTypeInfo.u2startPC == 0 ||
+ localVariableTypeInfo.u2length > 0))
{
localVariableTypeInfos[newIndex++] = localVariableTypeInfos[index];
}
}
// Clean up any remaining array elements.
- for (int index = newIndex; index < localVariableTypeInfoCount; index++)
+ Arrays.fill(localVariableTypeInfos, newIndex, localVariableTypeInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ /**
+ * Sorts the given list of local variables and trims their code blocks
+ * when necessary. The block is trimmed at the end, which is a bit
+ * arbitrary.
+ */
+ private void trimLocalVariables(LocalVariableInfo[] localVariableInfos,
+ int localVariableInfoCount,
+ int maxLocals)
+ {
+ // Sort the local variable entries.
+ Arrays.sort(localVariableInfos, 0, localVariableInfoCount);
+
+ int[] startPCs = createMaxArray(maxLocals);
+
+ // Trim the local variable entries, starting at the last one.
+ for (int index = localVariableInfoCount-1; index >= 0; index--)
{
- localVariableTypeInfos[index] = null;
+ LocalVariableInfo localVariableInfo = localVariableInfos[index];
+
+ // Make sure the variable's code block doesn't overlap with the
+ // next one for the same variable.
+ int maxLength = startPCs[localVariableInfo.u2index] -
+ localVariableInfo.u2startPC;
+
+ if (localVariableInfo.u2length > maxLength)
+ {
+ localVariableInfo.u2length = maxLength;
+ }
+
+ startPCs[localVariableInfo.u2index] = localVariableInfo.u2startPC;
}
+ }
- return newIndex;
+
+ /**
+ * Sorts the given list of local variable types and trims their code blocks
+ * when necessary. The block is trimmed at the end, which is a bit
+ * arbitrary.
+ */
+ private void trimLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
+ int localVariableTypeInfoCount,
+ int maxLocals)
+ {
+ // Sort the local variable entries.
+ Arrays.sort(localVariableTypeInfos, 0, localVariableTypeInfoCount);
+
+ int[] startPCs = createMaxArray(maxLocals);
+
+ // Trim the local variable entries, starting at the last one.
+ for (int index = localVariableTypeInfoCount-1; index >= 0; index--)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
+
+ // Make sure the variable's code block doesn't overlap with the
+ // next one for the same variable.
+ int maxLength = startPCs[localVariableTypeInfo.u2index] -
+ localVariableTypeInfo.u2startPC;
+
+ if (localVariableTypeInfo.u2length > maxLength)
+ {
+ localVariableTypeInfo.u2length = maxLength;
+ }
+
+ startPCs[localVariableTypeInfo.u2index] = localVariableTypeInfo.u2startPC;
+ }
+ }
+
+
+ /**
+ * Creates an integer array of the given length, initialized with
+ * Integer.MAX_VALUE.
+ */
+ private int[] createMaxArray(int length)
+ {
+ int[] startPCs = new int[length];
+ for (int index = 0; index < length; index++)
+ {
+ startPCs[index] = Integer.MAX_VALUE;
+ }
+ return startPCs;
}
} \ No newline at end of file
diff --git a/src/proguard/classfile/editor/VariableEditor.java b/src/proguard/classfile/editor/VariableEditor.java
index a583b49..b5143b5 100644
--- a/src/proguard/classfile/editor/VariableEditor.java
+++ b/src/proguard/classfile/editor/VariableEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,6 +25,8 @@ import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor accumulates specified changes to local variables, and
* then applies these accumulated changes to the code attributes that it visits.
@@ -53,14 +55,13 @@ implements AttributeVisitor
// Try to reuse the previous array.
if (deleted.length < maxLocals)
{
+ // Create a new array.
deleted = new boolean[maxLocals];
}
else
{
- for (int index = 0; index < maxLocals; index++)
- {
- deleted[index] = false;
- }
+ // Reset the array.
+ Arrays.fill(deleted, 0, maxLocals, false);
}
modified = false;
diff --git a/src/proguard/classfile/editor/VariableRemapper.java b/src/proguard/classfile/editor/VariableRemapper.java
index 590cd4e..ca9d88a 100644
--- a/src/proguard/classfile/editor/VariableRemapper.java
+++ b/src/proguard/classfile/editor/VariableRemapper.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -40,6 +40,9 @@ implements AttributeVisitor,
LocalVariableInfoVisitor,
LocalVariableTypeInfoVisitor
{
+ private static final boolean DEBUG = false;
+
+
private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
private int[] variableMap;
@@ -62,6 +65,19 @@ implements AttributeVisitor,
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
+ if (DEBUG)
+ {
+ System.out.println("VariableRemapper: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ for (int index= 0; index < codeAttribute.u2maxLocals; index++)
+ {
+ System.out.println(" v"+index+" -> "+variableMap[index]);
+ }
+ }
+
+ // Remap the variables of the attributes, before editing the code and
+ // cleaning up its local variable frame.
+ codeAttribute.attributesAccept(clazz, method, this);
+
// Initially, the code attribute editor doesn't contain any changes.
codeAttributeEditor.reset(codeAttribute.u4codeLength);
@@ -70,9 +86,6 @@ implements AttributeVisitor,
// Apply the code atribute editor.
codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
-
- // Remap the variables of the attributes.
- codeAttribute.attributesAccept(clazz, method, this);
}
@@ -80,11 +93,6 @@ implements AttributeVisitor,
{
// Remap the variable references of the local variables.
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables that haven't been mapped.
- localVariableTableAttribute.u2localVariableTableLength =
- removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
- localVariableTableAttribute.u2localVariableTableLength);
}
@@ -92,11 +100,6 @@ implements AttributeVisitor,
{
// Remap the variable references of the local variables.
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables that haven't been mapped.
- localVariableTypeTableAttribute.u2localVariableTypeTableLength =
- removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
- localVariableTypeTableAttribute.u2localVariableTypeTableLength);
}
@@ -134,7 +137,7 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new VariableInstruction(variableInstruction.opcode,
newVariableIndex,
- variableInstruction.constant).shrink();
+ variableInstruction.constant);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
}
@@ -150,48 +153,4 @@ implements AttributeVisitor,
{
return variableMap[variableIndex];
}
-
-
- /**
- * Returns the given list of local variables, without the ones that have
- * been removed.
- */
- private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
- int localVariableInfoCount)
- {
- // Overwrite all empty local variable entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableInfoCount; index++)
- {
- LocalVariableInfo localVariableInfo = localVariableInfos[index];
- if (localVariableInfo.u2index >= 0)
- {
- localVariableInfos[newIndex++] = localVariableInfo;
- }
- }
-
- return newIndex;
- }
-
-
- /**
- * Returns the given list of local variable types, without the ones that
- * have been removed.
- */
- private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
- int localVariableTypeInfoCount)
- {
- // Overwrite all empty local variable type entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableTypeInfoCount; index++)
- {
- LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
- if (localVariableTypeInfo.u2index >= 0)
- {
- localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
- }
- }
-
- return newIndex;
- }
}
diff --git a/src/proguard/classfile/editor/VariableSizeUpdater.java b/src/proguard/classfile/editor/VariableSizeUpdater.java
index 18958c5..2feaa9d 100644
--- a/src/proguard/classfile/editor/VariableSizeUpdater.java
+++ b/src/proguard/classfile/editor/VariableSizeUpdater.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,7 +29,8 @@ import proguard.classfile.util.*;
/**
* This AttributeVisitor computes and updates the maximum local variable frame
- * size of the code attributes that it visits.
+ * size of the code attributes that it visits. It also cleans up the local
+ * variable tables.
*
* @author Eric Lafortune
*/
@@ -45,6 +46,9 @@ implements AttributeVisitor,
//*/
+ private VariableCleaner variableCleaner = new VariableCleaner();
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -69,6 +73,9 @@ implements AttributeVisitor,
// Go over all instructions.
codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Remove the unused variables of the attributes.
+ variableCleaner.visitCodeAttribute(clazz, method, codeAttribute);
}
@@ -91,7 +98,7 @@ implements AttributeVisitor,
if (DEBUG)
{
- System.out.println("Max locals: "+codeAttribute.u2maxLocals+" <- "+variableInstruction.toString(offset));
+ System.out.println(" Max locals: "+codeAttribute.u2maxLocals+" <- "+variableInstruction.toString(offset));
}
}
}
diff --git a/src/proguard/classfile/instruction/BranchInstruction.java b/src/proguard/classfile/instruction/BranchInstruction.java
index 2baa917..f3a7080 100644
--- a/src/proguard/classfile/instruction/BranchInstruction.java
+++ b/src/proguard/classfile/instruction/BranchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -174,7 +174,6 @@ public class BranchInstruction extends Instruction
*/
private int requiredBranchOffsetSize()
{
- return branchOffset << 16 >> 16 == branchOffset ? 2 :
- 4;
+ return (short)branchOffset == branchOffset ? 2 : 4;
}
}
diff --git a/src/proguard/classfile/instruction/ConstantInstruction.java b/src/proguard/classfile/instruction/ConstantInstruction.java
index 6c2d1a3..42d1523 100644
--- a/src/proguard/classfile/instruction/ConstantInstruction.java
+++ b/src/proguard/classfile/instruction/ConstantInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -93,13 +93,9 @@ implements ConstantVisitor
public byte canonicalOpcode()
{
// Remove the _w extension, if any.
- switch (opcode)
- {
- case InstructionConstants.OP_LDC_W:
- case InstructionConstants.OP_LDC2_W: return InstructionConstants.OP_LDC;
-
- default: return opcode;
- }
+ return
+ opcode == InstructionConstants.OP_LDC_W ? InstructionConstants.OP_LDC :
+ opcode;
}
public Instruction shrink()
@@ -185,7 +181,8 @@ implements ConstantVisitor
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
- // The some parameters may be popped from the stack.
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ // Some parameters may be popped from the stack.
clazz.constantPoolEntryAccept(constantIndex, this);
stackPopCount += parameterStackDelta;
break;
@@ -208,6 +205,7 @@ implements ConstantVisitor
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
// The field value or a return value may be pushed onto the stack.
clazz.constantPoolEntryAccept(constantIndex, this);
stackPushCount += typeStackDelta;
@@ -226,8 +224,9 @@ implements ConstantVisitor
public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) {}
public void visitStringConstant(Clazz clazz, StringConstant stringConstant) {}
public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) {}
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) {}
public void visitClassConstant(Clazz clazz, ClassConstant classConstant) {}
- public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) {}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) {}
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
@@ -238,21 +237,27 @@ implements ConstantVisitor
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+ }
+
+
public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
{
- visitRefConstant(clazz, interfaceMethodrefConstant);
+ clazz.constantPoolEntryAccept(interfaceMethodrefConstant.u2nameAndTypeIndex, this);
}
public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
{
- visitRefConstant(clazz, methodrefConstant);
+ clazz.constantPoolEntryAccept(methodrefConstant.u2nameAndTypeIndex, this);
}
- private void visitRefConstant(Clazz clazz, RefConstant methodrefConstant)
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
- String type = methodrefConstant.getType(clazz);
+ String type = nameAndTypeConstant.getType(clazz);
parameterStackDelta = ClassUtil.internalMethodParameterSize(type);
typeStackDelta = ClassUtil.internalTypeSize(ClassUtil.internalMethodReturnType(type));
@@ -263,7 +268,7 @@ implements ConstantVisitor
public String toString()
{
- return getName()+" #"+constantIndex;
+ return getName()+" #"+constantIndex+(constantSize() == 0 ? "" : ", "+constant);
}
@@ -285,6 +290,7 @@ implements ConstantVisitor
private int constantSize()
{
return opcode == InstructionConstants.OP_MULTIANEWARRAY ? 1 :
+ opcode == InstructionConstants.OP_INVOKEDYNAMIC ||
opcode == InstructionConstants.OP_INVOKEINTERFACE ? 2 :
0;
}
diff --git a/src/proguard/classfile/instruction/Instruction.java b/src/proguard/classfile/instruction/Instruction.java
index 8437495..33e705d 100644
--- a/src/proguard/classfile/instruction/Instruction.java
+++ b/src/proguard/classfile/instruction/Instruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -220,7 +220,7 @@ public abstract class Instruction
false, // invokespecial
false, // invokestatic
false, // invokeinterface
- false, // unused
+ false, // invokedynamic
false, // new
false, // newarray
false, // anewarray
@@ -429,7 +429,7 @@ public abstract class Instruction
1, // invokespecial
0, // invokestatic
1, // invokeinterface
- 0, // unused
+ 0, // invokedynamic
0, // new
1, // newarray
1, // anewarray
@@ -638,7 +638,7 @@ public abstract class Instruction
0, // invokespecial
0, // invokestatic
0, // invokeinterface
- 0, // unused
+ 0, // invokedynamic
1, // new
1, // newarray
1, // anewarray
@@ -887,7 +887,7 @@ public abstract class Instruction
protected static void writeSignedByte(byte[] code, int offset, int value)
{
- if (value << 24 >> 24 != value)
+ if ((byte)value != value)
{
throw new IllegalArgumentException("Signed byte value out of range ["+value+"]");
}
@@ -897,7 +897,7 @@ public abstract class Instruction
protected static void writeSignedShort(byte[] code, int offset, int value)
{
- if (value << 16 >> 16 != value)
+ if ((short)value != value)
{
throw new IllegalArgumentException("Signed short value out of range ["+value+"]");
}
diff --git a/src/proguard/classfile/instruction/InstructionConstants.java b/src/proguard/classfile/instruction/InstructionConstants.java
index 78730b3..d8cbd98 100644
--- a/src/proguard/classfile/instruction/InstructionConstants.java
+++ b/src/proguard/classfile/instruction/InstructionConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -213,22 +213,22 @@ public interface InstructionConstants
public static final byte OP_INVOKESPECIAL = -73;
public static final byte OP_INVOKESTATIC = -72;
public static final byte OP_INVOKEINTERFACE = -71;
-// public static final byte OP_UNUSED = -70;
- public static final byte OP_NEW = -69;
- public static final byte OP_NEWARRAY = -68;
- public static final byte OP_ANEWARRAY = -67;
- public static final byte OP_ARRAYLENGTH = -66;
- public static final byte OP_ATHROW = -65;
- public static final byte OP_CHECKCAST = -64;
- public static final byte OP_INSTANCEOF = -63;
- public static final byte OP_MONITORENTER = -62;
- public static final byte OP_MONITOREXIT = -61;
- public static final byte OP_WIDE = -60;
- public static final byte OP_MULTIANEWARRAY = -59;
- public static final byte OP_IFNULL = -58;
- public static final byte OP_IFNONNULL = -57;
- public static final byte OP_GOTO_W = -56;
- public static final byte OP_JSR_W = -55;
+ public static final byte OP_INVOKEDYNAMIC = -70;
+ public static final byte OP_NEW = -69;
+ public static final byte OP_NEWARRAY = -68;
+ public static final byte OP_ANEWARRAY = -67;
+ public static final byte OP_ARRAYLENGTH = -66;
+ public static final byte OP_ATHROW = -65;
+ public static final byte OP_CHECKCAST = -64;
+ public static final byte OP_INSTANCEOF = -63;
+ public static final byte OP_MONITORENTER = -62;
+ public static final byte OP_MONITOREXIT = -61;
+ public static final byte OP_WIDE = -60;
+ public static final byte OP_MULTIANEWARRAY = -59;
+ public static final byte OP_IFNULL = -58;
+ public static final byte OP_IFNONNULL = -57;
+ public static final byte OP_GOTO_W = -56;
+ public static final byte OP_JSR_W = -55;
public static final String[] NAMES =
@@ -419,7 +419,7 @@ public interface InstructionConstants
"invokespecial",
"invokestatic",
"invokeinterface",
- "unused",
+ "invokedynamic",
"new",
"newarray",
"anewarray",
diff --git a/src/proguard/classfile/instruction/InstructionFactory.java b/src/proguard/classfile/instruction/InstructionFactory.java
index f898471..89d498c 100644
--- a/src/proguard/classfile/instruction/InstructionFactory.java
+++ b/src/proguard/classfile/instruction/InstructionFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -182,6 +182,7 @@ public class InstructionFactory
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
case InstructionConstants.OP_NEW:
case InstructionConstants.OP_ANEWARRAY:
diff --git a/src/proguard/classfile/instruction/InstructionUtil.java b/src/proguard/classfile/instruction/InstructionUtil.java
index a3a328a..c6ae99b 100644
--- a/src/proguard/classfile/instruction/InstructionUtil.java
+++ b/src/proguard/classfile/instruction/InstructionUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/LookUpSwitchInstruction.java b/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
index 178cce5..807c0cc 100644
--- a/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
+++ b/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/SimpleInstruction.java b/src/proguard/classfile/instruction/SimpleInstruction.java
index 84e6344..c9a2957 100644
--- a/src/proguard/classfile/instruction/SimpleInstruction.java
+++ b/src/proguard/classfile/instruction/SimpleInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -248,8 +248,8 @@ public class SimpleInstruction extends Instruction
private int requiredConstantSize()
{
return constant >= -1 && constant <= 5 ? 0 :
- constant << 24 >> 24 == constant ? 1 :
- constant << 16 >> 16 == constant ? 2 :
+ (byte)constant == constant ? 1 :
+ (short)constant == constant ? 2 :
4;
}
}
diff --git a/src/proguard/classfile/instruction/SwitchInstruction.java b/src/proguard/classfile/instruction/SwitchInstruction.java
index b98c2fb..3706ba0 100644
--- a/src/proguard/classfile/instruction/SwitchInstruction.java
+++ b/src/proguard/classfile/instruction/SwitchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/TableSwitchInstruction.java b/src/proguard/classfile/instruction/TableSwitchInstruction.java
index ee81af5..45490e5 100644
--- a/src/proguard/classfile/instruction/TableSwitchInstruction.java
+++ b/src/proguard/classfile/instruction/TableSwitchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/VariableInstruction.java b/src/proguard/classfile/instruction/VariableInstruction.java
index 309f802..6390e0a 100644
--- a/src/proguard/classfile/instruction/VariableInstruction.java
+++ b/src/proguard/classfile/instruction/VariableInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -365,8 +365,8 @@ public class VariableInstruction extends Instruction
private int requiredConstantSize()
{
return opcode != InstructionConstants.OP_IINC ? 0 :
- constant << 24 >> 24 == constant ? 1 :
- constant << 16 >> 16 == constant ? 2 :
+ (byte)constant == constant ? 1 :
+ (short)constant == constant ? 2 :
4;
}
}
diff --git a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
index 71b2cde..4d739c2 100644
--- a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java b/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java
new file mode 100644
index 0000000..6b24e98
--- /dev/null
+++ b/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given ConstantVisitor visit all constants
+ * of the instructions it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionConstantVisitor
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new InstructionConstantVisitor.
+ * @param constantVisitor the ConstantVisitor to which visits will be
+ * delegated.
+ */
+ public InstructionConstantVisitor(ConstantVisitor constantVisitor)
+ {
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ constantVisitor);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/instruction/visitor/InstructionCounter.java b/src/proguard/classfile/instruction/visitor/InstructionCounter.java
index 1d10980..5623498 100644
--- a/src/proguard/classfile/instruction/visitor/InstructionCounter.java
+++ b/src/proguard/classfile/instruction/visitor/InstructionCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/InstructionVisitor.java b/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
index 11af131..cffb15e 100644
--- a/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
index aada455..444fd57 100644
--- a/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/io/LibraryClassReader.java b/src/proguard/classfile/io/LibraryClassReader.java
index f14471c..d1eab3e 100644
--- a/src/proguard/classfile/io/LibraryClassReader.java
+++ b/src/proguard/classfile/io/LibraryClassReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -277,6 +277,18 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ dataInput.skipBytes(4);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ dataInput.skipBytes(3);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
dataInput.skipBytes(4);
@@ -289,6 +301,12 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ dataInput.skipBytes(2);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
dataInput.skipBytes(4);
@@ -325,16 +343,19 @@ implements ClassVisitor,
switch (u1tag)
{
- case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
case ClassConstants.CONSTANT_Integer: return new IntegerConstant();
case ClassConstants.CONSTANT_Float: return new FloatConstant();
case ClassConstants.CONSTANT_Long: return new LongConstant();
case ClassConstants.CONSTANT_Double: return new DoubleConstant();
case ClassConstants.CONSTANT_String: return new StringConstant();
+ case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
+ case ClassConstants.CONSTANT_InvokeDynamic: return new InvokeDynamicConstant();
+ case ClassConstants.CONSTANT_MethodHandle: return new MethodHandleConstant();
case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant();
case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant();
case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
case ClassConstants.CONSTANT_Class: return new ClassConstant();
+ case ClassConstants.CONSTANT_MethodType : return new MethodTypeConstant();
case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant();
default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool");
diff --git a/src/proguard/classfile/io/ProgramClassReader.java b/src/proguard/classfile/io/ProgramClassReader.java
index 476a346..80a38f7 100644
--- a/src/proguard/classfile/io/ProgramClassReader.java
+++ b/src/proguard/classfile/io/ProgramClassReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -46,6 +46,7 @@ implements ClassVisitor,
MemberVisitor,
ConstantVisitor,
AttributeVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
ExceptionInfoVisitor,
StackMapFrameVisitor,
@@ -250,6 +251,20 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.u2bootstrapMethodAttributeIndex = dataInput.readUnsignedShort();
+ invokeDynamicConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ methodHandleConstant.u1referenceKind = dataInput.readUnsignedByte();
+ methodHandleConstant.u2referenceIndex = dataInput.readUnsignedShort();
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
refConstant.u2classIndex = dataInput.readUnsignedShort();
@@ -263,6 +278,12 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ methodTypeConstant.u2descriptorIndex = dataInput.readUnsignedShort();
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
nameAndTypeConstant.u2nameIndex = dataInput.readUnsignedShort();
@@ -281,6 +302,21 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Read the bootstrap methods.
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount = dataInput.readUnsignedShort();
+
+ bootstrapMethodsAttribute.bootstrapMethods = new BootstrapMethodInfo[bootstrapMethodsAttribute.u2bootstrapMethodsCount];
+ for (int index = 0; index < bootstrapMethodsAttribute.u2bootstrapMethodsCount; index++)
+ {
+ BootstrapMethodInfo bootstrapMethodInfo = new BootstrapMethodInfo();
+ visitBootstrapMethodInfo(clazz, bootstrapMethodInfo);
+ bootstrapMethodsAttribute.bootstrapMethods[index] = bootstrapMethodInfo;
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
sourceFileAttribute.u2sourceFileIndex = dataInput.readUnsignedShort();
@@ -302,7 +338,7 @@ implements ClassVisitor,
for (int index = 0; index < innerClassesAttribute.u2classesCount; index++)
{
InnerClassesInfo innerClassesInfo = new InnerClassesInfo();
- this.visitInnerClassesInfo(clazz, innerClassesInfo);
+ visitInnerClassesInfo(clazz, innerClassesInfo);
innerClassesAttribute.classes[index] = innerClassesInfo;
}
}
@@ -372,7 +408,7 @@ implements ClassVisitor,
for (int index = 0; index < codeAttribute.u2exceptionTableLength; index++)
{
ExceptionInfo exceptionInfo = new ExceptionInfo();
- this.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
codeAttribute.exceptionTable[index] = exceptionInfo;
}
@@ -398,7 +434,7 @@ implements ClassVisitor,
for (int index = 0; index < stackMapAttribute.u2stackMapFramesCount; index++)
{
FullFrame stackMapFrame = new FullFrame();
- this.visitFullFrame(clazz, method, codeAttribute, index, stackMapFrame);
+ visitFullFrame(clazz, method, codeAttribute, index, stackMapFrame);
stackMapAttribute.stackMapFrames[index] = stackMapFrame;
}
}
@@ -428,7 +464,7 @@ implements ClassVisitor,
for (int index = 0; index < lineNumberTableAttribute.u2lineNumberTableLength; index++)
{
LineNumberInfo lineNumberInfo = new LineNumberInfo();
- this.visitLineNumberInfo(clazz, method, codeAttribute, lineNumberInfo);
+ visitLineNumberInfo(clazz, method, codeAttribute, lineNumberInfo);
lineNumberTableAttribute.lineNumberTable[index] = lineNumberInfo;
}
}
@@ -443,7 +479,7 @@ implements ClassVisitor,
for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++)
{
LocalVariableInfo localVariableInfo = new LocalVariableInfo();
- this.visitLocalVariableInfo(clazz, method, codeAttribute, localVariableInfo);
+ visitLocalVariableInfo(clazz, method, codeAttribute, localVariableInfo);
localVariableTableAttribute.localVariableTable[index] = localVariableInfo;
}
}
@@ -458,7 +494,7 @@ implements ClassVisitor,
for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++)
{
LocalVariableTypeInfo localVariableTypeInfo = new LocalVariableTypeInfo();
- this.visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeInfo);
+ visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeInfo);
localVariableTypeTableAttribute.localVariableTypeTable[index] = localVariableTypeInfo;
}
}
@@ -473,7 +509,7 @@ implements ClassVisitor,
for (int index = 0; index < annotationsAttribute.u2annotationsCount; index++)
{
Annotation annotation = new Annotation();
- this.visitAnnotation(clazz, annotation);
+ visitAnnotation(clazz, annotation);
annotationsAttribute.annotations[index] = annotation;
}
}
@@ -508,7 +544,7 @@ implements ClassVisitor,
for (int index = 0; index < u2annotationsCount; index++)
{
Annotation annotation = new Annotation();
- this.visitAnnotation(clazz, annotation);
+ visitAnnotation(clazz, annotation);
annotations[index] = annotation;
}
@@ -527,6 +563,22 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ bootstrapMethodInfo.u2methodHandleIndex = dataInput.readUnsignedShort();
+
+ // Read the bootstrap method arguments.
+ bootstrapMethodInfo.u2methodArgumentCount = dataInput.readUnsignedShort();
+ bootstrapMethodInfo.u2methodArguments = new int[bootstrapMethodInfo.u2methodArgumentCount];
+ for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++)
+ {
+ bootstrapMethodInfo.u2methodArguments[index] = dataInput.readUnsignedShort();
+ }
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
@@ -721,7 +773,7 @@ implements ClassVisitor,
{
// Read the annotation.
Annotation annotationValue = new Annotation();
- this.visitAnnotation(clazz, annotationValue);
+ visitAnnotation(clazz, annotationValue);
annotationElementValue.annotationValue = annotationValue;
}
@@ -749,16 +801,19 @@ implements ClassVisitor,
switch (u1tag)
{
- case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
case ClassConstants.CONSTANT_Integer: return new IntegerConstant();
case ClassConstants.CONSTANT_Float: return new FloatConstant();
case ClassConstants.CONSTANT_Long: return new LongConstant();
case ClassConstants.CONSTANT_Double: return new DoubleConstant();
case ClassConstants.CONSTANT_String: return new StringConstant();
+ case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
+ case ClassConstants.CONSTANT_InvokeDynamic: return new InvokeDynamicConstant();
+ case ClassConstants.CONSTANT_MethodHandle: return new MethodHandleConstant();
case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant();
case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant();
case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
case ClassConstants.CONSTANT_Class: return new ClassConstant();
+ case ClassConstants.CONSTANT_MethodType : return new MethodTypeConstant();
case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant();
default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool");
@@ -771,7 +826,9 @@ implements ClassVisitor,
int u2attributeNameIndex = dataInput.readUnsignedShort();
int u4attributeLength = dataInput.readInt();
String attributeName = clazz.getString(u2attributeNameIndex);
+
Attribute attribute =
+ attributeName.equals(ClassConstants.ATTR_BootstrapMethods) ? (Attribute)new BootstrapMethodsAttribute():
attributeName.equals(ClassConstants.ATTR_SourceFile) ? (Attribute)new SourceFileAttribute():
attributeName.equals(ClassConstants.ATTR_SourceDir) ? (Attribute)new SourceDirAttribute():
attributeName.equals(ClassConstants.ATTR_InnerClasses) ? (Attribute)new InnerClassesAttribute():
@@ -849,7 +906,7 @@ implements ClassVisitor,
case ClassConstants.INTERNAL_TYPE_FLOAT:
case ClassConstants.INTERNAL_TYPE_LONG:
case ClassConstants.INTERNAL_TYPE_DOUBLE:
- case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue(u1tag);
+ case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue((char)u1tag);
case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT: return new EnumConstantElementValue();
case ClassConstants.ELEMENT_VALUE_CLASS: return new ClassElementValue();
diff --git a/src/proguard/classfile/io/ProgramClassWriter.java b/src/proguard/classfile/io/ProgramClassWriter.java
index e56f08a..dbf1de3 100644
--- a/src/proguard/classfile/io/ProgramClassWriter.java
+++ b/src/proguard/classfile/io/ProgramClassWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -57,7 +57,7 @@ implements ClassVisitor,
/**
- * Creates a new ProgramClassWriter for reading from the given DataOutput.
+ * Creates a new ProgramClassWriter for writing to the given DataOutput.
*/
public ProgramClassWriter(DataOutput dataOutput)
{
@@ -208,6 +208,20 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ dataOutput.writeShort(invokeDynamicConstant.u2bootstrapMethodAttributeIndex);
+ dataOutput.writeShort(invokeDynamicConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ dataOutput.writeByte(methodHandleConstant.u1referenceKind);
+ dataOutput.writeShort(methodHandleConstant.u2referenceIndex);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
dataOutput.writeShort(refConstant.u2classIndex);
@@ -221,6 +235,12 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ dataOutput.writeShort(methodTypeConstant.u2descriptorIndex);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
dataOutput.writeShort(nameAndTypeConstant.u2nameIndex);
@@ -263,6 +283,7 @@ implements ClassVisitor,
private class AttributeBodyWriter
extends SimplifiedVisitor
implements AttributeVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
ExceptionInfoVisitor,
StackMapFrameVisitor,
@@ -282,6 +303,15 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Write the bootstrap methods.
+ dataOutput.writeShort(bootstrapMethodsAttribute.u2bootstrapMethodsCount);
+
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex);
@@ -438,8 +468,7 @@ implements ClassVisitor,
for (int index = 0; index < u2annotationsCount; index++)
{
- Annotation annotation = annotations[index];
- this.visitAnnotation(clazz, annotation);
+ visitAnnotation(clazz, annotations[index]);
}
}
@@ -453,6 +482,22 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ dataOutput.writeShort(bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Write the bootstrap method arguments.
+ dataOutput.writeShort(bootstrapMethodInfo.u2methodArgumentCount);
+
+ for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++)
+ {
+ dataOutput.writeShort(bootstrapMethodInfo.u2methodArguments[index]);
+ }
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
diff --git a/src/proguard/classfile/io/RuntimeDataInput.java b/src/proguard/classfile/io/RuntimeDataInput.java
index 104b7c9..ce2d1a5 100644
--- a/src/proguard/classfile/io/RuntimeDataInput.java
+++ b/src/proguard/classfile/io/RuntimeDataInput.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/io/RuntimeDataOutput.java b/src/proguard/classfile/io/RuntimeDataOutput.java
index ffde3af..44acc70 100644
--- a/src/proguard/classfile/io/RuntimeDataOutput.java
+++ b/src/proguard/classfile/io/RuntimeDataOutput.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/AccessUtil.java b/src/proguard/classfile/util/AccessUtil.java
index 3ad6961..d16f576 100644
--- a/src/proguard/classfile/util/AccessUtil.java
+++ b/src/proguard/classfile/util/AccessUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/ClassReferenceInitializer.java b/src/proguard/classfile/util/ClassReferenceInitializer.java
index b1f2c27..a5748ee 100644
--- a/src/proguard/classfile/util/ClassReferenceInitializer.java
+++ b/src/proguard/classfile/util/ClassReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,7 +64,8 @@ implements ClassVisitor,
private final ClassPool programClassPool;
private final ClassPool libraryClassPool;
private final WarningPrinter missingClassWarningPrinter;
- private final WarningPrinter missingMemberWarningPrinter;
+ private final WarningPrinter missingProgramMemberWarningPrinter;
+ private final WarningPrinter missingLibraryMemberWarningPrinter;
private final WarningPrinter dependencyWarningPrinter;
private final MemberFinder memberFinder = new MemberFinder();
@@ -78,14 +79,16 @@ implements ClassVisitor,
public ClassReferenceInitializer(ClassPool programClassPool,
ClassPool libraryClassPool,
WarningPrinter missingClassWarningPrinter,
- WarningPrinter missingMemberWarningPrinter,
+ WarningPrinter missingProgramMemberWarningPrinter,
+ WarningPrinter missingLibraryMemberWarningPrinter,
WarningPrinter dependencyWarningPrinter)
{
- this.programClassPool = programClassPool;
- this.libraryClassPool = libraryClassPool;
- this.missingClassWarningPrinter = missingClassWarningPrinter;
- this.missingMemberWarningPrinter = missingMemberWarningPrinter;
- this.dependencyWarningPrinter = dependencyWarningPrinter;
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.missingClassWarningPrinter = missingClassWarningPrinter;
+ this.missingProgramMemberWarningPrinter = missingProgramMemberWarningPrinter;
+ this.missingLibraryMemberWarningPrinter = missingLibraryMemberWarningPrinter;
+ this.dependencyWarningPrinter = dependencyWarningPrinter;
}
@@ -166,17 +169,30 @@ implements ClassVisitor,
}
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Fill out the MethodHandle class.
+ methodHandleConstant.javaLangInvokeMethodHandleClass =
+ findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
String className = refConstant.getClassName(clazz);
+ // Methods for array types should be found in the Object class.
+ if (ClassUtil.isInternalArrayType(className))
+ {
+ className = ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT;
+ }
+
// See if we can find the referenced class.
// Unresolved references are assumed to refer to library classes
// that will not change anyway.
Clazz referencedClass = findClass(clazz.getName(), className);
- if (referencedClass != null &&
- !ClassUtil.isInternalArrayType(className))
+ if (referencedClass != null)
{
String name = refConstant.getName(clazz);
String type = refConstant.getType(clazz);
@@ -194,7 +210,13 @@ implements ClassVisitor,
if (refConstant.referencedMember == null)
{
- // We've haven't found the class member anywhere in the hierarchy.
+ // We haven't found the class member anywhere in the hierarchy.
+ boolean isProgramClass = referencedClass instanceof ProgramClass;
+
+ WarningPrinter missingMemberWarningPrinter = isProgramClass ?
+ missingProgramMemberWarningPrinter :
+ missingLibraryMemberWarningPrinter;
+
missingMemberWarningPrinter.print(clazz.getName(),
className,
"Warning: " +
@@ -203,7 +225,11 @@ implements ClassVisitor,
(isFieldRef ?
"field '" + ClassUtil.externalFullFieldDescription(0, name, type) :
"method '" + ClassUtil.externalFullMethodDescription(className, 0, name, type)) +
- "' in class " +
+ "' in " +
+ (isProgramClass ?
+ "program" :
+ "library") +
+ " class " +
ClassUtil.externalClassName(className));
}
}
@@ -216,7 +242,7 @@ implements ClassVisitor,
// Fill out the referenced class.
classConstant.referencedClass =
- findClass(className, classConstant.getName(clazz));
+ findClass(className, ClassUtil.internalClassNameFromClassType(classConstant.getName(clazz)));
// Fill out the Class class.
classConstant.javaLangClassClass =
@@ -224,6 +250,14 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ // Fill out the MethodType class.
+ methodTypeConstant.javaLangInvokeMethodTypeClass =
+ findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE);
+ }
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -235,49 +269,36 @@ implements ClassVisitor,
String enclosingClassName = enclosingMethodAttribute.getClassName(clazz);
// See if we can find the referenced class.
- Clazz referencedClass = findClass(className, enclosingClassName);
+ enclosingMethodAttribute.referencedClass =
+ findClass(className, enclosingClassName);
- if (referencedClass == null)
+ if (enclosingMethodAttribute.referencedClass != null)
{
- // We couldn't find the enclosing class.
- missingClassWarningPrinter.print(className,
- enclosingClassName,
- "Warning: " +
- ClassUtil.externalClassName(className) +
- ": can't find enclosing class " +
- ClassUtil.externalClassName(enclosingClassName));
- return;
- }
-
- // Make sure there is actually an enclosed method.
- if (enclosingMethodAttribute.u2nameAndTypeIndex == 0)
- {
- return;
- }
-
- String name = enclosingMethodAttribute.getName(clazz);
- String type = enclosingMethodAttribute.getType(clazz);
+ // Is there an enclosing method? Otherwise it's just initialization
+ // code outside of the constructors.
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ String name = enclosingMethodAttribute.getName(clazz);
+ String type = enclosingMethodAttribute.getType(clazz);
- // See if we can find the method in the referenced class.
- Method referencedMethod = referencedClass.findMethod(name, type);
+ // See if we can find the method in the referenced class.
+ enclosingMethodAttribute.referencedMethod =
+ enclosingMethodAttribute.referencedClass.findMethod(name, type);
- if (referencedMethod == null)
- {
- // We couldn't find the enclosing method.
- missingMemberWarningPrinter.print(className,
- enclosingClassName,
- "Warning: " +
- ClassUtil.externalClassName(className) +
- ": can't find enclosing method '" +
- ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) +
- "' in class " +
- ClassUtil.externalClassName(enclosingClassName));
- return;
+ if (enclosingMethodAttribute.referencedMethod == null)
+ {
+ // We couldn't find the enclosing method.
+ missingProgramMemberWarningPrinter.print(className,
+ enclosingClassName,
+ "Warning: " +
+ ClassUtil.externalClassName(className) +
+ ": can't find enclosing method '" +
+ ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) +
+ "' in program class " +
+ ClassUtil.externalClassName(enclosingClassName));
+ }
+ }
}
-
- // Save the references.
- enclosingMethodAttribute.referencedClass = referencedClass;
- enclosingMethodAttribute.referencedMethod = referencedMethod;
}
@@ -501,11 +522,17 @@ implements ClassVisitor,
*/
private Clazz findClass(String referencingClassName, String name)
{
- // Ignore any primitive array types.
- if (ClassUtil.isInternalArrayType(name) &&
- !ClassUtil.isInternalClassType(name))
+ // Is it an array type?
+ if (ClassUtil.isInternalArrayType(name))
{
- return null;
+ // Ignore any primitive array types.
+ if (!ClassUtil.isInternalClassType(name))
+ {
+ return null;
+ }
+
+ // Strip the array part.
+ name = ClassUtil.internalClassNameFromClassType(name);
}
// First look for the class in the program class pool.
diff --git a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
index 30fd526..993a559 100644
--- a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
+++ b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
index af2a209..fb431b8 100644
--- a/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
+++ b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -106,11 +106,6 @@ implements ClassVisitor,
libraryClass.interfaceClasses = interfaceClasses;
}
-
- // Discard the name Strings. From now on, we'll use the object
- // references.
- libraryClass.superClassName = null;
- libraryClass.interfaceNames = null;
}
diff --git a/src/proguard/classfile/util/ClassUtil.java b/src/proguard/classfile/util/ClassUtil.java
index 5f25f01..fb38616 100644
--- a/src/proguard/classfile/util/ClassUtil.java
+++ b/src/proguard/classfile/util/ClassUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -100,6 +100,8 @@ public class ClassUtil
classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_5) ? ClassConstants.INTERNAL_CLASS_VERSION_1_5 :
classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6_ALIAS) ||
classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6) ? ClassConstants.INTERNAL_CLASS_VERSION_1_6 :
+ classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_7_ALIAS) ||
+ classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_7) ? ClassConstants.INTERNAL_CLASS_VERSION_1_7 :
0;
}
@@ -119,6 +121,7 @@ public class ClassUtil
case ClassConstants.INTERNAL_CLASS_VERSION_1_4: return ClassConstants.EXTERNAL_CLASS_VERSION_1_4;
case ClassConstants.INTERNAL_CLASS_VERSION_1_5: return ClassConstants.EXTERNAL_CLASS_VERSION_1_5;
case ClassConstants.INTERNAL_CLASS_VERSION_1_6: return ClassConstants.EXTERNAL_CLASS_VERSION_1_6;
+ case ClassConstants.INTERNAL_CLASS_VERSION_1_7: return ClassConstants.EXTERNAL_CLASS_VERSION_1_7;
default: return null;
}
}
@@ -132,11 +135,14 @@ public class ClassUtil
public static void checkVersionNumbers(int classVersion) throws UnsupportedOperationException
{
if (classVersion < ClassConstants.INTERNAL_CLASS_VERSION_1_0 ||
- classVersion > ClassConstants.INTERNAL_CLASS_VERSION_1_6)
+ classVersion > ClassConstants.INTERNAL_CLASS_VERSION_1_7)
{
- throw new UnsupportedOperationException("Unsupported version number ["+
+ throw new UnsupportedOperationException("Unsupported class version number ["+
internalMajorClassVersion(classVersion)+"."+
- internalMinorClassVersion(classVersion)+"] for class format");
+ internalMinorClassVersion(classVersion)+"] (maximum "+
+ ClassConstants.INTERNAL_CLASS_VERSION_1_7_MAJOR+"."+
+ ClassConstants.INTERNAL_CLASS_VERSION_1_7_MINOR+", Java "+
+ ClassConstants.EXTERNAL_CLASS_VERSION_1_7+")");
}
}
@@ -189,8 +195,25 @@ public class ClassUtil
/**
- * Converts an internal class name into an external short class name, without
- * package specification.
+ * Returns the external base type of an external array type, dropping any
+ * array brackets.
+ * @param externalArrayType the external array type,
+ * e.g. "<code>java.lang.Object[][]</code>"
+ * @return the external base type,
+ * e.g. "<code>java.lang.Object</code>".
+ */
+ public static String externalBaseType(String externalArrayType)
+ {
+ int index = externalArrayType.indexOf(ClassConstants.EXTERNAL_TYPE_ARRAY);
+ return index >= 0 ?
+ externalArrayType.substring(0, index) :
+ externalArrayType;
+ }
+
+
+ /**
+ * Returns the external short class name of an external class name, dropping
+ * the package specification.
* @param externalClassName the external class name,
* e.g. "<code>java.lang.Object</code>"
* @return the external short class name,
@@ -410,6 +433,21 @@ public class ClassUtil
/**
+ * Returns whether the given method name refers to a class initializer or
+ * an instance initializer.
+ * @param internalMethodName the internal method name,
+ * e.g. "<code>&ltclinit&gt;</code>".
+ * @return whether the method name refers to an initializer,
+ * e.g. <code>true</code>.
+ */
+ public static boolean isInitializer(String internalMethodName)
+ {
+ return internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ||
+ internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);
+ }
+
+
+ /**
* Returns the internal type of the given internal method descriptor.
* @param internalMethodDescriptor the internal method descriptor,
* e.g. "<code>(II)Z</code>".
@@ -869,6 +907,21 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(' ');
+ }
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(' ');
+ }
if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0)
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(' ');
@@ -889,6 +942,10 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(' ');
}
+ else if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' ');
+ }
return string.toString();
}
@@ -950,6 +1007,10 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_TRANSIENT).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' ');
+ }
return string.toString();
}
@@ -1007,6 +1068,14 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_BRIDGE) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_BRIDGE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_VARARGS) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_VARARGS).append(' ');
+ }
if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0)
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_NATIVE).append(' ');
@@ -1019,6 +1088,10 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STRICT).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' ');
+ }
return string.toString();
}
diff --git a/src/proguard/classfile/util/DescriptorClassEnumeration.java b/src/proguard/classfile/util/DescriptorClassEnumeration.java
index 0bee2d5..81590fa 100644
--- a/src/proguard/classfile/util/DescriptorClassEnumeration.java
+++ b/src/proguard/classfile/util/DescriptorClassEnumeration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
index 09ffdd0..865e094 100644
--- a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
+++ b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -301,7 +301,8 @@ implements InstructionVisitor,
{
// Save a reference to the corresponding class.
String externalClassName = stringConstant.getString(clazz);
- String internalClassName = ClassUtil.internalClassName(externalClassName);
+ String internalClassName = ClassUtil.internalClassName(
+ ClassUtil.externalBaseType(externalClassName));
stringConstant.referencedClass = findClass(clazz.getName(), internalClassName);
}
@@ -350,7 +351,7 @@ implements InstructionVisitor,
return;
}
- String className = methodrefConstant.getClassName(clazz);
+ String className = methodrefConstant.getClassName(clazz);
// Note that we look for the class by name, since the referenced
// class has not been initialized yet.
@@ -434,11 +435,17 @@ implements InstructionVisitor,
*/
private Clazz findClass(String referencingClassName, String name)
{
- // Ignore any primitive array types.
- if (ClassUtil.isInternalArrayType(name) &&
- !ClassUtil.isInternalClassType(name))
+ // Is it an array type?
+ if (ClassUtil.isInternalArrayType(name))
{
- return null;
+ // Ignore any primitive array types.
+ if (!ClassUtil.isInternalClassType(name))
+ {
+ return null;
+ }
+
+ // Strip the array part.
+ name = ClassUtil.internalClassNameFromClassType(name);
}
// First look for the class in the program class pool.
diff --git a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
index 1f57708..23c8d40 100644
--- a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
+++ b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -52,17 +52,22 @@ public class DynamicMemberReferenceInitializer
extends SimplifiedVisitor
implements InstructionVisitor,
ConstantVisitor,
- AttributeVisitor,
MemberVisitor
{
- public static final int X = InstructionSequenceMatcher.X;
- public static final int Y = InstructionSequenceMatcher.Y;
- public static final int Z = InstructionSequenceMatcher.Z;
+ /*
+ private static boolean DEBUG = true;
+ /*/
+ private static final boolean DEBUG = false;
+ //*/
- public static final int A = InstructionSequenceMatcher.A;
- public static final int B = InstructionSequenceMatcher.B;
- public static final int C = InstructionSequenceMatcher.C;
- public static final int D = InstructionSequenceMatcher.D;
+ public static final int CLASS_INDEX = InstructionSequenceMatcher.X;
+ public static final int MEMBER_NAME_INDEX = InstructionSequenceMatcher.Y;
+ public static final int TYPE_CLASS_INDEX = InstructionSequenceMatcher.Z;
+
+ public static final int PARAMETER0_CLASS_INDEX = InstructionSequenceMatcher.A;
+ public static final int PARAMETER1_CLASS_INDEX = InstructionSequenceMatcher.B;
+ public static final int PARAMETER2_CLASS_INDEX = InstructionSequenceMatcher.C;
+ public static final int PARAMETER3_CLASS_INDEX = InstructionSequenceMatcher.D;
private final Constant[] GET_FIELD_CONSTANTS = new Constant[]
@@ -85,6 +90,26 @@ implements InstructionVisitor,
new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD),
};
+ private final Constant[] GET_CONSTRUCTOR_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR),
+ };
+
+ private final Constant[] GET_DECLARED_CONSTRUCTOR_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR),
+ };
+
private final Constant[] GET_METHOD_CONSTANTS = new Constant[]
{
new MethodrefConstant(1, 2, null, null),
@@ -105,19 +130,88 @@ implements InstructionVisitor,
new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD),
};
+ private final Constant[] NEW_INTEGER_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_INTEGER_UPDATER),
+ };
+
+ private final Constant[] NEW_LONG_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_LONG_UPDATER),
+ };
+
+ private final Constant[] NEW_REFERENCE_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_REFERENCE_UPDATER),
+ };
+
// SomeClass.class.get[Declared]Field("someField").
private final Instruction[] CONSTANT_GET_FIELD_INSTRUCTIONS = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
+// // SomeClass.class.get[Declared]Constructor(new Class[] {}).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+//
+// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class }).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+//
+// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class, B.class }).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+
// SomeClass.class.get[Declared]Method("someMethod", new Class[] {}).
private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS0 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
@@ -126,13 +220,13 @@ implements InstructionVisitor,
// SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class }).
private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS1 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
@@ -140,32 +234,86 @@ implements InstructionVisitor,
// SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class, B.class }).
private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS2 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_2),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
- new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
+ // AtomicIntegerFieldUpdater.newUpdater(A.class, "someField").
+ // AtomicLongFieldUpdater.newUpdater(A.class, "someField").
+ private final Instruction[] CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+ // AtomicReferenceFieldUpdater.newUpdater(A.class, B.class, "someField").
+ private final Instruction[] CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, TYPE_CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
// get[Declared]Field("someField").
private final Instruction[] GET_FIELD_INSTRUCTIONS = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+// // get[Declared]Constructor(new Class[] {}).
+// private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[]
+// {
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+
+ // get[Declared]Constructor(new Class[] { A.class }).
+ private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // get[Declared]Constructor(new Class[] { A.class, B.class }).
+ private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
// get[Declared]Method("someMethod", new Class[] {}).
private final Instruction[] GET_METHOD_INSTRUCTIONS0 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
@@ -174,12 +322,12 @@ implements InstructionVisitor,
// get[Declared]Method("someMethod", new Class[] { A.class }).
private final Instruction[] GET_METHOD_INSTRUCTIONS1 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
@@ -187,20 +335,29 @@ implements InstructionVisitor,
// get[Declared]Method("someMethod", new Class[] { A.class, B.class }).
private final Instruction[] GET_METHOD_INSTRUCTIONS2 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_2),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
- new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
+ // AtomicIntegerFieldUpdater.newUpdater(..., "someField").
+ // AtomicLongFieldUpdater.newUpdater(..., "someField").
+ // AtomicReferenceFieldUpdater.newUpdater(..., "someField").
+ private final Instruction[] NEW_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
private final ClassPool programClassPool;
private final ClassPool libraryClassPool;
@@ -217,6 +374,30 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS,
CONSTANT_GET_FIELD_INSTRUCTIONS);
+// private final InstructionSequenceMatcher constantGetConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher constantGetConstructorMatcher1 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher1 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1);
+//
+// private final InstructionSequenceMatcher constantGetConstructorMatcher2 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher2 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2);
+
private final InstructionSequenceMatcher constantGetMethodMatcher0 =
new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
CONSTANT_GET_METHOD_INSTRUCTIONS0);
@@ -241,6 +422,18 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
CONSTANT_GET_METHOD_INSTRUCTIONS2);
+ private final InstructionSequenceMatcher constantGetIntegerUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS,
+ CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher constantGetLongUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS,
+ CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher constantGetReferenceUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS,
+ CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS);
+
private final InstructionSequenceMatcher getFieldMatcher =
new InstructionSequenceMatcher(GET_FIELD_CONSTANTS,
GET_FIELD_INSTRUCTIONS);
@@ -249,6 +442,30 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS,
GET_FIELD_INSTRUCTIONS);
+// private final InstructionSequenceMatcher getConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher getDeclaredConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// GET_CONSTRUCTOR_INSTRUCTIONS0);
+
+ private final InstructionSequenceMatcher getConstructorMatcher1 =
+ new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getDeclaredConstructorMatcher1 =
+ new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getConstructorMatcher2 =
+ new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher getDeclaredConstructorMatcher2 =
+ new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS2);
+
private final InstructionSequenceMatcher getMethodMatcher0 =
new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
GET_METHOD_INSTRUCTIONS0);
@@ -273,11 +490,24 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
GET_METHOD_INSTRUCTIONS2);
+ private final InstructionSequenceMatcher getIntegerUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getLongUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getReferenceUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
private final MemberFinder memberFinder = new MemberFinder();
// Fields acting as parameters for the visitors.
private Clazz referencedClass;
+ private String descriptor;
private boolean isDeclared;
private boolean isField;
@@ -307,48 +537,110 @@ implements InstructionVisitor,
// Try to match the SomeClass.class.getField("someField") construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetFieldMatcher,
- getFieldMatcher, true, false);
+ getFieldMatcher, true, false, null, null);
// Try to match the SomeClass.class.getDeclaredField("someField") construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredFieldMatcher,
- getDeclaredFieldMatcher, true, true);
+ getDeclaredFieldMatcher, true, true, null, null);
+
+// // Try to match the SomeClass.class.getConstructor(new Class[]
+// // {}) construct.
+// matchGetMember(clazz, method, codeAttribute, offset, instruction,
+// cnull, //onstantGetConstructorMatcher0,
+// getConstructorMatcher0, false, false,
+// ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+//
+// // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+// // {}) construct.
+// matchGetMember(clazz, method, codeAttribute, offset, instruction,
+// null, //constantGetDeclaredConstructorMatcher0,
+// getDeclaredConstructorMatcher0, false, true,
+// ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getConstructor(new Class[]
+ // { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetConstructorMatcher1,
+ getConstructorMatcher1, false, false,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+ // { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetDeclaredConstructorMatcher1,
+ getDeclaredConstructorMatcher1, false, true,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getConstructor(new Class[]
+ // { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetConstructorMatcher2,
+ getConstructorMatcher2, false, false,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+ // { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetDeclaredConstructorMatcher2,
+ getDeclaredConstructorMatcher2, false, true,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
// Try to match the SomeClass.class.getMethod("someMethod", new Class[]
// {}) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetMethodMatcher0,
- getMethodMatcher0, false, false);
+ getMethodMatcher0, false, false, null, null);
// Try to match the SomeClass.class.getDeclaredMethod("someMethod",
- // new Class[] {}) construct.
+ // new Class[] {}) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredMethodMatcher0,
- getDeclaredMethodMatcher0, false, true);
+ getDeclaredMethodMatcher0, false, true, null, null);
// Try to match the SomeClass.class.getMethod("someMethod", new Class[]
// { A.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetMethodMatcher1,
- getMethodMatcher1, false, false);
+ getMethodMatcher1, false, false, null, null);
// Try to match the SomeClass.class.getDeclaredMethod("someMethod",
// new Class[] { A.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredMethodMatcher1,
- getDeclaredMethodMatcher1, false, true);
+ getDeclaredMethodMatcher1, false, true, null, null);
// Try to match the SomeClass.class.getMethod("someMethod", new Class[]
// { A.class, B.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetMethodMatcher2,
- getMethodMatcher2, false, false);
+ getMethodMatcher2, false, false, null, null);
// Try to match the SomeClass.class.getDeclaredMethod("someMethod",
- // new Class[] { A.class, B.class }) construct.
+ // new Class[] { A.class, B.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredMethodMatcher2,
- getDeclaredMethodMatcher2, false, true);
+ getDeclaredMethodMatcher2, false, true, null, null);
+
+ // Try to match the AtomicIntegerFieldUpdater.newUpdater(
+ // SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetIntegerUpdaterMatcher,
+ getIntegerUpdaterMatcher, true, false, null,
+ "" + ClassConstants.INTERNAL_TYPE_INT);
+
+ // Try to match the AtomicLongFieldUpdater.newUpdater(
+ // SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetLongUpdaterMatcher,
+ getLongUpdaterMatcher, true, false, null,
+ "" + ClassConstants.INTERNAL_TYPE_LONG);
+
+ // Try to match the AtomicReferenceFieldUpdater.newUpdater(
+ // SomeClass.class, SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetReferenceUpdaterMatcher,
+ getReferenceUpdaterMatcher, true, false, null, null);
}
@@ -364,26 +656,28 @@ implements InstructionVisitor,
InstructionSequenceMatcher constantSequenceMatcher,
InstructionSequenceMatcher variableSequenceMatcher,
boolean isField,
- boolean isDeclared)
+ boolean isDeclared,
+ String defaultName,
+ String defaultDescriptor)
{
- // Try to match the next instruction in the constant sequence.
- instruction.accept(clazz, method, codeAttribute, offset,
- constantSequenceMatcher);
-
- // Did we find a match to fill out the string constant?
- if (constantSequenceMatcher.isMatching())
+ if (constantSequenceMatcher != null)
{
- this.isField = isField;
- this.isDeclared = isDeclared;
-
- // Get the member's class.
- clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(X), this);
-
- // Fill out the matched string constant.
- clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(Y), this);
+ // Try to match the next instruction in the constant sequence.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ constantSequenceMatcher);
- // Don't look for the dynamic construct.
- variableSequenceMatcher.reset();
+ // Did we find a match to fill out the string constant?
+ if (constantSequenceMatcher.isMatching())
+ {
+ initializeStringReference(clazz,
+ constantSequenceMatcher,
+ isField,
+ isDeclared,
+ defaultDescriptor);
+
+ // Don't look for the dynamic construct.
+ variableSequenceMatcher.reset();
+ }
}
// Try to match the next instruction in the variable sequence.
@@ -397,11 +691,41 @@ implements InstructionVisitor,
printDynamicInvocationNote(clazz,
variableSequenceMatcher,
isField,
- isDeclared);
+ isDeclared,
+ defaultName,
+ defaultDescriptor);
}
}
+ /**
+ * Initializes the reference of the matched string constant to the
+ * referenced class member and its class.
+ */
+ private void initializeStringReference(Clazz clazz,
+ InstructionSequenceMatcher constantSequenceMatcher,
+ boolean isField,
+ boolean isDeclared,
+ String defaultDescriptor)
+ {
+ this.isField = isField;
+ this.isDeclared = isDeclared;
+
+ // Get the member's class.
+ int classIndex = constantSequenceMatcher.matchedConstantIndex(CLASS_INDEX);
+ clazz.constantPoolEntryAccept(classIndex, this);
+
+ // Get the field's reference type, if applicable.
+ int typeClassIndex = constantSequenceMatcher.matchedConstantIndex(TYPE_CLASS_INDEX);
+ descriptor = typeClassIndex <= 0 ? defaultDescriptor :
+ ClassUtil.internalTypeFromClassName(clazz.getClassName(typeClassIndex));
+
+ // Fill out the matched string constant.
+ int memberNameIndex = constantSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX);
+ clazz.constantPoolEntryAccept(memberNameIndex, this);
+ }
+
+
// Implementations for ConstantVisitor.
/**
@@ -409,6 +733,11 @@ implements InstructionVisitor,
*/
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
+ if (DEBUG)
+ {
+ System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched class ["+classConstant.getName(clazz)+"]");
+ }
+
// Remember the referenced class.
referencedClass = ClassUtil.isInternalArrayType(classConstant.getName(clazz)) ?
null :
@@ -425,15 +754,20 @@ implements InstructionVisitor,
{
String name = stringConstant.getString(clazz);
+ if (DEBUG)
+ {
+ System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched string ["+name+"]");
+ }
+
// See if we can find the referenced class member locally, or
// somewhere in the hierarchy.
Member referencedMember = isDeclared ? isField ?
- (Member)referencedClass.findField(name, null) :
- (Member)referencedClass.findMethod(name, null) :
+ (Member)referencedClass.findField(name, descriptor) :
+ (Member)referencedClass.findMethod(name, descriptor) :
(Member)memberFinder.findMember(clazz,
referencedClass,
name,
- null,
+ descriptor,
isField);
if (referencedMember != null)
{
@@ -454,7 +788,9 @@ implements InstructionVisitor,
private void printDynamicInvocationNote(Clazz clazz,
InstructionSequenceMatcher noteSequenceMatcher,
boolean isField,
- boolean isDeclared)
+ boolean isDeclared,
+ String defaultName,
+ String defaultDescriptor)
{
// Print out a note about the dynamic invocation.
if (notePrinter != null &&
@@ -465,8 +801,9 @@ implements InstructionVisitor,
noteFieldExceptionMatcher :
noteMethodExceptionMatcher;
- int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(Y);
- String memberName = clazz.getStringString(memberNameIndex);
+ int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX);
+ String memberName = memberNameIndex <= 0 ? defaultName :
+ clazz.getStringString(memberNameIndex);
if (noteExceptionMatcher == null ||
!noteExceptionMatcher.matches(memberName))
@@ -479,7 +816,8 @@ implements InstructionVisitor,
externalMemberDescription += '(';
for (int count = 0; count < 2; count++)
{
- int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(A + count);
+ int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(
+ PARAMETER0_CLASS_INDEX + count);
if (memberArgumentIndex > 0)
{
if (count > 0)
@@ -501,7 +839,9 @@ implements InstructionVisitor,
ClassUtil.externalClassName(clazz.getName()) +
" accesses a " +
(isDeclared ? "declared " : "") +
- (isField ? "field" : "method") +
+ (isField ? "field" :
+ memberName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ?
+ "constructor" : "method") +
" '" +
externalMemberDescription +
"' dynamically");
@@ -511,9 +851,12 @@ implements InstructionVisitor,
if (isField)
{
- classVisitor =
+ classVisitor = defaultDescriptor == null ?
+ new AllFieldVisitor(
+ new MemberNameFilter(memberName, this)) :
new AllFieldVisitor(
- new MemberNameFilter(memberName, this));
+ new MemberNameFilter(memberName,
+ new MemberDescriptorFilter(defaultDescriptor, this)));
}
else
{
@@ -521,20 +864,16 @@ implements InstructionVisitor,
String methodDescriptor = "(";
for (int count = 0; count < 2; count++)
{
- int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(A + count);
+ int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(PARAMETER0_CLASS_INDEX + count);
if (memberArgumentIndex > 0)
{
- if (count > 0)
- {
- methodDescriptor += ',';
- }
String className = clazz.getClassName(memberArgumentIndex);
methodDescriptor += ClassUtil.isInternalArrayType(className) ?
className :
ClassUtil.internalTypeFromClassName(className);
}
}
- methodDescriptor += ")L///;";
+ methodDescriptor += ")L***;";
classVisitor =
new AllMethodVisitor(
@@ -571,7 +910,7 @@ implements InstructionVisitor,
System.out.println(" Maybe this is program method '" +
ClassUtil.externalFullClassDescription(0, programClass.getName()) +
" { " +
- ClassUtil.externalFullMethodDescription(null, 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) +
+ ClassUtil.externalFullMethodDescription(programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) +
"; }'");
}
}
@@ -597,7 +936,7 @@ implements InstructionVisitor,
System.out.println(" Maybe this is library method '" +
ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
" { " +
- ClassUtil.externalFullMethodDescription(null, 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) +
+ ClassUtil.externalFullMethodDescription(libraryClass.getName(), 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) +
"; }'");
}
}
diff --git a/src/proguard/classfile/util/EnumFieldReferenceInitializer.java b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java
new file mode 100644
index 0000000..dae6db2
--- /dev/null
+++ b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java
@@ -0,0 +1,150 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.*;
+import proguard.classfile.visitor.*;
+import proguard.util.StringMatcher;
+
+/**
+ * This ElementValueVisitor initializes the field references of the
+ * EnumConstantElementValue instances that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class EnumFieldReferenceInitializer
+extends SimplifiedVisitor
+implements ElementValueVisitor,
+ InstructionVisitor,
+ ConstantVisitor
+{
+ /*
+ private static boolean DEBUG = true;
+ /*/
+ private static final boolean DEBUG = false;
+ //*/
+
+ private MemberVisitor enumFieldFinder = new AllAttributeVisitor(
+ new AllInstructionVisitor(this));
+
+ // Fields acting as parameters and return values for the visitors.
+ private String enumTypeName;
+ private String enumConstantName;
+ private boolean enumConstantNameFound;
+ private Clazz referencedEnumClass;
+ private Field referencedEnumField;
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {}
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+
+ if (enumConstantElementValue.referencedClasses != null &&
+ enumConstantElementValue.referencedClasses.length > 0)
+ {
+ referencedEnumClass = enumConstantElementValue.referencedClasses[0];
+ if (referencedEnumClass != null)
+ {
+ // Try to find the enum field through the static enum
+ // initialization code (at least for program classes).
+ enumTypeName = enumConstantElementValue.getTypeName(clazz);
+ enumConstantName = enumConstantElementValue.getConstantName(clazz);
+ referencedEnumField = null;
+ referencedEnumClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
+ enumFieldFinder);
+
+ // Otherwise try to find the enum field through its name.
+ // The constant name could be different from the field name, if
+ // the latter is already obfuscated.
+ if (referencedEnumField == null)
+ {
+ referencedEnumField =
+ referencedEnumClass.findField(enumConstantName,
+ enumTypeName);
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("EnumFieldReferenceInitializer: ["+referencedEnumClass.getName()+"."+enumConstantName+"] -> "+referencedEnumField);
+ }
+
+ enumConstantElementValue.referencedField = referencedEnumField;
+ }
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_LDC:
+ case InstructionConstants.OP_LDC_W:
+ case InstructionConstants.OP_PUTSTATIC:
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ enumConstantNameFound =
+ enumConstantName.equals(stringConstant.getString(clazz));
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ if (enumConstantNameFound)
+ {
+ if (enumTypeName.equals(fieldrefConstant.getType(clazz)))
+ {
+ referencedEnumField = (Field)fieldrefConstant.referencedMember;
+ }
+
+ enumConstantNameFound = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/util/ExternalTypeEnumeration.java b/src/proguard/classfile/util/ExternalTypeEnumeration.java
index 6371888..e5b7067 100644
--- a/src/proguard/classfile/util/ExternalTypeEnumeration.java
+++ b/src/proguard/classfile/util/ExternalTypeEnumeration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/InstructionSequenceMatcher.java b/src/proguard/classfile/util/InstructionSequenceMatcher.java
index 8a689d5..8c529a9 100644
--- a/src/proguard/classfile/util/InstructionSequenceMatcher.java
+++ b/src/proguard/classfile/util/InstructionSequenceMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
+import java.util.Arrays;
+
/**
* This InstructionVisitor checks whether a given pattern instruction sequence
* occurs in the instructions that are visited. The arguments of the
@@ -40,8 +42,8 @@ implements InstructionVisitor,
ConstantVisitor
{
/*
- private static boolean DEBUG = false;
- public static boolean DEBUG_MORE = false;
+ public static boolean DEBUG = true;
+ public static boolean DEBUG_MORE = true;
/*/
private static final boolean DEBUG = false;
private static final boolean DEBUG_MORE = false;
@@ -60,14 +62,15 @@ implements InstructionVisitor,
private final Constant[] patternConstants;
private final Instruction[] patternInstructions;
- private boolean matching;
- private boolean matchingAnyWildCards;
- private int patternInstructionIndex;
- private final int[] matchedInstructionOffsets;
- private int matchedArgumentFlags;
- private final int[] matchedArguments = new int[7];
- private long matchedConstantFlags;
- private final int[] matchedConstantIndices;
+ private boolean matching;
+ private int patternInstructionIndex;
+ private final int[] matchedInstructionOffsets;
+ private int matchedArgumentFlags;
+ private final int[] matchedArguments = new int[7];
+ private final long[] matchedConstantFlags;
+ private final int[] matchedConstantIndices;
+ private int constantFlags;
+ private int previousConstantFlags;
// Fields acting as a parameter and a return value for visitor methods.
private Constant patternConstant;
@@ -87,6 +90,7 @@ implements InstructionVisitor,
this.patternInstructions = patternInstructions;
matchedInstructionOffsets = new int[patternInstructions.length];
+ matchedConstantFlags = new long[(patternConstants.length + 63) / 64];
matchedConstantIndices = new int[patternConstants.length];
}
@@ -98,34 +102,55 @@ implements InstructionVisitor,
{
patternInstructionIndex = 0;
matchedArgumentFlags = 0;
- matchedConstantFlags = 0L;
- }
+ Arrays.fill(matchedConstantFlags, 0L);
- public boolean isMatching()
- {
- return matching;
+ previousConstantFlags = constantFlags;
+ constantFlags = 0;
}
- public boolean isMatchingAnyWildcards()
+ /**
+ * Returns whether the complete pattern sequence has been matched.
+ */
+ public boolean isMatching()
{
- return matchingAnyWildCards;
+ return matching;
}
+ /**
+ * Returns the number of instructions in the pattern sequence.
+ */
public int instructionCount()
{
return patternInstructions.length;
}
+ /**
+ * Returns the matched instruction offset of the specified pattern
+ * instruction.
+ */
public int matchedInstructionOffset(int index)
{
return matchedInstructionOffsets[index];
}
+ /**
+ * Returns whether the specified wildcard argument was a constant from
+ * the constant pool in the most recent match.
+ */
+ public boolean wasConstant(int argument)
+ {
+ return (previousConstantFlags & (1 << (argument - X))) != 0;
+ }
+
+
+ /**
+ * Returns the value of the specified matched argument (wildcard or not).
+ */
public int matchedArgument(int argument)
{
int argumentIndex = argument - X;
@@ -135,6 +160,9 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the values of the specified matched arguments (wildcard or not).
+ */
public int[] matchedArguments(int[] arguments)
{
int[] matchedArguments = new int[arguments.length];
@@ -148,6 +176,9 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the index of the specified matched constant (wildcard or not).
+ */
public int matchedConstantIndex(int constantIndex)
{
int argumentIndex = constantIndex - X;
@@ -157,6 +188,10 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the value of the specified matched branch offset (wildcard or
+ * not).
+ */
public int matchedBranchOffset(int offset, int branchOffset)
{
int argumentIndex = branchOffset - X;
@@ -166,6 +201,10 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the values of the specified matched jump offsets (wildcard or
+ * not).
+ */
public int[] matchedJumpOffsets(int offset, int[] jumpOffsets)
{
int[] matchedJumpOffsets = new int[jumpOffsets.length];
@@ -387,6 +426,35 @@ implements InstructionVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ InvokeDynamicConstant invokeDynamicPatternConstant = (InvokeDynamicConstant)patternConstant;
+
+ // Check the bootstrap method and the name and type.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ invokeDynamicConstant.getBootstrapMethodAttributeIndex(),
+ invokeDynamicPatternConstant.getBootstrapMethodAttributeIndex()) &&
+ matchingConstantIndices(clazz,
+ invokeDynamicConstant.getNameAndTypeIndex(),
+ invokeDynamicPatternConstant.getNameAndTypeIndex());
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ MethodHandleConstant methodHandlePatternConstant = (MethodHandleConstant)patternConstant;
+
+ // Check the handle type and the name and type.
+ matchingConstant =
+ matchingArguments(methodHandleConstant.getReferenceKind(),
+ methodHandlePatternConstant.getReferenceKind()) &&
+ matchingConstantIndices(clazz,
+ methodHandleConstant.getReferenceIndex(),
+ methodHandlePatternConstant.getReferenceIndex());
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
RefConstant refPatternConstant = (RefConstant)patternConstant;
@@ -414,6 +482,18 @@ implements InstructionVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ MethodTypeConstant typePatternConstant = (MethodTypeConstant)patternConstant;
+
+ // Check the descriptor.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ methodTypeConstant.u2descriptorIndex,
+ typePatternConstant.u2descriptorIndex);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
NameAndTypeConstant typePatternConstant = (NameAndTypeConstant)patternConstant;
@@ -449,11 +529,10 @@ implements InstructionVisitor,
// Check the literal argument.
return argument1 == argument2;
}
- else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0)
+ else if (!isMatchingArgumentIndex(argumentIndex))
{
- // Store a wildcard argument.
- matchedArguments[argumentIndex] = argument1;
- matchedArgumentFlags |= 1 << argumentIndex;
+ // Store the wildcard argument.
+ setMatchingArgument(argumentIndex, argument1);
return true;
}
@@ -465,6 +544,28 @@ implements InstructionVisitor,
}
+ /**
+ * Marks the specified argument (by index) as matching the specified
+ * argument value.
+ */
+ private void setMatchingArgument(int argumentIndex,
+ int argument)
+ {
+ matchedArguments[argumentIndex] = argument;
+ matchedArgumentFlags |= 1 << argumentIndex;
+ }
+
+
+ /**
+ * Returns whether the specified wildcard argument (by index) has been
+ * matched.
+ */
+ private boolean isMatchingArgumentIndex(int argumentIndex)
+ {
+ return (matchedArgumentFlags & (1 << argumentIndex)) != 0;
+ }
+
+
private boolean matchingArguments(int[] arguments1,
int[] arguments2)
{
@@ -491,10 +592,13 @@ implements InstructionVisitor,
{
if (constantIndex2 >= X)
{
+ // Remember that we are trying to match a constant.
+ constantFlags |= 1 << (constantIndex2 - X);
+
// Check the constant index.
return matchingArguments(constantIndex1, constantIndex2);
}
- else if ((matchedConstantFlags & (1L << constantIndex2)) == 0)
+ else if (!isMatchingConstantIndex(constantIndex2))
{
// Check the actual constant.
matchingConstant = false;
@@ -507,8 +611,7 @@ implements InstructionVisitor,
if (matchingConstant)
{
// Store the constant index.
- matchedConstantIndices[constantIndex2] = constantIndex1;
- matchedConstantFlags |= 1L << constantIndex2;
+ setMatchingConstant(constantIndex2, constantIndex1);
}
}
@@ -522,6 +625,27 @@ implements InstructionVisitor,
}
+ /**
+ * Marks the specified constant (by index) as matching the specified
+ * constant index value.
+ */
+ private void setMatchingConstant(int constantIndex,
+ int constantIndex1)
+ {
+ matchedConstantIndices[constantIndex] = constantIndex1;
+ matchedConstantFlags[constantIndex / 64] |= 1L << constantIndex;
+ }
+
+
+ /**
+ * Returns whether the specified wildcard constant has been matched.
+ */
+ private boolean isMatchingConstantIndex(int constantIndex)
+ {
+ return (matchedConstantFlags[constantIndex / 64] & (1L << constantIndex)) != 0;
+ }
+
+
private boolean matchingBranchOffsets(int offset,
int branchOffset1,
int branchOffset2)
@@ -532,11 +656,10 @@ implements InstructionVisitor,
// Check the literal argument.
return branchOffset1 == branchOffset2;
}
- else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0)
+ else if (!isMatchingArgumentIndex(argumentIndex))
{
// Store a wildcard argument.
- matchedArguments[argumentIndex] = offset + branchOffset1;
- matchedArgumentFlags |= 1 << argumentIndex;
+ setMatchingArgument(argumentIndex, offset + branchOffset1);
return true;
}
@@ -595,9 +718,6 @@ implements InstructionVisitor,
// Did we match all instructions in the sequence?
matching = patternInstructionIndex == patternInstructions.length;
- // Did we match any wildcards along the way?
- matchingAnyWildCards = matchedArgumentFlags != 0;
-
if (matching)
{
if (DEBUG)
diff --git a/src/proguard/classfile/util/InternalTypeEnumeration.java b/src/proguard/classfile/util/InternalTypeEnumeration.java
index 76f7e84..9c63ad9 100644
--- a/src/proguard/classfile/util/InternalTypeEnumeration.java
+++ b/src/proguard/classfile/util/InternalTypeEnumeration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,7 +27,7 @@ import proguard.classfile.ClassConstants;
* An <code>InternalTypeEnumeration</code> provides an enumeration of all
* parameter types listed in a given internal method descriptor or signature.
* The signature can also be a class signature. The return type of a method
- * descriptor can retrieved separately.
+ * descriptor can be retrieved separately.
*
* @author Eric Lafortune
*/
diff --git a/src/proguard/classfile/util/MemberFinder.java b/src/proguard/classfile/util/MemberFinder.java
index 0fdeec0..36c0003 100644
--- a/src/proguard/classfile/util/MemberFinder.java
+++ b/src/proguard/classfile/util/MemberFinder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/MethodLinker.java b/src/proguard/classfile/util/MethodLinker.java
index 5f2ea6f..56b6723 100644
--- a/src/proguard/classfile/util/MethodLinker.java
+++ b/src/proguard/classfile/util/MethodLinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,16 +26,11 @@ import proguard.classfile.visitor.*;
import java.util.*;
/**
- * This ClassVisitor links all corresponding non-private methods in the class
- * hierarchies of all visited classes. Visited classes are typically all class
- * files that are not being subclassed. Chains of links that have been created
- * in previous invocations are merged with new chains of links, in order to
- * create a consistent set of chains.
- * <p>
- * As a MemberVisitor, it links all corresponding class members that it visits,
- * including fields and private class members.
- * <p>
- * Class initialization methods and constructors are always ignored.
+ * This ClassVisitor links all corresponding non-private, non-static,
+ * non-initializer methods in the class hierarchies of all visited classes.
+ * Visited classes are typically all class files that are not being subclassed.
+ * Chains of links that have been created in previous invocations are merged
+ * with new chains of links, in order to create a consistent set of chains.
*
* @author Eric Lafortune
*/
@@ -56,7 +51,7 @@ implements ClassVisitor,
// Collect all non-private members in this class hierarchy.
clazz.hierarchyAccept(true, true, true, false,
new AllMethodVisitor(
- new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
+ new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC,
this)));
// Clean up for the next class hierarchy.
diff --git a/src/proguard/classfile/util/SimplifiedVisitor.java b/src/proguard/classfile/util/SimplifiedVisitor.java
index 87b7fe4..aed46eb 100644
--- a/src/proguard/classfile/util/SimplifiedVisitor.java
+++ b/src/proguard/classfile/util/SimplifiedVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -42,7 +42,7 @@ public abstract class SimplifiedVisitor
/**
* Visits any type of class member of the given class.
*/
- public void visitAnyClass(Clazz Clazz)
+ public void visitAnyClass(Clazz clazz)
{
throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
}
@@ -157,6 +157,18 @@ public abstract class SimplifiedVisitor
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ visitAnyConstant(clazz, invokeDynamicConstant);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ visitAnyConstant(clazz, methodHandleConstant);
+ }
+
+
/**
* Visits any type of RefConstant of the given class.
*/
@@ -199,6 +211,12 @@ public abstract class SimplifiedVisitor
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ visitAnyConstant(clazz, methodTypeConstant);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
visitAnyConstant(clazz, nameAndTypeConstant);
@@ -222,6 +240,12 @@ public abstract class SimplifiedVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ visitAnyAttribute(clazz, bootstrapMethodsAttribute);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
visitAnyAttribute(clazz, sourceFileAttribute);
diff --git a/src/proguard/classfile/util/StringReferenceInitializer.java b/src/proguard/classfile/util/StringReferenceInitializer.java
index 3884a04..f00f0d3 100644
--- a/src/proguard/classfile/util/StringReferenceInitializer.java
+++ b/src/proguard/classfile/util/StringReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -62,7 +62,8 @@ implements ConstantVisitor
{
// See if we can find the referenced class.
stringConstant.referencedClass =
- findClass(ClassUtil.internalClassName(stringConstant.getString(clazz)));
+ findClass(ClassUtil.internalClassName(
+ ClassUtil.externalBaseType(stringConstant.getString(clazz))));
}
}
diff --git a/src/proguard/classfile/util/StringSharer.java b/src/proguard/classfile/util/StringSharer.java
index 56de7c5..dacb2d1 100644
--- a/src/proguard/classfile/util/StringSharer.java
+++ b/src/proguard/classfile/util/StringSharer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,6 +64,23 @@ implements ClassVisitor,
{
libraryClass.superClassName = superClass.getName();
}
+
+ // Replace the interface name strings by the shared name strings.
+ if (libraryClass.interfaceNames != null)
+ {
+ String[] interfaceNames = libraryClass.interfaceNames;
+ Clazz[] interfaceClasses = new Clazz[interfaceNames.length];
+
+ for (int index = 0; index < interfaceNames.length; index++)
+ {
+ // Keep a reference to the interface class.
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null)
+ {
+ interfaceNames[index] = interfaceClass.getName();
+ }
+ }
+ }
}
@@ -73,7 +90,7 @@ implements ClassVisitor,
public void visitAnyConstant(Clazz clazz, Constant constant) {}
- public void visitAnyStringConstant(Clazz clazz, StringConstant stringConstant)
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
{
Member referencedMember = stringConstant.referencedMember;
if (referencedMember != null)
diff --git a/src/proguard/classfile/util/WarningPrinter.java b/src/proguard/classfile/util/WarningPrinter.java
index 87d8978..39172dd 100644
--- a/src/proguard/classfile/util/WarningPrinter.java
+++ b/src/proguard/classfile/util/WarningPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllClassVisitor.java b/src/proguard/classfile/visitor/AllClassVisitor.java
index 06aca2c..5c6f3de 100644
--- a/src/proguard/classfile/visitor/AllClassVisitor.java
+++ b/src/proguard/classfile/visitor/AllClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllFieldVisitor.java b/src/proguard/classfile/visitor/AllFieldVisitor.java
index 8bff7d4..92c4b05 100644
--- a/src/proguard/classfile/visitor/AllFieldVisitor.java
+++ b/src/proguard/classfile/visitor/AllFieldVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllMemberVisitor.java b/src/proguard/classfile/visitor/AllMemberVisitor.java
index 448470e..ab26bf3 100644
--- a/src/proguard/classfile/visitor/AllMemberVisitor.java
+++ b/src/proguard/classfile/visitor/AllMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllMethodVisitor.java b/src/proguard/classfile/visitor/AllMethodVisitor.java
index 75b919d..5d8e6a3 100644
--- a/src/proguard/classfile/visitor/AllMethodVisitor.java
+++ b/src/proguard/classfile/visitor/AllMethodVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/BottomClassFilter.java b/src/proguard/classfile/visitor/BottomClassFilter.java
index 8f5bdd1..e094ce3 100644
--- a/src/proguard/classfile/visitor/BottomClassFilter.java
+++ b/src/proguard/classfile/visitor/BottomClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassAccessFilter.java b/src/proguard/classfile/visitor/ClassAccessFilter.java
index a8815b6..1855662 100644
--- a/src/proguard/classfile/visitor/ClassAccessFilter.java
+++ b/src/proguard/classfile/visitor/ClassAccessFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassCleaner.java b/src/proguard/classfile/visitor/ClassCleaner.java
index 36165ef..a7ad1f6 100644
--- a/src/proguard/classfile/visitor/ClassCleaner.java
+++ b/src/proguard/classfile/visitor/ClassCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassCollector.java b/src/proguard/classfile/visitor/ClassCollector.java
index a69fe76..a24bb0b 100644
--- a/src/proguard/classfile/visitor/ClassCollector.java
+++ b/src/proguard/classfile/visitor/ClassCollector.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassCounter.java b/src/proguard/classfile/visitor/ClassCounter.java
index c58c090..b6deef2 100644
--- a/src/proguard/classfile/visitor/ClassCounter.java
+++ b/src/proguard/classfile/visitor/ClassCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
index 2e1755e..38ba3d6 100644
--- a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
+++ b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassNameFilter.java b/src/proguard/classfile/visitor/ClassNameFilter.java
index c016a34..bd66eb1 100644
--- a/src/proguard/classfile/visitor/ClassNameFilter.java
+++ b/src/proguard/classfile/visitor/ClassNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -70,7 +70,7 @@ public class ClassNameFilter implements ClassVisitor
/**
* Creates a new ClassNameFilter.
- * @param regularExpressionMatcher the regular expression against which
+ * @param regularExpressionMatcher the string matcher against which
* class names will be matched.
* @param classVisitor the <code>ClassVisitor</code> to which
* visits will be delegated.
diff --git a/src/proguard/classfile/visitor/ClassPoolFiller.java b/src/proguard/classfile/visitor/ClassPoolFiller.java
index e1773de..ae234be 100644
--- a/src/proguard/classfile/visitor/ClassPoolFiller.java
+++ b/src/proguard/classfile/visitor/ClassPoolFiller.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPoolVisitor.java b/src/proguard/classfile/visitor/ClassPoolVisitor.java
index 0b659dc..821304a 100644
--- a/src/proguard/classfile/visitor/ClassPoolVisitor.java
+++ b/src/proguard/classfile/visitor/ClassPoolVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPresenceFilter.java b/src/proguard/classfile/visitor/ClassPresenceFilter.java
index 429c340..0c55d1d 100644
--- a/src/proguard/classfile/visitor/ClassPresenceFilter.java
+++ b/src/proguard/classfile/visitor/ClassPresenceFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPrinter.java b/src/proguard/classfile/visitor/ClassPrinter.java
index 1da7d16..3121e58 100644
--- a/src/proguard/classfile/visitor/ClassPrinter.java
+++ b/src/proguard/classfile/visitor/ClassPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -48,8 +48,9 @@ implements ClassVisitor,
ConstantVisitor,
MemberVisitor,
AttributeVisitor,
- ExceptionInfoVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
StackMapFrameVisitor,
VerificationTypeVisitor,
LineNumberInfoVisitor,
@@ -62,7 +63,8 @@ implements ClassVisitor,
private static final String INDENTATION = " ";
private final PrintStream ps;
- private int indentation;
+
+ private int indentation;
/**
@@ -95,6 +97,7 @@ implements ClassVisitor,
println("Superclass: " + programClass.getSuperName());
println("Major version: 0x" + Integer.toHexString(ClassUtil.internalMajorClassVersion(programClass.u4version)));
println("Minor version: 0x" + Integer.toHexString(ClassUtil.internalMinorClassVersion(programClass.u4version)));
+ println(" = target " + ClassUtil.externalClassVersion(programClass.u4version));
println("Access flags: 0x" + Integer.toHexString(programClass.u2accessFlags));
println(" = " +
((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") +
@@ -222,10 +225,30 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ println(visitorInfo(invokeDynamicConstant) + " InvokeDynamic [bootstrap method index = " + invokeDynamicConstant.u2bootstrapMethodAttributeIndex + "]:");
+
+ indent();
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+ outdent();
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ println(visitorInfo(methodHandleConstant) + " MethodHandle [kind = " + methodHandleConstant.u1referenceKind + "]:");
+
+ indent();
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ outdent();
+ }
+
+
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
println(visitorInfo(fieldrefConstant) + " Fieldref [" +
- clazz.getClassName(fieldrefConstant.u2classIndex) + "." +
+ clazz.getClassName(fieldrefConstant.u2classIndex) + "." +
clazz.getName(fieldrefConstant.u2nameAndTypeIndex) + " " +
clazz.getType(fieldrefConstant.u2nameAndTypeIndex) + "]");
}
@@ -256,6 +279,13 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ println(visitorInfo(methodTypeConstant) + " MethodType [" +
+ clazz.getString(methodTypeConstant.u2descriptorIndex) + "]");
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
println(visitorInfo(nameAndTypeConstant) + " NameAndType [" +
@@ -361,6 +391,17 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ println(visitorInfo(bootstrapMethodsAttribute) +
+ " Bootstrap methods attribute (count = " + bootstrapMethodsAttribute.u2bootstrapMethodsCount + "):");
+
+ indent();
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ outdent();
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
println(visitorInfo(sourceFileAttribute) +
@@ -595,6 +636,21 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ println(visitorInfo(bootstrapMethodInfo) +
+ " BootstrapMethodInfo (argument count = " +
+ bootstrapMethodInfo.u2methodArgumentCount+ "):");
+
+ indent();
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
+ outdent();
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
@@ -603,6 +659,8 @@ implements ClassVisitor,
" InnerClassesInfo:");
indent();
+ println("Access flags: 0x" + Integer.toHexString(innerClassesInfo.u2innerClassAccessFlags) + " = " +
+ ClassUtil.externalClassAccessFlags(innerClassesInfo.u2innerClassAccessFlags));
innerClassesInfo.innerClassConstantAccept(clazz, this);
innerClassesInfo.outerClassConstantAccept(clazz, this);
innerClassesInfo.innerNameConstantAccept(clazz, this);
@@ -816,7 +874,7 @@ implements ClassVisitor,
public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
{
- println("#" + localVariableInfo.u2index + ": " +
+ println("v" + localVariableInfo.u2index + ": " +
localVariableInfo.u2startPC + " -> " +
(localVariableInfo.u2startPC + localVariableInfo.u2length) + " [" +
clazz.getString(localVariableInfo.u2descriptorIndex) + " " +
@@ -828,7 +886,7 @@ implements ClassVisitor,
public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
{
- println("#" + localVariableTypeInfo.u2index + ": " +
+ println("v" + localVariableTypeInfo.u2index + ": " +
localVariableTypeInfo.u2startPC + " -> " +
(localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length) + " [" +
clazz.getString(localVariableTypeInfo.u2signatureIndex) + " " +
diff --git a/src/proguard/classfile/visitor/ClassVersionFilter.java b/src/proguard/classfile/visitor/ClassVersionFilter.java
index 578cabf..73bcc6a 100644
--- a/src/proguard/classfile/visitor/ClassVersionFilter.java
+++ b/src/proguard/classfile/visitor/ClassVersionFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,6 +39,19 @@ public class ClassVersionFilter implements ClassVisitor
/**
* Creates a new ClassVersionFilter.
* @param minimumClassVersion the minimum class version number.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ClassVersionFilter(int minimumClassVersion,
+ ClassVisitor classVisitor)
+ {
+ this(minimumClassVersion, Integer.MAX_VALUE, classVisitor);
+ }
+
+
+ /**
+ * Creates a new ClassVersionFilter.
+ * @param minimumClassVersion the minimum class version number.
* @param maximumClassVersion the maximum class version number.
* @param classVisitor the <code>ClassVisitor</code> to which visits
* will be delegated.
diff --git a/src/proguard/classfile/visitor/ClassVersionSetter.java b/src/proguard/classfile/visitor/ClassVersionSetter.java
index 34dfbc1..d3f0183 100644
--- a/src/proguard/classfile/visitor/ClassVersionSetter.java
+++ b/src/proguard/classfile/visitor/ClassVersionSetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassVisitor.java b/src/proguard/classfile/visitor/ClassVisitor.java
index fdba2df..c423446 100644
--- a/src/proguard/classfile/visitor/ClassVisitor.java
+++ b/src/proguard/classfile/visitor/ClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java b/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
index ec3fe68..0b971f0 100644
--- a/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
+++ b/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/DotClassClassVisitor.java b/src/proguard/classfile/visitor/DotClassClassVisitor.java
index 263dbd5..979f846 100644
--- a/src/proguard/classfile/visitor/DotClassClassVisitor.java
+++ b/src/proguard/classfile/visitor/DotClassClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -36,8 +36,6 @@ import proguard.classfile.util.SimplifiedVisitor;
* Note that before JDK 1.5, <code>.class</code> constructs are actually
* compiled differently, using <code>Class.forName</code> constructs.
*
- * @see ClassForNameClassVisitor
- *
* @author Eric Lafortune
*/
public class DotClassClassVisitor
diff --git a/src/proguard/classfile/visitor/ExceptClassFilter.java b/src/proguard/classfile/visitor/ExceptClassFilter.java
index 924485e..25c6e68 100644
--- a/src/proguard/classfile/visitor/ExceptClassFilter.java
+++ b/src/proguard/classfile/visitor/ExceptClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptClassesFilter.java b/src/proguard/classfile/visitor/ExceptClassesFilter.java
index 7380c40..bdf72bd 100644
--- a/src/proguard/classfile/visitor/ExceptClassesFilter.java
+++ b/src/proguard/classfile/visitor/ExceptClassesFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionCounter.java b/src/proguard/classfile/visitor/ExceptionCounter.java
index c324129..5c476b6 100644
--- a/src/proguard/classfile/visitor/ExceptionCounter.java
+++ b/src/proguard/classfile/visitor/ExceptionCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java b/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
index 3911e39..2fd18ae 100644
--- a/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java b/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
index e0fdec3..de7139b 100644
--- a/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
+++ b/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionHandlerFilter.java b/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
index a90fb56..36ead5e 100644
--- a/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionOffsetFilter.java b/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
index e2a4fc9..c84473a 100644
--- a/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionRangeFilter.java b/src/proguard/classfile/visitor/ExceptionRangeFilter.java
index c541b1f..626a32e 100644
--- a/src/proguard/classfile/visitor/ExceptionRangeFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionRangeFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java b/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
index 6fe2e7d..334b85f 100644
--- a/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
+++ b/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ImplementedClassFilter.java b/src/proguard/classfile/visitor/ImplementedClassFilter.java
index 955a74e..abbacfb 100644
--- a/src/proguard/classfile/visitor/ImplementedClassFilter.java
+++ b/src/proguard/classfile/visitor/ImplementedClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java b/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
index 9e9cea3..8e7010d 100644
--- a/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
+++ b/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/LibraryClassFilter.java b/src/proguard/classfile/visitor/LibraryClassFilter.java
index 0e40f2f..7437ed3 100644
--- a/src/proguard/classfile/visitor/LibraryClassFilter.java
+++ b/src/proguard/classfile/visitor/LibraryClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/LibraryMemberFilter.java b/src/proguard/classfile/visitor/LibraryMemberFilter.java
index 0ee80e5..eae0698 100644
--- a/src/proguard/classfile/visitor/LibraryMemberFilter.java
+++ b/src/proguard/classfile/visitor/LibraryMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberAccessFilter.java b/src/proguard/classfile/visitor/MemberAccessFilter.java
index 6fd32e3..6bdc152 100644
--- a/src/proguard/classfile/visitor/MemberAccessFilter.java
+++ b/src/proguard/classfile/visitor/MemberAccessFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberClassAccessFilter.java b/src/proguard/classfile/visitor/MemberClassAccessFilter.java
index 85272ff..3605407 100644
--- a/src/proguard/classfile/visitor/MemberClassAccessFilter.java
+++ b/src/proguard/classfile/visitor/MemberClassAccessFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberCollector.java b/src/proguard/classfile/visitor/MemberCollector.java
index ec68b2d..46665f8 100644
--- a/src/proguard/classfile/visitor/MemberCollector.java
+++ b/src/proguard/classfile/visitor/MemberCollector.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberCounter.java b/src/proguard/classfile/visitor/MemberCounter.java
index c2da72e..58df4a7 100644
--- a/src/proguard/classfile/visitor/MemberCounter.java
+++ b/src/proguard/classfile/visitor/MemberCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberDescriptorFilter.java b/src/proguard/classfile/visitor/MemberDescriptorFilter.java
index bd69304..cce515a 100644
--- a/src/proguard/classfile/visitor/MemberDescriptorFilter.java
+++ b/src/proguard/classfile/visitor/MemberDescriptorFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberNameFilter.java b/src/proguard/classfile/visitor/MemberNameFilter.java
index 0fe450e..9996a4e 100644
--- a/src/proguard/classfile/visitor/MemberNameFilter.java
+++ b/src/proguard/classfile/visitor/MemberNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -47,7 +47,8 @@ public class MemberNameFilter implements MemberVisitor
public MemberNameFilter(String regularExpression,
MemberVisitor memberVisitor)
{
- this(new NameParser().parse(regularExpression), memberVisitor);
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ memberVisitor);
}
diff --git a/src/proguard/classfile/visitor/MemberToClassVisitor.java b/src/proguard/classfile/visitor/MemberToClassVisitor.java
index a405cfc..e82e52f 100644
--- a/src/proguard/classfile/visitor/MemberToClassVisitor.java
+++ b/src/proguard/classfile/visitor/MemberToClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberVisitor.java b/src/proguard/classfile/visitor/MemberVisitor.java
index 01fdf71..7b45662 100644
--- a/src/proguard/classfile/visitor/MemberVisitor.java
+++ b/src/proguard/classfile/visitor/MemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MethodImplementationFilter.java b/src/proguard/classfile/visitor/MethodImplementationFilter.java
index 57d923a..893a699 100644
--- a/src/proguard/classfile/visitor/MethodImplementationFilter.java
+++ b/src/proguard/classfile/visitor/MethodImplementationFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MethodImplementationTraveler.java b/src/proguard/classfile/visitor/MethodImplementationTraveler.java
index dc0ea36..c9f942e 100644
--- a/src/proguard/classfile/visitor/MethodImplementationTraveler.java
+++ b/src/proguard/classfile/visitor/MethodImplementationTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiClassPoolVisitor.java b/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
index 044d55a..0e96cf1 100644
--- a/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
+++ b/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiClassVisitor.java b/src/proguard/classfile/visitor/MultiClassVisitor.java
index d34d91e..059e9b7 100644
--- a/src/proguard/classfile/visitor/MultiClassVisitor.java
+++ b/src/proguard/classfile/visitor/MultiClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiMemberVisitor.java b/src/proguard/classfile/visitor/MultiMemberVisitor.java
index cc4629c..800d65f 100644
--- a/src/proguard/classfile/visitor/MultiMemberVisitor.java
+++ b/src/proguard/classfile/visitor/MultiMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedClassVisitor.java b/src/proguard/classfile/visitor/NamedClassVisitor.java
index a14d04a..79e14c9 100644
--- a/src/proguard/classfile/visitor/NamedClassVisitor.java
+++ b/src/proguard/classfile/visitor/NamedClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedFieldVisitor.java b/src/proguard/classfile/visitor/NamedFieldVisitor.java
index 76b66c6..685f62d 100644
--- a/src/proguard/classfile/visitor/NamedFieldVisitor.java
+++ b/src/proguard/classfile/visitor/NamedFieldVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedMethodVisitor.java b/src/proguard/classfile/visitor/NamedMethodVisitor.java
index d4611c1..c2baf19 100644
--- a/src/proguard/classfile/visitor/NamedMethodVisitor.java
+++ b/src/proguard/classfile/visitor/NamedMethodVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ProgramClassFilter.java b/src/proguard/classfile/visitor/ProgramClassFilter.java
index fba3b21..976658c 100644
--- a/src/proguard/classfile/visitor/ProgramClassFilter.java
+++ b/src/proguard/classfile/visitor/ProgramClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ProgramMemberFilter.java b/src/proguard/classfile/visitor/ProgramMemberFilter.java
index 048a1e6..cf187fb 100644
--- a/src/proguard/classfile/visitor/ProgramMemberFilter.java
+++ b/src/proguard/classfile/visitor/ProgramMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ReferencedClassVisitor.java b/src/proguard/classfile/visitor/ReferencedClassVisitor.java
index 986c3f9..e7fe855 100644
--- a/src/proguard/classfile/visitor/ReferencedClassVisitor.java
+++ b/src/proguard/classfile/visitor/ReferencedClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -123,6 +123,13 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Let the visitor visit the class referenced in the reference constant.
+ invokeDynamicConstant.referencedClassesAccept(classVisitor);
+ }
+
+
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
// Let the visitor visit the class referenced in the class constant.
diff --git a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
index c4d34b8..3c59075 100644
--- a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
+++ b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SimilarMemberVisitor.java b/src/proguard/classfile/visitor/SimilarMemberVisitor.java
index 6dc06af..5087f48 100644
--- a/src/proguard/classfile/visitor/SimilarMemberVisitor.java
+++ b/src/proguard/classfile/visitor/SimilarMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SimpleClassPrinter.java b/src/proguard/classfile/visitor/SimpleClassPrinter.java
index a661110..df630c7 100644
--- a/src/proguard/classfile/visitor/SimpleClassPrinter.java
+++ b/src/proguard/classfile/visitor/SimpleClassPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SubclassFilter.java b/src/proguard/classfile/visitor/SubclassFilter.java
index 69ea1a1..6b6f84b 100644
--- a/src/proguard/classfile/visitor/SubclassFilter.java
+++ b/src/proguard/classfile/visitor/SubclassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SubclassTraveler.java b/src/proguard/classfile/visitor/SubclassTraveler.java
index 4170341..32dccb7 100644
--- a/src/proguard/classfile/visitor/SubclassTraveler.java
+++ b/src/proguard/classfile/visitor/SubclassTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/VariableClassVisitor.java b/src/proguard/classfile/visitor/VariableClassVisitor.java
index 2f575c4..17a5522 100644
--- a/src/proguard/classfile/visitor/VariableClassVisitor.java
+++ b/src/proguard/classfile/visitor/VariableClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/VariableMemberVisitor.java b/src/proguard/classfile/visitor/VariableMemberVisitor.java
index c58cff3..34c39f3 100644
--- a/src/proguard/classfile/visitor/VariableMemberVisitor.java
+++ b/src/proguard/classfile/visitor/VariableMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/BasicBranchUnit.java b/src/proguard/evaluation/BasicBranchUnit.java
index 3a2db76..127e922 100644
--- a/src/proguard/evaluation/BasicBranchUnit.java
+++ b/src/proguard/evaluation/BasicBranchUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/BasicInvocationUnit.java b/src/proguard/evaluation/BasicInvocationUnit.java
index bccd866..474556c 100644
--- a/src/proguard/evaluation/BasicInvocationUnit.java
+++ b/src/proguard/evaluation/BasicInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -162,6 +162,7 @@ implements InvocationUnit,
break;
case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
isStatic = true;
break;
@@ -230,6 +231,31 @@ implements InvocationUnit,
}
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ String type = invokeDynamicConstant.getType(clazz);
+
+ // Count the number of parameters.
+ int parameterCount = ClassUtil.internalMethodParameterCount(type);
+ if (!isStatic)
+ {
+ parameterCount++;
+ }
+
+ // Pop the parameters and the class reference, in reverse order.
+ for (int parameterIndex = parameterCount-1; parameterIndex >= 0; parameterIndex--)
+ {
+ stack.pop();
+ }
+
+ // Push the return value, if applicable.
+ String returnType = ClassUtil.internalMethodReturnType(type);
+ if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID)
+ {
+ stack.push(getMethodReturnValue(clazz, invokeDynamicConstant, returnType));
+ }
+ }
+
/**
* Sets the class through which the specified field is accessed.
@@ -340,6 +366,25 @@ implements InvocationUnit,
}
+ /**
+ * Returns the return value of the specified method.
+ */
+ protected Value getMethodReturnValue(Clazz clazz,
+ InvokeDynamicConstant invokeDynamicConstant,
+ String type)
+ {
+ // Try to figure out the class of the return type.
+ Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses;
+
+ Clazz returnTypeClass = referencedClasses == null ? null :
+ referencedClasses[referencedClasses.length - 1];
+
+ return valueFactory.createValue(type,
+ returnTypeClass,
+ true);
+ }
+
+
// Implementations for MemberVisitor.
public void visitProgramField(ProgramClass programClass, ProgramField programField)
diff --git a/src/proguard/evaluation/BranchUnit.java b/src/proguard/evaluation/BranchUnit.java
index b709807..a381da7 100644
--- a/src/proguard/evaluation/BranchUnit.java
+++ b/src/proguard/evaluation/BranchUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/ClassConstantValueFactory.java b/src/proguard/evaluation/ClassConstantValueFactory.java
new file mode 100644
index 0000000..1c418c2
--- /dev/null
+++ b/src/proguard/evaluation/ClassConstantValueFactory.java
@@ -0,0 +1,53 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This class creates java.lang.Class ReferenceValue instances that correspond
+ * to specified constant pool entries.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassConstantValueFactory
+extends ConstantValueFactory
+{
+ public ClassConstantValueFactory(ValueFactory valueFactory)
+ {
+ super(valueFactory);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Create a Class reference instead of a reference to the class.
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS,
+ classConstant.javaLangClassClass,
+ false);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/evaluation/ConstantValueFactory.java b/src/proguard/evaluation/ConstantValueFactory.java
new file mode 100644
index 0000000..0afb20c
--- /dev/null
+++ b/src/proguard/evaluation/ConstantValueFactory.java
@@ -0,0 +1,113 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This class creates Value instance that correspond to specified constant pool
+ * entries.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantValueFactory
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ protected final ValueFactory valueFactory;
+
+ // Field acting as a parameter for the ConstantVisitor methods.
+ protected Value value;
+
+
+ public ConstantValueFactory(ValueFactory valueFactory)
+ {
+ this.valueFactory = valueFactory;
+ }
+
+
+ /**
+ * Returns the Value of the constant pool element at the given index.
+ */
+ public Value constantValue(Clazz clazz,
+ int constantIndex)
+ {
+ // Visit the constant pool entry to get its return value.
+ clazz.constantPoolEntryAccept(constantIndex, this);
+
+ return value;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ value = valueFactory.createIntegerValue(integerConstant.getValue());
+ }
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ value = valueFactory.createLongValue(longConstant.getValue());
+ }
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ value = valueFactory.createFloatValue(floatConstant.getValue());
+ }
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ value = valueFactory.createDoubleValue(doubleConstant.getValue());
+ }
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING,
+ stringConstant.javaLangStringClass,
+ false);
+ }
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE,
+ methodHandleConstant.javaLangInvokeMethodHandleClass,
+ false);
+ }
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ value = valueFactory.createReferenceValue(classConstant.getName(clazz),
+ classConstant.referencedClass,
+ false);
+ }
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE,
+ methodTypeConstant.javaLangInvokeMethodTypeClass,
+ false);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/evaluation/InvocationUnit.java b/src/proguard/evaluation/InvocationUnit.java
index cb4d3c5..e526b35 100644
--- a/src/proguard/evaluation/InvocationUnit.java
+++ b/src/proguard/evaluation/InvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/Processor.java b/src/proguard/evaluation/Processor.java
index 74afd0b..3bfc5f3 100644
--- a/src/proguard/evaluation/Processor.java
+++ b/src/proguard/evaluation/Processor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,11 +22,8 @@ package proguard.evaluation;
import proguard.classfile.*;
import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
import proguard.evaluation.value.*;
/**
@@ -36,9 +33,7 @@ import proguard.evaluation.value.*;
* @author Eric Lafortune
*/
public class Processor
-extends SimplifiedVisitor
-implements InstructionVisitor,
- ConstantVisitor
+implements InstructionVisitor
{
private final Variables variables;
private final Stack stack;
@@ -46,9 +41,8 @@ implements InstructionVisitor,
private final BranchUnit branchUnit;
private final InvocationUnit invocationUnit;
- // Fields acting as parameters for the ConstantVisitor methods.
- private boolean handleClassConstantAsClassValue;
- private Value cpValue;
+ private final ConstantValueFactory constantValueFactory;
+ private final ClassConstantValueFactory classConstantValueFactory;
/**
@@ -69,6 +63,9 @@ implements InstructionVisitor,
this.valueFactory = valueFactory;
this.branchUnit = branchUnit;
this.invocationUnit = invocationUnit;
+
+ constantValueFactory = new ConstantValueFactory(valueFactory);
+ classConstantValueFactory = new ClassConstantValueFactory(valueFactory);
}
@@ -561,7 +558,7 @@ implements InstructionVisitor,
case InstructionConstants.OP_LDC:
case InstructionConstants.OP_LDC_W:
case InstructionConstants.OP_LDC2_W:
- stack.push(cpValue(clazz, constantIndex, true));
+ stack.push(classConstantValueFactory.constantValue(clazz, constantIndex));
break;
case InstructionConstants.OP_GETSTATIC:
@@ -572,16 +569,17 @@ implements InstructionVisitor,
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
invocationUnit.invokeMember(clazz, method, codeAttribute, offset, constantInstruction, stack);
break;
case InstructionConstants.OP_NEW:
- stack.push(cpValue(clazz, constantIndex).referenceValue());
+ stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
break;
case InstructionConstants.OP_ANEWARRAY:
{
- ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue();
+ ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
stack.push(valueFactory.createArrayReferenceValue(referenceValue.internalType(),
referenceValue.getReferencedClass(),
@@ -594,14 +592,14 @@ implements InstructionVisitor,
ReferenceValue castValue = stack.apop();
ReferenceValue castResultValue =
castValue.isNull() == Value.ALWAYS ? castValue :
- castValue.isNull() == Value.NEVER ? cpValue(clazz, constantIndex).referenceValue() :
- cpValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull());
+ castValue.isNull() == Value.NEVER ? constantValueFactory.constantValue(clazz, constantIndex).referenceValue() :
+ constantValueFactory.constantValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull());
stack.push(castResultValue);
break;
case InstructionConstants.OP_INSTANCEOF:
{
- ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue();
+ ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
int instanceOf = stack.apop().instanceOf(referenceValue.getType(),
referenceValue.getReferencedClass());
@@ -621,7 +619,7 @@ implements InstructionVisitor,
IntegerValue arrayLength = stack.ipop();
}
- stack.push(cpValue(clazz, constantIndex).referenceValue());
+ stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
break;
}
@@ -907,73 +905,4 @@ implements InstructionVisitor,
}
}
}
-
-
- // Implementations for ConstantVisitor.
-
- public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
- {
- cpValue = valueFactory.createIntegerValue(integerConstant.getValue());
- }
-
- public void visitLongConstant(Clazz clazz, LongConstant longConstant)
- {
- cpValue = valueFactory.createLongValue(longConstant.getValue());
- }
-
- public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
- {
- cpValue = valueFactory.createFloatValue(floatConstant.getValue());
- }
-
- public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
- {
- cpValue = valueFactory.createDoubleValue(doubleConstant.getValue());
- }
-
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
- {
- cpValue = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING,
- stringConstant.javaLangStringClass,
- false);
- }
-
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
- {
- cpValue = handleClassConstantAsClassValue ?
- valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS,
- classConstant.javaLangClassClass,
- false) :
- valueFactory.createReferenceValue(classConstant.getName(clazz),
- classConstant.referencedClass,
- false);
- }
-
-
- // Small utility methods.
-
- /**
- * Returns the Value of the constant pool element at the given index.
- */
- private Value cpValue(Clazz clazz,
- int constantIndex)
- {
- return cpValue(clazz, constantIndex, false);
- }
-
-
- /**
- * Returns the Value of the constant pool element at the given index.
- */
- private Value cpValue(Clazz clazz,
- int constantIndex,
- boolean handleClassConstantAsClassValue)
- {
- this.handleClassConstantAsClassValue = handleClassConstantAsClassValue;
-
- // Visit the constant pool entry to get its return value.
- clazz.constantPoolEntryAccept(constantIndex, this);
-
- return cpValue;
- }
}
diff --git a/src/proguard/evaluation/Stack.java b/src/proguard/evaluation/Stack.java
index 2808e62..c449e86 100644
--- a/src/proguard/evaluation/Stack.java
+++ b/src/proguard/evaluation/Stack.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,6 +22,8 @@ package proguard.evaluation;
import proguard.evaluation.value.*;
+import java.util.Arrays;
+
/**
* This class represents an operand stack that contains <code>Value</code>
* objects.
@@ -163,10 +165,7 @@ public class Stack
public void clear()
{
// Clear the stack contents.
- for (int index = 0; index < currentSize; index++)
- {
- values[index] = null;
- }
+ Arrays.fill(values, 0, currentSize, null);
currentSize = 0;
}
diff --git a/src/proguard/evaluation/TracedStack.java b/src/proguard/evaluation/TracedStack.java
index c24f783..08778a1 100644
--- a/src/proguard/evaluation/TracedStack.java
+++ b/src/proguard/evaluation/TracedStack.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/TracedVariables.java b/src/proguard/evaluation/TracedVariables.java
index 1ae6ba6..fef54e1 100644
--- a/src/proguard/evaluation/TracedVariables.java
+++ b/src/proguard/evaluation/TracedVariables.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -30,9 +30,6 @@ import proguard.evaluation.value.Value;
* stores. It then generalizes a given collected Value with the producer Value
* of each Value it loads. The producer Value and the initial collected Value
* can be set; the generalized collected Value can be retrieved.
- * <p>
- * In addition, an initialization index can be reset and retrieved, pointing
- * to the most recent variable that has been initialized by a store operation.
*
* @author Eric Lafortune
*/
@@ -43,7 +40,6 @@ public class TracedVariables extends Variables
private Value producerValue;
private Variables producerVariables;
- private int initializationIndex;
/**
@@ -78,24 +74,6 @@ public class TracedVariables extends Variables
/**
- * Resets the initialization index.
- */
- public void resetInitialization()
- {
- initializationIndex = NONE;
- }
-
-
- /**
- * Returns the most recent initialization index since it has been reset.
- */
- public int getInitializationIndex()
- {
- return initializationIndex;
- }
-
-
- /**
* Gets the producer Value for the specified variable, without disturbing it.
* @param index the variable index.
* @return the producer value of the given variable.
@@ -164,14 +142,6 @@ public class TracedVariables extends Variables
public void store(int index, Value value)
{
- // Is this store operation an initialization of the variable?
- Value previousValue = super.load(index);
- if (previousValue == null ||
- previousValue.computationalType() != value.computationalType())
- {
- initializationIndex = index;
- }
-
// Store the value itself in the variable.
super.store(index, value);
diff --git a/src/proguard/evaluation/Variables.java b/src/proguard/evaluation/Variables.java
index 4496aaa..16b39e7 100644
--- a/src/proguard/evaluation/Variables.java
+++ b/src/proguard/evaluation/Variables.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,6 +22,8 @@ package proguard.evaluation;
import proguard.evaluation.value.*;
+import java.util.Arrays;
+
/**
* This class represents a local variable frame that contains <code>Value</code>
* objects. Values are generalizations of all values that have been stored in
@@ -75,10 +77,7 @@ public class Variables
else
{
// Clear the variables.
- for (int index = 0; index < values.length; index++)
- {
- values[index] = null;
- }
+ Arrays.fill(values, null);
}
this.size = size;
diff --git a/src/proguard/evaluation/value/Category1Value.java b/src/proguard/evaluation/value/Category1Value.java
index b8c5db2..a5ebf86 100644
--- a/src/proguard/evaluation/value/Category1Value.java
+++ b/src/proguard/evaluation/value/Category1Value.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/Category2Value.java b/src/proguard/evaluation/value/Category2Value.java
index 65916c7..2be6e71 100644
--- a/src/proguard/evaluation/value/Category2Value.java
+++ b/src/proguard/evaluation/value/Category2Value.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ComparisonValue.java b/src/proguard/evaluation/value/ComparisonValue.java
index e4e2e02..abbf31c 100644
--- a/src/proguard/evaluation/value/ComparisonValue.java
+++ b/src/proguard/evaluation/value/ComparisonValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -35,11 +35,11 @@ final class ComparisonValue extends SpecificIntegerValue
/**
* Creates a new comparison integer value of the two given scalar values.
*/
- public ComparisonValue(Value integerValue1,
- Value integerValue2)
+ public ComparisonValue(Value value1,
+ Value value2)
{
- this.value1 = integerValue1;
- this.value2 = integerValue2;
+ this.value1 = value1;
+ this.value2 = value2;
}
diff --git a/src/proguard/evaluation/value/CompositeDoubleValue.java b/src/proguard/evaluation/value/CompositeDoubleValue.java
index a6d48ef..be739ed 100644
--- a/src/proguard/evaluation/value/CompositeDoubleValue.java
+++ b/src/proguard/evaluation/value/CompositeDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/CompositeFloatValue.java b/src/proguard/evaluation/value/CompositeFloatValue.java
index 4df890a..0961068 100644
--- a/src/proguard/evaluation/value/CompositeFloatValue.java
+++ b/src/proguard/evaluation/value/CompositeFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -36,7 +36,7 @@ final class CompositeFloatValue extends SpecificFloatValue
private final FloatValue floatValue1;
- private final byte operation;
+ private final byte operation;
private final FloatValue floatValue2;
@@ -45,11 +45,11 @@ final class CompositeFloatValue extends SpecificFloatValue
* and the given operation.
*/
public CompositeFloatValue(FloatValue floatValue1,
- byte operation,
- FloatValue floatValue2)
+ byte operation,
+ FloatValue floatValue2)
{
this.floatValue1 = floatValue1;
- this.operation = operation;
+ this.operation = operation;
this.floatValue2 = floatValue2;
}
diff --git a/src/proguard/evaluation/value/CompositeIntegerValue.java b/src/proguard/evaluation/value/CompositeIntegerValue.java
index 6d4f59c..97caa2f 100644
--- a/src/proguard/evaluation/value/CompositeIntegerValue.java
+++ b/src/proguard/evaluation/value/CompositeIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/CompositeLongValue.java b/src/proguard/evaluation/value/CompositeLongValue.java
index 7f63211..3b8a97f 100644
--- a/src/proguard/evaluation/value/CompositeLongValue.java
+++ b/src/proguard/evaluation/value/CompositeLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedByteValue.java b/src/proguard/evaluation/value/ConvertedByteValue.java
index 7ab5d0a..eb1a350 100644
--- a/src/proguard/evaluation/value/ConvertedByteValue.java
+++ b/src/proguard/evaluation/value/ConvertedByteValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedCharacterValue.java b/src/proguard/evaluation/value/ConvertedCharacterValue.java
index 76568d1..a491bed 100644
--- a/src/proguard/evaluation/value/ConvertedCharacterValue.java
+++ b/src/proguard/evaluation/value/ConvertedCharacterValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedDoubleValue.java b/src/proguard/evaluation/value/ConvertedDoubleValue.java
index a6afe34..65fab84 100644
--- a/src/proguard/evaluation/value/ConvertedDoubleValue.java
+++ b/src/proguard/evaluation/value/ConvertedDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedFloatValue.java b/src/proguard/evaluation/value/ConvertedFloatValue.java
index 33683b7..e74ec8d 100644
--- a/src/proguard/evaluation/value/ConvertedFloatValue.java
+++ b/src/proguard/evaluation/value/ConvertedFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedIntegerValue.java b/src/proguard/evaluation/value/ConvertedIntegerValue.java
index aecb533..273b5a1 100644
--- a/src/proguard/evaluation/value/ConvertedIntegerValue.java
+++ b/src/proguard/evaluation/value/ConvertedIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedLongValue.java b/src/proguard/evaluation/value/ConvertedLongValue.java
index ec97008..5cb9104 100644
--- a/src/proguard/evaluation/value/ConvertedLongValue.java
+++ b/src/proguard/evaluation/value/ConvertedLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedShortValue.java b/src/proguard/evaluation/value/ConvertedShortValue.java
index ab79b49..cef2a20 100644
--- a/src/proguard/evaluation/value/ConvertedShortValue.java
+++ b/src/proguard/evaluation/value/ConvertedShortValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/DoubleValue.java b/src/proguard/evaluation/value/DoubleValue.java
index e39ee5c..6630b2f 100644
--- a/src/proguard/evaluation/value/DoubleValue.java
+++ b/src/proguard/evaluation/value/DoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -342,11 +342,6 @@ public abstract class DoubleValue extends Category2Value
return this;
}
- public Value refresh()
- {
- return this;
- }
-
public final Value generalize(Value other)
{
return this.generalize(other.doubleValue());
diff --git a/src/proguard/evaluation/value/FloatValue.java b/src/proguard/evaluation/value/FloatValue.java
index b30e395..6dc8bee 100644
--- a/src/proguard/evaluation/value/FloatValue.java
+++ b/src/proguard/evaluation/value/FloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedDoubleValue.java b/src/proguard/evaluation/value/IdentifiedDoubleValue.java
index 4009c6e..4ff2466 100644
--- a/src/proguard/evaluation/value/IdentifiedDoubleValue.java
+++ b/src/proguard/evaluation/value/IdentifiedDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedFloatValue.java b/src/proguard/evaluation/value/IdentifiedFloatValue.java
index 87bed64..c8349bc 100644
--- a/src/proguard/evaluation/value/IdentifiedFloatValue.java
+++ b/src/proguard/evaluation/value/IdentifiedFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedIntegerValue.java b/src/proguard/evaluation/value/IdentifiedIntegerValue.java
index 66e88ee..6c3ee5d 100644
--- a/src/proguard/evaluation/value/IdentifiedIntegerValue.java
+++ b/src/proguard/evaluation/value/IdentifiedIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedLongValue.java b/src/proguard/evaluation/value/IdentifiedLongValue.java
index eea1816..e0b68f2 100644
--- a/src/proguard/evaluation/value/IdentifiedLongValue.java
+++ b/src/proguard/evaluation/value/IdentifiedLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedReferenceValue.java b/src/proguard/evaluation/value/IdentifiedReferenceValue.java
index cb5efc1..5cfbd60 100644
--- a/src/proguard/evaluation/value/IdentifiedReferenceValue.java
+++ b/src/proguard/evaluation/value/IdentifiedReferenceValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -57,6 +57,17 @@ final class IdentifiedReferenceValue extends ReferenceValue
}
+ // Implementations of binary methods of ReferenceValue.
+
+ public ReferenceValue generalize(ReferenceValue other)
+ {
+ // Remove the ID if both values don't share the same ID.
+ return this.equals(other) ?
+ this :
+ new ReferenceValue(type, referencedClass, mayBeNull).generalize(other);
+ }
+
+
// Implementations for Value.
public boolean isSpecific()
diff --git a/src/proguard/evaluation/value/IdentifiedValueFactory.java b/src/proguard/evaluation/value/IdentifiedValueFactory.java
index 2b14e72..be5c885 100644
--- a/src/proguard/evaluation/value/IdentifiedValueFactory.java
+++ b/src/proguard/evaluation/value/IdentifiedValueFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/InstructionOffsetValue.java b/src/proguard/evaluation/value/InstructionOffsetValue.java
index 10b5a6f..07a44ee 100644
--- a/src/proguard/evaluation/value/InstructionOffsetValue.java
+++ b/src/proguard/evaluation/value/InstructionOffsetValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IntegerValue.java b/src/proguard/evaluation/value/IntegerValue.java
index 508c5f5..b1824c6 100644
--- a/src/proguard/evaluation/value/IntegerValue.java
+++ b/src/proguard/evaluation/value/IntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/LongValue.java b/src/proguard/evaluation/value/LongValue.java
index f7ba162..e23c13c 100644
--- a/src/proguard/evaluation/value/LongValue.java
+++ b/src/proguard/evaluation/value/LongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedDoubleValue.java b/src/proguard/evaluation/value/NegatedDoubleValue.java
index 2bc9423..7619be7 100644
--- a/src/proguard/evaluation/value/NegatedDoubleValue.java
+++ b/src/proguard/evaluation/value/NegatedDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedFloatValue.java b/src/proguard/evaluation/value/NegatedFloatValue.java
index 0ddf4ab..51b5074 100644
--- a/src/proguard/evaluation/value/NegatedFloatValue.java
+++ b/src/proguard/evaluation/value/NegatedFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedIntegerValue.java b/src/proguard/evaluation/value/NegatedIntegerValue.java
index a89a2d9..1729083 100644
--- a/src/proguard/evaluation/value/NegatedIntegerValue.java
+++ b/src/proguard/evaluation/value/NegatedIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedLongValue.java b/src/proguard/evaluation/value/NegatedLongValue.java
index c3b22bb..7510524 100644
--- a/src/proguard/evaluation/value/NegatedLongValue.java
+++ b/src/proguard/evaluation/value/NegatedLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ParticularDoubleValue.java b/src/proguard/evaluation/value/ParticularDoubleValue.java
index 05bc559..e8c5aa7 100644
--- a/src/proguard/evaluation/value/ParticularDoubleValue.java
+++ b/src/proguard/evaluation/value/ParticularDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -79,17 +79,23 @@ final class ParticularDoubleValue extends SpecificDoubleValue
public DoubleValue add(DoubleValue other)
{
- return value == 0.0 ? other : other.add(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.add(this);
+ return other.add(this);
}
public DoubleValue subtract(DoubleValue other)
{
- return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ return other.subtractFrom(this);
}
public DoubleValue subtractFrom(DoubleValue other)
{
- return value == 0.0 ? other : other.subtract(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.subtract(this);
+ return other.subtract(this);
}
public DoubleValue multiply(DoubleValue other)
@@ -128,7 +134,10 @@ final class ParticularDoubleValue extends SpecificDoubleValue
public DoubleValue generalize(ParticularDoubleValue other)
{
- return this.value == other.value ? this : ValueFactory.DOUBLE_VALUE;
+ // Also handle NaN and Infinity.
+ return Double.doubleToRawLongBits(this.value) ==
+ Double.doubleToRawLongBits(other.value) ?
+ this : ValueFactory.DOUBLE_VALUE;
}
public DoubleValue add(ParticularDoubleValue other)
@@ -191,8 +200,10 @@ final class ParticularDoubleValue extends SpecificDoubleValue
public boolean equals(Object object)
{
- return super.equals(object) &&
- this.value == ((ParticularDoubleValue)object).value;
+ // Also handle NaN and Infinity.
+ return super.equals(object) &&
+ Double.doubleToLongBits(this.value) ==
+ Double.doubleToLongBits(((ParticularDoubleValue)object).value);
}
diff --git a/src/proguard/evaluation/value/ParticularFloatValue.java b/src/proguard/evaluation/value/ParticularFloatValue.java
index 59e4357..cbdde31 100644
--- a/src/proguard/evaluation/value/ParticularFloatValue.java
+++ b/src/proguard/evaluation/value/ParticularFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -79,17 +79,23 @@ final class ParticularFloatValue extends SpecificFloatValue
public FloatValue add(FloatValue other)
{
- return value == 0.0 ? other : other.add(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.add(this);
+ return other.add(this);
}
public FloatValue subtract(FloatValue other)
{
- return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ return other.subtractFrom(this);
}
public FloatValue subtractFrom(FloatValue other)
{
- return value == 0.0 ? other : other.subtract(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.subtract(this);
+ return other.subtract(this);
}
public FloatValue multiply(FloatValue other)
@@ -128,7 +134,10 @@ final class ParticularFloatValue extends SpecificFloatValue
public FloatValue generalize(ParticularFloatValue other)
{
- return this.value == other.value ? this : ValueFactory.FLOAT_VALUE;
+ // Also handle NaN and Infinity.
+ return Float.floatToRawIntBits(this.value) ==
+ Float.floatToRawIntBits(other.value) ?
+ this : ValueFactory.FLOAT_VALUE;
}
public FloatValue add(ParticularFloatValue other)
@@ -191,8 +200,10 @@ final class ParticularFloatValue extends SpecificFloatValue
public boolean equals(Object object)
{
+ // Also handle NaN and Infinity.
return super.equals(object) &&
- this.value == ((ParticularFloatValue)object).value;
+ Float.floatToIntBits(this.value) ==
+ Float.floatToIntBits(((ParticularFloatValue)object).value);
}
diff --git a/src/proguard/evaluation/value/ParticularIntegerValue.java b/src/proguard/evaluation/value/ParticularIntegerValue.java
index 8a4ac1d..609e95f 100644
--- a/src/proguard/evaluation/value/ParticularIntegerValue.java
+++ b/src/proguard/evaluation/value/ParticularIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ParticularLongValue.java b/src/proguard/evaluation/value/ParticularLongValue.java
index 61d2e04..1903235 100644
--- a/src/proguard/evaluation/value/ParticularLongValue.java
+++ b/src/proguard/evaluation/value/ParticularLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ReferenceValue.java b/src/proguard/evaluation/value/ReferenceValue.java
index 418c6f8..4a52e82 100644
--- a/src/proguard/evaluation/value/ReferenceValue.java
+++ b/src/proguard/evaluation/value/ReferenceValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -280,11 +280,25 @@ public class ReferenceValue extends Category1Value
thisReferencedClass.hierarchyAccept(false, true, true, false,
new ClassCollector(thisSuperClasses));
+ int thisSuperClassesCount = thisSuperClasses.size();
+ if (thisSuperClassesCount == 0 &&
+ thisReferencedClass.getSuperName() != null)
+ {
+ throw new IllegalArgumentException("Can't find any super classes of ["+thisType+"] (not even immediate super class ["+thisReferencedClass.getSuperName()+"])");
+ }
+
// Collect the superclasses and interfaces of the other class.
Set otherSuperClasses = new HashSet();
otherReferencedClass.hierarchyAccept(false, true, true, false,
new ClassCollector(otherSuperClasses));
+ int otherSuperClassesCount = otherSuperClasses.size();
+ if (otherSuperClassesCount == 0 &&
+ otherReferencedClass.getSuperName() != null)
+ {
+ throw new IllegalArgumentException("Can't find any super classes of ["+otherType+"] (not even immediate super class ["+otherReferencedClass.getSuperName()+"])");
+ }
+
if (DEBUG)
{
System.out.println("ReferenceValue.generalize this ["+thisReferencedClass.getName()+"] with other ["+otherReferencedClass.getName()+"]");
@@ -302,7 +316,7 @@ public class ReferenceValue extends Category1Value
// Find a class that is a subclass of all common superclasses,
// or that at least has the maximum number of common superclasses.
- Clazz commonClazz = null;
+ Clazz commonClass = null;
int maximumSuperClassCount = -1;
@@ -317,31 +331,33 @@ public class ReferenceValue extends Category1Value
int superClassCount = superClassCount(commonSuperClass, thisSuperClasses);
if (maximumSuperClassCount < superClassCount ||
(maximumSuperClassCount == superClassCount &&
- commonClazz != null &&
- commonClazz.getName().compareTo(commonSuperClass.getName()) > 0))
+ commonClass != null &&
+ commonClass.getName().compareTo(commonSuperClass.getName()) > 0))
{
- commonClazz = commonSuperClass;
+ commonClass = commonSuperClass;
maximumSuperClassCount = superClassCount;
}
}
- if (commonClazz == null)
+ if (commonClass == null)
{
- throw new IllegalArgumentException("Can't find common super class of ["+thisType+"] and ["+otherType+"]");
+ throw new IllegalArgumentException("Can't find common super class of ["+
+ thisType +"] (with "+thisSuperClassesCount +" known super classes) and ["+
+ otherType+"] (with "+otherSuperClassesCount+" known super classes)");
}
if (DEBUG)
{
- System.out.println(" Best common class: ["+commonClazz.getName()+"]");
+ System.out.println(" Best common class: ["+commonClass.getName()+"]");
}
// TODO: Handle more difficult cases, with multiple global subclasses.
return new ReferenceValue(commonDimensionCount == 0 ?
- commonClazz.getName() :
- ClassUtil.internalArrayTypeFromClassName(commonClazz.getName(),
+ commonClass.getName() :
+ ClassUtil.internalArrayTypeFromClassName(commonClass.getName(),
commonDimensionCount),
- commonClazz,
+ commonClass,
mayBeNull);
}
}
@@ -402,8 +418,6 @@ public class ReferenceValue extends Category1Value
}
}
- //System.out.println("ReferenceValue.superClassCount: ["+subClass.getName()+"]: "+count);
-
return count;
}
diff --git a/src/proguard/evaluation/value/SpecificDoubleValue.java b/src/proguard/evaluation/value/SpecificDoubleValue.java
index 572d891..644f553 100644
--- a/src/proguard/evaluation/value/SpecificDoubleValue.java
+++ b/src/proguard/evaluation/value/SpecificDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -153,9 +153,12 @@ abstract class SpecificDoubleValue extends DoubleValue
public IntegerValue compare(SpecificDoubleValue other)
{
- return this.equals(other) ?
- SpecificValueFactory.INTEGER_VALUE_0 :
- new ComparisonValue(this, other);
+ return ValueFactory.INTEGER_VALUE;
+
+ // Not handling NaN properly.
+ //return this.equals(other) ?
+ // SpecificValueFactory.INTEGER_VALUE_0 :
+ // new ComparisonValue(this, other);
}
diff --git a/src/proguard/evaluation/value/SpecificFloatValue.java b/src/proguard/evaluation/value/SpecificFloatValue.java
index 3bc3679..d88baa3 100644
--- a/src/proguard/evaluation/value/SpecificFloatValue.java
+++ b/src/proguard/evaluation/value/SpecificFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -153,9 +153,12 @@ abstract class SpecificFloatValue extends FloatValue
public IntegerValue compare(SpecificFloatValue other)
{
- return this.equals(other) ?
- SpecificValueFactory.INTEGER_VALUE_0 :
- new ComparisonValue(this, other);
+ return ValueFactory.INTEGER_VALUE;
+
+ // Not handling NaN properly.
+ //return this.equals(other) ?
+ // SpecificValueFactory.INTEGER_VALUE_0 :
+ // new ComparisonValue(this, other);
}
diff --git a/src/proguard/evaluation/value/SpecificIntegerValue.java b/src/proguard/evaluation/value/SpecificIntegerValue.java
index 57c48b1..81f8646 100644
--- a/src/proguard/evaluation/value/SpecificIntegerValue.java
+++ b/src/proguard/evaluation/value/SpecificIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/SpecificLongValue.java b/src/proguard/evaluation/value/SpecificLongValue.java
index 5e12bde..15138b4 100644
--- a/src/proguard/evaluation/value/SpecificLongValue.java
+++ b/src/proguard/evaluation/value/SpecificLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/SpecificValueFactory.java b/src/proguard/evaluation/value/SpecificValueFactory.java
index 72dd1d3..f761938 100644
--- a/src/proguard/evaluation/value/SpecificValueFactory.java
+++ b/src/proguard/evaluation/value/SpecificValueFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -45,6 +45,10 @@ extends ValueFactory
static final DoubleValue DOUBLE_VALUE_1 = new ParticularDoubleValue(1.0);
+ private static int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f);
+ private static long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
+
+
// Implementations for ValueFactory.
public IntegerValue createIntegerValue(int value)
@@ -73,7 +77,9 @@ extends ValueFactory
public FloatValue createFloatValue(float value)
{
- return value == 0.0f ? FLOAT_VALUE_0 :
+ // Make sure to distinguish between +0.0 and -0.0.
+ return value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS
+ ? FLOAT_VALUE_0 :
value == 1.0f ? FLOAT_VALUE_1 :
value == 2.0f ? FLOAT_VALUE_2 :
new ParticularFloatValue(value);
@@ -82,7 +88,9 @@ extends ValueFactory
public DoubleValue createDoubleValue(double value)
{
- return value == 0.0 ? DOUBLE_VALUE_0 :
+ // Make sure to distinguish between +0.0 and -0.0.
+ return value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS
+ ? DOUBLE_VALUE_0 :
value == 1.0 ? DOUBLE_VALUE_1 :
new ParticularDoubleValue(value);
}
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/TopValue.java
index 048a1ff..c7320fa 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/TopValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/UnknownDoubleValue.java b/src/proguard/evaluation/value/UnknownDoubleValue.java
index 79cc4de..f8bad9a 100644
--- a/src/proguard/evaluation/value/UnknownDoubleValue.java
+++ b/src/proguard/evaluation/value/UnknownDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/UnknownFloatValue.java b/src/proguard/evaluation/value/UnknownFloatValue.java
index 3f9622a..464ceed 100644
--- a/src/proguard/evaluation/value/UnknownFloatValue.java
+++ b/src/proguard/evaluation/value/UnknownFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -120,6 +120,6 @@ public class UnknownFloatValue extends FloatValue
public String toString()
{
- return "d";
+ return "f";
}
} \ No newline at end of file
diff --git a/src/proguard/evaluation/value/UnknownIntegerValue.java b/src/proguard/evaluation/value/UnknownIntegerValue.java
index be5e79d..b273b12 100644
--- a/src/proguard/evaluation/value/UnknownIntegerValue.java
+++ b/src/proguard/evaluation/value/UnknownIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/UnknownLongValue.java b/src/proguard/evaluation/value/UnknownLongValue.java
index 83a75dc..ee315be 100644
--- a/src/proguard/evaluation/value/UnknownLongValue.java
+++ b/src/proguard/evaluation/value/UnknownLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/Value.java b/src/proguard/evaluation/value/Value.java
index e24ece1..f8d9327 100644
--- a/src/proguard/evaluation/value/Value.java
+++ b/src/proguard/evaluation/value/Value.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ValueFactory.java b/src/proguard/evaluation/value/ValueFactory.java
index 8415381..c94ac65 100644
--- a/src/proguard/evaluation/value/ValueFactory.java
+++ b/src/proguard/evaluation/value/ValueFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gradle/ProGuardTask.java b/src/proguard/gradle/ProGuardTask.java
new file mode 100644
index 0000000..f5f96e8
--- /dev/null
+++ b/src/proguard/gradle/ProGuardTask.java
@@ -0,0 +1,1532 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gradle;
+
+import groovy.lang.Closure;
+import org.gradle.api.*;
+import org.gradle.api.file.*;
+import org.gradle.api.logging.*;
+import org.gradle.api.tasks.*;
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This Task allows to configure and run ProGuard from Gradle.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuardTask extends DefaultTask
+{
+ // Accumulated input and output, for the sake of Gradle's lazy file
+ // resolution and lazy task execution.
+ private final List inJarFiles = new ArrayList();
+ private final List inJarFilters = new ArrayList();
+ private final List outJarFiles = new ArrayList();
+ private final List outJarFilters = new ArrayList();
+ private final List inJarCounts = new ArrayList();
+ private final List libraryJarFiles = new ArrayList();
+ private final List libraryJarFilters = new ArrayList();
+ private final List configurationFiles = new ArrayList();
+
+ // Accumulated configuration.
+ private final Configuration configuration = new Configuration();
+
+ // Field acting as a parameter for the class member specification methods.
+ private ClassSpecification classSpecification;
+
+
+ // Gradle task inputs and outputs, because annotations on the List fields
+ // (private or not) don't seem to work. Private methods don't work either,
+ // but package visible or protected methods are ok.
+
+ @InputFiles
+ protected FileCollection getInJarFiles() throws ParseException
+ {
+ return getProject().files(inJarFiles);
+ }
+
+ @Optional @OutputFiles
+ protected FileCollection getOutJarFiles() throws ParseException
+ {
+ return getProject().files(outJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getLibraryJarFiles() throws ParseException
+ {
+ return getProject().files(libraryJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getConfigurationFiles() throws ParseException
+ {
+ return getProject().files(configurationFiles);
+ }
+
+
+ // Gradle task settings corresponding to all ProGuard options.
+
+ public void configuration(Object configurationFiles)
+ throws ParseException, IOException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.configurationFiles.add(configurationFiles);
+ }
+
+ public void injars(Object inJarFiles)
+ throws ParseException
+ {
+ injars(null, inJarFiles);
+ }
+
+ public void injars(Map filterArgs, Object inJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.inJarFiles.add(inJarFiles);
+ this.inJarFilters.add(filterArgs);
+ }
+
+ public void outjars(Object outJarFiles)
+ throws ParseException
+ {
+ outjars(null, outJarFiles);
+ }
+
+ public void outjars(Map filterArgs, Object outJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.outJarFiles.add(getProject().file(outJarFiles));
+ this.outJarFilters.add(filterArgs);
+ this.inJarCounts.add(Integer.valueOf(inJarFiles.size()));
+ }
+
+ public void libraryjars(Object libraryJarFiles)
+ throws ParseException
+ {
+ libraryjars(null, libraryJarFiles);
+ }
+
+ public void libraryjars(Map filterArgs, Object libraryJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.libraryJarFiles.add(libraryJarFiles);
+ this.libraryJarFilters.add(filterArgs);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getskipnonpubliclibraryclasses()
+ {
+ skipnonpubliclibraryclasses();
+ return null;
+ }
+
+ public void skipnonpubliclibraryclasses()
+ {
+ configuration.skipNonPublicLibraryClasses = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontskipnonpubliclibraryclassmembers()
+ {
+ dontskipnonpubliclibraryclassmembers();
+ return null;
+ }
+
+ public void dontskipnonpubliclibraryclassmembers()
+ {
+ configuration.skipNonPublicLibraryClassMembers = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepdirectories()
+ {
+ keepdirectories();
+ return null;
+ }
+
+ public void keepdirectories()
+ {
+ keepdirectories(null);
+ }
+
+ public void keepdirectories(String filter)
+ {
+ configuration.keepDirectories =
+ extendFilter(configuration.keepDirectories, filter);
+ }
+
+ public void target(String targetClassVersion)
+ {
+ configuration.targetClassVersion =
+ ClassUtil.internalClassVersion(targetClassVersion);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getforceprocessing()
+ {
+ forceprocessing();
+ return null;
+ }
+
+ public void forceprocessing()
+ {
+ configuration.lastModified = Long.MAX_VALUE;
+ }
+
+ public void keep(String classSpecificationString)
+ throws ParseException
+ {
+ keep(null, classSpecificationString);
+ }
+
+ public void keep(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keep(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keep(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keep(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembers(null, classSpecificationString);
+ }
+
+ public void keepclassmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembers(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepnames(String classSpecificationString)
+ throws ParseException
+ {
+ keepnames(null, classSpecificationString);
+ }
+
+ public void keepnames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepnames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembernames(null, classSpecificationString);
+ }
+
+ public void keepclassmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembernames(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintseeds()
+ {
+ printseeds();
+ return null;
+ }
+
+ public void printseeds()
+ {
+ configuration.printSeeds = Configuration.STD_OUT;
+ }
+
+ public void printseeds(Object printSeeds)
+ throws ParseException
+ {
+ configuration.printSeeds = getProject().file(printSeeds);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontshrink()
+ {
+ dontshrink();
+ return null;
+ }
+
+ public void dontshrink()
+ {
+ configuration.shrink = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintusage()
+ {
+ printusage();
+ return null;
+ }
+
+ public void printusage()
+ {
+ configuration.printUsage = Configuration.STD_OUT;
+ }
+
+ public void printusage(Object printUsage)
+ throws ParseException
+ {
+ configuration.printUsage = getProject().file(printUsage);
+ }
+
+ public void whyareyoukeeping(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs)
+ throws ParseException
+ {
+ whyareyoukeeping(classSpecificationArgs, null);
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontoptimize()
+ {
+ dontoptimize();
+ return null;
+ }
+
+ public void dontoptimize()
+ {
+ configuration.optimize = false;
+ }
+
+ public void optimizations(String filter)
+ {
+ configuration.optimizations =
+ extendFilter(configuration.optimizations, filter);
+ }
+
+
+ public void optimizationpasses(int optimizationPasses)
+ {
+ configuration.optimizationPasses = optimizationPasses;
+ }
+
+ public void assumenosideeffects(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void assumenosideeffects(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getallowaccessmodification()
+ {
+ allowaccessmodification();
+ return null;
+ }
+
+ public void allowaccessmodification()
+ {
+ configuration.allowAccessModification = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmergeinterfacesaggressively()
+ {
+ mergeinterfacesaggressively();
+ return null;
+ }
+
+ public void mergeinterfacesaggressively()
+ {
+ configuration.mergeInterfacesAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontobfuscate()
+ {
+ dontobfuscate();
+ return null;
+ }
+
+ public void dontobfuscate()
+ {
+ configuration.obfuscate = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintmapping()
+ {
+ printmapping();
+ return null;
+ }
+
+ public void printmapping()
+ {
+ configuration.printMapping = Configuration.STD_OUT;
+ }
+
+ public void printmapping(Object printMapping)
+ throws ParseException
+ {
+ configuration.printMapping = getProject().file(printMapping);
+ }
+
+ public void applymapping(Object applyMapping)
+ throws ParseException
+ {
+ configuration.applyMapping = getProject().file(applyMapping);
+ }
+
+ public void obfuscationdictionary(Object obfuscationDictionary)
+ throws ParseException
+ {
+ configuration.obfuscationDictionary =
+ getProject().file(obfuscationDictionary);
+ }
+
+ public void classobfuscationdictionary(Object classObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.classObfuscationDictionary =
+ getProject().file(classObfuscationDictionary);
+ }
+
+ public void packageobfuscationdictionary(Object packageObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.packageObfuscationDictionary =
+ getProject().file(packageObfuscationDictionary);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getoverloadaggressively()
+ {
+ overloadaggressively();
+ return null;
+ }
+
+ public void overloadaggressively()
+ {
+ configuration.overloadAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getuseuniqueclassmembernames()
+ {
+ useuniqueclassmembernames();
+ return null;
+ }
+
+ public void useuniqueclassmembernames()
+ {
+ configuration.useUniqueClassMemberNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontusemixedcaseclassnames()
+ {
+ dontusemixedcaseclassnames();
+ return null;
+ }
+
+ public void dontusemixedcaseclassnames()
+ {
+ configuration.useMixedCaseClassNames = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeeppackagenames()
+ {
+ keeppackagenames();
+ return null;
+ }
+
+ public void keeppackagenames()
+ {
+ keeppackagenames(null);
+ }
+
+ public void keeppackagenames(String filter)
+ {
+ configuration.keepPackageNames =
+ extendFilter(configuration.keepPackageNames, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getflattenpackagehierarchy()
+ {
+ flattenpackagehierarchy();
+ return null;
+ }
+
+ public void flattenpackagehierarchy()
+ {
+ flattenpackagehierarchy("");
+ }
+
+ public void flattenpackagehierarchy(String flattenPackageHierarchy)
+ {
+ configuration.flattenPackageHierarchy =
+ ClassUtil.internalClassName(flattenPackageHierarchy);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrepackageclasses()
+ {
+ repackageclasses();
+ return null;
+ }
+
+ public void repackageclasses()
+ {
+ repackageclasses("");
+ }
+
+ public void repackageclasses(String repackageClasses)
+ {
+ configuration.repackageClasses =
+ ClassUtil.internalClassName(repackageClasses);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepattributes()
+ {
+ keepattributes();
+ return null;
+ }
+
+ public void keepattributes()
+ {
+ keepattributes(null);
+ }
+
+ public void keepattributes(String filter)
+ {
+ configuration.keepAttributes =
+ extendFilter(configuration.keepAttributes, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepparameternames()
+ {
+ keepparameternames();
+ return null;
+ }
+
+ public void keepparameternames()
+ {
+ configuration.keepParameterNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrenamesourcefileattribute()
+ {
+ renamesourcefileattribute();
+ return null;
+ }
+
+ public void renamesourcefileattribute()
+ {
+ renamesourcefileattribute("");
+ }
+
+ public void renamesourcefileattribute(String newSourceFileAttribute)
+ {
+ configuration.newSourceFileAttribute = newSourceFileAttribute;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptclassstrings()
+ {
+ adaptclassstrings();
+ return null;
+ }
+
+ public void adaptclassstrings()
+ {
+ adaptclassstrings(null);
+ }
+
+ public void adaptclassstrings(String filter)
+ {
+ configuration.adaptClassStrings =
+ extendFilter(configuration.adaptClassStrings, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilenames()
+ {
+ adaptresourcefilenames();
+ return null;
+ }
+
+ public void adaptresourcefilenames()
+ {
+ adaptresourcefilenames(null);
+ }
+
+ public void adaptresourcefilenames(String filter)
+ {
+ configuration.adaptResourceFileNames =
+ extendFilter(configuration.adaptResourceFileNames, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilecontents()
+ {
+ adaptresourcefilecontents();
+ return null;
+ }
+
+ public void adaptresourcefilecontents()
+ {
+ adaptresourcefilecontents(null);
+ }
+
+ public void adaptresourcefilecontents(String filter)
+ {
+ configuration.adaptResourceFileContents =
+ extendFilter(configuration.adaptResourceFileContents, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontpreverify()
+ {
+ dontpreverify();
+ return null;
+ }
+
+ public void dontpreverify()
+ {
+ configuration.preverify = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmicroedition()
+ {
+ microedition();
+ return null;
+ }
+
+ public void microedition()
+ {
+ configuration.microEdition = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getverbose()
+ {
+ verbose();
+ return null;
+ }
+
+ public void verbose()
+ {
+ configuration.verbose = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontnote()
+ {
+ dontnote();
+ return null;
+ }
+
+ public void dontnote()
+ {
+ dontnote(null);
+ }
+
+ public void dontnote(String filter)
+ {
+ configuration.note = extendFilter(configuration.note, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontwarn()
+ {
+ dontwarn();
+ return null;
+ }
+
+ public void dontwarn()
+ {
+ dontwarn(null);
+ }
+
+ public void dontwarn(String filter)
+ {
+ configuration.warn = extendFilter(configuration.warn, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getignorewarnings()
+ {
+ ignorewarnings();
+ return null;
+ }
+
+ public void ignorewarnings()
+ {
+ configuration.ignoreWarnings = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintconfiguration()
+ {
+ printconfiguration();
+ return null;
+ }
+
+ public void printconfiguration()
+ {
+ configuration.printConfiguration = Configuration.STD_OUT;
+ }
+
+ public void printconfiguration(Object printConfiguration)
+ throws ParseException
+ {
+ configuration.printConfiguration =
+ getProject().file(printConfiguration);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdump()
+ {
+ dump();
+ return null;
+ }
+
+ public void dump()
+ {
+ configuration.dump = Configuration.STD_OUT;
+ }
+
+ public void dump(Object dump)
+ throws ParseException
+ {
+ configuration.dump = getProject().file(dump);
+ }
+
+
+ // Class member methods.
+
+ public void field(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'field' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addField(createMemberSpecification(false,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ public void constructor(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'constructor' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ true,
+ memberSpecificationArgs));
+ }
+
+
+ public void method(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'method' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ // Gradle task execution.
+
+ @TaskAction
+ public void proguard()
+ throws ParseException, IOException
+ {
+ // Weave the input jars and the output jars into a single class path,
+ // with lazy resolution of the files.
+ configuration.programJars = new ClassPath();
+
+ int outJarIndex = 0;
+
+ int inJarCount = inJarCounts.size() == 0 ? -1 :
+ ((Integer)inJarCounts.get(0)).intValue();
+
+ for (int inJarIndex = 0; inJarIndex < inJarFiles.size(); inJarIndex++)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ inJarFiles.get(inJarIndex),
+ (Map)inJarFilters.get(inJarIndex),
+ false);
+
+ while (inJarIndex == inJarCount - 1)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ outJarFiles.get(outJarIndex),
+ (Map)outJarFilters.get(outJarIndex),
+ true);
+
+ outJarIndex++;
+
+ inJarCount = inJarCounts.size() == outJarIndex ? -1 :
+ ((Integer)inJarCounts.get(outJarIndex)).intValue();
+ }
+ }
+
+ // Copy the library jars into a single class path, with lazy resolution
+ // of the files.
+ configuration.libraryJars = new ClassPath();
+
+ for (int libraryJarIndex = 0; libraryJarIndex < libraryJarFiles.size(); libraryJarIndex++)
+ {
+ configuration.libraryJars =
+ extendClassPath(configuration.libraryJars,
+ libraryJarFiles.get(libraryJarIndex),
+ (Map)libraryJarFilters.get(libraryJarIndex),
+ false);
+ }
+
+ // Lazily apply the external configuration files.
+ ConfigurableFileCollection fileCollection =
+ getProject().files(configurationFiles);
+
+ Iterator<File> files = fileCollection.iterator();
+ while (files.hasNext())
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(files.next(), System.getProperties());
+
+ try
+ {
+ parser.parse(configuration);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+
+ // Make sure the code is processed. Gradle has already checked that it
+ // was necessary.
+ configuration.lastModified = Long.MAX_VALUE;
+
+ // Let the logging manager capture the standard output and errors from
+ // ProGuard.
+ LoggingManager loggingManager = getLogging();
+ loggingManager.captureStandardOutput(LogLevel.INFO);
+ loggingManager.captureStandardError(LogLevel.WARN);
+
+ // Run ProGuard with the collected configuration.
+ new ProGuard(configuration).execute();
+
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Extends the given class path with the given filtered input or output
+ * files.
+ */
+ private ClassPath extendClassPath(ClassPath classPath,
+ Object files,
+ Map filterArgs,
+ boolean output)
+ {
+ ConfigurableFileCollection fileCollection = getProject().files(files);
+
+ if (classPath == null)
+ {
+ classPath = new ClassPath();
+ }
+
+ Iterator fileIterator = fileCollection.iterator();
+ while (fileIterator.hasNext())
+ {
+ File file = (File)fileIterator.next();
+ if (output || file.exists())
+ {
+ // Create the class path entry.
+ ClassPathEntry classPathEntry = new ClassPathEntry(file, output);
+
+ // Add any filters to the class path entry.
+ if (filterArgs != null)
+ {
+ classPathEntry.setFilter(ListUtil.commaSeparatedList((String)filterArgs.get("filter")));
+ classPathEntry.setJarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("jarfilter")));
+ classPathEntry.setWarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("warfilter")));
+ classPathEntry.setEarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("earfilter")));
+ classPathEntry.setZipFilter(ListUtil.commaSeparatedList((String)filterArgs.get("zipfilter")));
+ }
+
+ classPath.add(classPathEntry);
+ }
+ }
+
+ return classPath;
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationString);
+
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ keepArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure);
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ classSpecificationArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ ClassSpecification classSpecification)
+ {
+ return
+ new KeepClassSpecification(markClasses,
+ markConditionally,
+ retrieveBoolean(keepArgs, "allowshrinking", allowShrinking),
+ retrieveBoolean(keepArgs, "allowoptimization", false),
+ retrieveBoolean(keepArgs, "allowobfuscation", false),
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given ProGuard-style class specification.
+ */
+ private ClassSpecification createClassSpecification(String classSpecificationString)
+ throws ParseException
+ {
+ try
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(new String[] { classSpecificationString }, null);
+
+ try
+ {
+ return parser.parseClassSpecificationArguments();
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ParseException(e.getMessage());
+ }
+ }
+
+
+ /**
+ * Creates a specification of classes and class members, based on the
+ * given parameters.
+ */
+ private ClassSpecification createClassSpecification(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String type = (String)classSpecificationArgs.get("type");
+ String name = (String)classSpecificationArgs.get("name");
+ String extendsAnnotation = (String)classSpecificationArgs.get("extendsannotation");
+ String extends_ = (String)classSpecificationArgs.get("extends");
+ if (extends_ == null)
+ {
+ extends_ = (String)classSpecificationArgs.get("implements");
+ }
+
+ // Create the class specification.
+ ClassSpecification classSpecification =
+ new ClassSpecification(null,
+ requiredClassAccessFlags(true, access, type),
+ requiredClassAccessFlags(false, access, type),
+ annotation != null ? ClassUtil.internalType(annotation) : null,
+ name != null ? ClassUtil.internalClassName(name) : null,
+ extendsAnnotation != null ? ClassUtil.internalType(extendsAnnotation) : null,
+ extends_ != null ? ClassUtil.internalClassName(extends_) : null);
+
+ // Initialize the class specification with its closure.
+ if (classMembersClosure != null)
+ {
+ // Temporarily remember the class specification, so we can add
+ // class member specifications.
+ this.classSpecification = classSpecification;
+ classMembersClosure.call(classSpecification);
+ this.classSpecification = null;
+ }
+
+ return classSpecification;
+ }
+
+
+ /**
+ * Parses the class access flags that must be set (or not), based on the
+ * given ProGuard-style flag specification.
+ */
+ private int requiredClassAccessFlags(boolean set,
+ String access,
+ String type)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ if (type != null && (type.startsWith("!") ^ set))
+ {
+ int accessFlag =
+ type.equals("class") ? 0 :
+ type.equals( ClassConstants.EXTERNAL_ACC_INTERFACE) ||
+ type.equals("!" + ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE :
+ type.equals( ClassConstants.EXTERNAL_ACC_ENUM) ||
+ type.equals("!" + ClassConstants.EXTERNAL_ACC_ENUM) ? ClassConstants.INTERNAL_ACC_ENUM :
+ -1;
+ if (accessFlag == -1)
+ {
+ throw new ParseException("Incorrect class type ["+type+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Creates a specification of class members, based on the given parameters.
+ */
+ private MemberSpecification createMemberSpecification(boolean isMethod,
+ boolean isConstructor,
+ Map classSpecificationArgs)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String type = (String)classSpecificationArgs.get("type");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String name = (String)classSpecificationArgs.get("name");
+ String parameters = (String)classSpecificationArgs.get("parameters");
+
+ // Perform some basic conversions and checks on the attributes.
+ if (annotation != null)
+ {
+ annotation = ClassUtil.internalType(annotation);
+ }
+
+ if (isMethod)
+ {
+ if (isConstructor)
+ {
+ if (type != null)
+ {
+ throw new ParseException("Type attribute not allowed in constructor specification ["+type+"]");
+ }
+
+ if (parameters != null)
+ {
+ type = ClassConstants.EXTERNAL_TYPE_VOID;
+ }
+
+ name = ClassConstants.INTERNAL_METHOD_NAME_INIT;
+ }
+ else if ((type != null) ^ (parameters != null))
+ {
+ throw new ParseException("Type and parameters attributes must always be present in combination in method specification");
+ }
+ }
+ else
+ {
+ if (parameters != null)
+ {
+ throw new ParseException("Parameters attribute not allowed in field specification ["+parameters+"]");
+ }
+ }
+
+ List parameterList = ListUtil.commaSeparatedList(parameters);
+
+ String descriptor =
+ parameters != null ? ClassUtil.internalMethodDescriptor(type, parameterList) :
+ type != null ? ClassUtil.internalType(type) :
+ null;
+
+ return new MemberSpecification(requiredMemberAccessFlags(true, access),
+ requiredMemberAccessFlags(false, access),
+ annotation,
+ name,
+ descriptor);
+ }
+
+
+ /**
+ * Parses the class member access flags that must be set (or not), based on
+ * the given ProGuard-style flag specification.
+ */
+ private int requiredMemberAccessFlags(boolean set,
+ String access)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PRIVATE) ? ClassConstants.INTERNAL_ACC_PRIVATE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PROTECTED) ? ClassConstants.INTERNAL_ACC_PROTECTED :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_STATIC) ? ClassConstants.INTERNAL_ACC_STATIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class member access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Retrieves a specified boolean flag from the given map.
+ */
+ private boolean retrieveBoolean(Map args, String name, boolean defaultValue)
+ {
+ if (args == null)
+ {
+ return defaultValue;
+ }
+
+ Object arg = args.get(name);
+
+ return arg == null ? defaultValue : ((Boolean)arg).booleanValue();
+ }
+
+
+ /**
+ * Adds the given class specification to the given list, creating a new list
+ * if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ ClassSpecification classSpecification)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.add(classSpecification);
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given class specifications to the given list, creating a new
+ * list if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ List additionalClassSpecifications)
+ {
+ if (additionalClassSpecifications != null)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.addAll(additionalClassSpecifications);
+ }
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary.
+ */
+ private List extendFilter(List filter,
+ String filterString)
+ {
+ return extendFilter(filter, filterString, false);
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary. External class names are converted to internal class names,
+ * if requested.
+ */
+ private List extendFilter(List filter,
+ String filterString,
+ boolean convertExternalClassNames)
+ {
+ if (filter == null)
+ {
+ filter = new ArrayList();
+ }
+
+ if (filterString == null)
+ {
+ // Clear the filter to keep all names.
+ filter.clear();
+ }
+ else
+ {
+ if (convertExternalClassNames)
+ {
+ filterString = ClassUtil.internalClassName(filterString);
+ }
+
+ // Append the filter.
+ filter.addAll(ListUtil.commaSeparatedList(filterString));
+ }
+
+ return filter;
+ }
+}
diff --git a/src/proguard/gui/ClassPathPanel.java b/src/proguard/gui/ClassPathPanel.java
index 95f3d1b..8f41db6 100644
--- a/src/proguard/gui/ClassPathPanel.java
+++ b/src/proguard/gui/ClassPathPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,7 +26,7 @@ import proguard.util.ListUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
-import java.io.File;
+import java.io.*;
import java.util.List;
/**
@@ -141,7 +141,7 @@ class ClassPathPanel extends ListPanel
// Up to JDK 1.3.1, setSelectedFiles doesn't show in the file
// chooser, so we just use setSelectedFile first. It also sets
// the current directory.
- chooser.setSelectedFile(selectedFiles[0]);
+ chooser.setSelectedFile(selectedFiles[0].getAbsoluteFile());
chooser.setSelectedFiles(selectedFiles);
int returnValue = chooser.showOpenDialog(owner);
@@ -432,7 +432,7 @@ class ClassPathPanel extends ListPanel
filter = new StringBuffer().append('(');
}
- filter.append(ListUtil.commaSeparatedString(additionalFilter));
+ filter.append(ListUtil.commaSeparatedString(additionalFilter, true));
}
return filter;
diff --git a/src/proguard/gui/ClassSpecificationDialog.java b/src/proguard/gui/ClassSpecificationDialog.java
index 36d80d4..38a3146 100644
--- a/src/proguard/gui/ClassSpecificationDialog.java
+++ b/src/proguard/gui/ClassSpecificationDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,9 +63,10 @@ final class ClassSpecificationDialog extends JDialog
private final JRadioButton[] publicRadioButtons;
private final JRadioButton[] finalRadioButtons;
private final JRadioButton[] abstractRadioButtons;
- private final JRadioButton[] enumRadioButtons;
- private final JRadioButton[] annotationRadioButtons;
private final JRadioButton[] interfaceRadioButtons;
+ private final JRadioButton[] annotationRadioButtons;
+ private final JRadioButton[] enumRadioButtons;
+ private final JRadioButton[] syntheticRadioButtons;
private final JTextField annotationTypeTextField = new JTextField(20);
private final JTextField classNameTextField = new JTextField(20);
@@ -199,9 +200,10 @@ final class ClassSpecificationDialog extends JDialog
publicRadioButtons = addRadioButtonTriplet("Public", accessPanel);
finalRadioButtons = addRadioButtonTriplet("Final", accessPanel);
abstractRadioButtons = addRadioButtonTriplet("Abstract", accessPanel);
- enumRadioButtons = addRadioButtonTriplet("Enum", accessPanel);
- annotationRadioButtons = addRadioButtonTriplet("Annotation", accessPanel);
interfaceRadioButtons = addRadioButtonTriplet("Interface", accessPanel);
+ annotationRadioButtons = addRadioButtonTriplet("Annotation", accessPanel);
+ enumRadioButtons = addRadioButtonTriplet("Enum", accessPanel);
+ syntheticRadioButtons = addRadioButtonTriplet("Synthetic", accessPanel);
// Create the annotation type panel.
final JPanel annotationTypePanel = new JPanel(layout);
@@ -393,9 +395,10 @@ final class ClassSpecificationDialog extends JDialog
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons);
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
- setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
- setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE, interfaceRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
// Set the class and annotation text fields.
annotationTypeTextField .setText(annotationType == null ? "" : ClassUtil.externalType(annotationType));
@@ -453,9 +456,10 @@ final class ClassSpecificationDialog extends JDialog
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons);
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
- getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
- getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE, interfaceRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
// Get the keep class member option lists.
classSpecification.fieldSpecifications = memberSpecificationsPanel.getMemberSpecifications(true);
diff --git a/src/proguard/gui/ClassSpecificationsPanel.java b/src/proguard/gui/ClassSpecificationsPanel.java
index 2cf0b1d..bc29247 100644
--- a/src/proguard/gui/ClassSpecificationsPanel.java
+++ b/src/proguard/gui/ClassSpecificationsPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ExtensionFileFilter.java b/src/proguard/gui/ExtensionFileFilter.java
index d67be40..ee09714 100644
--- a/src/proguard/gui/ExtensionFileFilter.java
+++ b/src/proguard/gui/ExtensionFileFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/FilterBuilder.java b/src/proguard/gui/FilterBuilder.java
index e46193f..c362cb6 100644
--- a/src/proguard/gui/FilterBuilder.java
+++ b/src/proguard/gui/FilterBuilder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/FilterDialog.java b/src/proguard/gui/FilterDialog.java
index 1567a31..88dbd8b 100644
--- a/src/proguard/gui/FilterDialog.java
+++ b/src/proguard/gui/FilterDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -182,7 +182,7 @@ public class FilterDialog extends JDialog
*/
public void setFilter(List filter)
{
- filterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_FILTER);
+ filterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_FILTER);
}
@@ -202,7 +202,7 @@ public class FilterDialog extends JDialog
*/
public void setJarFilter(List filter)
{
- jarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_JAR_FILTER);
+ jarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_JAR_FILTER);
}
@@ -222,7 +222,7 @@ public class FilterDialog extends JDialog
*/
public void setWarFilter(List filter)
{
- warFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_WAR_FILTER);
+ warFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_WAR_FILTER);
}
@@ -242,7 +242,7 @@ public class FilterDialog extends JDialog
*/
public void setEarFilter(List filter)
{
- earFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_EAR_FILTER);
+ earFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_EAR_FILTER);
}
@@ -262,7 +262,7 @@ public class FilterDialog extends JDialog
*/
public void setZipFilter(List filter)
{
- zipFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_ZIP_FILTER);
+ zipFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_ZIP_FILTER);
}
diff --git a/src/proguard/gui/GUIResources.java b/src/proguard/gui/GUIResources.java
index 85d582c..3d7c6c6 100644
--- a/src/proguard/gui/GUIResources.java
+++ b/src/proguard/gui/GUIResources.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/GUIResources.properties b/src/proguard/gui/GUIResources.properties
index 86ab7a1..b27075d 100644
--- a/src/proguard/gui/GUIResources.properties
+++ b/src/proguard/gui/GUIResources.properties
@@ -1,5 +1,5 @@
# ProGuard -- shrinking, optimization, and obfuscation of Java class files.
-# Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+# Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
#
# Tab names.
@@ -25,7 +25,7 @@ preverification = Preverification
#
# Panel titles.
#
-welcome = Welcome to ProGuard, version 4.4
+welcome = Welcome to ProGuard, version 4.10
options = Options
keepAdditional = Keep additional classes and class members
keepNamesAdditional = Keep additional class names and class member names
@@ -51,20 +51,26 @@ whyAreYouKeepingTip = \
# Info texts.
#
proGuardInfo = \
- ProGuard is a free class file shrinker, optimizer, obfuscator, and preverifier.\
- \n\n\
- With this GUI, you can create, load, modify, and save ProGuard configurations. \
- \n\
+ <html>ProGuard is a free class file shrinker, optimizer, obfuscator, and preverifier.\
+ <p>\
+ With this GUI, you can create, load, modify, and save ProGuard configurations.\
+ <br>\
You can then process your code right away, or you can run ProGuard from the \
- command line using your saved configuration. \
- \n\n\
+ command line using your saved configuration.\
+ <p>\
With the ReTrace part of this GUI you can de-obfuscate your stack traces.\
- \n\n\
+ <p>\
ProGuard and ReTrace are written and maintained by Eric Lafortune.\
- \n\n\
+ <p>\
+ Official site at Sourceforge: \
+ <a href="http://proguard.sourceforge.net/\">http://proguard.sourceforge.net/</a>\
+ <br>\
+ Professional support by Saikoa: \
+ <a href="http://www.saikoa.com/\">http://www.saikoa.com/</a>\
+ <p>\
Distributed under the GNU General Public License.\
- \n\
- Copyright (c) 2002-2009.
+ <br>\
+ Copyright &copy; 2002-2013.</html>
processingInfo = \
You can now start processing your code, \
@@ -105,6 +111,7 @@ flattenPackageHierarchy = Flatten package hierarchy
repackageClasses = Repackage classes
useMixedCaseClassNames = Use mixed-case class names
keepAttributes = Keep attributes
+keepParameterNames = Keep parameter names
renameSourceFileAttribute = Rename SourceFile attribute
adaptClassStrings = Adapt class strings
adaptResourceFileNames = Adapt resource file names
@@ -115,14 +122,14 @@ microEdition = Micro Edition
verbose = Verbose
note = Note potential mistakes in the configuration
-warn = Warn about possibly erronous input
-ignoreWarnings = Ignore warnings about possibly erronous input
+warn = Warn about possibly erroneous input
+ignoreWarnings = Ignore warnings about possibly erroneous input
skipNonPublicLibraryClasses = Skip non-public library classes
skipNonPublicLibraryClassMembers = Skip non-public library class members
keepDirectories = Keep directories
forceProcessing = Force processing
target = Target
-targets = 1.0,1.1,1.2,1.3,1.4,1.5,1.6
+targets = 1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7
printSeeds = Print seeds
printConfiguration = Print configuration
dump = Print class files
@@ -209,6 +216,9 @@ attributesTip = \
<li>"*Annotations*" is necessary for preserving annotations.\
</ul>\
The wildcard <code>*</code> and the negator <code>!</code> are allowed.</html>
+keepParameterNamesTip = \
+ <html>Keep parameter names and types in "LocalVariable*Table" attributes<br>\
+ in methods that are not obfuscated.</html>
renameSourceFileAttributeTip = \
<html>Put the given string in the "SourceFile" attribute of the processed class files.<br>\
It will appear as the file name of the classes in stack traces.</html>
@@ -246,12 +256,12 @@ noteTip = \
noteFilterTip = \
A filter matching classes for which no notes should be printed.
warnTip = \
- <html>Print out warnings about possibly erronous input.<br>\
+ <html>Print out warnings about possibly erroneous input.<br>\
<i>Only unset this option if you know what you're doing!</i></html>
warnFilterTip = \
A filter matching classes for which no warnings should be printed.
ignoreWarningsTip = \
- <html>Ignore any warnings about possibly erronous input.<br>\
+ <html>Ignore any warnings about possibly erroneous input.<br>\
<i>Only set this option if you know what you're doing!</i></html>
skipNonPublicLibraryClassesTip = \
<html>Skip reading non-public library classes, for efficiency.<br>\
@@ -495,6 +505,8 @@ code_simplification_fieldTip = \
Perform peephole optimizations for field loading and storing.
code_simplification_branchTip = \
Perform peephole optimizations for branch instructions.
+code_simplification_stringTip = \
+ Perform peephole optimizations for constant strings.
code_simplification_advancedTip = \
Simplify code based on control flow analysis and data flow analysis.
code_removal_advancedTip = \
@@ -504,7 +516,7 @@ code_removal_simpleTip = \
code_removal_variableTip = \
Remove unused variables from the local variable frame.
code_removal_exceptionTip = \
- Remove exceptions with empty catch blocks.
+ Remove exceptions with empty try blocks.
code_allocation_variableTip = \
Optimize variable allocation on the local variable frame.
diff --git a/src/proguard/gui/KeepSpecificationsPanel.java b/src/proguard/gui/KeepSpecificationsPanel.java
index 4c3c953..908f028 100644
--- a/src/proguard/gui/KeepSpecificationsPanel.java
+++ b/src/proguard/gui/KeepSpecificationsPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ListPanel.java b/src/proguard/gui/ListPanel.java
index 0132340..19a0c4d 100644
--- a/src/proguard/gui/ListPanel.java
+++ b/src/proguard/gui/ListPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/MemberSpecificationDialog.java b/src/proguard/gui/MemberSpecificationDialog.java
index 46a3f6f..4bf72ca 100644
--- a/src/proguard/gui/MemberSpecificationDialog.java
+++ b/src/proguard/gui/MemberSpecificationDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -56,6 +56,7 @@ final class MemberSpecificationDialog extends JDialog
private final JRadioButton[] protectedRadioButtons;
private final JRadioButton[] staticRadioButtons;
private final JRadioButton[] finalRadioButtons;
+ private final JRadioButton[] syntheticRadioButtons;
private JRadioButton[] volatileRadioButtons;
private JRadioButton[] transientRadioButtons;
@@ -64,6 +65,8 @@ final class MemberSpecificationDialog extends JDialog
private JRadioButton[] nativeRadioButtons;
private JRadioButton[] abstractRadioButtons;
private JRadioButton[] strictRadioButtons;
+ private JRadioButton[] bridgeRadioButtons;
+ private JRadioButton[] varargsRadioButtons;
private final JTextField annotationTypeTextField = new JTextField(20);
private final JTextField nameTextField = new JTextField(20);
@@ -166,6 +169,7 @@ final class MemberSpecificationDialog extends JDialog
protectedRadioButtons = addRadioButtonTriplet("Protected", accessPanel);
staticRadioButtons = addRadioButtonTriplet("Static", accessPanel);
finalRadioButtons = addRadioButtonTriplet("Final", accessPanel);
+ syntheticRadioButtons = addRadioButtonTriplet("Synthetic", accessPanel);
if (isField)
{
@@ -178,6 +182,8 @@ final class MemberSpecificationDialog extends JDialog
nativeRadioButtons = addRadioButtonTriplet("Native", accessPanel);
abstractRadioButtons = addRadioButtonTriplet("Abstract", accessPanel);
strictRadioButtons = addRadioButtonTriplet("Strict", accessPanel);
+ bridgeRadioButtons = addRadioButtonTriplet("Bridge", accessPanel);
+ varargsRadioButtons = addRadioButtonTriplet("Varargs", accessPanel);
}
// Create the type panel.
@@ -332,12 +338,15 @@ final class MemberSpecificationDialog extends JDialog
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNCHRONIZED, synchronizedRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_BRIDGE, bridgeRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VARARGS, varargsRadioButtons);
// Set the class name text fields.
nameTextField.setText(name == null ? "*" : name);
@@ -403,12 +412,15 @@ final class MemberSpecificationDialog extends JDialog
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNCHRONIZED, synchronizedRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_BRIDGE, bridgeRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VARARGS, varargsRadioButtons);
return memberSpecification;
}
diff --git a/src/proguard/gui/MemberSpecificationsPanel.java b/src/proguard/gui/MemberSpecificationsPanel.java
index 20b2f17..6a72a1d 100644
--- a/src/proguard/gui/MemberSpecificationsPanel.java
+++ b/src/proguard/gui/MemberSpecificationsPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/MessageDialogRunnable.java b/src/proguard/gui/MessageDialogRunnable.java
index e58f1c6..6c2152c 100644
--- a/src/proguard/gui/MessageDialogRunnable.java
+++ b/src/proguard/gui/MessageDialogRunnable.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/OptimizationsDialog.java b/src/proguard/gui/OptimizationsDialog.java
index 044c338..0af0979 100644
--- a/src/proguard/gui/OptimizationsDialog.java
+++ b/src/proguard/gui/OptimizationsDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ProGuardGUI.java b/src/proguard/gui/ProGuardGUI.java
index f27d698..6b08aa8 100644
--- a/src/proguard/gui/ProGuardGUI.java
+++ b/src/proguard/gui/ProGuardGUI.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -33,7 +33,6 @@ import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.List;
-import java.lang.reflect.InvocationTargetException;
/**
@@ -110,6 +109,7 @@ public class ProGuardGUI extends JFrame
private final JCheckBox flattenPackageHierarchyCheckBox = new JCheckBox(msg("flattenPackageHierarchy"));
private final JCheckBox repackageClassesCheckBox = new JCheckBox(msg("repackageClasses"));
private final JCheckBox keepAttributesCheckBox = new JCheckBox(msg("keepAttributes"));
+ private final JCheckBox keepParameterNamesCheckBox = new JCheckBox(msg("keepParameterNames"));
private final JCheckBox newSourceFileAttributeCheckBox = new JCheckBox(msg("renameSourceFileAttribute"));
private final JCheckBox adaptClassStringsCheckBox = new JCheckBox(msg("adaptClassStrings"));
private final JCheckBox adaptResourceFileNamesCheckBox = new JCheckBox(msg("adaptResourceFileNames"));
@@ -202,13 +202,13 @@ public class ProGuardGUI extends JFrame
splashPanelConstraints.anchor = GridBagConstraints.NORTHWEST;
//splashPanelConstraints.insets = constraints.insets;
- GridBagConstraints welcomeTextAreaConstraints = new GridBagConstraints();
- welcomeTextAreaConstraints.gridwidth = GridBagConstraints.REMAINDER;
- welcomeTextAreaConstraints.fill = GridBagConstraints.NONE;
- welcomeTextAreaConstraints.weightx = 1.0;
- welcomeTextAreaConstraints.weighty = 0.01;
- welcomeTextAreaConstraints.anchor = GridBagConstraints.CENTER;//NORTHWEST;
- welcomeTextAreaConstraints.insets = new Insets(20, 40, 20, 40);
+ GridBagConstraints welcomePaneConstraints = new GridBagConstraints();
+ welcomePaneConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ welcomePaneConstraints.fill = GridBagConstraints.NONE;
+ welcomePaneConstraints.weightx = 1.0;
+ welcomePaneConstraints.weighty = 0.01;
+ welcomePaneConstraints.anchor = GridBagConstraints.CENTER;//NORTHWEST;
+ welcomePaneConstraints.insets = new Insets(20, 40, 20, 40);
GridBagConstraints panelConstraints = new GridBagConstraints();
panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
@@ -295,18 +295,19 @@ public class ProGuardGUI extends JFrame
splashPanel = new SplashPanel(splash, 0.5, 5500L);
splashPanel.setPreferredSize(new Dimension(0, 200));
- JTextArea welcomeTextArea = new JTextArea(msg("proGuardInfo"), 18, 50);
- welcomeTextArea.setOpaque(false);
- welcomeTextArea.setEditable(false);
- welcomeTextArea.setLineWrap(true);
- welcomeTextArea.setWrapStyleWord(true);
- welcomeTextArea.setPreferredSize(new Dimension(0, 0));
- welcomeTextArea.setBorder(new EmptyBorder(20, 20, 20, 20));
- addBorder(welcomeTextArea, "welcome");
+ JEditorPane welcomePane = new JEditorPane("text/html", msg("proGuardInfo"));
+ welcomePane.setPreferredSize(new Dimension(640, 350));
+ // The constant HONOR_DISPLAY_PROPERTIES isn't present yet in JDK 1.4.
+ //welcomePane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
+ welcomePane.putClientProperty("JEditorPane.honorDisplayProperties", Boolean.TRUE);
+ welcomePane.setOpaque(false);
+ welcomePane.setEditable(false);
+ welcomePane.setBorder(new EmptyBorder(20, 20, 20, 20));
+ addBorder(welcomePane, "welcome");
JPanel proGuardPanel = new JPanel(layout);
proGuardPanel.add(splashPanel, splashPanelConstraints);
- proGuardPanel.add(welcomeTextArea, welcomeTextAreaConstraints);
+ proGuardPanel.add(welcomePane, welcomePaneConstraints);
// Create the input panel.
// TODO: properly clone the ClassPath objects.
@@ -403,6 +404,7 @@ public class ProGuardGUI extends JFrame
obfuscationOptionsPanel.add(tip(repackageClassesTextField, "packageTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(keepAttributesCheckBox, "keepAttributesTip"), constraints);
obfuscationOptionsPanel.add(tip(keepAttributesTextField, "attributesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(keepParameterNamesCheckBox, "keepParameterNamesTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(newSourceFileAttributeCheckBox, "renameSourceFileAttributeTip"), constraints);
obfuscationOptionsPanel.add(tip(newSourceFileAttributeTextField, "sourceFileAttributeTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(adaptClassStringsCheckBox, "adaptClassStringsTip"), constraints);
@@ -631,11 +633,14 @@ public class ProGuardGUI extends JFrame
reTracePanel .add(tip(loadStackTraceButton, "loadStackTraceTip"), bottomButtonConstraints);
reTracePanel .add(tip(reTraceButton, "reTraceTip"), lastBottomButtonConstraints);
+ // Add the main tabs to the frame.
+ getContentPane().add(tabs);
+
+ // Pack the entire GUI before setting some default values.
+ pack();
+
// Initialize the GUI settings to reasonable defaults.
loadConfiguration(this.getClass().getResource(DEFAULT_CONFIGURATION));
-
- // Add the main tabs to the frame and pack it.
- getContentPane().add(tabs);
}
@@ -661,7 +666,9 @@ public class ProGuardGUI extends JFrame
{
// Parse the boilerplate configuration file.
ConfigurationParser parser = new ConfigurationParser(
- this.getClass().getResource(BOILERPLATE_CONFIGURATION));
+ this.getClass().getResource(BOILERPLATE_CONFIGURATION),
+ System.getProperties());
+
Configuration configuration = new Configuration();
try
@@ -1019,6 +1026,7 @@ public class ProGuardGUI extends JFrame
flattenPackageHierarchyCheckBox .setSelected(configuration.flattenPackageHierarchy != null);
repackageClassesCheckBox .setSelected(configuration.repackageClasses != null);
keepAttributesCheckBox .setSelected(configuration.keepAttributes != null);
+ keepParameterNamesCheckBox .setSelected(configuration.keepParameterNames);
newSourceFileAttributeCheckBox .setSelected(configuration.newSourceFileAttribute != null);
adaptClassStringsCheckBox .setSelected(configuration.adaptClassStrings != null);
adaptResourceFileNamesCheckBox .setSelected(configuration.adaptResourceFileNames != null);
@@ -1041,21 +1049,23 @@ public class ProGuardGUI extends JFrame
dumpCheckBox .setSelected(configuration.dump != null);
printUsageTextField .setText(fileName(configuration.printUsage));
- optimizationsTextField .setText(configuration.optimizations == null ? OPTIMIZATIONS_DEFAULT : ListUtil.commaSeparatedString(configuration.optimizations));
+ optimizationsTextField .setText(configuration.optimizations == null ? OPTIMIZATIONS_DEFAULT : ListUtil.commaSeparatedString(configuration.optimizations, true));
printMappingTextField .setText(fileName(configuration.printMapping));
applyMappingTextField .setText(fileName(configuration.applyMapping));
obfuscationDictionaryTextField .setText(fileName(configuration.obfuscationDictionary));
- keepPackageNamesTextField .setText(configuration.keepPackageNames == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.keepPackageNames)));
+ classObfuscationDictionaryTextField .setText(fileName(configuration.classObfuscationDictionary));
+ packageObfuscationDictionaryTextField .setText(fileName(configuration.packageObfuscationDictionary));
+ keepPackageNamesTextField .setText(configuration.keepPackageNames == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.keepPackageNames, true)));
flattenPackageHierarchyTextField .setText(configuration.flattenPackageHierarchy);
repackageClassesTextField .setText(configuration.repackageClasses);
- keepAttributesTextField .setText(configuration.keepAttributes == null ? KEEP_ATTRIBUTE_DEFAULT : ListUtil.commaSeparatedString(configuration.keepAttributes));
+ keepAttributesTextField .setText(configuration.keepAttributes == null ? KEEP_ATTRIBUTE_DEFAULT : ListUtil.commaSeparatedString(configuration.keepAttributes, true));
newSourceFileAttributeTextField .setText(configuration.newSourceFileAttribute == null ? SOURCE_FILE_ATTRIBUTE_DEFAULT : configuration.newSourceFileAttribute);
- adaptClassStringsTextField .setText(configuration.adaptClassStrings == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.adaptClassStrings)));
- adaptResourceFileNamesTextField .setText(configuration.adaptResourceFileNames == null ? ADAPT_RESOURCE_FILE_NAMES_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileNames));
- adaptResourceFileContentsTextField .setText(configuration.adaptResourceFileContents == null ? ADAPT_RESOURCE_FILE_CONTENTS_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileContents));
- noteTextField .setText(ListUtil.commaSeparatedString(configuration.note));
- warnTextField .setText(ListUtil.commaSeparatedString(configuration.warn));
- keepDirectoriesTextField .setText(ListUtil.commaSeparatedString(configuration.keepDirectories));
+ adaptClassStringsTextField .setText(configuration.adaptClassStrings == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.adaptClassStrings, true)));
+ adaptResourceFileNamesTextField .setText(configuration.adaptResourceFileNames == null ? ADAPT_RESOURCE_FILE_NAMES_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileNames, true));
+ adaptResourceFileContentsTextField .setText(configuration.adaptResourceFileContents == null ? ADAPT_RESOURCE_FILE_CONTENTS_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileContents, true));
+ noteTextField .setText(ListUtil.commaSeparatedString(configuration.note, true));
+ warnTextField .setText(ListUtil.commaSeparatedString(configuration.warn, true));
+ keepDirectoriesTextField .setText(ListUtil.commaSeparatedString(configuration.keepDirectories, true));
printSeedsTextField .setText(fileName(configuration.printSeeds));
printConfigurationTextField .setText(fileName(configuration.printConfiguration));
dumpTextField .setText(fileName(configuration.dump));
@@ -1182,6 +1192,7 @@ public class ProGuardGUI extends JFrame
configuration.flattenPackageHierarchy = flattenPackageHierarchyCheckBox .isSelected() ? ClassUtil.internalClassName(flattenPackageHierarchyTextField .getText()) : null;
configuration.repackageClasses = repackageClassesCheckBox .isSelected() ? ClassUtil.internalClassName(repackageClassesTextField .getText()) : null;
configuration.keepAttributes = keepAttributesCheckBox .isSelected() ? ListUtil.commaSeparatedList(keepAttributesTextField .getText()) : null;
+ configuration.keepParameterNames = keepParameterNamesCheckBox .isSelected();
configuration.newSourceFileAttribute = newSourceFileAttributeCheckBox .isSelected() ? newSourceFileAttributeTextField .getText() : null;
configuration.adaptClassStrings = adaptClassStringsCheckBox .isSelected() ? adaptClassStringsTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(adaptClassStringsTextField.getText())) : new ArrayList() : null;
configuration.adaptResourceFileNames = adaptResourceFileNamesCheckBox .isSelected() ? ListUtil.commaSeparatedList(adaptResourceFileNamesTextField .getText()) : null;
@@ -1339,7 +1350,9 @@ public class ProGuardGUI extends JFrame
try
{
// Parse the configuration file.
- ConfigurationParser parser = new ConfigurationParser(file);
+ ConfigurationParser parser = new ConfigurationParser(file,
+ System.getProperties());
+
Configuration configuration = new Configuration();
try
@@ -1379,7 +1392,9 @@ public class ProGuardGUI extends JFrame
try
{
// Parse the configuration file.
- ConfigurationParser parser = new ConfigurationParser(url);
+ ConfigurationParser parser = new ConfigurationParser(url,
+ System.getProperties());
+
Configuration configuration = new Configuration();
try
@@ -1436,13 +1451,13 @@ public class ProGuardGUI extends JFrame
/**
* Loads the given stack trace into the GUI.
*/
- private void loadStackTrace(String fileName)
+ private void loadStackTrace(File file)
{
try
{
StringBuffer buffer = new StringBuffer(1024);
- Reader reader = new BufferedReader(new FileReader(fileName));
+ Reader reader = new BufferedReader(new FileReader(file));
try
{
while (true)
@@ -1467,7 +1482,7 @@ public class ProGuardGUI extends JFrame
catch (IOException ex)
{
JOptionPane.showMessageDialog(getContentPane(),
- msg("cantOpenStackTraceFile", fileName),
+ msg("cantOpenStackTraceFile", fileName(file)),
msg("warning"),
JOptionPane.ERROR_MESSAGE);
}
@@ -1600,10 +1615,8 @@ public class ProGuardGUI extends JFrame
int returnValue = fileChooser.showOpenDialog(ProGuardGUI.this);
if (returnValue == JFileChooser.APPROVE_OPTION)
{
- File selectedFile = fileChooser.getSelectedFile();
- String fileName = selectedFile.getPath();
- loadStackTrace(fileName);
+ loadStackTrace(fileChooser.getSelectedFile());
}
}
}
@@ -1641,11 +1654,26 @@ public class ProGuardGUI extends JFrame
// Small utility methods.
/**
- * Returns the file name of the given file, if any.
+ * Returns the canonical file name for the given file, or the empty string
+ * if the file name is empty.
*/
- private static String fileName(File file)
+ private String fileName(File file)
{
- return file == null ? "" : file.getAbsolutePath();
+ if (file == null)
+ {
+ return "";
+ }
+ else
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
}
@@ -1693,46 +1721,51 @@ public class ProGuardGUI extends JFrame
{
public void run()
{
- ProGuardGUI gui = new ProGuardGUI();
- gui.pack();
-
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- Dimension guiSize = gui.getSize();
- gui.setLocation((screenSize.width - guiSize.width) / 2,
- (screenSize.height - guiSize.height) / 2);
- gui.show();
-
- // Start the splash animation, unless specified otherwise.
- int argIndex = 0;
- if (argIndex < args.length &&
- NO_SPLASH_OPTION.startsWith(args[argIndex]))
- {
- gui.skipSplash();
- argIndex++;
- }
- else
- {
- gui.startSplash();
- }
-
- // Load an initial configuration, if specified.
- if (argIndex < args.length)
+ try
{
- gui.loadConfiguration(new File(args[argIndex]));
- argIndex++;
+ ProGuardGUI gui = new ProGuardGUI();
+
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension guiSize = gui.getSize();
+ gui.setLocation((screenSize.width - guiSize.width) / 2,
+ (screenSize.height - guiSize.height) / 2);
+ gui.show();
+
+ // Start the splash animation, unless specified otherwise.
+ int argIndex = 0;
+ if (argIndex < args.length &&
+ NO_SPLASH_OPTION.startsWith(args[argIndex]))
+ {
+ gui.skipSplash();
+ argIndex++;
+ }
+ else
+ {
+ gui.startSplash();
+ }
+
+ // Load an initial configuration, if specified.
+ if (argIndex < args.length)
+ {
+ gui.loadConfiguration(new File(args[argIndex]));
+ argIndex++;
+ }
+
+ if (argIndex < args.length)
+ {
+ System.out.println(gui.getClass().getName() + ": ignoring extra arguments [" + args[argIndex] + "...]");
+ }
}
-
- if (argIndex < args.length)
+ catch (Exception e)
{
- System.out.println(gui.getClass().getName() + ": ignoring extra arguments [" + args[argIndex] + "...]");
+ System.out.println("Internal problem starting the ProGuard GUI (" + e.getMessage() + ")");
}
-
}
});
}
catch (Exception e)
{
- // Nothing.
+ System.out.println("Internal problem starting the ProGuard GUI (" + e.getMessage() + ")");
}
}
}
diff --git a/src/proguard/gui/ProGuardRunnable.java b/src/proguard/gui/ProGuardRunnable.java
index c5c5937..b341b7b 100644
--- a/src/proguard/gui/ProGuardRunnable.java
+++ b/src/proguard/gui/ProGuardRunnable.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ReTraceRunnable.java b/src/proguard/gui/ReTraceRunnable.java
index 1ca19ca..6f1b135 100644
--- a/src/proguard/gui/ReTraceRunnable.java
+++ b/src/proguard/gui/ReTraceRunnable.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/SwingUtil.java b/src/proguard/gui/SwingUtil.java
index 75d2f02..373fdc9 100644
--- a/src/proguard/gui/SwingUtil.java
+++ b/src/proguard/gui/SwingUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/TabbedPane.java b/src/proguard/gui/TabbedPane.java
index a6460f5..c6b6678 100644
--- a/src/proguard/gui/TabbedPane.java
+++ b/src/proguard/gui/TabbedPane.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/TextAreaOutputStream.java b/src/proguard/gui/TextAreaOutputStream.java
index 57f983d..84ba562 100644
--- a/src/proguard/gui/TextAreaOutputStream.java
+++ b/src/proguard/gui/TextAreaOutputStream.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/boilerplate.pro b/src/proguard/gui/boilerplate.pro
index 70efb82..711c07d 100644
--- a/src/proguard/gui/boilerplate.pro
+++ b/src/proguard/gui/boilerplate.pro
@@ -257,13 +257,6 @@
public boolean isInfinite();
public int compareTo(java.lang.Double);
- public <init>(byte);
- public <init>(short);
- public <init>(int);
- public <init>(long);
- public <init>(float);
- public <init>(double);
- public <init>(java.lang.String);
public byte byteValue();
public short shortValue();
public int intValue();
@@ -280,17 +273,6 @@
# Remove - String method calls. Remove all invocations of String
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.String {
- public java.lang.String();
- public java.lang.String(byte[]);
- public java.lang.String(byte[],int);
- public java.lang.String(byte[],int,int);
- public java.lang.String(byte[],int,int,int);
- public java.lang.String(byte[],int,int,java.lang.String);
- public java.lang.String(byte[],java.lang.String);
- public java.lang.String(char[]);
- public java.lang.String(char[],int,int);
- public java.lang.String(java.lang.String);
- public java.lang.String(java.lang.StringBuffer);
public static java.lang.String copyValueOf(char[]);
public static java.lang.String copyValueOf(char[],int,int);
public static java.lang.String valueOf(boolean);
@@ -348,10 +330,6 @@
# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuffer {
- public java.lang.StringBuffer();
- public java.lang.StringBuffer(int);
- public java.lang.StringBuffer(java.lang.String);
- public java.lang.StringBuffer(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
@@ -368,10 +346,6 @@
# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuilder {
- public java.lang.StringBuilder();
- public java.lang.StringBuilder(int);
- public java.lang.StringBuilder(java.lang.String);
- public java.lang.StringBuilder(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
diff --git a/src/proguard/gui/default.pro b/src/proguard/gui/default.pro
index 3bfe2d6..752c9b2 100644
--- a/src/proguard/gui/default.pro
+++ b/src/proguard/gui/default.pro
@@ -190,13 +190,6 @@
public boolean isNaN();
public boolean isInfinite();
public int compareTo(java.lang.Double);
- public <init>(byte);
- public <init>(short);
- public <init>(int);
- public <init>(long);
- public <init>(float);
- public <init>(double);
- public <init>(java.lang.String);
public byte byteValue();
public short shortValue();
public int intValue();
@@ -212,17 +205,6 @@
# Remove - String method calls. Remove all invocations of String
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.String {
- public <init>();
- public <init>(byte[]);
- public <init>(byte[],int);
- public <init>(byte[],int,int);
- public <init>(byte[],int,int,int);
- public <init>(byte[],int,int,java.lang.String);
- public <init>(byte[],java.lang.String);
- public <init>(char[]);
- public <init>(char[],int,int);
- public <init>(java.lang.String);
- public <init>(java.lang.StringBuffer);
public static java.lang.String copyValueOf(char[]);
public static java.lang.String copyValueOf(char[],int,int);
public static java.lang.String valueOf(boolean);
@@ -280,10 +262,6 @@
# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuffer {
- public <init>();
- public <init>(int);
- public <init>(java.lang.String);
- public <init>(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
@@ -300,10 +278,6 @@
# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuilder {
- public <init>();
- public <init>(int);
- public <init>(java.lang.String);
- public <init>(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
diff --git a/src/proguard/gui/splash/BufferedSprite.java b/src/proguard/gui/splash/BufferedSprite.java
index 8427832..5625acb 100644
--- a/src/proguard/gui/splash/BufferedSprite.java
+++ b/src/proguard/gui/splash/BufferedSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/CircleSprite.java b/src/proguard/gui/splash/CircleSprite.java
index 5dc65eb..0443a0c 100644
--- a/src/proguard/gui/splash/CircleSprite.java
+++ b/src/proguard/gui/splash/CircleSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ClipSprite.java b/src/proguard/gui/splash/ClipSprite.java
index 55f9eac..a8ac368 100644
--- a/src/proguard/gui/splash/ClipSprite.java
+++ b/src/proguard/gui/splash/ClipSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ColorSprite.java b/src/proguard/gui/splash/ColorSprite.java
index 3f9bc3b..95153a2 100644
--- a/src/proguard/gui/splash/ColorSprite.java
+++ b/src/proguard/gui/splash/ColorSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/CompositeSprite.java b/src/proguard/gui/splash/CompositeSprite.java
index 2480ead..68cbe35 100644
--- a/src/proguard/gui/splash/CompositeSprite.java
+++ b/src/proguard/gui/splash/CompositeSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantColor.java b/src/proguard/gui/splash/ConstantColor.java
index 94c78df..fa7f3a5 100644
--- a/src/proguard/gui/splash/ConstantColor.java
+++ b/src/proguard/gui/splash/ConstantColor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantDouble.java b/src/proguard/gui/splash/ConstantDouble.java
index 0874d6d..c969332 100644
--- a/src/proguard/gui/splash/ConstantDouble.java
+++ b/src/proguard/gui/splash/ConstantDouble.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantFont.java b/src/proguard/gui/splash/ConstantFont.java
index 3f1ac03..26691b9 100644
--- a/src/proguard/gui/splash/ConstantFont.java
+++ b/src/proguard/gui/splash/ConstantFont.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantInt.java b/src/proguard/gui/splash/ConstantInt.java
index 537196d..ff79dd0 100644
--- a/src/proguard/gui/splash/ConstantInt.java
+++ b/src/proguard/gui/splash/ConstantInt.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantString.java b/src/proguard/gui/splash/ConstantString.java
index 7617c3f..e76f1eb 100644
--- a/src/proguard/gui/splash/ConstantString.java
+++ b/src/proguard/gui/splash/ConstantString.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantTiming.java b/src/proguard/gui/splash/ConstantTiming.java
index dfde644..b6a7762 100644
--- a/src/proguard/gui/splash/ConstantTiming.java
+++ b/src/proguard/gui/splash/ConstantTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/FontSprite.java b/src/proguard/gui/splash/FontSprite.java
index 9a554ba..42f165d 100644
--- a/src/proguard/gui/splash/FontSprite.java
+++ b/src/proguard/gui/splash/FontSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ImageSprite.java b/src/proguard/gui/splash/ImageSprite.java
index 6e7c189..f7704f9 100644
--- a/src/proguard/gui/splash/ImageSprite.java
+++ b/src/proguard/gui/splash/ImageSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearColor.java b/src/proguard/gui/splash/LinearColor.java
index 3a7674d..283a1c9 100644
--- a/src/proguard/gui/splash/LinearColor.java
+++ b/src/proguard/gui/splash/LinearColor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearDouble.java b/src/proguard/gui/splash/LinearDouble.java
index 046ae84..bf926b0 100644
--- a/src/proguard/gui/splash/LinearDouble.java
+++ b/src/proguard/gui/splash/LinearDouble.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearInt.java b/src/proguard/gui/splash/LinearInt.java
index 8d299bc..46c35bc 100644
--- a/src/proguard/gui/splash/LinearInt.java
+++ b/src/proguard/gui/splash/LinearInt.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearTiming.java b/src/proguard/gui/splash/LinearTiming.java
index 9b26644..c35348e 100644
--- a/src/proguard/gui/splash/LinearTiming.java
+++ b/src/proguard/gui/splash/LinearTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/OverrideGraphics2D.java b/src/proguard/gui/splash/OverrideGraphics2D.java
index 4333459..81a9429 100644
--- a/src/proguard/gui/splash/OverrideGraphics2D.java
+++ b/src/proguard/gui/splash/OverrideGraphics2D.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/RectangleSprite.java b/src/proguard/gui/splash/RectangleSprite.java
index d204831..547b549 100644
--- a/src/proguard/gui/splash/RectangleSprite.java
+++ b/src/proguard/gui/splash/RectangleSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SawToothTiming.java b/src/proguard/gui/splash/SawToothTiming.java
index 076d5e2..393f27e 100644
--- a/src/proguard/gui/splash/SawToothTiming.java
+++ b/src/proguard/gui/splash/SawToothTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ShadowedSprite.java b/src/proguard/gui/splash/ShadowedSprite.java
index c3504f3..fadca5f 100644
--- a/src/proguard/gui/splash/ShadowedSprite.java
+++ b/src/proguard/gui/splash/ShadowedSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SineTiming.java b/src/proguard/gui/splash/SineTiming.java
index eb0a7cc..ab3d0c1 100644
--- a/src/proguard/gui/splash/SineTiming.java
+++ b/src/proguard/gui/splash/SineTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SmoothTiming.java b/src/proguard/gui/splash/SmoothTiming.java
index a985712..a691d3c 100644
--- a/src/proguard/gui/splash/SmoothTiming.java
+++ b/src/proguard/gui/splash/SmoothTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SplashPanel.java b/src/proguard/gui/splash/SplashPanel.java
index 23a9ce4..af959e9 100644
--- a/src/proguard/gui/splash/SplashPanel.java
+++ b/src/proguard/gui/splash/SplashPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/Sprite.java b/src/proguard/gui/splash/Sprite.java
index ada7a81..f1f6e72 100644
--- a/src/proguard/gui/splash/Sprite.java
+++ b/src/proguard/gui/splash/Sprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TextSprite.java b/src/proguard/gui/splash/TextSprite.java
index bbf37d4..69bd4c7 100644
--- a/src/proguard/gui/splash/TextSprite.java
+++ b/src/proguard/gui/splash/TextSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TimeSwitchSprite.java b/src/proguard/gui/splash/TimeSwitchSprite.java
index 921bef2..dd292ad 100644
--- a/src/proguard/gui/splash/TimeSwitchSprite.java
+++ b/src/proguard/gui/splash/TimeSwitchSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/Timing.java b/src/proguard/gui/splash/Timing.java
index 887d737..bb15900 100644
--- a/src/proguard/gui/splash/Timing.java
+++ b/src/proguard/gui/splash/Timing.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TypeWriterString.java b/src/proguard/gui/splash/TypeWriterString.java
index 9f1441e..d304dca 100644
--- a/src/proguard/gui/splash/TypeWriterString.java
+++ b/src/proguard/gui/splash/TypeWriterString.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableColor.java b/src/proguard/gui/splash/VariableColor.java
index 6a30062..ce573aa 100644
--- a/src/proguard/gui/splash/VariableColor.java
+++ b/src/proguard/gui/splash/VariableColor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableDouble.java b/src/proguard/gui/splash/VariableDouble.java
index 39302dd..7317403 100644
--- a/src/proguard/gui/splash/VariableDouble.java
+++ b/src/proguard/gui/splash/VariableDouble.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableFont.java b/src/proguard/gui/splash/VariableFont.java
index a7de8d7..0668c38 100644
--- a/src/proguard/gui/splash/VariableFont.java
+++ b/src/proguard/gui/splash/VariableFont.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableInt.java b/src/proguard/gui/splash/VariableInt.java
index 68a33af..b4523ef 100644
--- a/src/proguard/gui/splash/VariableInt.java
+++ b/src/proguard/gui/splash/VariableInt.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableSizeFont.java b/src/proguard/gui/splash/VariableSizeFont.java
index e36d28c..52b8ab2 100644
--- a/src/proguard/gui/splash/VariableSizeFont.java
+++ b/src/proguard/gui/splash/VariableSizeFont.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableString.java b/src/proguard/gui/splash/VariableString.java
index 1dec23b..81ca8f6 100644
--- a/src/proguard/gui/splash/VariableString.java
+++ b/src/proguard/gui/splash/VariableString.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/CascadingDataEntryWriter.java b/src/proguard/io/CascadingDataEntryWriter.java
index 15719e6..62f3bf7 100644
--- a/src/proguard/io/CascadingDataEntryWriter.java
+++ b/src/proguard/io/CascadingDataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ClassFilter.java b/src/proguard/io/ClassFilter.java
index bf591ab..aabc5ba 100644
--- a/src/proguard/io/ClassFilter.java
+++ b/src/proguard/io/ClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ClassReader.java b/src/proguard/io/ClassReader.java
index e21968c..0ad382b 100644
--- a/src/proguard/io/ClassReader.java
+++ b/src/proguard/io/ClassReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -109,7 +109,7 @@ public class ClassReader implements DataEntryReader
}
catch (Exception ex)
{
- throw new IOException("Can't process class ["+dataEntry.getName()+"] ("+ex.getMessage()+")");
+ throw (IOException)new IOException("Can't process class ["+dataEntry.getName()+"] ("+ex.getMessage()+")").initCause(ex);
}
}
}
diff --git a/src/proguard/io/ClassRewriter.java b/src/proguard/io/ClassRewriter.java
index bd19e1d..97e8aef 100644
--- a/src/proguard/io/ClassRewriter.java
+++ b/src/proguard/io/ClassRewriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntry.java b/src/proguard/io/DataEntry.java
index af0e373..681331b 100644
--- a/src/proguard/io/DataEntry.java
+++ b/src/proguard/io/DataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryClassWriter.java b/src/proguard/io/DataEntryClassWriter.java
new file mode 100644
index 0000000..e9f0327
--- /dev/null
+++ b/src/proguard/io/DataEntryClassWriter.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.*;
+import proguard.classfile.io.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.io.*;
+
+/**
+ * This ClassVisitor writes out the ProgramClass objects that it visits to the
+ * given DataEntry, modified to have the correct name.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryClassWriter
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final DataEntryWriter dataEntryWriter;
+ private final DataEntry templateDataEntry;
+
+
+ /**
+ * Creates a new DataEntryClassWriter for writing to the given
+ * DataEntryWriter, based on the given template DataEntry.
+ */
+ public DataEntryClassWriter(DataEntryWriter dataEntryWriter,
+ DataEntry templateDataEntry)
+ {
+ this.dataEntryWriter = dataEntryWriter;
+ this.templateDataEntry = templateDataEntry;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Rename the data entry if necessary.
+ String actualClassName = programClass.getName();
+ DataEntry actualDataEntry =
+ new RenamedDataEntry(templateDataEntry,
+ actualClassName + ClassConstants.CLASS_FILE_EXTENSION);
+
+ try
+ {
+ // Get the output entry corresponding to this input entry.
+ OutputStream outputStream = dataEntryWriter.getOutputStream(actualDataEntry);
+ if (outputStream != null)
+ {
+ // Write the class to the output entry.
+ DataOutputStream classOutputStream = new DataOutputStream(outputStream);
+
+ new ProgramClassWriter(classOutputStream).visitProgramClass(programClass);
+
+ classOutputStream.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Can't write program class ["+actualClassName+"] to ["+actualDataEntry+"] ("+e.getMessage()+")", e);
+ }
+ }
+}
diff --git a/src/proguard/io/DataEntryCopier.java b/src/proguard/io/DataEntryCopier.java
index faaa555..440e73b 100644
--- a/src/proguard/io/DataEntryCopier.java
+++ b/src/proguard/io/DataEntryCopier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,11 +64,16 @@ public class DataEntryCopier implements DataEntryReader
{
InputStream inputStream = dataEntry.getInputStream();
- // Copy the data from the input entry to the output entry.
- copyData(inputStream, outputStream);
-
- // Close the data entries.
- dataEntry.closeInputStream();
+ try
+ {
+ // Copy the data from the input entry to the output entry.
+ copyData(inputStream, outputStream);
+ }
+ finally
+ {
+ // Close the data entries.
+ dataEntry.closeInputStream();
+ }
}
}
}
@@ -76,6 +81,10 @@ public class DataEntryCopier implements DataEntryReader
{
System.err.println("Warning: can't write resource [" + dataEntry.getName() + "] (" + ex.getMessage() + ")");
}
+ catch (Exception ex)
+ {
+ throw (IOException)new IOException("Can't write resource ["+dataEntry.getName()+"] ("+ex.getMessage()+")").initCause(ex);
+ }
}
diff --git a/src/proguard/io/DataEntryDirectoryFilter.java b/src/proguard/io/DataEntryDirectoryFilter.java
index bb36f3e..5bf46bb 100644
--- a/src/proguard/io/DataEntryDirectoryFilter.java
+++ b/src/proguard/io/DataEntryDirectoryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryFilter.java b/src/proguard/io/DataEntryFilter.java
index ddcd0be..b8b6b20 100644
--- a/src/proguard/io/DataEntryFilter.java
+++ b/src/proguard/io/DataEntryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryNameFilter.java b/src/proguard/io/DataEntryNameFilter.java
index d6afd2e..5aebcdd 100644
--- a/src/proguard/io/DataEntryNameFilter.java
+++ b/src/proguard/io/DataEntryNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryObfuscator.java b/src/proguard/io/DataEntryObfuscator.java
index aa63af1..c5742e9 100644
--- a/src/proguard/io/DataEntryObfuscator.java
+++ b/src/proguard/io/DataEntryObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -75,7 +75,7 @@ public class DataEntryObfuscator implements DataEntryReader
String dataEntryName = dataEntry.getName();
// Try to find a corresponding class name by removing increasingly
- // long suffixes,
+ // long suffixes.
for (int suffixIndex = dataEntryName.length() - 1;
suffixIndex > 0;
suffixIndex--)
@@ -106,25 +106,44 @@ public class DataEntryObfuscator implements DataEntryReader
return new RenamedDataEntry(dataEntry, newDataEntryName);
}
-
- // Otherwise stop looking.
- break;
+ else
+ {
+ // Otherwise stop looking.
+ return dataEntry;
+ }
}
}
}
- // Did the package get a new name?
- String packagePrefix = ClassUtil.internalPackagePrefix(dataEntryName);
- String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
- if (newPackagePrefix != null &&
- !packagePrefix.equals(newPackagePrefix))
+ // Try to find a corresponding package name by increasingly removing
+ // more subpackages.
+ String packagePrefix = dataEntryName;
+ do
{
- // Return a renamed data entry.
- String newDataEntryName =
- newPackagePrefix + dataEntryName.substring(packagePrefix.length());
+ // Chop off the class name or the last subpackage name.
+ packagePrefix = ClassUtil.internalPackagePrefix(packagePrefix);
- return new RenamedDataEntry(dataEntry, newDataEntryName);
+ // Is there a package corresponding to the package prefix?
+ String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
+ if (newPackagePrefix != null)
+ {
+ // Did the package get a new name?
+ if (!packagePrefix.equals(newPackagePrefix))
+ {
+ // Return a renamed data entry.
+ String newDataEntryName =
+ newPackagePrefix + dataEntryName.substring(packagePrefix.length());
+
+ return new RenamedDataEntry(dataEntry, newDataEntryName);
+ }
+ else
+ {
+ // Otherwise stop looking.
+ return dataEntry;
+ }
+ }
}
+ while (packagePrefix.length() > 0);
return dataEntry;
}
diff --git a/src/proguard/io/DataEntryParentFilter.java b/src/proguard/io/DataEntryParentFilter.java
index fbeac4f..1cc1997 100644
--- a/src/proguard/io/DataEntryParentFilter.java
+++ b/src/proguard/io/DataEntryParentFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryPump.java b/src/proguard/io/DataEntryPump.java
index bfe22a3..ddf946b 100644
--- a/src/proguard/io/DataEntryPump.java
+++ b/src/proguard/io/DataEntryPump.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryReader.java b/src/proguard/io/DataEntryReader.java
index e77f7bf..39dc82d 100644
--- a/src/proguard/io/DataEntryReader.java
+++ b/src/proguard/io/DataEntryReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryRenamer.java b/src/proguard/io/DataEntryRenamer.java
index 45c61ee..99600ae 100644
--- a/src/proguard/io/DataEntryRenamer.java
+++ b/src/proguard/io/DataEntryRenamer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -87,7 +87,7 @@ public class DataEntryRenamer implements DataEntryReader
String newName = (String)nameMap.get(name);
if (newName != null)
{
- // Add remove the directory separator if necessary.
+ // Remove the directory separator if necessary.
if (dataEntry.isDirectory() &&
newName.length() > 0)
{
@@ -101,4 +101,4 @@ public class DataEntryRenamer implements DataEntryReader
missingDataEntryReader.read(dataEntry);
}
}
-} \ No newline at end of file
+}
diff --git a/src/proguard/io/DataEntryRewriter.java b/src/proguard/io/DataEntryRewriter.java
index eefced4..ec07767 100644
--- a/src/proguard/io/DataEntryRewriter.java
+++ b/src/proguard/io/DataEntryRewriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryWriter.java b/src/proguard/io/DataEntryWriter.java
index 9ecf79b..871f823 100644
--- a/src/proguard/io/DataEntryWriter.java
+++ b/src/proguard/io/DataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryFilter.java b/src/proguard/io/DirectoryFilter.java
index a45d1aa..72e2e6d 100644
--- a/src/proguard/io/DirectoryFilter.java
+++ b/src/proguard/io/DirectoryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryPump.java b/src/proguard/io/DirectoryPump.java
index cab2ff3..cd6c2ab 100644
--- a/src/proguard/io/DirectoryPump.java
+++ b/src/proguard/io/DirectoryPump.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryWriter.java b/src/proguard/io/DirectoryWriter.java
index c6605df..7948ee2 100644
--- a/src/proguard/io/DirectoryWriter.java
+++ b/src/proguard/io/DirectoryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FileDataEntry.java b/src/proguard/io/FileDataEntry.java
index d0449ee..618a092 100644
--- a/src/proguard/io/FileDataEntry.java
+++ b/src/proguard/io/FileDataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FilteredDataEntryReader.java b/src/proguard/io/FilteredDataEntryReader.java
index 11da0d4..03b5dd8 100644
--- a/src/proguard/io/FilteredDataEntryReader.java
+++ b/src/proguard/io/FilteredDataEntryReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FilteredDataEntryWriter.java b/src/proguard/io/FilteredDataEntryWriter.java
index 40a8c64..b3b751c 100644
--- a/src/proguard/io/FilteredDataEntryWriter.java
+++ b/src/proguard/io/FilteredDataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/Finisher.java b/src/proguard/io/Finisher.java
index 8c4cc1e..7d5f93f 100644
--- a/src/proguard/io/Finisher.java
+++ b/src/proguard/io/Finisher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/JarReader.java b/src/proguard/io/JarReader.java
index f96b4aa..be4c97b 100644
--- a/src/proguard/io/JarReader.java
+++ b/src/proguard/io/JarReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/JarWriter.java b/src/proguard/io/JarWriter.java
index 3e40cdf..d85e63b 100644
--- a/src/proguard/io/JarWriter.java
+++ b/src/proguard/io/JarWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ManifestRewriter.java b/src/proguard/io/ManifestRewriter.java
index f10307e..8a8c7ae 100644
--- a/src/proguard/io/ManifestRewriter.java
+++ b/src/proguard/io/ManifestRewriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -55,13 +55,14 @@ public class ManifestRewriter extends DataEntryRewriter
/**
- * This Reader reads manifest files, joining any split lines.
+ * This Reader reads manifest files, joining any split lines. It replaces
+ * the allowed CR/LF/CR+LF alternatives by simple LF in the process.
*/
private static class SplitLineReader extends FilterReader
{
- private char[] buffer = new char[2];
- private int bufferIndex = 0;
- private int bufferSize = 0;
+ private static final int NONE = -2;
+
+ private int bufferedCharacter = NONE;
public SplitLineReader(Reader reader)
@@ -76,45 +77,39 @@ public class ManifestRewriter extends DataEntryRewriter
{
while (true)
{
- if (bufferIndex < bufferSize)
- {
- return buffer[bufferIndex++];
- }
+ // Get the buffered character or the first character.
+ int c1 = bufferedCharacter != NONE ?
+ bufferedCharacter :
+ super.read();
+
+ // Clear the buffered character.
+ bufferedCharacter = NONE;
- // Read the first character.
- int c1 = super.read();
+ // Return it if it's an ordinary character.
if (c1 != '\n' && c1 != '\r')
{
return c1;
}
- bufferIndex = 0;
- bufferSize = 0;
- buffer[bufferSize++] = '\n';
-
- // Read the second character.
+ // It's a newline. Read the second character to see if it's a
+ // continuation.
int c2 = super.read();
- if (c2 == ' ')
- {
- bufferSize = 0;
- continue;
- }
- if (c1 != '\r' || c2 != '\n')
+ // Skip any corresponding, redundant \n or \r.
+ if ((c2 == '\n' || c2 == '\r') && c1 != c2)
{
- buffer[bufferSize++] = (char)c2;
- continue;
+ c2 = super.read();
}
- // Read the third character.
- int c3 = super.read();
- if (c3 == ' ')
+ // Isn't it a continuation after all?
+ if (c2 != ' ')
{
- bufferSize = 0;
- continue;
+ // Buffer the second character and return a newline.
+ bufferedCharacter = c2;
+ return '\n';
}
- buffer[bufferSize++] = (char)c3;
+ // Just continue after the continuation characters.
}
}
@@ -184,7 +179,7 @@ public class ManifestRewriter extends DataEntryRewriter
}
else if (counter == 70)
{
- // Insert are newline and space.
+ // Insert a newline and a space.
super.write('\n');
super.write(' ');
diff --git a/src/proguard/io/NameFilter.java b/src/proguard/io/NameFilter.java
index 2a9fbc3..67d630e 100644
--- a/src/proguard/io/NameFilter.java
+++ b/src/proguard/io/NameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ParentDataEntryWriter.java b/src/proguard/io/ParentDataEntryWriter.java
index 4f16d12..f24ef37 100644
--- a/src/proguard/io/ParentDataEntryWriter.java
+++ b/src/proguard/io/ParentDataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/RenamedDataEntry.java b/src/proguard/io/RenamedDataEntry.java
index ae2d267..a0f5657 100644
--- a/src/proguard/io/RenamedDataEntry.java
+++ b/src/proguard/io/RenamedDataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ZipDataEntry.java b/src/proguard/io/ZipDataEntry.java
index 5779fd8..20a9d3b 100644
--- a/src/proguard/io/ZipDataEntry.java
+++ b/src/proguard/io/ZipDataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/AttributeShrinker.java b/src/proguard/obfuscate/AttributeShrinker.java
index a8bc36b..0c3ab94 100644
--- a/src/proguard/obfuscate/AttributeShrinker.java
+++ b/src/proguard/obfuscate/AttributeShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,6 +26,8 @@ import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.*;
+import java.util.Arrays;
+
/**
* This ClassVisitor removes attributes that are not marked as being used or
* required.
@@ -111,10 +113,7 @@ implements ClassVisitor,
}
// Clear the remaining array elements.
- for (int index = counter; index < length; index++)
- {
- array[index] = null;
- }
+ Arrays.fill(array, counter, length, null);
return counter;
}
diff --git a/src/proguard/obfuscate/AttributeUsageMarker.java b/src/proguard/obfuscate/AttributeUsageMarker.java
index e772324..32a512b 100644
--- a/src/proguard/obfuscate/AttributeUsageMarker.java
+++ b/src/proguard/obfuscate/AttributeUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,7 +26,7 @@ import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
/**
- * This ClassVisitor marks all attributes that it visits.
+ * This AttributeVisitor marks all attributes that it visits.
*
* @see AttributeShrinker
*
diff --git a/src/proguard/obfuscate/ClassObfuscator.java b/src/proguard/obfuscate/ClassObfuscator.java
index 9af0c82..9e1a91c 100644
--- a/src/proguard/obfuscate/ClassObfuscator.java
+++ b/src/proguard/obfuscate/ClassObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -164,6 +164,14 @@ implements ClassVisitor,
}
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // This can happen for dubious input, if the outer class of a program
+ // class is a library class, and its name is requested.
+ newClassName = libraryClass.getName();
+ }
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -469,13 +477,25 @@ implements ClassVisitor,
{
// Come up with class names until we get an original one.
String newClassName;
+ String newMixedCaseClassName;
do
{
// Let the factory produce a class name.
newClassName = newPackagePrefix +
classNameFactory.nextName();
+
+ newMixedCaseClassName = mixedCaseClassName(newClassName);
+ }
+ while (classNamesToAvoid.contains(newMixedCaseClassName));
+
+ // Explicitly make sure the name isn't used again if we have a
+ // user-specified dictionary and we're not allowed to have mixed case
+ // class names -- just to protect against problematic dictionaries.
+ if (this.classNameFactory != null &&
+ !useMixedCaseClassNames)
+ {
+ classNamesToAvoid.add(newMixedCaseClassName);
}
- while (classNamesToAvoid.contains(mixedCaseClassName(newClassName)));
return newClassName;
}
diff --git a/src/proguard/obfuscate/ClassRenamer.java b/src/proguard/obfuscate/ClassRenamer.java
index 143e3fb..4c5e496 100644
--- a/src/proguard/obfuscate/ClassRenamer.java
+++ b/src/proguard/obfuscate/ClassRenamer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/DictionaryNameFactory.java b/src/proguard/obfuscate/DictionaryNameFactory.java
index f262664..4a7e28c 100644
--- a/src/proguard/obfuscate/DictionaryNameFactory.java
+++ b/src/proguard/obfuscate/DictionaryNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MapCleaner.java b/src/proguard/obfuscate/MapCleaner.java
index fdefec5..d11f443 100644
--- a/src/proguard/obfuscate/MapCleaner.java
+++ b/src/proguard/obfuscate/MapCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingKeeper.java b/src/proguard/obfuscate/MappingKeeper.java
index c9d6aa6..7ab1e25 100644
--- a/src/proguard/obfuscate/MappingKeeper.java
+++ b/src/proguard/obfuscate/MappingKeeper.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingPrinter.java b/src/proguard/obfuscate/MappingPrinter.java
index aa8b13e..a28d10c 100644
--- a/src/proguard/obfuscate/MappingPrinter.java
+++ b/src/proguard/obfuscate/MappingPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,8 @@
package proguard.obfuscate;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
@@ -38,7 +40,8 @@ import java.io.PrintStream;
public class MappingPrinter
extends SimplifiedVisitor
implements ClassVisitor,
- MemberVisitor
+ MemberVisitor,
+ AttributeVisitor
{
private final PrintStream ps;
@@ -80,11 +83,6 @@ implements ClassVisitor,
}
- public void visitLibraryClass(LibraryClass libraryClass)
- {
- }
-
-
// Implementations for MemberVisitor.
public void visitProgramField(ProgramClass programClass, ProgramField programField)
@@ -93,7 +91,6 @@ implements ClassVisitor,
if (newName != null)
{
ps.println(" " +
- //lineNumberRange(programClass, programField) +
ClassUtil.externalFullFieldDescription(
0,
programField.getName(programClass),
@@ -118,9 +115,9 @@ implements ClassVisitor,
String newName = MemberObfuscator.newMemberName(programMethod);
if (newName != null)
{
- ps.println(" " +
- lineNumberRange(programClass, programMethod) +
- ClassUtil.externalFullMethodDescription(
+ ps.print(" ");
+ programMethod.attributesAccept(programClass, this);
+ ps.println(ClassUtil.externalFullMethodDescription(
programClass.getName(),
0,
programMethod.getName(programClass),
@@ -131,17 +128,20 @@ implements ClassVisitor,
}
- // Small utility methods.
+ // Implementations for AttributeVisitor.
- /**
- * Returns the line number range of the given class member, followed by a
- * colon, or just an empty String if no range is available.
- */
- private static String lineNumberRange(ProgramClass programClass, ProgramMember programMember)
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
- String range = programMember.getLineNumberRange(programClass);
- return range != null ?
- (range + ":") :
- "";
+ ps.print(lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ":");
}
}
diff --git a/src/proguard/obfuscate/MappingProcessor.java b/src/proguard/obfuscate/MappingProcessor.java
index 01c1809..92a916a 100644
--- a/src/proguard/obfuscate/MappingProcessor.java
+++ b/src/proguard/obfuscate/MappingProcessor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingReader.java b/src/proguard/obfuscate/MappingReader.java
index 24fd26c..51d14ac 100644
--- a/src/proguard/obfuscate/MappingReader.java
+++ b/src/proguard/obfuscate/MappingReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameCleaner.java b/src/proguard/obfuscate/MemberNameCleaner.java
index c41c59d..5205fee 100644
--- a/src/proguard/obfuscate/MemberNameCleaner.java
+++ b/src/proguard/obfuscate/MemberNameCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameCollector.java b/src/proguard/obfuscate/MemberNameCollector.java
index c248820..1544901 100644
--- a/src/proguard/obfuscate/MemberNameCollector.java
+++ b/src/proguard/obfuscate/MemberNameCollector.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameConflictFixer.java b/src/proguard/obfuscate/MemberNameConflictFixer.java
index b9093a6..68e7c05 100644
--- a/src/proguard/obfuscate/MemberNameConflictFixer.java
+++ b/src/proguard/obfuscate/MemberNameConflictFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameFilter.java b/src/proguard/obfuscate/MemberNameFilter.java
new file mode 100644
index 0000000..6d95270
--- /dev/null
+++ b/src/proguard/obfuscate/MemberNameFilter.java
@@ -0,0 +1,120 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member has a new name.
+ * Constructors are judged based on the class name.
+ *
+ * @see ClassObfuscator
+ * @see MemberObfuscator
+ *
+ * @author Eric Lafortune
+ */
+public class MemberNameFilter implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberNameFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MemberNameFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (hasName(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (hasName(programClass, programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (hasName(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (hasName(libraryClass, libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given class has a new name.
+ */
+ private boolean hasName(Clazz clazz)
+ {
+ return ClassObfuscator.newClassName(clazz) != null;
+ }
+
+
+ /**
+ * Returns whether the given method has a new name.
+ */
+ private boolean hasName(Clazz clazz, Method method)
+ {
+ return
+ hasName(method) ||
+ (hasName(clazz) &&
+ method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT));
+ }
+
+
+ /**
+ * Returns whether the given class member has a new name.
+ */
+ private boolean hasName(Member member)
+ {
+ return MemberObfuscator.newMemberName(member) != null;
+ }
+}
diff --git a/src/proguard/obfuscate/MemberObfuscator.java b/src/proguard/obfuscate/MemberObfuscator.java
index 332b849..adf590c 100644
--- a/src/proguard/obfuscate/MemberObfuscator.java
+++ b/src/proguard/obfuscate/MemberObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberSpecialNameFilter.java b/src/proguard/obfuscate/MemberSpecialNameFilter.java
index f83374b..0eb4d2d 100644
--- a/src/proguard/obfuscate/MemberSpecialNameFilter.java
+++ b/src/proguard/obfuscate/MemberSpecialNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -54,7 +54,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- if (isSpecialName(programField))
+ if (hasSpecialName(programField))
{
memberVisitor.visitProgramField(programClass, programField);
}
@@ -63,7 +63,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- if (isSpecialName(programMethod))
+ if (hasSpecialName(programMethod))
{
memberVisitor.visitProgramMethod(programClass, programMethod);
}
@@ -72,7 +72,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
{
- if (isSpecialName(libraryField))
+ if (hasSpecialName(libraryField))
{
memberVisitor.visitLibraryField(libraryClass, libraryField);
}
@@ -81,7 +81,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
{
- if (isSpecialName(libraryMethod))
+ if (hasSpecialName(libraryMethod))
{
memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
}
@@ -94,7 +94,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
* Returns whether the given class member has a special new name.
* @param member the class member.
*/
- private static boolean isSpecialName(Member member)
+ private static boolean hasSpecialName(Member member)
{
return SpecialNameFactory.isSpecialName(MemberObfuscator.newMemberName(member));
}
diff --git a/src/proguard/obfuscate/MultiMappingProcessor.java b/src/proguard/obfuscate/MultiMappingProcessor.java
index 4074ff8..051260f 100644
--- a/src/proguard/obfuscate/MultiMappingProcessor.java
+++ b/src/proguard/obfuscate/MultiMappingProcessor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameAndTypeShrinker.java b/src/proguard/obfuscate/NameAndTypeShrinker.java
deleted file mode 100644
index 1284c82..0000000
--- a/src/proguard/obfuscate/NameAndTypeShrinker.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package proguard.obfuscate;
-
-import proguard.classfile.*;
-import proguard.classfile.constant.Constant;
-import proguard.classfile.editor.ConstantPoolRemapper;
-import proguard.classfile.visitor.ClassVisitor;
-
-
-/**
- * This ClassVisitor removes NameAndType constant pool entries
- * that are not marked as being used.
- *
- * @see NameAndTypeUsageMarker
- *
- * @author Eric Lafortune
- */
-public class NameAndTypeShrinker implements ClassVisitor
-{
- private int[] constantIndexMap;
- private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
-
-
- // Implementations for ClassVisitor.
-
- public void visitProgramClass(ProgramClass programClass)
- {
- // Shift the used constant pool entries together, filling out the
- // index map.
- programClass.u2constantPoolCount =
- shrinkConstantPool(programClass.constantPool,
- programClass.u2constantPoolCount);
-
-
- // Remap all constant pool references.
- constantPoolRemapper.setConstantIndexMap(constantIndexMap);
- constantPoolRemapper.visitProgramClass(programClass);
- }
-
-
- public void visitLibraryClass(LibraryClass libraryClass)
- {
- }
-
-
- // Small utility methods.
-
- /**
- * Removes all NameAndType entries that are not marked as being used
- * from the given constant pool.
- * @return the new number of entries.
- */
- private int shrinkConstantPool(Constant[] constantPool, int length)
- {
- // Create a new index map, if necessary.
- if (constantIndexMap == null ||
- constantIndexMap.length < length)
- {
- constantIndexMap = new int[length];
- }
-
- int counter = 1;
- boolean isUsed = false;
-
- // Shift the used constant pool entries together.
- for (int index = 1; index < length; index++)
- {
- constantIndexMap[index] = counter;
-
- Constant constant = constantPool[index];
-
- // Don't update the flag if this is the second half of a long entry.
- if (constant != null)
- {
- isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType ||
- NameAndTypeUsageMarker.isUsed(constant);
- }
-
- if (isUsed)
- {
- constantPool[counter++] = constant;
- }
- }
-
- // Clear the remaining constant pool elements.
- for (int index = counter; index < length; index++)
- {
- constantPool[index] = null;
- }
-
- return counter;
- }
-}
diff --git a/src/proguard/obfuscate/NameFactory.java b/src/proguard/obfuscate/NameFactory.java
index c64d1ad..97ebe5a 100644
--- a/src/proguard/obfuscate/NameFactory.java
+++ b/src/proguard/obfuscate/NameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameFactoryResetter.java b/src/proguard/obfuscate/NameFactoryResetter.java
index b6ba6ad..b04d12e 100644
--- a/src/proguard/obfuscate/NameFactoryResetter.java
+++ b/src/proguard/obfuscate/NameFactoryResetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameMarker.java b/src/proguard/obfuscate/NameMarker.java
index 2ce0ee9..5283ef3 100644
--- a/src/proguard/obfuscate/NameMarker.java
+++ b/src/proguard/obfuscate/NameMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NumericNameFactory.java b/src/proguard/obfuscate/NumericNameFactory.java
index cc21c4b..b1e38b1 100644
--- a/src/proguard/obfuscate/NumericNameFactory.java
+++ b/src/proguard/obfuscate/NumericNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Obfuscator.java b/src/proguard/obfuscate/Obfuscator.java
index dce563a..cc79b0d 100644
--- a/src/proguard/obfuscate/Obfuscator.java
+++ b/src/proguard/obfuscate/Obfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -99,19 +99,30 @@ public class Obfuscator
libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker));
// Mark attributes that have to be kept.
- AttributeUsageMarker requiredAttributeUsageMarker =
- new AttributeUsageMarker();
+ AttributeVisitor attributeUsageMarker =
+ new NonEmptyAttributeFilter(
+ new AttributeUsageMarker());
AttributeVisitor optionalAttributeUsageMarker =
configuration.keepAttributes == null ? null :
new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes),
- requiredAttributeUsageMarker);
+ attributeUsageMarker);
programClassPool.classesAccept(
new AllAttributeVisitor(true,
- new RequiredAttributeFilter(requiredAttributeUsageMarker,
+ new RequiredAttributeFilter(attributeUsageMarker,
optionalAttributeUsageMarker)));
+ // Keep parameter names and types if specified.
+ if (configuration.keepParameterNames)
+ {
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new MemberNameFilter(
+ new AllAttributeVisitor(true,
+ new ParameterNameMarker(attributeUsageMarker)))));
+ }
+
// Remove the attributes that can be discarded. Note that the attributes
// may only be discarded after the seeds have been marked, since the
// configuration may rely on annotations.
@@ -135,17 +146,23 @@ public class Obfuscator
reader.pump(keeper);
// Print out a summary of the warnings if necessary.
- int mappingWarningCount = warningPrinter.getWarningCount();
- if (mappingWarningCount > 0)
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
{
- System.err.println("Warning: there were " + mappingWarningCount +
- " kept classes and class members that were remapped anyway.");
+ System.err.println("Warning: there were " + warningCount +
+ " kept classes and class members that were remapped anyway.");
System.err.println(" You should adapt your configuration or edit the mapping file.");
if (!configuration.ignoreWarnings)
{
- System.err.println(" If you are sure this remapping won't hurt,");
- System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ System.err.println(" If you are sure this remapping won't hurt, you could try your luck");
+ System.err.println(" using the '-ignorewarnings' option.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#mappingconflict1)");
+
+ if (!configuration.ignoreWarnings)
+ {
throw new IOException("Please correct the above warnings first.");
}
}
@@ -248,6 +265,19 @@ public class Obfuscator
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)))),
+ // Collect all member names from interfaces of abstract
+ // classes down the hierarchy.
+ // Due to an error in the JLS/JVMS, virtual invocations
+ // may end up at a private method otherwise (Sun/Oracle
+ // bugs #6691741 and #6684387, ProGuard bug #3471941,
+ // and ProGuard test #1180).
+ new ClassHierarchyTraveler(false, false, false, true,
+ new ClassAccessFilter(ClassConstants.INTERNAL_ACC_ABSTRACT, 0,
+ new ClassHierarchyTraveler(false, false, true, false,
+ new AllMemberVisitor(
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap))))),
+
// Assign new names to all private members in this class.
new AllMemberVisitor(
new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0,
@@ -361,6 +391,12 @@ public class Obfuscator
{
System.err.println(" If you are sure the conflicts are harmless,");
System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#mappingconflict2)");
+
+ if (!configuration.ignoreWarnings)
+ {
throw new IOException("Please correct the above warnings first.");
}
}
@@ -368,14 +404,20 @@ public class Obfuscator
// Print out the mapping, if requested.
if (configuration.printMapping != null)
{
- PrintStream ps = isFile(configuration.printMapping) ?
- new PrintStream(new BufferedOutputStream(new FileOutputStream(configuration.printMapping))) :
- System.out;
+ PrintStream ps =
+ configuration.printMapping == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(configuration.printMapping)));
// Print out items that will be removed.
programClassPool.classesAcceptAlphabetically(new MappingPrinter(ps));
- if (ps != System.out)
+ if (ps == System.out)
+ {
+ ps.flush();
+ }
+ else
{
ps.close();
}
@@ -398,32 +440,27 @@ public class Obfuscator
programClassPool.classesAccept(
new AllConstantVisitor(
new AccessFixer()));
+
+ // Fix the access flags of the inner classes information.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllInnerClassesInfoVisitor(
+ new InnerClassesAccessFixer())));
}
+ // Fix the bridge method flags.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new BridgeMethodFixer()));
+
// Rename the source file attributes, if requested.
if (configuration.newSourceFileAttribute != null)
{
programClassPool.classesAccept(new SourceFileRenamer(configuration.newSourceFileAttribute));
}
- // Mark NameAndType constant pool entries that have to be kept
- // and remove the other ones.
- programClassPool.classesAccept(new NameAndTypeUsageMarker());
- programClassPool.classesAccept(new NameAndTypeShrinker());
-
- // Mark Utf8 constant pool entries that have to be kept
- // and remove the other ones.
- programClassPool.classesAccept(new Utf8UsageMarker());
- programClassPool.classesAccept(new Utf8Shrinker());
- }
-
-
- /**
- * Returns whether the given file is actually a file, or just a placeholder
- * for the standard output.
- */
- private boolean isFile(File file)
- {
- return file.getPath().length() > 0;
+ // Remove unused constants.
+ programClassPool.classesAccept(
+ new ConstantPoolShrinker());
}
}
diff --git a/src/proguard/obfuscate/ParameterNameMarker.java b/src/proguard/obfuscate/ParameterNameMarker.java
new file mode 100644
index 0000000..22af125
--- /dev/null
+++ b/src/proguard/obfuscate/ParameterNameMarker.java
@@ -0,0 +1,128 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This AttributeVisitor trims and marks all local variable (type) table
+ * attributes that it visits. It keeps parameter names and types and removes
+ * the ordinary local variable names and types.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterNameMarker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final AttributeVisitor attributeUsageMarker;
+
+
+ /**
+ * Constructs a new ParameterNameMarker.
+ * @param attributeUsageMarker the marker that will be used to mark
+ * attributes containing local variable info.
+ */
+ public ParameterNameMarker(AttributeVisitor attributeUsageMarker)
+ {
+ this.attributeUsageMarker = attributeUsageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (!AttributeUsageMarker.isUsed(localVariableTableAttribute) &&
+ hasParameters(clazz, method))
+ {
+ // Shift the entries that start at offset 0 to the front.
+ int newIndex = 0;
+
+ for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++)
+ {
+ LocalVariableInfo localVariableInfo =
+ localVariableTableAttribute.localVariableTable[index];
+
+ if (localVariableInfo.u2startPC == 0)
+ {
+ localVariableTableAttribute.localVariableTable[newIndex++] =
+ localVariableInfo;
+ }
+ }
+
+ // Trim the table.
+ localVariableTableAttribute.u2localVariableTableLength = newIndex;
+
+ // Mark the table if there are any entries.
+ if (newIndex > 0)
+ {
+ attributeUsageMarker.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (!AttributeUsageMarker.isUsed(localVariableTypeTableAttribute) &&
+ hasParameters(clazz, method))
+ {
+ // Shift the entries that start at offset 0 to the front.
+ int newIndex = 0;
+
+ for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo =
+ localVariableTypeTableAttribute.localVariableTypeTable[index];
+
+ if (localVariableTypeInfo.u2startPC == 0)
+ {
+ localVariableTypeTableAttribute.localVariableTypeTable[newIndex++] =
+ localVariableTypeInfo;
+ }
+ }
+
+ // Trim the table.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength = newIndex;
+
+ // Mark the table if there are any entries.
+ if (newIndex > 0)
+ {
+ attributeUsageMarker.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean hasParameters(Clazz clazz, Method method)
+ {
+ return method.getDescriptor(clazz).charAt(1) != ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE;
+ }
+} \ No newline at end of file
diff --git a/src/proguard/obfuscate/SimpleNameFactory.java b/src/proguard/obfuscate/SimpleNameFactory.java
index bce22de..0473852 100644
--- a/src/proguard/obfuscate/SimpleNameFactory.java
+++ b/src/proguard/obfuscate/SimpleNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/SourceFileRenamer.java b/src/proguard/obfuscate/SourceFileRenamer.java
index cbf1b63..248d18f 100644
--- a/src/proguard/obfuscate/SourceFileRenamer.java
+++ b/src/proguard/obfuscate/SourceFileRenamer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/SpecialNameFactory.java b/src/proguard/obfuscate/SpecialNameFactory.java
index a5431ca..596f919 100644
--- a/src/proguard/obfuscate/SpecialNameFactory.java
+++ b/src/proguard/obfuscate/SpecialNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Utf8Shrinker.java b/src/proguard/obfuscate/Utf8Shrinker.java
deleted file mode 100644
index 87ada80..0000000
--- a/src/proguard/obfuscate/Utf8Shrinker.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package proguard.obfuscate;
-
-import proguard.classfile.*;
-import proguard.classfile.constant.Constant;
-import proguard.classfile.editor.ConstantPoolRemapper;
-import proguard.classfile.visitor.ClassVisitor;
-
-
-/**
- * This ClassVisitor removes UTF-8 constant pool entries that are not marked
- * as being used.
- *
- * @see Utf8UsageMarker
- *
- * @author Eric Lafortune
- */
-public class Utf8Shrinker implements ClassVisitor
-{
- private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
- private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
-
-
- // Implementations for ClassVisitor.
-
- public void visitProgramClass(ProgramClass programClass)
- {
- // Shift the used constant pool entries together, filling out the
- // index map.
- programClass.u2constantPoolCount =
- shrinkConstantPool(programClass.constantPool,
- programClass.u2constantPoolCount);
-
- // Remap all constant pool references.
- constantPoolRemapper.setConstantIndexMap(constantIndexMap);
- constantPoolRemapper.visitProgramClass(programClass);
- }
-
-
- public void visitLibraryClass(LibraryClass libraryClass)
- {
- }
-
-
- // Small utility methods.
-
- /**
- * Removes all UTF-8 entries that are not marked as being used
- * from the given constant pool.
- * @return the new number of entries.
- */
- private int shrinkConstantPool(Constant[] constantPool, int length)
- {
- // Create a new index map, if necessary.
- if (constantIndexMap.length < length)
- {
- constantIndexMap = new int[length];
- }
-
- int counter = 1;
- boolean isUsed = false;
-
- // Shift the used constant pool entries together.
- for (int index = 1; index < length; index++)
- {
- constantIndexMap[index] = counter;
-
- Constant constant = constantPool[index];
-
- // Don't update the flag if this is the second half of a long entry.
- if (constant != null)
- {
- isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 ||
- Utf8UsageMarker.isUsed(constant);
- }
-
- if (isUsed)
- {
- constantPool[counter++] = constant;
- }
- }
-
- // Clear the remaining constant pool elements.
- for (int index = counter; index < length; index++)
- {
- constantPool[index] = null;
- }
-
- return counter;
- }
-}
diff --git a/src/proguard/optimize/BootstrapMethodArgumentShrinker.java b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java
new file mode 100644
index 0000000..26f1349
--- /dev/null
+++ b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java
@@ -0,0 +1,103 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.ConstantPoolEditor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.*;
+import proguard.optimize.peephole.VariableShrinker;
+
+/**
+ * This BootstrapMethodInfoVisitor removes unused constant arguments from
+ * bootstrap method entries that it visits.
+ *
+ * @see ParameterUsageMarker
+ * @see VariableUsageMarker
+ * @see VariableShrinker
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodArgumentShrinker
+extends SimplifiedVisitor
+implements BootstrapMethodInfoVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ private long usedParameters;
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Check which method parameters are used.
+ usedParameters = -1L;
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
+
+ // Remove the unused arguments.
+ int methodArgumentCount = bootstrapMethodInfo.u2methodArgumentCount;
+ int[] methodArguments = bootstrapMethodInfo.u2methodArguments;
+
+ int newArgumentIndex = 0;
+
+ for (int argumentIndex = 0; argumentIndex < methodArgumentCount; argumentIndex++)
+ {
+ if (argumentIndex >= 64 ||
+ (usedParameters & (1L << argumentIndex)) != 0L)
+ {
+ methodArguments[newArgumentIndex++] = methodArguments[argumentIndex];
+ }
+ }
+
+ // Update the number of arguments.
+ bootstrapMethodInfo.u2methodArgumentCount = newArgumentIndex;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the referenced bootstrap method.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Check the referenced class member itself.
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ usedParameters = ParameterUsageMarker.getUsedParameters(programMethod);
+ }
+}
diff --git a/src/proguard/optimize/ChangedCodePrinter.java b/src/proguard/optimize/ChangedCodePrinter.java
index 67a79ab..668d43d 100644
--- a/src/proguard/optimize/ChangedCodePrinter.java
+++ b/src/proguard/optimize/ChangedCodePrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -54,6 +54,12 @@ implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute);
diff --git a/src/proguard/optimize/ConstantMemberFilter.java b/src/proguard/optimize/ConstantMemberFilter.java
index 56437c3..1f30a30 100644
--- a/src/proguard/optimize/ConstantMemberFilter.java
+++ b/src/proguard/optimize/ConstantMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/ConstantParameterFilter.java b/src/proguard/optimize/ConstantParameterFilter.java
index 24a7040..1500fd0 100644
--- a/src/proguard/optimize/ConstantParameterFilter.java
+++ b/src/proguard/optimize/ConstantParameterFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/DuplicateInitializerFixer.java b/src/proguard/optimize/DuplicateInitializerFixer.java
index 746d182..95bc2f1 100644
--- a/src/proguard/optimize/DuplicateInitializerFixer.java
+++ b/src/proguard/optimize/DuplicateInitializerFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -86,7 +86,7 @@ implements MemberVisitor,
if (!programMethod.equals(similarMethod))
{
// Should this initializer be preserved?
- if (!KeepMarker.isKept(programMethod))
+ if (KeepMarker.isKept(programMethod))
{
// Fix the other initializer.
programMethod = (ProgramMethod)similarMethod;
@@ -95,12 +95,23 @@ implements MemberVisitor,
int index = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
// Try to find a new, unique descriptor.
- for (int typeIndex = 0; typeIndex < TYPES.length; typeIndex++)
+ int typeCounter = 0;
+ while (true)
{
- String newDescriptor =
- descriptor.substring(0, index) +
- TYPES[typeIndex] +
- descriptor.substring(index);
+ // Construct the new descriptor by inserting a new type
+ // as an additional last argument.
+ StringBuffer newDescriptorBuffer =
+ new StringBuffer(descriptor.substring(0, index));
+
+ for (int arrayDimension = 0; arrayDimension < typeCounter / TYPES.length; arrayDimension++)
+ {
+ newDescriptorBuffer.append(ClassConstants.INTERNAL_TYPE_ARRAY);
+ }
+
+ newDescriptorBuffer.append(TYPES[typeCounter % TYPES.length]);
+ newDescriptorBuffer.append(descriptor.substring(index));
+
+ String newDescriptor = newDescriptorBuffer.toString();
// Is the new initializer descriptor unique?
if (programClass.findMethod(name, newDescriptor) == null)
@@ -108,7 +119,7 @@ implements MemberVisitor,
if (DEBUG)
{
System.out.println("DuplicateInitializerFixer:");
- System.out.println(" ["+programClass.getName()+"]: "+name+descriptor+" -> "+newDescriptor);
+ System.out.println(" ["+programClass.getName()+"."+name+descriptor+"] ("+ClassUtil.externalClassAccessFlags(programMethod.getAccessFlags())+") -> ["+newDescriptor+"]");
}
// Update the descriptor.
@@ -130,12 +141,9 @@ implements MemberVisitor,
// We're done with this constructor.
return;
}
- }
- throw new IllegalStateException("Can't find unique constructor descriptor for ["+
- programClass.getName()+"."+
- programMethod.getName(programClass)+
- programMethod.getDescriptor(programClass)+"]");
+ typeCounter++;
+ }
}
}
}
diff --git a/src/proguard/optimize/DuplicateInitializerInvocationFixer.java b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
index ca24481..5edaba0 100644
--- a/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
+++ b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,7 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.editor.CodeAttributeEditor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
/**
@@ -48,12 +48,12 @@ implements AttributeVisitor,
private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
- private String descriptor;
- private boolean hasBeenFixed;
+ private String descriptor;
+ private int descriptorLengthDelta;
/**
- * Creates a new EvaluationSimplifier.
+ * Creates a new DuplicateInitializerInvocationFixer.
*/
public DuplicateInitializerInvocationFixer()
{
@@ -62,7 +62,7 @@ implements AttributeVisitor,
/**
- * Creates a new EvaluationSimplifier.
+ * Creates a new DuplicateInitializerInvocationFixer.
* @param extraAddedInstructionVisitor an optional extra visitor for all
* added instructions.
*/
@@ -102,21 +102,22 @@ implements AttributeVisitor,
{
if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL)
{
- hasBeenFixed = false;
+ descriptorLengthDelta = 0;
clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
- if (hasBeenFixed)
+ if (descriptorLengthDelta > 0)
{
Instruction extraInstruction =
- new SimpleInstruction(InstructionConstants.OP_ICONST_0);
+ new SimpleInstruction(descriptorLengthDelta == 1 ?
+ InstructionConstants.OP_ICONST_0 :
+ InstructionConstants.OP_ACONST_NULL);
codeAttributeEditor.insertBeforeInstruction(offset,
extraInstruction);
if (DEBUG)
{
- System.out.println("DuplicateInitializerInvocationFixer:");
- System.out.println(" Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset));
+ System.out.println(" ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset));
}
if (extraAddedInstructionVisitor != null)
@@ -145,6 +146,16 @@ implements AttributeVisitor,
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- hasBeenFixed = !descriptor.equals(programMethod.getDescriptor(programClass));
+ descriptorLengthDelta =
+ programMethod.getDescriptor(programClass).length() - descriptor.length();
+
+ if (DEBUG)
+ {
+ if (descriptorLengthDelta > 0)
+ {
+ System.out.println("DuplicateInitializerInvocationFixer:");
+ System.out.println(" ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] ("+ClassUtil.externalClassAccessFlags(programMethod.getAccessFlags())+") referenced by:");
+ }
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/proguard/optimize/KeepMarker.java b/src/proguard/optimize/KeepMarker.java
index 4297996..b0eab7b 100644
--- a/src/proguard/optimize/KeepMarker.java
+++ b/src/proguard/optimize/KeepMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,6 +23,7 @@ package proguard.optimize;
import proguard.classfile.*;
import proguard.classfile.util.MethodLinker;
import proguard.classfile.visitor.*;
+import proguard.optimize.info.NoSideEffectMethodMarker;
/**
@@ -30,6 +31,7 @@ import proguard.classfile.visitor.*;
* marks classes and class members it visits. The marked elements
* will remain unchanged as necessary in the optimization step.
*
+ * @see NoSideEffectMethodMarker
* @author Eric Lafortune
*/
public class KeepMarker
@@ -90,6 +92,12 @@ implements ClassVisitor,
public static boolean isKept(VisitorAccepter visitorAccepter)
{
- return MethodLinker.lastVisitorAccepter(visitorAccepter).getVisitorInfo() == KEPT;
+ // We're also checking for the constant in NoSideEffectMethodMarker,
+ // to keep things simple.
+ Object visitorInfo =
+ MethodLinker.lastVisitorAccepter(visitorAccepter).getVisitorInfo();
+
+ return visitorInfo == KEPT ||
+ visitorInfo == NoSideEffectMethodMarker.KEPT_BUT_NO_SIDE_EFFECTS;
}
}
diff --git a/src/proguard/optimize/KeptClassFilter.java b/src/proguard/optimize/KeptClassFilter.java
new file mode 100644
index 0000000..60a9d3e
--- /dev/null
+++ b/src/proguard/optimize/KeptClassFilter.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are marked as kept.
+ *
+ * @see KeepMarker
+ *
+ * @author Eric Lafortune
+ */
+public class KeptClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new KeptClassFilter.
+ * @param classVisitor the class visitor to which the visiting will be
+ * delegated.
+ */
+ public KeptClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (KeepMarker.isKept(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (KeepMarker.isKept(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/KeptMemberFilter.java b/src/proguard/optimize/KeptMemberFilter.java
new file mode 100644
index 0000000..1bdadb4
--- /dev/null
+++ b/src/proguard/optimize/KeptMemberFilter.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Member objects that are marked as kept.
+ *
+ * @see KeepMarker
+ *
+ * @author Eric Lafortune
+ */
+public class KeptMemberFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new KeptMemberFilter.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public KeptMemberFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (KeepMarker.isKept(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (KeepMarker.isKept(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (KeepMarker.isKept(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (KeepMarker.isKept(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/MemberDescriptorSpecializer.java b/src/proguard/optimize/MemberDescriptorSpecializer.java
index 0d0b841..4dce62e 100644
--- a/src/proguard/optimize/MemberDescriptorSpecializer.java
+++ b/src/proguard/optimize/MemberDescriptorSpecializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,7 +39,7 @@ public class MemberDescriptorSpecializer
extends SimplifiedVisitor
implements MemberVisitor
{
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private final MemberVisitor extraParameterMemberVisitor;
diff --git a/src/proguard/optimize/MethodDescriptorShrinker.java b/src/proguard/optimize/MethodDescriptorShrinker.java
index 48374e7..d8d4425 100644
--- a/src/proguard/optimize/MethodDescriptorShrinker.java
+++ b/src/proguard/optimize/MethodDescriptorShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,7 @@ package proguard.optimize;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.editor.ConstantPoolEditor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
@@ -95,11 +95,9 @@ implements MemberVisitor,
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);
+ System.out.println(" ["+programClass.getName()+"."+
+ name+descriptor+"] -> ["+
+ newName+newDescriptor+"]");
}
ConstantPoolEditor constantPoolEditor =
diff --git a/src/proguard/optimize/MethodStaticizer.java b/src/proguard/optimize/MethodStaticizer.java
index 8dd11e1..c8bdd11 100644
--- a/src/proguard/optimize/MethodStaticizer.java
+++ b/src/proguard/optimize/MethodStaticizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/OptimizationInfoMemberFilter.java b/src/proguard/optimize/OptimizationInfoMemberFilter.java
index 8760aee..2c5454c 100644
--- a/src/proguard/optimize/OptimizationInfoMemberFilter.java
+++ b/src/proguard/optimize/OptimizationInfoMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/Optimizer.java b/src/proguard/optimize/Optimizer.java
index a3e8a6e..8042825 100644
--- a/src/proguard/optimize/Optimizer.java
+++ b/src/proguard/optimize/Optimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,8 @@ package proguard.optimize;
import proguard.*;
import proguard.classfile.*;
import proguard.classfile.attribute.visitor.*;
-import proguard.classfile.constant.visitor.AllConstantVisitor;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.visitor.*;
import proguard.classfile.editor.*;
import proguard.classfile.instruction.visitor.*;
import proguard.classfile.util.MethodLinker;
@@ -66,6 +67,7 @@ public class Optimizer
private static final String CODE_SIMPLIFICATION_CAST = "code/simplification/cast";
private static final String CODE_SIMPLIFICATION_FIELD = "code/simplification/field";
private static final String CODE_SIMPLIFICATION_BRANCH = "code/simplification/branch";
+ private static final String CODE_SIMPLIFICATION_STRING = "code/simplification/string";
private static final String CODE_SIMPLIFICATION_ADVANCED = "code/simplification/advanced";
private static final String CODE_REMOVAL_ADVANCED = "code/removal/advanced";
private static final String CODE_REMOVAL_SIMPLE = "code/removal/simple";
@@ -80,6 +82,7 @@ public class Optimizer
CLASS_MERGING_VERTICAL,
CLASS_MERGING_HORIZONTAL,
FIELD_REMOVAL_WRITEONLY,
+ FIELD_MARKING_PRIVATE,
FIELD_PROPAGATION_VALUE,
METHOD_MARKING_PRIVATE,
METHOD_MARKING_STATIC,
@@ -96,6 +99,7 @@ public class Optimizer
CODE_SIMPLIFICATION_CAST,
CODE_SIMPLIFICATION_FIELD,
CODE_SIMPLIFICATION_BRANCH,
+ CODE_SIMPLIFICATION_STRING,
CODE_SIMPLIFICATION_ADVANCED,
CODE_REMOVAL_ADVANCED,
CODE_REMOVAL_SIMPLE,
@@ -157,6 +161,7 @@ public class Optimizer
boolean codeSimplificationCast = filter.matches(CODE_SIMPLIFICATION_CAST);
boolean codeSimplificationField = filter.matches(CODE_SIMPLIFICATION_FIELD);
boolean codeSimplificationBranch = filter.matches(CODE_SIMPLIFICATION_BRANCH);
+ boolean codeSimplificationString = filter.matches(CODE_SIMPLIFICATION_STRING);
boolean codeSimplificationAdvanced = filter.matches(CODE_SIMPLIFICATION_ADVANCED);
boolean codeRemovalAdvanced = filter.matches(CODE_REMOVAL_ADVANCED);
boolean codeRemovalSimple = filter.matches(CODE_REMOVAL_SIMPLE);
@@ -186,13 +191,15 @@ public class Optimizer
InstructionCounter codeSimplificationCastCounter = new InstructionCounter();
InstructionCounter codeSimplificationFieldCounter = new InstructionCounter();
InstructionCounter codeSimplificationBranchCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationStringCounter = new InstructionCounter();
InstructionCounter codeSimplificationAdvancedCounter = new InstructionCounter();
InstructionCounter deletedCounter = new InstructionCounter();
InstructionCounter addedCounter = new InstructionCounter();
MemberCounter codeRemovalVariableCounter = new MemberCounter();
ExceptionCounter codeRemovalExceptionCounter = new ExceptionCounter();
MemberCounter codeAllocationVariableCounter = new MemberCounter();
- MemberCounter initializerFixCounter = new MemberCounter();
+ MemberCounter initializerFixCounter1 = new MemberCounter();
+ MemberCounter initializerFixCounter2 = new MemberCounter();
// Some optimizations are required by other optimizations.
codeSimplificationAdvanced =
@@ -250,10 +257,27 @@ public class Optimizer
new AllInstructionVisitor(
new DotClassClassVisitor(keepMarker)))));
- // We also keep all classes that are involved in Class.forName constructs.
+ // We also keep all classes that are accessed dynamically.
programClassPool.classesAccept(
new AllConstantVisitor(
- new ClassForNameClassVisitor(keepMarker)));
+ new ConstantTagFilter(ClassConstants.CONSTANT_String,
+ new ReferencedClassVisitor(keepMarker))));
+
+ // We also keep all class members that are accessed dynamically.
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new ConstantTagFilter(ClassConstants.CONSTANT_String,
+ new ReferencedMemberVisitor(keepMarker))));
+
+ // We also keep all bootstrap method signatures.
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_7,
+ new AllAttributeVisitor(
+ new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods,
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodHandleTraveler(
+ new MethodrefTraveler(
+ new ReferencedMemberVisitor(keepMarker))))))));
// Attach some optimization info to all classes and class members, so
// it can be filled out later.
@@ -320,6 +344,9 @@ public class Optimizer
new ParameterUsageMarker(!methodMarkingStatic,
!methodRemovalParameter))));
+ // Mark all classes that have static initializers.
+ programClassPool.classesAccept(new StaticInitializerContainingClassMarker());
+
// Mark all methods that have side effects.
programClassPool.accept(new SideEffectMethodMarker());
@@ -347,18 +374,29 @@ public class Optimizer
new AllAttributeVisitor(
new PartialEvaluator(valueFactory, storingInvocationUnit, false))));
- // Count the constant fields and methods.
- programClassPool.classesAccept(
- new MultiClassVisitor(
- new ClassVisitor[]
- {
+ if (fieldPropagationValue)
+ {
+ // Count the constant fields.
+ programClassPool.classesAccept(
new AllFieldVisitor(
- new ConstantMemberFilter(fieldPropagationValueCounter)),
+ new ConstantMemberFilter(fieldPropagationValueCounter)));
+ }
+
+ if (methodPropagationParameter)
+ {
+ // Count the constant method parameters.
+ programClassPool.classesAccept(
new AllMethodVisitor(
- new ConstantParameterFilter(methodPropagationParameterCounter)),
+ new ConstantParameterFilter(methodPropagationParameterCounter)));
+ }
+
+ if (methodPropagationReturnvalue)
+ {
+ // Count the constant method return values.
+ programClassPool.classesAccept(
new AllMethodVisitor(
- new ConstantMemberFilter(methodPropagationReturnvalueCounter)),
- }));
+ new ConstantMemberFilter(methodPropagationReturnvalueCounter)));
+ }
}
InvocationUnit loadingInvocationUnit =
@@ -418,6 +456,12 @@ public class Optimizer
// This operation also updates the stack sizes.
programClassPool.classesAccept(
new MemberReferenceFixer());
+
+ // Remove unused bootstrap method arguments.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodArgumentShrinker())));
}
if (methodRemovalParameter ||
@@ -441,17 +485,39 @@ public class Optimizer
new StackSizeUpdater())));
}
-// // Specializing the class member descriptors seems to increase the
-// // class file size, on average.
-// // Specialize all class member descriptors.
-// programClassPool.classesAccept(new AllMemberVisitor(
-// new OptimizationInfoMemberFilter(
-// new MemberDescriptorSpecializer())));
-//
-// // Fix all references to classes, for MemberDescriptorSpecializer.
-// programClassPool.classesAccept(new AllMemberVisitor(
-// new OptimizationInfoMemberFilter(
-// new ClassReferenceFixer(true))));
+ if (methodRemovalParameter &&
+ methodRemovalParameterCounter.getCount() > 0)
+ {
+ // Tweak the descriptors of duplicate initializers, due to removed
+ // method parameters.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new DuplicateInitializerFixer(initializerFixCounter1)));
+
+ if (initializerFixCounter1.getCount() > 0)
+ {
+ // Fix all invocations of tweaked initializers.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new DuplicateInitializerInvocationFixer(addedCounter))));
+
+ // Fix all references to tweaked initializers.
+ programClassPool.classesAccept(new MemberReferenceFixer());
+ }
+ }
+
+ //// Specializing the class member descriptors seems to increase the
+ //// class file size, on average.
+ //// Specialize all class member descriptors.
+ //programClassPool.classesAccept(new AllMemberVisitor(
+ // new OptimizationInfoMemberFilter(
+ // new MemberDescriptorSpecializer())));
+ //
+ //// Fix all references to classes, for MemberDescriptorSpecializer.
+ //programClassPool.classesAccept(new AllMemberVisitor(
+ // new OptimizationInfoMemberFilter(
+ // new ClassReferenceFixer(true))));
// Mark all classes with package visible members.
// Mark all exception catches of methods.
@@ -461,13 +527,13 @@ public class Optimizer
new MultiClassVisitor(
new ClassVisitor[]
{
+ new PackageVisibleMemberContainingClassMarker(),
new AllConstantVisitor(
new PackageVisibleMemberInvokingClassMarker()),
new AllMethodVisitor(
new MultiMemberVisitor(
new MemberVisitor[]
{
- new PackageVisibleMemberContainingClassMarker(),
new AllAttributeVisitor(
new MultiAttributeVisitor(
new AttributeVisitor[]
@@ -511,8 +577,8 @@ public class Optimizer
classMergingHorizontalCounter));
}
- if (classMergingVertical ||
- classMergingHorizontal)
+ if (classMergingVerticalCounter .getCount() > 0 ||
+ classMergingHorizontalCounter.getCount() > 0)
{
// Clean up inner class attributes to avoid loops.
programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover());
@@ -530,18 +596,20 @@ public class Optimizer
new AllConstantVisitor(
new AccessFixer()));
}
- }
- if (methodRemovalParameter ||
- classMergingVertical ||
- classMergingHorizontal)
- {
- // Tweak the descriptors of duplicate initializers.
+ // Fix the access flags of the inner classes information.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllInnerClassesInfoVisitor(
+ new InnerClassesAccessFixer())));
+
+ // Tweak the descriptors of duplicate initializers, due to merged
+ // parameter classes.
programClassPool.classesAccept(
new AllMethodVisitor(
- new DuplicateInitializerFixer(initializerFixCounter)));
+ new DuplicateInitializerFixer(initializerFixCounter2)));
- if (initializerFixCounter.getCount() > 0)
+ if (initializerFixCounter2.getCount() > 0)
{
// Fix all invocations of tweaked initializers.
programClassPool.classesAccept(
@@ -595,14 +663,14 @@ public class Optimizer
new NonPrivateMemberMarker());
}
- if (fieldMarkingPrivate ||
- methodMarkingPrivate)
+ if (fieldMarkingPrivate)
{
// Make all non-private fields private, whereever possible.
programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.INTERNAL_ACC_INTERFACE,
new AllFieldVisitor(
new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
- new MemberPrivatizer(fieldMarkingPrivateCounter))));
+ new MemberPrivatizer(fieldMarkingPrivateCounter)))));
}
if (methodMarkingPrivate)
@@ -615,9 +683,9 @@ public class Optimizer
new MemberPrivatizer(methodMarkingPrivateCounter)))));
}
- if ((methodInliningUnique ||
- methodInliningShort ||
- methodInliningTailrecursion) &&
+ if ((methodInliningUniqueCounter .getCount() > 0 ||
+ methodInliningShortCounter .getCount() > 0 ||
+ methodInliningTailrecursionCounter.getCount() > 0) &&
configuration.allowAccessModification)
{
// Fix the access flags of referenced classes and class members,
@@ -627,10 +695,10 @@ public class Optimizer
new AccessFixer()));
}
- if (methodRemovalParameter ||
- classMergingVertical ||
- classMergingHorizontal ||
- methodMarkingPrivate)
+ if (methodRemovalParameterCounter .getCount() > 0 ||
+ classMergingVerticalCounter .getCount() > 0 ||
+ classMergingHorizontalCounter .getCount() > 0 ||
+ methodMarkingPrivateCounter .getCount() > 0 )
{
// Fix invocations of interface methods, of methods that have become
// non-abstract or private, and of methods that have moved to a
@@ -707,6 +775,15 @@ public class Optimizer
new GotoReturnReplacer(codeAttributeEditor, codeSimplificationBranchCounter));
}
+ if (codeSimplificationString)
+ {
+ // Peephole optimizations involving branches.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS,
+ InstructionSequenceConstants.STRING,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationStringCounter));
+ }
+
if (!peepholeOptimizations.isEmpty())
{
// Convert the list into an array.
@@ -749,14 +826,6 @@ public class Optimizer
new AllAttributeVisitor(
new VariableShrinker(codeRemovalVariableCounter))));
}
- else
- {
- // Clean up all unused local variables.
- programClassPool.classesAccept(
- new AllMethodVisitor(
- new AllAttributeVisitor(
- new VariableCleaner())));
- }
if (codeAllocationVariable)
{
@@ -767,6 +836,11 @@ public class Optimizer
new VariableOptimizer(false, codeAllocationVariableCounter))));
}
+
+ // Remove unused constants.
+ programClassPool.classesAccept(
+ new ConstantPoolShrinker());
+
int classMarkingFinalCount = classMarkingFinalCounter .getCount();
int classMergingVerticalCount = classMergingVerticalCounter .getCount();
int classMergingHorizontalCount = classMergingHorizontalCounter .getCount();
@@ -776,7 +850,7 @@ public class Optimizer
int methodMarkingPrivateCount = methodMarkingPrivateCounter .getCount();
int methodMarkingStaticCount = methodMarkingStaticCounter .getCount();
int methodMarkingFinalCount = methodMarkingFinalCounter .getCount();
- int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter.getCount();
+ int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter1.getCount() - initializerFixCounter2.getCount();
int methodPropagationParameterCount = methodPropagationParameterCounter .getCount();
int methodPropagationReturnvalueCount = methodPropagationReturnvalueCounter.getCount();
int methodInliningShortCount = methodInliningShortCounter .getCount();
@@ -788,12 +862,23 @@ public class Optimizer
int codeSimplificationCastCount = codeSimplificationCastCounter .getCount();
int codeSimplificationFieldCount = codeSimplificationFieldCounter .getCount();
int codeSimplificationBranchCount = codeSimplificationBranchCounter .getCount();
+ int codeSimplificationStringCount = codeSimplificationStringCounter .getCount();
int codeSimplificationAdvancedCount = codeSimplificationAdvancedCounter .getCount();
int codeRemovalCount = deletedCounter .getCount() - addedCounter.getCount();
int codeRemovalVariableCount = codeRemovalVariableCounter .getCount();
int codeRemovalExceptionCount = codeRemovalExceptionCounter .getCount();
int codeAllocationVariableCount = codeAllocationVariableCounter .getCount();
+ // Forget about constant fields, parameters, and return values, if they
+ // didn't lead to any useful optimizations. We want to avoid fruitless
+ // additional optimization passes.
+ if (codeSimplificationAdvancedCount == 0)
+ {
+ fieldPropagationValueCount = 0;
+ methodPropagationParameterCount = 0;
+ methodPropagationReturnvalueCount = 0;
+ }
+
if (configuration.verbose)
{
System.out.println(" Number of finalized classes: " + classMarkingFinalCount + disabled(classMarkingFinal));
@@ -817,6 +902,7 @@ public class Optimizer
System.out.println(" Number of cast peephole optimizations: " + codeSimplificationCastCount + disabled(codeSimplificationCast));
System.out.println(" Number of field peephole optimizations: " + codeSimplificationFieldCount + disabled(codeSimplificationField));
System.out.println(" Number of branch peephole optimizations: " + codeSimplificationBranchCount + disabled(codeSimplificationBranch));
+ System.out.println(" Number of string peephole optimizations: " + codeSimplificationStringCount + disabled(codeSimplificationString));
System.out.println(" Number of simplified instructions: " + codeSimplificationAdvancedCount + disabled(codeSimplificationAdvanced));
System.out.println(" Number of removed instructions: " + codeRemovalCount + disabled(codeRemovalAdvanced));
System.out.println(" Number of removed local variables: " + codeRemovalVariableCount + disabled(codeRemovalVariable));
@@ -845,6 +931,7 @@ public class Optimizer
codeSimplificationCastCount > 0 ||
codeSimplificationFieldCount > 0 ||
codeSimplificationBranchCount > 0 ||
+ codeSimplificationStringCount > 0 ||
codeSimplificationAdvancedCount > 0 ||
codeRemovalCount > 0 ||
codeRemovalVariableCount > 0 ||
diff --git a/src/proguard/optimize/ParameterShrinker.java b/src/proguard/optimize/ParameterShrinker.java
index a2bc6d3..33d37d1 100644
--- a/src/proguard/optimize/ParameterShrinker.java
+++ b/src/proguard/optimize/ParameterShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,7 @@ package proguard.optimize;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.editor.*;
+import proguard.classfile.editor.VariableRemapper;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
import proguard.optimize.info.ParameterUsageMarker;
diff --git a/src/proguard/optimize/TailRecursionSimplifier.java b/src/proguard/optimize/TailRecursionSimplifier.java
index 0946b6a..f820566 100644
--- a/src/proguard/optimize/TailRecursionSimplifier.java
+++ b/src/proguard/optimize/TailRecursionSimplifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -54,9 +54,9 @@ implements AttributeVisitor,
private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
+ private final MyRecursionChecker recursionChecker = new MyRecursionChecker();
private Method targetMethod;
- private boolean recursive;
private boolean inlinedAny;
@@ -105,38 +105,31 @@ implements AttributeVisitor,
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
- targetMethod = method;
- inlinedAny = false;
+ targetMethod = method;
+ inlinedAny = false;
codeAttributeComposer.reset();
- // Append the body of the code.
- copyCode(clazz, method, codeAttribute);
+ // The code may expand, due to expanding constant and variable
+ // instructions.
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+
+ // Copy the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
// Update the code attribute if any code has been inlined.
if (inlinedAny)
{
- codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
- }
- }
- }
+ // Copy the exceptions.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
- /**
- * Appends the code of the given code attribute.
- */
- private void copyCode(Clazz clazz, Method method, CodeAttribute codeAttribute)
- {
- // The code may expand, due to expanding constant and variable
- // instructions.
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
-
- // Copy the instructions.
- codeAttribute.instructionsAccept(clazz, method, this);
+ codeAttributeComposer.endCodeFragment();
- // Append a label just after the code.
- codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
-
- codeAttributeComposer.endCodeFragment();
+ codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
}
@@ -145,7 +138,7 @@ implements AttributeVisitor,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
// Copy the instruction.
- codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, instruction);
}
@@ -159,9 +152,9 @@ implements AttributeVisitor,
case InstructionConstants.OP_INVOKESTATIC:
{
// Is it a recursive call?
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, recursionChecker);
- if (recursive)
+ if (recursionChecker.isRecursive())
{
// Is the next instruction a return?
int nextOffset =
@@ -180,13 +173,13 @@ implements AttributeVisitor,
case InstructionConstants.OP_RETURN:
{
// Isn't the recursive call inside a try/catch block?
- codeAttribute.exceptionsAccept(clazz, method, offset, this);
+ codeAttribute.exceptionsAccept(clazz, method, offset, recursionChecker);
- if (recursive)
+ if (recursionChecker.isRecursive())
{
if (DEBUG)
{
- System.out.println("TailRecursionSimplifier.visitConstantInstruction: ["+
+ System.out.println("TailRecursionSimplifier: ["+
clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"], inlining "+constantInstruction.toString(offset));
}
@@ -223,23 +216,56 @@ implements AttributeVisitor,
}
// Copy the instruction.
- codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, constantInstruction);
}
- // Implementations for ConstantVisitor.
+ // Implementations for ExceptionInfoVisitor.
- public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- recursive = targetMethod.equals(methodrefConstant.referencedMember);
+ codeAttributeComposer.appendException(new ExceptionInfo(exceptionInfo.u2startPC,
+ exceptionInfo.u2endPC,
+ exceptionInfo.u2handlerPC,
+ exceptionInfo.u2catchType));
}
- // Implementations for ExceptionInfoVisitor.
-
- public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ /**
+ * This ConstantVisitor and ExceptionInfoVisitor returns whether a method
+ * invocation can be treated as tail-recursive.
+ */
+ private class MyRecursionChecker
+ extends SimplifiedVisitor
+ implements ConstantVisitor,
+ ExceptionInfoVisitor
{
- recursive = false;
+ private boolean recursive;
+
+
+ /**
+ * Returns whether the method invocation can be treated as
+ * tail-recursive.
+ */
+ public boolean isRecursive()
+ {
+ return recursive;
+ }
+
+ // Implementations for ConstantVisitor.
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ recursive = targetMethod.equals(methodrefConstant.referencedMember);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ recursive = false;
+ }
}
@@ -257,7 +283,6 @@ implements AttributeVisitor,
(method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0;
// Count the number of parameters, taking into account their categories.
- int parameterCount = ClassUtil.internalMethodParameterCount(descriptor);
int parameterSize = ClassUtil.internalMethodParameterSize(descriptor);
int parameterOffset = isStatic ? 0 : 1;
@@ -315,7 +340,7 @@ implements AttributeVisitor,
}
codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
- new VariableInstruction(opcode, parameterOffset + parameterIndex).shrink());
+ new VariableInstruction(opcode, parameterOffset + parameterIndex));
}
}
@@ -323,7 +348,7 @@ implements AttributeVisitor,
if (!isStatic)
{
codeAttributeComposer.appendInstruction(parameterSize,
- new VariableInstruction(InstructionConstants.OP_ASTORE, 0).shrink());
+ new VariableInstruction(InstructionConstants.OP_ASTORE, 0));
}
codeAttributeComposer.endCodeFragment();
diff --git a/src/proguard/optimize/WriteOnlyFieldFilter.java b/src/proguard/optimize/WriteOnlyFieldFilter.java
index 578beb2..762bd91 100644
--- a/src/proguard/optimize/WriteOnlyFieldFilter.java
+++ b/src/proguard/optimize/WriteOnlyFieldFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/EvaluationShrinker.java b/src/proguard/optimize/evaluation/EvaluationShrinker.java
index 1463feb..2e86532 100644
--- a/src/proguard/optimize/evaluation/EvaluationShrinker.java
+++ b/src/proguard/optimize/evaluation/EvaluationShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -34,6 +34,8 @@ import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.info.*;
+import java.util.Arrays;
+
/**
* This AttributeVisitor simplifies the code attributes that it visits, based
* on partial evaluation.
@@ -52,21 +54,55 @@ implements AttributeVisitor
private static boolean DEBUG = true;
//*/
+ private static final int UNSUPPORTED = -1;
+ private static final int NOP = InstructionConstants.OP_NOP & 0xff;
+ private static final int POP = InstructionConstants.OP_POP & 0xff;
+ private static final int POP2 = InstructionConstants.OP_POP2 & 0xff;
+ private static final int DUP = InstructionConstants.OP_DUP & 0xff;
+ private static final int DUP_X1 = InstructionConstants.OP_DUP_X1 & 0xff;
+ private static final int DUP_X2 = InstructionConstants.OP_DUP_X2 & 0xff;
+ private static final int DUP2 = InstructionConstants.OP_DUP2 & 0xff;
+ private static final int DUP2_X1 = InstructionConstants.OP_DUP2_X1 & 0xff;
+ private static final int DUP2_X2 = InstructionConstants.OP_DUP2_X2 & 0xff;
+ private static final int SWAP = InstructionConstants.OP_SWAP & 0xff;
+ private static final int MOV_X2 = DUP_X2 | (POP << 8);
+ private static final int MOV2_X1 = DUP2_X1 | (POP2 << 8);
+ private static final int MOV2_X2 = DUP2_X2 | (POP2 << 8);
+ private static final int POP_X1 = SWAP | (POP << 8);
+ private static final int POP_X2 = DUP2_X1 | (POP2 << 8) | (POP << 16);
+ private static final int POP_X3 = UNSUPPORTED;
+ private static final int POP2_X1 = DUP_X2 | (POP << 8) | (POP2 << 16);
+ private static final int POP2_X2 = DUP2_X2 | (POP2 << 8) | (POP2 << 16);
+ private static final int POP3 = POP2 | (POP << 8);
+ private static final int POP4 = POP2 | (POP2 << 8);
+ private static final int POP_DUP = POP | (DUP << 8);
+ private static final int POP_SWAP_POP = POP | (SWAP << 8) | (POP << 16);
+ private static final int POP2_SWAP_POP = POP2 | (SWAP << 8) | (POP << 16);
+ private static final int SWAP_DUP_X1 = SWAP | (DUP_X1 << 8);
+ private static final int SWAP_DUP_X1_SWAP = SWAP | (DUP_X1 << 8) | (SWAP << 16);
+ private static final int SWAP_POP_DUP = SWAP | (POP << 8) | (DUP << 16);
+ private static final int SWAP_POP_DUP_X1 = SWAP | (POP << 8) | (DUP_X1 << 16);
+ private static final int DUP_X2_POP2 = DUP_X2 | (POP2 << 8);
+ private static final int DUP2_X1_POP3 = DUP2_X1 | (POP2 << 8) | (POP << 16);
+ private static final int DUP2_X2_POP3 = DUP2_X2 | (POP2 << 8) | (POP << 16);
+ private static final int DUP2_X2_SWAP_POP = DUP2_X2 | (SWAP << 8) | (POP << 16);
+
+
private final InstructionVisitor extraDeletedInstructionVisitor;
private final InstructionVisitor extraAddedInstructionVisitor;
- private final PartialEvaluator partialEvaluator;
- private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
- private final MyUnusedParameterSimplifier unusedParameterSimplifier = new MyUnusedParameterSimplifier();
- private final MyProducerMarker producerMarker = new MyProducerMarker();
- private final MyStackConsistencyFixer stackConsistencyFixer = new MyStackConsistencyFixer();
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false);
+ private final PartialEvaluator partialEvaluator;
+ private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true);
+ private final MyUnusedParameterSimplifier unusedParameterSimplifier = new MyUnusedParameterSimplifier();
+ private final MyProducerMarker producerMarker = new MyProducerMarker();
+ private final MyVariableInitializationMarker variableInitializationMarker = new MyVariableInitializationMarker();
+ private final MyStackConsistencyFixer stackConsistencyFixer = new MyStackConsistencyFixer();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, false);
- private boolean[][] variablesNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_VARIABLES_SIZE];
- private boolean[][] stacksNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
- private boolean[][] stacksSimplifiedBefore = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
- private boolean[] instructionsNecessary = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+ private boolean[][] stacksNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
+ private boolean[][] stacksSimplifiedBefore = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
+ private boolean[] instructionsNecessary = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
private int maxMarkedOffset;
@@ -154,6 +190,9 @@ implements AttributeVisitor
// Evaluate the method.
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+ // Evaluate the method the way the JVM verifier would do it.
+ simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
int codeLength = codeAttribute.u4codeLength;
// Reset the code changes.
@@ -272,22 +311,13 @@ implements AttributeVisitor
for (int offset = 0; offset < codeLength; offset++)
{
- // Is it a variable initialization that hasn't been marked yet?
- if (partialEvaluator.isTraced(offset) &&
- !isInstructionNecessary(offset))
+ if (isInstructionNecessary(offset))
{
- // Is the corresponding variable necessary anywhere in the code,
- // accoriding to a simple partial evaluation?
- int variableIndex = partialEvaluator.initializedVariable(offset);
- if (variableIndex >= 0 &&
- isVariableInitializationNecessary(clazz,
- method,
- codeAttribute,
- offset,
- variableIndex))
- {
- markInstruction(offset);
- }
+ // Mark initializations of the required instruction.
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, variableInitializationMarker);
}
}
if (DEBUG) System.out.println();
@@ -383,12 +413,9 @@ implements AttributeVisitor
offset);
if (!isInstructionNecessary(offset))
{
+ codeAttributeEditor.clearModifications(offset);
codeAttributeEditor.deleteInstruction(offset);
- codeAttributeEditor.insertBeforeInstruction(offset, (Instruction)null);
- codeAttributeEditor.replaceInstruction(offset, (Instruction)null);
- codeAttributeEditor.insertAfterInstruction(offset, (Instruction)null);
-
// Visit the instruction, if required.
if (extraDeletedInstructionVisitor != null)
{
@@ -467,7 +494,9 @@ implements AttributeVisitor
*/
private class MyUnusedParameterSimplifier
extends SimplifiedVisitor
- implements InstructionVisitor, ConstantVisitor, MemberVisitor
+ implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
{
private int invocationOffset;
private ConstantInstruction invocationInstruction;
@@ -614,8 +643,8 @@ implements AttributeVisitor
public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
{
- // Is the variable being loaded (or incremented)?
- if (variableInstruction.opcode < InstructionConstants.OP_ISTORE)
+ // Is the variable being loaded or incremented?
+ if (variableInstruction.isLoad())
{
markVariableProducers(offset, variableInstruction.variableIndex);
}
@@ -657,6 +686,32 @@ implements AttributeVisitor
/**
+ * This InstructionVisitor marks variable initializations that are
+ * necessary to appease the JVM.
+ */
+ private class MyVariableInitializationMarker
+ extends SimplifiedVisitor
+ implements InstructionVisitor
+ {
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Is the variable being loaded or incremented?
+ if (variableInstruction.isLoad())
+ {
+ // Mark any variable initializations for this variable load that
+ // are required according to the JVM.
+ markVariableInitializers(offset, variableInstruction.variableIndex);
+ }
+ }
+ }
+
+
+ /**
* This InstructionVisitor fixes instructions locally, popping any unused
* produced stack entries after marked instructions, and popping produced
* stack entries and pushing missing stack entries instead of unmarked
@@ -682,17 +737,25 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackBefore(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int requiredPushCount = 0;
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
- // Is the stack entry required by other consumers?
- if (!isStackSimplifiedBefore(offset, top - stackIndex) &&
- !isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex))
+ if (!isStackSimplifiedBefore(offset, stackIndex))
{
- // Remember to push it.
- requiredPushCount++;
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
+ {
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+ }
+ else
+ {
+ // Remember to push it.
+ requiredPushCount++;
+ }
}
}
@@ -703,13 +766,39 @@ implements AttributeVisitor
if (requiredPushCount > (instruction.isCategory2() ? 2 : 1))
{
- throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"]");
+ throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"] at ["+offset+"]");
}
insertPushInstructions(offset, false, tracedStack.getTop(0).computationalType());
}
}
+ // Check all other stack entries, if this is a return
+ // instruction.
+ // Typical case: the code returns, but there are still other
+ // entries left on the stack. These have to be consistent.
+ InstructionOffsetValue branchTargets =
+ partialEvaluator.branchTargets(offset);
+ if (branchTargets != null &&
+ branchTargets.instructionOffsetCount() == 0)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(offset);
+
+ int unpoppedStackSize = tracedStack.size() - popCount;
+
+ for (int stackIndex = 0; stackIndex < unpoppedStackSize; stackIndex++)
+ {
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
+ {
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+ }
+ }
+ }
+
// Check all stack entries that are pushed.
// Typical case: a return value that wasn't really required and
// that should be popped.
@@ -719,13 +808,13 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackAfter(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int requiredPopCount = 0;
- for (int stackIndex = 0; stackIndex < pushCount; stackIndex++)
+ for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
{
// Is the stack entry required by consumers?
- if (!isStackEntryNecessaryAfter(offset, top - stackIndex))
+ if (!isStackEntryNecessaryAfter(offset, stackIndex))
{
// Remember to pop it.
requiredPopCount++;
@@ -752,14 +841,18 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackBefore(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int expectedPopCount = 0;
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
- // Is the stack entry required by other consumers?
- if (isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex))
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
{
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+
// Remember to pop it.
expectedPopCount++;
}
@@ -782,13 +875,13 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackAfter(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int expectedPushCount = 0;
- for (int stackIndex = 0; stackIndex < pushCount; stackIndex++)
+ for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
{
// Is the stack entry required by consumers?
- if (isStackEntryNecessaryAfter(offset, top - stackIndex))
+ if (isStackEntryNecessaryAfter(offset, stackIndex))
{
// Remember to push it.
expectedPushCount++;
@@ -812,44 +905,546 @@ implements AttributeVisitor
if (isInstructionNecessary(offset) &&
isDupOrSwap(simpleInstruction))
{
- fixDupInstruction(clazz, codeAttribute, offset, simpleInstruction);
+ int stackSizeBefore = partialEvaluator.getStackBefore(offset).size();
+
+ // Check all stack entries that are popped.
+ // Typical case: a freshly marked variable initialization that
+ // requires some value on the stack.
+ int popCount = simpleInstruction.stackPopCount(clazz);
+ if (popCount > 0)
+ {
+ for (int stackIndex = stackSizeBefore - popCount; stackIndex < stackSizeBefore; stackIndex++)
+ {
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
+ {
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+ }
+ }
+ }
+
+ int topBefore = stackSizeBefore - 1;
+ int topAfter = partialEvaluator.getStackAfter(offset).size() - 1;
+
+ byte oldOpcode = simpleInstruction.opcode;
+
+ // Simplify the dup/swap instruction if possible.
+ int newOpcodes = fixDupSwap(offset, oldOpcode, topBefore, topAfter);
+
+ // Did we find a suitabe (extended) opcode?
+ if (newOpcodes == UNSUPPORTED)
+ {
+ // We can't easily emulate some constructs.
+ throw new UnsupportedOperationException("Can't handle "+simpleInstruction.toString()+" instruction at ["+offset +"]");
+ }
+
+ // Is there a single replacement opcode?
+ if ((newOpcodes & ~0xff) == 0)
+ {
+ byte newOpcode = (byte)newOpcodes;
+
+ if (newOpcode == InstructionConstants.OP_NOP)
+ {
+ // Delete the instruction.
+ codeAttributeEditor.deleteInstruction(offset);
+
+ if (extraDeletedInstructionVisitor != null)
+ {
+ extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
+ }
+
+ if (DEBUG) System.out.println(" Deleting marked instruction "+simpleInstruction.toString(offset));
+ }
+ else if (newOpcode == oldOpcode)
+ {
+ // Leave the instruction unchanged.
+ codeAttributeEditor.undeleteInstruction(offset);
+
+ if (DEBUG) System.out.println(" Marking unchanged instruction "+simpleInstruction.toString(offset));
+ }
+ else
+ {
+ // Replace the instruction.
+ Instruction replacementInstruction = new SimpleInstruction(newOpcode);
+ codeAttributeEditor.replaceInstruction(offset,
+ replacementInstruction);
+
+ if (DEBUG) System.out.println(" Replacing instruction "+simpleInstruction.toString(offset)+" by "+replacementInstruction.toString());
+ }
+ }
+ else
+ {
+ // Collect the replacement instructions.
+ Instruction[] replacementInstructions = new Instruction[4];
+
+ if (DEBUG) System.out.println(" Replacing instruction "+simpleInstruction.toString(offset)+" by");
+ int count = 0;
+ while (newOpcodes != 0)
+ {
+ SimpleInstruction replacementInstruction = new SimpleInstruction((byte)newOpcodes);
+ replacementInstructions[count++] = replacementInstruction;
+
+ if (DEBUG) System.out.println(" "+replacementInstruction.toString());
+ newOpcodes >>>= 8;
+ }
+
+ // Create a properly sized array.
+ if (count < 4)
+ {
+ Instruction[] newInstructions = new Instruction[count];
+ System.arraycopy(replacementInstructions, 0, newInstructions, 0, count);
+ replacementInstructions = newInstructions;
+ }
+
+ codeAttributeEditor.replaceInstruction(offset,
+ replacementInstructions);
+ }
}
else
{
visitAnyInstruction(clazz, method, codeAttribute, offset, simpleInstruction);
}
}
+
+
+ /**
+ * Returns a dup/swap opcode that is corrected for the stack entries
+ * that are present before the instruction and necessary after the
+ * instruction. The returned integer opcode may contain multiple byte
+ * opcodes (least significant byte first).
+ * @param instructionOffset the offset of the dup/swap instruction.
+ * @param dupSwapOpcode the original dup/swap opcode.
+ * @param topBefore the index of the top stack entry before
+ * the instruction (counting from the bottom).
+ * @param topAfter the index of the top stack entry after
+ * the instruction (counting from the bottom).
+ * @return the corrected opcode.
+ */
+ private int fixDupSwap(int instructionOffset,
+ byte dupSwapOpcode,
+ int topBefore,
+ int topAfter)
+ {
+ switch (dupSwapOpcode)
+ {
+ case InstructionConstants.OP_DUP: return fixedDup (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP_X1: return fixedDup_x1 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP_X2: return fixedDup_x2 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2: return fixedDup2 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2_X1: return fixedDup2_x1(instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2_X2: return fixedDup2_x2(instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_SWAP: return fixedSwap (instructionOffset, topBefore, topAfter);
+ default: throw new IllegalArgumentException("Not a dup/swap opcode ["+dupSwapOpcode+"]");
+ }
+ }
+
+
+ private int fixedDup(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary0 ?
+ stackEntryNecessary1 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ stackEntryNecessary1 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup_x1(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...XO -> ...OXO
+ SWAP : // ...XO -> ...OX
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? NOP : // ...XO -> ...XO
+ stackEntryPresent0 ? POP : // ...XO -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...XO -> ...OO
+ POP_X1 : // ...XO -> ...O
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? POP_X1 : // ...XO -> ...O
+ stackEntryPresent0 ? POP2 : // ...XO -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup_x2(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore(instructionOffset, topBefore - 2);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 3);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X2 : // ...XYO -> ...OXYO
+ MOV_X2 : // ...XYO -> ...OXY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...XYO -> ...XYO
+ stackEntryPresent0 ? POP : // ...XYO -> ...XY
+ NOP : // ...XY -> ...XY
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ // stackEntryNecessary0 ? UNSUPPORTED : // ...XYO -> ...OYO
+ UNSUPPORTED : // ...XYO -> ...OY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X2 : // ...XYO -> ...YO
+ stackEntryPresent0 ? POP_SWAP_POP : // ...XYO -> ...Y
+ POP_X1 : // ...XY -> ...Y
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...YO -> ...OYO
+ SWAP : // ...YO -> ...OY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...YO -> ...YO
+ stackEntryPresent0 ? POP : // ...YO -> ...Y
+ NOP : // ...Y -> ...Y
+ stackEntryPresent1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP_X1 : // ...XYO -> ...OXO
+ DUP_X2_POP2 : // ...XYO -> ...OX
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...XYO -> ...XO
+ stackEntryPresent0 ? POP2 : // ...XYO -> ...X
+ POP : // ...XY -> ...X
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? UNSUPPORTED : // ...XYO -> ...OO
+ POP2_X1 : // ...XYO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP2_X1 : // ...XYO -> ...O
+ stackEntryPresent0 ? POP3 : // ...XYO -> ...
+ POP2 : // ...XY -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...YO -> ...OO
+ POP_X1 : // ...YO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...YO -> ...O
+ stackEntryPresent0 ? POP2 : // ...YO -> ...
+ POP : // ...Y -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...XO -> ...OXO
+ SWAP : // ...XO -> ...OX
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...XO -> ...XO
+ stackEntryPresent0 ? POP : // ...XO -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...XO -> ...OO
+ POP_X1 : // ...XO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...XO -> ...O
+ stackEntryPresent0 ? POP2 : // ...XO -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 3);
+
+ return
+ stackEntryNecessary3 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? DUP2 : // ...AB -> ...ABAB
+ SWAP_DUP_X1 : // ...AB -> ...ABA
+ // !stackEntryNecessary1
+ stackEntryNecessary0 ? DUP : // ...AB -> ...ABB
+ NOP : // ...AB -> ...AB
+ // !stackEntryNecessary2
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? SWAP_DUP_X1_SWAP : // ...AB -> ...AAB
+ stackEntryPresent0 ? POP_DUP : // ...AB -> ...AA
+ DUP : // ...A -> ...AA
+ // !stackEntryNecessary1
+ stackEntryNecessary0 ? NOP : // ...AB -> ...AB
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ // !stackEntryNecessary3
+ stackEntryNecessary2 ?
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...AB -> ...BAB
+ SWAP : // ...AB -> ...BA
+ stackEntryPresent1 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...AB -> ...BB
+ POP_X1 : // ...AB -> ...B
+ // !stackEntryPresent1
+ stackEntryNecessary0 ? POP : // ...B -> ...BB
+ NOP : // ...B -> ...B
+ // !stackEntryNecessary2
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? NOP : // ...AB -> ...AB
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ stackEntryPresent1 ?
+ stackEntryNecessary0 ? POP_X1 : // ...AB -> ...B
+ stackEntryPresent0 ? POP2 : // ...AB -> ...
+ POP : // ...A -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary0 ? NOP : // ...B -> ...B
+ stackEntryPresent0 ? POP : // ...B -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2_x1(int instructionOffset, int topBefore, int topAfter)
+ {
+ // We're currently assuming the value to be duplicated
+ // is a long or a double, taking up two slots, or at
+ // least consistent.
+ boolean stackEntriesPresent01 = isStackEntriesPresentBefore(instructionOffset, topBefore - 0, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore( instructionOffset, topBefore - 2);
+
+ boolean stackEntriesNecessary01 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 0, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 2);
+ boolean stackEntriesNecessary34 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 3, topAfter - 4);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary2 ?
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...XAB -> ...ABXAB
+ MOV2_X1 : // ...XAB -> ...ABX
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? NOP : // ...XAB -> ...XAB
+ stackEntriesPresent01 ? POP2 : // ...XAB -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent2 ?
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XAB -> ...ABAB
+ POP_X2 : // ...XAB -> ...AB
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? DUP2_X1_POP3 : // ...XAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...XAB -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent2
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? DUP2 : // ...AB -> ...ABAB
+ NOP : // ...AB -> ...AB
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? NOP : // ...AB -> ...AB
+ stackEntriesPresent01 ? POP2 : // ...AB -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2_x2(int instructionOffset, int topBefore, int topAfter)
+ {
+ // We're currently assuming the value to be duplicated
+ // is a long or a double, taking up two slots, or at
+ // least consistent.
+ boolean stackEntriesPresent01 = isStackEntriesPresentBefore(instructionOffset, topBefore - 0, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore( instructionOffset, topBefore - 2);
+ boolean stackEntryPresent3 = isStackEntryPresentBefore( instructionOffset, topBefore - 3);
+
+ boolean stackEntriesNecessary01 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 0, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 3);
+ boolean stackEntriesNecessary45 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 4, topAfter - 5);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X2 : // ...XYAB -> ...ABXYAB
+ MOV2_X2 : // ...XYAB -> ...ABXY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...XYAB -> ...XYAB
+ stackEntriesPresent01 ? POP2 : // ...XYAB -> ...XY
+ NOP : // ...XY -> ...XY
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABYAB
+ DUP2_X2_SWAP_POP : // ...XYAB -> ...ABY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X3 : // ...XYAB -> ...YAB
+ stackEntriesPresent01 ? POP2_SWAP_POP : // ...XYAB -> ...Y
+ POP_X1 : // ...XY -> ...Y
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...YAB -> ...ABYAB
+ MOV2_X1 : // ...YAB -> ...ABY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...YAB -> ...YAB
+ stackEntriesPresent01 ? POP2 : // ...YAB -> ...Y
+ NOP : // ...Y -> ...Y
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABXAB
+ DUP2_X2_POP3 : // ...XYAB -> ...ABX
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...XYAB -> ...XAB
+ stackEntriesPresent01 ? POP3 : // ...XYAB -> ...X
+ POP : // ...XY -> ...X
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABAB
+ POP2_X2 : // ...XYAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP2_X2 : // ...XYAB -> ...AB
+ stackEntriesPresent01 ? POP4 : // ...XYAB -> ...
+ POP2 : // ...XY -> ...
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...YAB -> ...ABAB
+ POP_X2 : // ...YAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...YAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...YAB -> ...
+ POP : // ...Y -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...XAB -> ...ABXAB
+ MOV2_X1 : // ...XAB -> ...ABX
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...XAB -> ...XAB
+ stackEntriesPresent01 ? POP2 : // ...XAB -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XAB -> ...ABAB
+ POP_X2 : // ...XAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...XAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...XAB -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2 : // ...AB -> ...ABAB
+ NOP : // ...AB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...AB -> ...AB
+ stackEntriesPresent01 ? POP2 : // ...AB -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedSwap(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+
+ // Figure out which stack entries should be moved
+ // or removed.
+ return
+ stackEntryNecessary0 ?
+ stackEntryNecessary1 ? SWAP : // ...AB -> ...BA
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ stackEntryPresent1 ? POP_X1 : // ...AB -> ...B
+ NOP; // ...B -> ...B
+ }
}
// Small utility methods.
/**
- * Marks the variable and the corresponding producing instructions
- * of the consumer at the given offset.
- * @param consumerOffset the offset of the consumer.
- * @param variableIndex the index of the variable to be marked.
+ * Marks the producing instructions of the variable consumer at the given
+ * offset.
+ * @param consumerOffset the offset of the variable consumer.
+ * @param variableIndex the index of the variable that is loaded.
*/
private void markVariableProducers(int consumerOffset,
int variableIndex)
{
- TracedVariables tracedVariables =
- partialEvaluator.getVariablesBefore(consumerOffset);
+ InstructionOffsetValue producerOffsets =
+ partialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
- // Mark the producer of the loaded value.
- markVariableProducers(tracedVariables.getProducerValue(variableIndex).instructionOffsetValue(),
- variableIndex);
+ if (producerOffsets != null)
+ {
+ int offsetCount = producerOffsets.instructionOffsetCount();
+ for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
+ {
+ // Make sure the variable and the instruction are marked
+ // at the producing offset.
+ int offset = producerOffsets.instructionOffset(offsetIndex);
+
+ markInstruction(offset);
+ }
+ }
}
/**
- * Marks the variable and its producing instructions at the given offsets.
- * @param producerOffsets the offsets of the producers to be marked.
- * @param variableIndex the index of the variable to be marked.
+ * Marks the initializing instructions of the variable consumer at the given
+ * offset.
+ * @param consumerOffset the offset of the variable consumer.
+ * @param variableIndex the index of the variable that is loaded.
*/
- private void markVariableProducers(InstructionOffsetValue producerOffsets,
- int variableIndex)
+ private void markVariableInitializers(int consumerOffset,
+ int variableIndex)
{
+ InstructionOffsetValue producerOffsets =
+ simplePartialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
+
if (producerOffsets != null)
{
int offsetCount = producerOffsets.instructionOffsetCount();
@@ -859,8 +1454,15 @@ implements AttributeVisitor
// at the producing offset.
int offset = producerOffsets.instructionOffset(offsetIndex);
- markVariableAfter(offset, variableIndex);
- markInstruction(offset);
+ if (!isInstructionNecessary(offset) &&
+ isVariableInitialization(offset, variableIndex))
+ {
+ if (DEBUG) System.out.print(" Marking initialization of v"+variableIndex+" at ");
+
+ markInstruction(offset);
+
+ if (DEBUG) System.out.println();
+ }
}
}
}
@@ -877,9 +1479,14 @@ implements AttributeVisitor
int consumerOffset,
Instruction consumer)
{
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(consumerOffset);
+
+ int stackSize = tracedStack.size();
+
// Mark the producers of the popped values.
int popCount = consumer.stackPopCount(clazz);
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
markStackEntryProducers(consumerOffset, stackIndex);
}
@@ -891,20 +1498,22 @@ implements AttributeVisitor
* of the consumer at the given offset, if the stack entry of the
* consumer is marked.
* @param consumerOffset the offset of the consumer.
- * @param consumerStackIndex the index of the stack entry to be checked
+ * @param consumerTopStackIndex the index of the stack entry to be checked
* (counting from the top).
- * @param producerStackIndex the index of the stack entry to be marked
+ * @param producerTopStackIndex the index of the stack entry to be marked
* (counting from the top).
*/
private void conditionallyMarkStackEntryProducers(int consumerOffset,
- int consumerStackIndex,
- int producerStackIndex)
+ int consumerTopStackIndex,
+ int producerTopStackIndex)
{
- int top = partialEvaluator.getStackAfter(consumerOffset).size() - 1;
+ int consumerBottomStackIndex = partialEvaluator.getStackAfter(consumerOffset).size() - consumerTopStackIndex - 1;
- if (isStackEntryNecessaryAfter(consumerOffset, top - consumerStackIndex))
+ if (isStackEntryNecessaryAfter(consumerOffset, consumerBottomStackIndex))
{
- markStackEntryProducers(consumerOffset, producerStackIndex);
+ int producerBottomStackIndex = partialEvaluator.getStackBefore(consumerOffset).size() - producerTopStackIndex - 1;
+
+ markStackEntryProducers(consumerOffset, producerBottomStackIndex);
}
}
@@ -914,20 +1523,15 @@ implements AttributeVisitor
* of the consumer at the given offset.
* @param consumerOffset the offset of the consumer.
* @param stackIndex the index of the stack entry to be marked
- * (counting from the top).
+ * (counting from the bottom).
*/
private void markStackEntryProducers(int consumerOffset,
int stackIndex)
{
- TracedStack tracedStack =
- partialEvaluator.getStackBefore(consumerOffset);
-
- int stackBottomIndex = tracedStack.size() - 1 - stackIndex;
-
- if (!isStackSimplifiedBefore(consumerOffset, stackBottomIndex))
+ if (!isStackSimplifiedBefore(consumerOffset, stackIndex))
{
- markStackEntryProducers(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(),
- stackBottomIndex);
+ markStackEntryProducers(partialEvaluator.getStackBefore(consumerOffset).getBottomProducerValue(stackIndex).instructionOffsetValue(),
+ stackIndex);
}
}
@@ -1036,244 +1640,6 @@ implements AttributeVisitor
/**
- * Marks the specified instruction if it is a required dup/swap instruction,
- * replacing it by an appropriate variant if necessary.
- * @param clazz the class that is being checked.
- * @param codeAttribute the code that is being checked.
- * @param dupOffset the offset of the dup/swap instruction.
- * @param instruction the dup/swap instruction.
- */
- private void fixDupInstruction(Clazz clazz,
- CodeAttribute codeAttribute,
- int dupOffset,
- Instruction instruction)
- {
- int top = partialEvaluator.getStackAfter(dupOffset).size() - 1;
-
- byte oldOpcode = instruction.opcode;
- byte newOpcode = 0;
-
- // Simplify the popping instruction if possible.
- switch (oldOpcode)
- {
- case InstructionConstants.OP_DUP:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent1)
- {
- // Should both the original element and the copy be present?
- if (stackEntryPresent0 &&
- stackEntryPresent1)
- {
- newOpcode = InstructionConstants.OP_DUP;
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP_X1:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent2)
- {
- // Should the copy be present?
- if (stackEntryPresent2)
- {
- // Compute the number of elements to be skipped.
- int skipCount = stackEntryPresent1 ? 1 : 0;
-
- // Should the original element be present?
- if (stackEntryPresent0)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount);
- }
- else if (skipCount == 1)
- {
- // Move the original element.
- newOpcode = InstructionConstants.OP_SWAP;
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP_X2:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, top - 3);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent3)
- {
- // Should the copy be present?
- if (stackEntryPresent3)
- {
- int skipCount = (stackEntryPresent1 ? 1 : 0) +
- (stackEntryPresent2 ? 1 : 0);
-
- // Should the original element be present?
- if (stackEntryPresent0)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount);
- }
- else if (skipCount == 1)
- {
- // Move the original element.
- newOpcode = InstructionConstants.OP_SWAP;
- }
- else if (skipCount == 2)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup_x2 instruction moving original element across two elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntriesPresent23 = isStackEntriesNecessaryAfter(dupOffset, top - 2, top - 3);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent23)
- {
- // Should both the original element and the copy be present?
- if (stackEntriesPresent01 &&
- stackEntriesPresent23)
- {
- newOpcode = InstructionConstants.OP_DUP2;
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2_X1:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntriesPresent34 = isStackEntriesNecessaryAfter(dupOffset, top - 3, top - 4);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent34)
- {
- // Should the copy be present?
- if (stackEntriesPresent34)
- {
- int skipCount = stackEntryPresent2 ? 1 : 0;
-
- // Should the original element be present?
- if (stackEntriesPresent01)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount);
- }
- else if (skipCount > 0)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup2_x1 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2_X2:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, top - 3);
- boolean stackEntriesPresent45 = isStackEntriesNecessaryAfter(dupOffset, top - 4, top - 5);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent45)
- {
- // Should the copy be present?
- if (stackEntriesPresent45)
- {
- int skipCount = (stackEntryPresent2 ? 1 : 0) +
- (stackEntryPresent3 ? 1 : 0);
-
- // Should the original element be present?
- if (stackEntriesPresent01)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount);
- }
- else if (skipCount > 0)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup2_x2 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_SWAP:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
-
- // Will either element be present?
- if (stackEntryPresent0 ||
- stackEntryPresent1)
- {
- // Will both elements be present?
- if (stackEntryPresent0 &&
- stackEntryPresent1)
- {
- newOpcode = InstructionConstants.OP_SWAP;
- }
- }
- break;
- }
- }
-
- if (newOpcode == 0)
- {
- // Delete the instruction.
- codeAttributeEditor.deleteInstruction(dupOffset);
-
- if (extraDeletedInstructionVisitor != null)
- {
- extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, dupOffset, null);
- }
-
- if (DEBUG) System.out.println(" Marking but deleting instruction "+instruction.toString(dupOffset));
- }
- else if (newOpcode == oldOpcode)
- {
- // Leave the instruction unchanged.
- codeAttributeEditor.undeleteInstruction(dupOffset);
-
- if (DEBUG) System.out.println(" Marking unchanged instruction "+instruction.toString(dupOffset));
- }
- else
- {
- // Replace the instruction.
- Instruction replacementInstruction = new SimpleInstruction(newOpcode);
- codeAttributeEditor.replaceInstruction(dupOffset,
- replacementInstruction);
-
- if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString());
- }
- }
-
-
- /**
* Pushes a specified type of stack entry before or at the given offset.
* The instruction is marked as necessary.
*/
@@ -1445,7 +1811,7 @@ implements AttributeVisitor
// Remember the replacement instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
- constantInstruction.constantIndex).shrink();
+ constantInstruction.constantIndex);
if (DEBUG) System.out.println(" Replacing by static invocation "+constantInstruction.toString(offset)+" -> "+replacementInstruction.toString());
@@ -1587,22 +1953,6 @@ implements AttributeVisitor
int maxStack = codeAttribute.u2maxStack;
// Create new arrays for storing information at each instruction offset.
- if (variablesNecessaryAfter.length < codeLength ||
- variablesNecessaryAfter[0].length < maxLocals)
- {
- variablesNecessaryAfter = new boolean[codeLength][maxLocals];
- }
- else
- {
- for (int offset = 0; offset < codeLength; offset++)
- {
- for (int index = 0; index < maxLocals; index++)
- {
- variablesNecessaryAfter[offset][index] = false;
- }
- }
- }
-
if (stacksNecessaryAfter.length < codeLength ||
stacksNecessaryAfter[0].length < maxStack)
{
@@ -1612,10 +1962,7 @@ implements AttributeVisitor
{
for (int offset = 0; offset < codeLength; offset++)
{
- for (int index = 0; index < maxStack; index++)
- {
- stacksNecessaryAfter[offset][index] = false;
- }
+ Arrays.fill(stacksNecessaryAfter[offset], 0, maxStack, false);
}
}
@@ -1628,10 +1975,7 @@ implements AttributeVisitor
{
for (int offset = 0; offset < codeLength; offset++)
{
- for (int index = 0; index < maxStack; index++)
- {
- stacksSimplifiedBefore[offset][index] = false;
- }
+ Arrays.fill(stacksSimplifiedBefore[offset], 0, maxStack, false);
}
}
@@ -1641,103 +1985,61 @@ implements AttributeVisitor
}
else
{
- for (int index = 0; index < codeLength; index++)
- {
- instructionsNecessary[index] = false;
- }
+ Arrays.fill(instructionsNecessary, 0, codeLength, false);
}
}
/**
- * Returns whether the given stack entry is present after execution of the
- * instruction at the given offset.
+ * Returns whether the specified variable is initialized at the specified
+ * offset.
*/
- private boolean isStackEntriesNecessaryAfter(int instructionOffset,
- int stackIndex1,
- int stackIndex2)
- {
- boolean present1 = isStackEntryNecessaryAfter(instructionOffset, stackIndex1);
- boolean present2 = isStackEntryNecessaryAfter(instructionOffset, stackIndex2);
-
-// if (present1 ^ present2)
-// {
-// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
-// }
-
- return present1 || present2;
- }
-
-
- /**
- * Returns whether the specified variable must be initialized at the
- * specified offset, according to the verifier of the JVM.
- */
- private boolean isVariableInitializationNecessary(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- int initializationOffset,
- int variableIndex)
+ private boolean isVariableInitialization(int instructionOffset,
+ int variableIndex)
{
- int codeLength = codeAttribute.u4codeLength;
-
- // Is the variable necessary anywhere at all?
- if (isVariableNecessaryAfterAny(0, codeLength, variableIndex))
+ // Wasn't the variable set yet?
+ Value valueBefore = partialEvaluator.getVariablesBefore(instructionOffset).getValue(variableIndex);
+ if (valueBefore == null)
{
- if (DEBUG) System.out.println("Simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
-
- // Lazily compute perform simple partial evaluation, the way the
- // JVM preverifier would do it.
- simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+ return true;
+ }
- if (DEBUG) System.out.println("End of simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
+ // Is the computational type different now?
+ Value valueAfter = partialEvaluator.getVariablesAfter(instructionOffset).getValue(variableIndex);
+ if (valueAfter.computationalType() != valueBefore.computationalType())
+ {
+ return true;
+ }
- // Check if the variable is necessary elsewhere.
- for (int offset = 0; offset < codeLength; offset++)
- {
- if (isInstructionNecessary(offset))
- {
- Value producer = partialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
- if (producer != null)
- {
- Value simpleProducer = simplePartialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
- if (simpleProducer != null)
- {
- InstructionOffsetValue producerOffsets =
- producer.instructionOffsetValue();
- InstructionOffsetValue simpleProducerOffsets =
- simpleProducer.instructionOffsetValue();
-
- // Does the sophisticated partial evaluation have fewer
- // producers than the simple one?
- // And does the simple partial evaluation point to an
- // initialization of the variable?
- if (producerOffsets.instructionOffsetCount() <
- simpleProducerOffsets.instructionOffsetCount() &&
- isVariableNecessaryAfterAny(producerOffsets, variableIndex) &&
- simpleProducerOffsets.contains(initializationOffset))
- {
- // Then the initialization is necessary.
- return true;
- }
- }
- }
- }
- }
+ // Is the reference type different now?
+ if (valueAfter.computationalType() == Value.TYPE_REFERENCE &&
+ (valueAfter.referenceValue().isNull() == Value.ALWAYS ||
+ !valueAfter.referenceValue().getType().equals(valueBefore.referenceValue().getType())))
+ {
+ return true;
}
- return false;
+ // Was the producer an argument (which may be removed)?
+ Value producersBefore = partialEvaluator.getVariablesBefore(instructionOffset).getProducerValue(variableIndex);
+ return producersBefore.instructionOffsetValue().instructionOffsetCount() == 1 &&
+ producersBefore.instructionOffsetValue().instructionOffset(0) == PartialEvaluator.AT_METHOD_ENTRY;
}
- private void markVariableAfter(int instructionOffset,
- int variableIndex)
+ /**
+ * Marks the stack entry after the given offset.
+ * @param instructionOffset the offset of the stack entry to be marked.
+ * @param stackIndex the index of the stack entry to be marked
+ * (counting from the bottom).
+ */
+ private void markStackEntryAfter(int instructionOffset,
+ int stackIndex)
{
- if (!isVariableNecessaryAfter(instructionOffset, variableIndex))
+ if (!isStackEntryNecessaryAfter(instructionOffset, stackIndex))
{
- if (DEBUG) System.out.print("["+instructionOffset+".v"+variableIndex+"],");
+ if (DEBUG) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
- variablesNecessaryAfter[instructionOffset][variableIndex] = true;
+ stacksNecessaryAfter[instructionOffset][stackIndex] = true;
if (maxMarkedOffset < instructionOffset)
{
@@ -1747,73 +2049,74 @@ implements AttributeVisitor
}
+
/**
- * Returns whether the specified variable is ever necessary after any
- * instruction in the specified block.
+ * Returns whether the stack specified entries before the given offset are
+ * present.
*/
- private boolean isVariableNecessaryAfterAny(int startOffset,
- int endOffset,
- int variableIndex)
+ private boolean isStackEntriesPresentBefore(int instructionOffset,
+ int stackIndex1,
+ int stackIndex2)
{
- for (int offset = startOffset; offset < endOffset; offset++)
- {
- if (isVariableNecessaryAfter(offset, variableIndex))
- {
- return true;
- }
- }
+ boolean present1 = isStackEntryPresentBefore(instructionOffset, stackIndex1);
+ boolean present2 = isStackEntryPresentBefore(instructionOffset, stackIndex2);
- return false;
+// if (present1 ^ present2)
+// {
+// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
+// }
+
+ return present1 || present2;
}
/**
- * Returns whether the specified variable is ever necessary after any
- * instruction in the specified set of instructions offsets.
+ * Returns whether the specified stack entry before the given offset is
+ * present.
+ * @param instructionOffset the offset of the stack entry to be checked.
+ * @param stackIndex the index of the stack entry to be checked
+ * (counting from the bottom).
*/
- private boolean isVariableNecessaryAfterAny(InstructionOffsetValue instructionOffsetValue,
- int variableIndex)
+ private boolean isStackEntryPresentBefore(int instructionOffset,
+ int stackIndex)
{
- int count = instructionOffsetValue.instructionOffsetCount();
-
- for (int index = 0; index < count; index++)
- {
- if (isVariableNecessaryAfter(instructionOffsetValue.instructionOffset(index),
- variableIndex))
- {
- return true;
- }
- }
-
- return false;
- }
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(instructionOffset);
+ InstructionOffsetValue producerOffsets =
+ tracedStack.getBottomProducerValue(stackIndex).instructionOffsetValue();
- private boolean isVariableNecessaryAfter(int instructionOffset,
- int variableIndex)
- {
- return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
- variablesNecessaryAfter[instructionOffset][variableIndex];
+ return isAnyStackEntryNecessaryAfter(producerOffsets, stackIndex);
}
- private void markStackEntryAfter(int instructionOffset,
- int stackIndex)
+ /**
+ * Returns whether the stack specified entries after the given offset are
+ * necessary.
+ */
+ private boolean isStackEntriesNecessaryAfter(int instructionOffset,
+ int stackIndex1,
+ int stackIndex2)
{
- if (!isStackEntryNecessaryAfter(instructionOffset, stackIndex))
- {
- if (DEBUG) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
+ boolean present1 = isStackEntryNecessaryAfter(instructionOffset, stackIndex1);
+ boolean present2 = isStackEntryNecessaryAfter(instructionOffset, stackIndex2);
- stacksNecessaryAfter[instructionOffset][stackIndex] = true;
+// if (present1 ^ present2)
+// {
+// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
+// }
- if (maxMarkedOffset < instructionOffset)
- {
- maxMarkedOffset = instructionOffset;
- }
- }
+ return present1 || present2;
}
+ /**
+ * Returns whether any of the stack entries after the given offsets are
+ * necessary.
+ * @param instructionOffsets the offsets of the stack entries to be checked.
+ * @param stackIndex the index of the stack entries to be checked
+ * (counting from the bottom).
+ */
private boolean isAnyStackEntryNecessaryAfter(InstructionOffsetValue instructionOffsets,
int stackIndex)
{
@@ -1831,6 +2134,13 @@ implements AttributeVisitor
}
+ /**
+ * Returns whether the specified stack entry after the given offset is
+ * necessary.
+ * @param instructionOffset the offset of the stack entry to be checked.
+ * @param stackIndex the index of the stack entry to be checked
+ * (counting from the bottom).
+ */
private boolean isStackEntryNecessaryAfter(int instructionOffset,
int stackIndex)
{
@@ -1909,4 +2219,4 @@ implements AttributeVisitor
return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
instructionsNecessary[instructionOffset];
}
-} \ No newline at end of file
+}
diff --git a/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
index 0c3a9c7..e6e73d9 100644
--- a/src/proguard/optimize/evaluation/EvaluationSimplifier.java
+++ b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -43,17 +43,20 @@ extends SimplifiedVisitor
implements AttributeVisitor,
InstructionVisitor
{
+ private static final int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f);
+ private static final long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
+
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = true;
//*/
private final InstructionVisitor extraInstructionVisitor;
private final PartialEvaluator partialEvaluator;
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false);
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true);
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true);
/**
@@ -426,8 +429,9 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
int value = pushedValue.integerValue().value();
- if (value << 16 >> 16 == value)
+ if ((short)value == value)
{
replaceConstantPushInstruction(clazz,
offset,
@@ -442,13 +446,14 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC,
- constantPoolEditor.addIntegerConstant(value)).shrink();
+ constantPoolEditor.addIntegerConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
@@ -459,6 +464,7 @@ implements AttributeVisitor,
instruction,
InstructionConstants.OP_ILOAD,
variableIndex);
+ break;
}
}
}
@@ -492,6 +498,7 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
long value = pushedValue.longValue().value();
if (value == 0L ||
value == 1L)
@@ -509,17 +516,21 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC2_W,
- constantPoolEditor.addLongConstant(value)).shrink();
+ constantPoolEditor.addLongConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
- if (pushedValue.equals(variables.load(variableIndex)))
+ // Note that we have to check the second part as well.
+ if (pushedValue.equals(variables.load(variableIndex)) &&
+ variables.load(variableIndex + 1) != null &&
+ variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
{
replaceVariablePushInstruction(clazz,
offset,
@@ -559,10 +570,12 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
+ // Make sure to distinguish between +0.0 and -0.0.
float value = pushedValue.floatValue().value();
- if (value == 0f ||
- value == 1f ||
- value == 2f)
+ if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
+ value == 1.0f ||
+ value == 2.0f)
{
replaceConstantPushInstruction(clazz,
offset,
@@ -577,13 +590,14 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC,
- constantPoolEditor.addFloatConstant(value)).shrink();
+ constantPoolEditor.addFloatConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
@@ -627,8 +641,10 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
+ // Make sure to distinguish between +0.0 and -0.0.
double value = pushedValue.doubleValue().value();
- if (value == 0.0 ||
+ if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
value == 1.0)
{
replaceConstantPushInstruction(clazz,
@@ -644,17 +660,21 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC2_W,
- constantPoolEditor.addDoubleConstant(value)).shrink();
+ constantPoolEditor.addDoubleConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
- if (pushedValue.equals(variables.load(variableIndex)))
+ // Note that we have to check the second part as well.
+ if (pushedValue.equals(variables.load(variableIndex)) &&
+ variables.load(variableIndex + 1) != null &&
+ variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
{
replaceVariablePushInstruction(clazz,
offset,
@@ -699,7 +719,7 @@ implements AttributeVisitor,
int value)
{
Instruction replacementInstruction =
- new SimpleInstruction(replacementOpcode, value).shrink();
+ new SimpleInstruction(replacementOpcode, value);
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
@@ -716,7 +736,7 @@ implements AttributeVisitor,
int variableIndex)
{
Instruction replacementInstruction =
- new VariableInstruction(replacementOpcode, variableIndex).shrink();
+ new VariableInstruction(replacementOpcode, variableIndex);
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
@@ -794,8 +814,8 @@ implements AttributeVisitor,
{
// Replace the branch instruction by a simple branch instruction.
Instruction replacementInstruction =
- new BranchInstruction(InstructionConstants.OP_GOTO_W,
- branchOffset).shrink();
+ new BranchInstruction(InstructionConstants.OP_GOTO,
+ branchOffset);
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
diff --git a/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
index 9915027..5ce8ccb 100644
--- a/src/proguard/optimize/evaluation/LivenessAnalyzer.java
+++ b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -79,6 +79,16 @@ implements AttributeVisitor,
/**
+ * Returns whether the instruction at the given offset has ever been
+ * executed during the partial evaluation.
+ */
+ public boolean isTraced(int instructionOffset)
+ {
+ return partialEvaluator.isTraced(instructionOffset);
+ }
+
+
+ /**
* Returns whether the specified variable is alive before the instruction
* at the given offset.
*/
diff --git a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
index 8379c57..d6baa67 100644
--- a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -35,9 +35,9 @@ import proguard.evaluation.value.*;
public class LoadingInvocationUnit
extends BasicInvocationUnit
{
- private boolean loadFieldValues;
- private boolean loadMethodParameterValues;
- private boolean loadMethodReturnValues;
+ private final boolean loadFieldValues;
+ private final boolean loadMethodParameterValues;
+ private final boolean loadMethodReturnValues;
/**
@@ -84,8 +84,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
}
@@ -110,8 +108,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
}
@@ -134,8 +130,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
@@ -163,8 +157,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
}
@@ -173,8 +165,8 @@ extends BasicInvocationUnit
refConstant,
type);
}
-//
-//
+
+
// // Small utility methods.
//
// private Value refresh(Value value)
diff --git a/src/proguard/optimize/evaluation/PartialEvaluator.java b/src/proguard/optimize/evaluation/PartialEvaluator.java
index 5790a36..6a5bedf 100644
--- a/src/proguard/optimize/evaluation/PartialEvaluator.java
+++ b/src/proguard/optimize/evaluation/PartialEvaluator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,6 +31,8 @@ import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.peephole.BranchTargetFinder;
+import java.util.Arrays;
+
/**
* This AttributeVisitor performs partial evaluation on the code attributes
* that it visits.
@@ -68,7 +70,6 @@ implements AttributeVisitor,
private TracedStack[] stacksAfter = new TracedStack[ClassConstants.TYPICAL_CODE_LENGTH];
private boolean[] generalizedContexts = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
private int[] evaluationCounts = new int[ClassConstants.TYPICAL_CODE_LENGTH];
- private int[] initializedVariables = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private boolean evaluateExceptions;
private final BasicBranchUnit branchUnit;
@@ -189,6 +190,47 @@ implements AttributeVisitor,
if (DEBUG)
{
method.accept(clazz, new ClassPrinter());
+
+ System.out.println("Evaluation results:");
+
+ int offset = 0;
+ do
+ {
+ if (isBranchOrExceptionTarget(offset))
+ {
+ System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
+ if (isTraced(offset))
+ {
+ System.out.println(" Vars: "+variablesBefore[offset]);
+ System.out.println(" Stack: "+stacksBefore[offset]);
+ }
+ }
+
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+ System.out.println(instruction.toString(offset));
+
+ if (isTraced(offset))
+ {
+ int initializationOffset = branchTargetFinder.initializationOffset(offset);
+ if (initializationOffset != NONE)
+ {
+ System.out.println(" is to be initialized at ["+initializationOffset+"]");
+ }
+
+ InstructionOffsetValue branchTargets = branchTargets(offset);
+ if (branchTargets != null)
+ {
+ System.out.println(" has overall been branching to "+branchTargets);
+ }
+
+ System.out.println(" Vars: "+variablesAfter[offset]);
+ System.out.println(" Stack: "+stacksAfter[offset]);
+ }
+
+ offset += instruction.length(offset);
+ }
+ while (offset < codeAttribute.u4codeLength);
}
throw ex;
@@ -212,7 +254,8 @@ implements AttributeVisitor,
TracedStack stack = new TracedStack(codeAttribute.u2maxStack);
// Initialize the reusable arrays and variables.
- initializeVariables(clazz, method, codeAttribute, variables, stack);
+ initializeArrays(codeAttribute);
+ initializeParameters(clazz, method, codeAttribute, variables);
// Find all instruction offsets,...
codeAttribute.accept(clazz, method, branchTargetFinder);
@@ -249,12 +292,6 @@ implements AttributeVisitor,
if (isTraced(offset))
{
- int variableIndex = initializedVariable(offset);
- if (variableIndex >= 0)
- {
- System.out.println(" is initializing variable v"+variableIndex);
- }
-
int initializationOffset = branchTargetFinder.initializationOffset(offset);
if (initializationOffset != NONE)
{
@@ -479,16 +516,6 @@ implements AttributeVisitor,
}
- /**
- * Returns the variable that is initialized at the given instruction offset,
- * or <code>NONE</code> if no variable was initialized.
- */
- public int initializedVariable(int instructionOffset)
- {
- return initializedVariables[instructionOffset];
- }
-
-
// Utility methods to evaluate instruction blocks.
/**
@@ -702,9 +729,6 @@ implements AttributeVisitor,
// Reset the trace value.
InstructionOffsetValue traceValue = InstructionOffsetValue.EMPTY_VALUE;
- // Reset the initialization flag.
- variables.resetInitialization();
-
// Note that the instruction is only volatile.
Instruction instruction = InstructionFactory.create(code, instructionOffset);
@@ -743,9 +767,6 @@ implements AttributeVisitor,
throw ex;
}
- // Collect the offsets of the instructions whose results were used.
- initializedVariables[instructionOffset] = variables.getInitializationIndex();
-
// Collect the branch targets from the branch unit.
InstructionOffsetValue branchTargets = branchUnit.getTraceBranchTargets();
int branchTargetCount = branchTargets.instructionOffsetCount();
@@ -844,8 +865,7 @@ implements AttributeVisitor,
if (instruction.opcode == InstructionConstants.OP_JSR ||
instruction.opcode == InstructionConstants.OP_JSR_W)
{
- // Evaluate the subroutine, possibly in another partial
- // evaluator.
+ // Evaluate the subroutine in another partial evaluator.
evaluateSubroutine(clazz,
method,
codeAttribute,
@@ -887,21 +907,13 @@ implements AttributeVisitor,
if (DEBUG) System.out.println("Evaluating subroutine from "+subroutineStart+" to "+subroutineEnd);
- PartialEvaluator subroutinePartialEvaluator = this;
-
- // Create a temporary partial evaluator if necessary.
- if (evaluationCounts[subroutineStart] > 0)
- {
- if (DEBUG) System.out.println("Creating new partial evaluator for subroutine");
-
- subroutinePartialEvaluator = new PartialEvaluator(this);
+ // Create a temporary partial evaluator, so there are no conflicts
+ // with variables that are alive across subroutine invocations, between
+ // different invocations.
+ PartialEvaluator subroutinePartialEvaluator =
+ new PartialEvaluator(this);
- subroutinePartialEvaluator.initializeVariables(clazz,
- method,
- codeAttribute,
- variables,
- stack);
- }
+ subroutinePartialEvaluator.initializeArrays(codeAttribute);
// Evaluate the subroutine.
subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz,
@@ -912,11 +924,9 @@ implements AttributeVisitor,
subroutineStart,
subroutineEnd);
- // Merge back the temporary partial evaluator if necessary.
- if (subroutinePartialEvaluator != this)
- {
- generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
- }
+ // Merge back the temporary partial evaluator. This way, we'll get
+ // the lowest common denominator of stacks and variables.
+ generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
if (DEBUG) System.out.println("Ending subroutine from "+subroutineStart+" to "+subroutineEnd);
}
@@ -952,13 +962,12 @@ implements AttributeVisitor,
if (evaluationCounts[offset] == 0)
{
- variablesBefore[offset] = other.variablesBefore[offset];
- stacksBefore[offset] = other.stacksBefore[offset];
- variablesAfter[offset] = other.variablesAfter[offset];
- stacksAfter[offset] = other.stacksAfter[offset];
- generalizedContexts[offset] = other.generalizedContexts[offset];
- evaluationCounts[offset] = other.evaluationCounts[offset];
- initializedVariables[offset] = other.initializedVariables[offset];
+ variablesBefore[offset] = other.variablesBefore[offset];
+ stacksBefore[offset] = other.stacksBefore[offset];
+ variablesAfter[offset] = other.variablesAfter[offset];
+ stacksAfter[offset] = other.stacksAfter[offset];
+ generalizedContexts[offset] = other.generalizedContexts[offset];
+ evaluationCounts[offset] = other.evaluationCounts[offset];
}
else
{
@@ -968,7 +977,6 @@ implements AttributeVisitor,
stacksAfter[offset] .generalize(other.stacksAfter[offset]);
//generalizedContexts[offset]
evaluationCounts[offset] += other.evaluationCounts[offset];
- //initializedVariables[offset]
}
}
}
@@ -1094,11 +1102,7 @@ implements AttributeVisitor,
/**
* Initializes the data structures for the variables, stack, etc.
*/
- private void initializeVariables(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- TracedVariables variables,
- TracedStack stack)
+ private void initializeArrays(CodeAttribute codeAttribute)
{
int codeLength = codeAttribute.u4codeLength;
@@ -1106,33 +1110,25 @@ implements AttributeVisitor,
if (variablesAfter.length < codeLength)
{
// Create new arrays.
- branchOriginValues = new InstructionOffsetValue[codeLength];
- branchTargetValues = new InstructionOffsetValue[codeLength];
- variablesBefore = new TracedVariables[codeLength];
- stacksBefore = new TracedStack[codeLength];
- variablesAfter = new TracedVariables[codeLength];
- stacksAfter = new TracedStack[codeLength];
- generalizedContexts = new boolean[codeLength];
- evaluationCounts = new int[codeLength];
- initializedVariables = new int[codeLength];
-
- // Reset the arrays.
- for (int index = 0; index < codeLength; index++)
- {
- initializedVariables[index] = NONE;
- }
+ branchOriginValues = new InstructionOffsetValue[codeLength];
+ branchTargetValues = new InstructionOffsetValue[codeLength];
+ variablesBefore = new TracedVariables[codeLength];
+ stacksBefore = new TracedStack[codeLength];
+ variablesAfter = new TracedVariables[codeLength];
+ stacksAfter = new TracedStack[codeLength];
+ generalizedContexts = new boolean[codeLength];
+ evaluationCounts = new int[codeLength];
}
else
{
// Reset the arrays.
+ Arrays.fill(branchOriginValues, null);
+ Arrays.fill(branchTargetValues, null);
+ Arrays.fill(generalizedContexts, false);
+ Arrays.fill(evaluationCounts, 0);
+
for (int index = 0; index < codeLength; index++)
{
- branchOriginValues[index] = null;
- branchTargetValues[index] = null;
- generalizedContexts[index] = false;
- evaluationCounts[index] = 0;
- initializedVariables[index] = NONE;
-
if (variablesBefore[index] != null)
{
variablesBefore[index].reset(codeAttribute.u2maxLocals);
@@ -1154,7 +1150,17 @@ implements AttributeVisitor,
}
}
}
+ }
+
+ /**
+ * Initializes the data structures for the variables, stack, etc.
+ */
+ private void initializeParameters(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables)
+ {
// Create the method parameters.
TracedVariables parameters = new TracedVariables(codeAttribute.u2maxLocals);
diff --git a/src/proguard/optimize/evaluation/StoringInvocationUnit.java b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
index bcbb69f..846f685 100644
--- a/src/proguard/optimize/evaluation/StoringInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/TracedBranchUnit.java b/src/proguard/optimize/evaluation/TracedBranchUnit.java
index fa5bb79..e6acf6f 100644
--- a/src/proguard/optimize/evaluation/TracedBranchUnit.java
+++ b/src/proguard/optimize/evaluation/TracedBranchUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/VariableOptimizer.java b/src/proguard/optimize/evaluation/VariableOptimizer.java
index b3ae81c..73efddc 100644
--- a/src/proguard/optimize/evaluation/VariableOptimizer.java
+++ b/src/proguard/optimize/evaluation/VariableOptimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,10 +21,10 @@
package proguard.optimize.evaluation;
import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.editor.*;
import proguard.classfile.visitor.MemberVisitor;
import proguard.classfile.attribute.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.editor.VariableRemapper;
import proguard.classfile.util.*;
/**
@@ -35,7 +35,9 @@ import proguard.classfile.util.*;
*/
public class VariableOptimizer
extends SimplifiedVisitor
-implements AttributeVisitor
+implements AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor
{
//*
private static final boolean DEBUG = false;
@@ -51,6 +53,7 @@ implements AttributeVisitor
private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
private final VariableRemapper variableRemapper = new VariableRemapper();
+ private VariableCleaner variableCleaner = new VariableCleaner();
private int[] variableMap = new int[ClassConstants.TYPICAL_VARIABLES_SIZE];
@@ -101,6 +104,11 @@ implements AttributeVisitor
// Analyze the liveness of the variables in the code.
livenessAnalyzer.visitCodeAttribute(clazz, method, codeAttribute);
+ // Trim the variables in the local variable tables, because even
+ // clipping the tables individually may leave some inconsistencies
+ // between them.
+ codeAttribute.attributesAccept(clazz, method, this);
+
int startIndex =
(method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ||
reuseThis ? 0 : 1;
@@ -142,23 +150,19 @@ implements AttributeVisitor
}
}
- // Remap the variables.
+ // Have we been able to remap any variables?
if (remapping)
{
if (DEBUG)
{
- System.out.println("Remapping variables:");
- System.out.println(" Class "+ ClassUtil.externalClassName(clazz.getName()));
- System.out.println(" Method "+ClassUtil.externalFullMethodDescription(clazz.getName(),
- 0,
- method.getName(clazz),
- method.getDescriptor(clazz)));
- for (int index = 0; index < variableSize; index++)
+ System.out.println("VariableOptimizer: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ for (int index= 0; index < variableSize; index++)
{
- System.out.println(" ["+index+"] -> ["+variableMap[index]+"]");
+ System.out.println(" v"+index+" -> "+variableMap[index]);
}
}
+ // Remap the variables.
variableRemapper.setVariableMap(variableMap);
variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
@@ -168,6 +172,71 @@ implements AttributeVisitor
method.accept(clazz, extraVariableMemberVisitor);
}
}
+ else
+ {
+ // Just clean up any empty variables.
+ variableCleaner.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Trim the variables in the local variable table.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Trim the variables in the local variable type table.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Trim the local variable to the instructions at which it is alive.
+ int variable = localVariableInfo.u2index;
+ int startPC = localVariableInfo.u2startPC;
+ int endPC = startPC + localVariableInfo.u2length;
+
+ startPC = firstLiveness(startPC, endPC, variable);
+ endPC = lastLiveness(startPC, endPC, variable);
+
+ // Leave the start address of unused variables unchanged.
+ int length = endPC - startPC;
+ if (length > 0)
+ {
+ localVariableInfo.u2startPC = startPC;
+ }
+
+ localVariableInfo.u2length = length;
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Trim the local variable type to the instructions at which it is alive.
+ int variable = localVariableTypeInfo.u2index;
+ int startPC = localVariableTypeInfo.u2startPC;
+ int endPC = startPC + localVariableTypeInfo.u2length;
+
+ startPC = firstLiveness(startPC, endPC, variable);
+ endPC = lastLiveness(startPC, endPC, variable);
+
+ // Leave the start address of unused variables unchanged.
+ int length = endPC - startPC;
+ if (length > 0)
+ {
+ localVariableTypeInfo.u2startPC = startPC;
+ }
+
+ localVariableTypeInfo.u2length = length;
}
@@ -241,4 +310,48 @@ implements AttributeVisitor
}
}
}
+
+
+ /**
+ * Returns the first instruction offset between the given offsets at which
+ * the given variable goes alive.
+ */
+ private int firstLiveness(int startOffset, int endOffset, int variableIndex)
+ {
+ for (int offset = startOffset; offset < endOffset; offset++)
+ {
+ if (livenessAnalyzer.isTraced(offset) &&
+ livenessAnalyzer.isAliveBefore(offset, variableIndex))
+ {
+ return offset;
+ }
+ }
+
+ return endOffset;
+ }
+
+
+ /**
+ * Returns the last instruction offset between the given offsets before
+ * which the given variable is still alive.
+ */
+ private int lastLiveness(int startOffset, int endOffset, int variableIndex)
+ {
+ int previousOffset = endOffset;
+
+ for (int offset = endOffset-1; offset >= startOffset; offset--)
+ {
+ if (livenessAnalyzer.isTraced(offset))
+ {
+ if (livenessAnalyzer.isAliveBefore(offset, variableIndex))
+ {
+ return previousOffset;
+ }
+
+ previousOffset = offset;
+ }
+ }
+
+ return endOffset;
+ }
}
diff --git a/src/proguard/optimize/info/AccessMethodMarker.java b/src/proguard/optimize/info/AccessMethodMarker.java
index 6965cec..e4c8d7c 100644
--- a/src/proguard/optimize/info/AccessMethodMarker.java
+++ b/src/proguard/optimize/info/AccessMethodMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,7 +21,8 @@
package proguard.optimize.info;
import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
@@ -71,6 +72,20 @@ implements InstructionVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Check the bootstrap method.
+ invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the method reference.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
// Check the referenced class.
diff --git a/src/proguard/optimize/info/BackwardBranchMarker.java b/src/proguard/optimize/info/BackwardBranchMarker.java
index 9e09b0f..07bfefb 100644
--- a/src/proguard/optimize/info/BackwardBranchMarker.java
+++ b/src/proguard/optimize/info/BackwardBranchMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/CatchExceptionMarker.java b/src/proguard/optimize/info/CatchExceptionMarker.java
index 3f2a06f..8f87a08 100644
--- a/src/proguard/optimize/info/CatchExceptionMarker.java
+++ b/src/proguard/optimize/info/CatchExceptionMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/CaughtClassFilter.java b/src/proguard/optimize/info/CaughtClassFilter.java
index 5e17763..762e7de 100644
--- a/src/proguard/optimize/info/CaughtClassFilter.java
+++ b/src/proguard/optimize/info/CaughtClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/CaughtClassMarker.java b/src/proguard/optimize/info/CaughtClassMarker.java
index 0cc350e..1752f0c 100644
--- a/src/proguard/optimize/info/CaughtClassMarker.java
+++ b/src/proguard/optimize/info/CaughtClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,8 +25,9 @@ import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
/**
- * This InstructionVisitor marks all classes that are used in an 'instanceof'
- * test by any of the instructions that it visits.
+ * This ClassVisitor marks all program classes that it visits as caught.
+ * This means that these classes are exception classes that occur in exception
+ * handlers.
*
* @author Eric Lafortune
*/
diff --git a/src/proguard/optimize/info/ClassOptimizationInfo.java b/src/proguard/optimize/info/ClassOptimizationInfo.java
index 99b6e7b..dbe041e 100644
--- a/src/proguard/optimize/info/ClassOptimizationInfo.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -34,6 +34,7 @@ public class ClassOptimizationInfo
private boolean isInstanceofed = false;
private boolean isDotClassed = false;
private boolean isCaught = false;
+ private boolean containsStaticInitializer = false;
private boolean containsPackageVisibleMembers = false;
private boolean invokesPackageVisibleMembers = false;
private Clazz targetClass;
@@ -87,6 +88,18 @@ public class ClassOptimizationInfo
}
+ public void setContainsStaticInitializer()
+ {
+ containsStaticInitializer = true;
+ }
+
+
+ public boolean containsStaticInitializer()
+ {
+ return containsStaticInitializer;
+ }
+
+
public void setContainsPackageVisibleMembers()
{
containsPackageVisibleMembers = true;
@@ -129,6 +142,7 @@ public class ClassOptimizationInfo
this.isInstanceofed |= other.isInstanceofed;
this.isDotClassed |= other.isDotClassed;
this.isCaught |= other.isCaught;
+ this.containsStaticInitializer |= other.containsStaticInitializer;
this.containsPackageVisibleMembers |= other.containsPackageVisibleMembers;
this.invokesPackageVisibleMembers |= other.invokesPackageVisibleMembers;
}
diff --git a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
index 9cb167c..f3d78e2 100644
--- a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/DotClassFilter.java b/src/proguard/optimize/info/DotClassFilter.java
index 8cbe7f0..c3fd878 100644
--- a/src/proguard/optimize/info/DotClassFilter.java
+++ b/src/proguard/optimize/info/DotClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/DotClassMarker.java b/src/proguard/optimize/info/DotClassMarker.java
index b5f12a7..ef5cfd1 100644
--- a/src/proguard/optimize/info/DotClassMarker.java
+++ b/src/proguard/optimize/info/DotClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/ExceptionInstructionChecker.java b/src/proguard/optimize/info/ExceptionInstructionChecker.java
index 2792d90..4bfa96f 100644
--- a/src/proguard/optimize/info/ExceptionInstructionChecker.java
+++ b/src/proguard/optimize/info/ExceptionInstructionChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -67,34 +67,39 @@ implements InstructionVisitor
byte opcode = simpleInstruction.opcode;
// Check for instructions that may throw exceptions.
- if (opcode == InstructionConstants.OP_IDIV ||
- opcode == InstructionConstants.OP_LDIV ||
- opcode == InstructionConstants.OP_IREM ||
- opcode == InstructionConstants.OP_LREM ||
- opcode == InstructionConstants.OP_IALOAD ||
- opcode == InstructionConstants.OP_LALOAD ||
- opcode == InstructionConstants.OP_FALOAD ||
- opcode == InstructionConstants.OP_DALOAD ||
- opcode == InstructionConstants.OP_AALOAD ||
- opcode == InstructionConstants.OP_BALOAD ||
- opcode == InstructionConstants.OP_CALOAD ||
- opcode == InstructionConstants.OP_SALOAD ||
- opcode == InstructionConstants.OP_IASTORE ||
- opcode == InstructionConstants.OP_LASTORE ||
- opcode == InstructionConstants.OP_FASTORE ||
- opcode == InstructionConstants.OP_DASTORE ||
- opcode == InstructionConstants.OP_AASTORE ||
- opcode == InstructionConstants.OP_BASTORE ||
- opcode == InstructionConstants.OP_CASTORE ||
- opcode == InstructionConstants.OP_SASTORE ||
- opcode == InstructionConstants.OP_NEWARRAY ||
- opcode == InstructionConstants.OP_ARRAYLENGTH ||
- opcode == InstructionConstants.OP_ATHROW ||
- opcode == InstructionConstants.OP_MONITORENTER ||
- opcode == InstructionConstants.OP_MONITOREXIT)
+ // Note that monitorexit can not sensibly throw exceptions, except the
+ // broken and deprecated asynchronous ThreadDeath. Removing the
+ // artificial infinite looping exception blocks that recent compilers
+ // add does not strictly follow the JVM specs, but it does have the
+ // additional benefit of avoiding a bug in the JVM in JDK 1.1.
+ switch (opcode)
{
- // These instructions may throw exceptions.
- mayThrowExceptions = true;
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_NEWARRAY:
+ case InstructionConstants.OP_ARRAYLENGTH:
+ case InstructionConstants.OP_ATHROW:
+ case InstructionConstants.OP_MONITORENTER:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
}
}
@@ -105,31 +110,32 @@ implements InstructionVisitor
byte opcode = constantInstruction.opcode;
// Check for instructions that may throw exceptions.
- if (opcode == InstructionConstants.OP_GETSTATIC ||
- opcode == InstructionConstants.OP_PUTSTATIC ||
- opcode == InstructionConstants.OP_GETFIELD ||
- opcode == InstructionConstants.OP_PUTFIELD ||
- opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
- opcode == InstructionConstants.OP_INVOKESPECIAL ||
- opcode == InstructionConstants.OP_INVOKESTATIC ||
- opcode == InstructionConstants.OP_INVOKEINTERFACE ||
- opcode == InstructionConstants.OP_NEW ||
- opcode == InstructionConstants.OP_ANEWARRAY ||
- opcode == InstructionConstants.OP_CHECKCAST ||
- opcode == InstructionConstants.OP_MULTIANEWARRAY)
+ switch (opcode)
{
- // These instructions may throw exceptions.
- mayThrowExceptions = true;
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ case InstructionConstants.OP_NEW:
+ case InstructionConstants.OP_ANEWARRAY:
+ case InstructionConstants.OP_CHECKCAST:
+ case InstructionConstants.OP_INSTANCEOF:
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
}
-// else
-// if (opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
-// opcode == InstructionConstants.OP_INVOKESPECIAL ||
-// opcode == InstructionConstants.OP_INVOKESTATIC ||
-// opcode == InstructionConstants.OP_INVOKEINTERFACE)
-// {
+
+// case InstructionConstants.OP_INVOKEVIRTUAL:
+// case InstructionConstants.OP_INVOKESPECIAL:
+// case InstructionConstants.OP_INVOKESTATIC:
+// case InstructionConstants.OP_INVOKEINTERFACE:
// // Check if the invoking the method may throw an exception.
// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
-// }
}
diff --git a/src/proguard/optimize/info/FieldOptimizationInfo.java b/src/proguard/optimize/info/FieldOptimizationInfo.java
index 7a2d068..0fa9167 100644
--- a/src/proguard/optimize/info/FieldOptimizationInfo.java
+++ b/src/proguard/optimize/info/FieldOptimizationInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,8 +21,11 @@
package proguard.optimize.info;
import proguard.classfile.*;
-import proguard.classfile.util.MethodLinker;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.*;
import proguard.evaluation.value.*;
+import proguard.evaluation.ConstantValueFactory;
/**
* This class stores some optimization information that can be attached to
@@ -31,8 +34,11 @@ import proguard.evaluation.value.*;
* @author Eric Lafortune
*/
public class FieldOptimizationInfo
+extends SimplifiedVisitor
+implements AttributeVisitor
{
- private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory();
+ private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory();
+ private static final ConstantValueFactory CONSTANT_VALUE_FACTORY = new ConstantValueFactory(VALUE_FACTORY);
private boolean isWritten;
private boolean isRead;
@@ -43,9 +49,33 @@ public class FieldOptimizationInfo
public FieldOptimizationInfo(Clazz clazz, Field field)
{
+ int accessFlags = field.getAccessFlags();
+
isWritten =
- isRead = (field.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0;
- value = initialValue(field.getDescriptor(clazz));
+ isRead = (accessFlags & ClassConstants.INTERNAL_ACC_VOLATILE) != 0;
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0)
+ {
+ // See if we can initialize the static field with a constant value.
+ field.accept(clazz, new AllAttributeVisitor(this));
+ }
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) == 0 &&
+ value == null)
+ {
+ // Otherwise initialize the non-final field with the default value.
+ value = initialValue(field.getDescriptor(clazz));
+ }
+ }
+
+
+ public FieldOptimizationInfo(FieldOptimizationInfo FieldOptimizationInfo)
+ {
+ this.isWritten = FieldOptimizationInfo.isWritten;
+ this.isRead = FieldOptimizationInfo.isRead;
+ this.canBeMadePrivate = FieldOptimizationInfo.canBeMadePrivate;
+ this.referencedClass = FieldOptimizationInfo.referencedClass;
+ this.value = FieldOptimizationInfo.value;
}
@@ -113,6 +143,18 @@ public class FieldOptimizationInfo
}
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ // Retrieve the initial static field value.
+ value = CONSTANT_VALUE_FACTORY.constantValue(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
// Small utility methods.
private Value initialValue(String type)
@@ -147,13 +189,13 @@ public class FieldOptimizationInfo
public static void setFieldOptimizationInfo(Clazz clazz, Field field)
{
- MethodLinker.lastMember(field).setVisitorInfo(new FieldOptimizationInfo(clazz, field));
+ field.setVisitorInfo(new FieldOptimizationInfo(clazz, field));
}
public static FieldOptimizationInfo getFieldOptimizationInfo(Field field)
{
- Object visitorInfo = MethodLinker.lastMember(field).getVisitorInfo();
+ Object visitorInfo = field.getVisitorInfo();
return visitorInfo instanceof FieldOptimizationInfo ?
(FieldOptimizationInfo)visitorInfo :
diff --git a/src/proguard/optimize/info/InstanceofClassFilter.java b/src/proguard/optimize/info/InstanceofClassFilter.java
index 35e1d77..7cd85bc 100644
--- a/src/proguard/optimize/info/InstanceofClassFilter.java
+++ b/src/proguard/optimize/info/InstanceofClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/InstanceofClassMarker.java b/src/proguard/optimize/info/InstanceofClassMarker.java
index c60e1f8..96d5baf 100644
--- a/src/proguard/optimize/info/InstanceofClassMarker.java
+++ b/src/proguard/optimize/info/InstanceofClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/InstantiationClassFilter.java b/src/proguard/optimize/info/InstantiationClassFilter.java
index a24e617..a659f06 100644
--- a/src/proguard/optimize/info/InstantiationClassFilter.java
+++ b/src/proguard/optimize/info/InstantiationClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/InstantiationClassMarker.java b/src/proguard/optimize/info/InstantiationClassMarker.java
index 124c23b..b4afffd 100644
--- a/src/proguard/optimize/info/InstantiationClassMarker.java
+++ b/src/proguard/optimize/info/InstantiationClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
index a170a8e..3c27c93 100644
--- a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -38,22 +38,22 @@ implements MemberVisitor
{
// Implementations for MemberVisitor.
- public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- if (!KeepMarker.isKept(programMethod))
+ if (!KeepMarker.isKept(programField))
{
- MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
- programMethod);
+ FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
+ programField);
}
}
- public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- if (!KeepMarker.isKept(programField))
+ if (!KeepMarker.isKept(programMethod))
{
- FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
- programField);
+ MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
+ programMethod);
}
}
}
diff --git a/src/proguard/optimize/info/MethodInvocationMarker.java b/src/proguard/optimize/info/MethodInvocationMarker.java
index 2528c94..afb2336 100644
--- a/src/proguard/optimize/info/MethodInvocationMarker.java
+++ b/src/proguard/optimize/info/MethodInvocationMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/MethodOptimizationInfo.java b/src/proguard/optimize/info/MethodOptimizationInfo.java
index d3b1bde..fe754e5 100644
--- a/src/proguard/optimize/info/MethodOptimizationInfo.java
+++ b/src/proguard/optimize/info/MethodOptimizationInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -204,7 +204,7 @@ public class MethodOptimizationInfo
public void setParameterUsed(int parameterIndex)
{
- usedParameters |= 1 << parameterIndex;
+ usedParameters |= 1L << parameterIndex;
}
@@ -216,7 +216,7 @@ public class MethodOptimizationInfo
public boolean isParameterUsed(int parameterIndex)
{
- return parameterIndex >= 64 || (usedParameters & (1 << parameterIndex)) != 0;
+ return parameterIndex >= 64 || (usedParameters & (1L << parameterIndex)) != 0;
}
diff --git a/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
index 5c78408..bf5ce45 100644
--- a/src/proguard/optimize/info/NoSideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -38,7 +38,7 @@ implements MemberVisitor
{
// A visitor info flag to indicate the visitor accepter is being kept,
// but that it doesn't have any side effects.
- private static final Object KEPT_BUT_NO_SIDE_EFFECTS = new Object();
+ public static final Object KEPT_BUT_NO_SIDE_EFFECTS = new Object();
// Implementations for MemberVisitor.
diff --git a/src/proguard/optimize/info/NonPrivateMemberMarker.java b/src/proguard/optimize/info/NonPrivateMemberMarker.java
index d451643..06f8500 100644
--- a/src/proguard/optimize/info/NonPrivateMemberMarker.java
+++ b/src/proguard/optimize/info/NonPrivateMemberMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -77,15 +77,9 @@ implements ClassVisitor,
public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
{
- Clazz referencedClass = stringConstant.referencedClass;
-
- // Is it refering to another class or class member?
- if (referencedClass != null &&
- !referencedClass.equals(clazz))
- {
- // The referenced class member, if any, can never be made private.
- stringConstant.referencedMemberAccept(this);
- }
+ // The referenced class member, if any, can never be made private,
+ // even if it's in the same class.
+ stringConstant.referencedMemberAccept(this);
}
@@ -93,7 +87,7 @@ implements ClassVisitor,
{
Clazz referencedClass = refConstant.referencedClass;
- // Is it refering to a class member in another class?
+ // Is it referring to a class member in another class?
// The class member might be in another class, or
// it may be referenced through another class.
if (referencedClass != null &&
diff --git a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
index d40bc6b..02e1a18 100644
--- a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
+++ b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,18 +22,36 @@ package proguard.optimize.info;
import proguard.classfile.*;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.MemberVisitor;
+import proguard.classfile.visitor.*;
/**
- * This MemberVisitor marks all classes that contain visited package visible
- * members.
+ * This ClassVisitor marks all classes that contain package visible members.
*
* @author Eric Lafortune
*/
public class PackageVisibleMemberContainingClassMarker
extends SimplifiedVisitor
-implements MemberVisitor
+implements ClassVisitor,
+ MemberVisitor
{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ // Check the class itself.
+ if ((clazz.getAccessFlags() & ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
+ {
+ setPackageVisibleMembers(clazz);
+ }
+ else
+ {
+ // Check the members.
+ clazz.fieldsAccept(this);
+ clazz.methodsAccept(this);
+ }
+ }
+
+
// Implementations for MemberVisitor.
public void visitAnyMember(Clazz clazz, Member member)
diff --git a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
index 9ec8ec6..3148e3d 100644
--- a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
+++ b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,39 +24,87 @@ import proguard.classfile.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.constant.*;
import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
/**
- * This ConstantVisitor marks all classes that invoke package visible members
- * in other classes.
+ * This ConstantVisitor marks all classes that refer to package visible classes
+ * or class members.
*
* @author Eric Lafortune
*/
public class PackageVisibleMemberInvokingClassMarker
extends SimplifiedVisitor
-implements ConstantVisitor
+implements ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
{
+ private Clazz referencingClass;
+
+
// Implementations for ConstantVisitor.
public void visitAnyConstant(Clazz clazz, Constant constant) {}
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Check the referenced class and class member, if any.
+ if (stringConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ stringConstant.referencedClassAccept(this);
+ stringConstant.referencedMemberAccept(this);
+ }
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
- Clazz referencedClass = refConstant.referencedClass;
- if (referencedClass != null &&
- (referencedClass.getAccessFlags() &
+ // Check the referenced class and class member.
+ if (refConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ refConstant.referencedClassAccept(this);
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check the referenced class.
+ if (classConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ classConstant.referencedClassAccept(this);
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if ((clazz.getAccessFlags() &
ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
{
- setInvokesPackageVisibleMembers(clazz);
+ setInvokesPackageVisibleMembers(referencingClass);
}
+ }
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null &&
- (referencedMember.getAccessFlags() &
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ if ((member.getAccessFlags() &
(ClassConstants.INTERNAL_ACC_PUBLIC |
ClassConstants.INTERNAL_ACC_PRIVATE)) == 0)
{
- setInvokesPackageVisibleMembers(clazz);
+ setInvokesPackageVisibleMembers(referencingClass);
}
}
diff --git a/src/proguard/optimize/info/ParameterUsageMarker.java b/src/proguard/optimize/info/ParameterUsageMarker.java
index 15ce88a..a2a264d 100644
--- a/src/proguard/optimize/info/ParameterUsageMarker.java
+++ b/src/proguard/optimize/info/ParameterUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,14 +21,14 @@
package proguard.optimize.info;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.attribute.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
import proguard.optimize.evaluation.PartialEvaluator;
-import proguard.evaluation.value.*;
/**
* This MemberVisitor counts the parameters and marks the used parameters
diff --git a/src/proguard/optimize/info/ReadWriteFieldMarker.java b/src/proguard/optimize/info/ReadWriteFieldMarker.java
index 57d8561..6bd4b2f 100644
--- a/src/proguard/optimize/info/ReadWriteFieldMarker.java
+++ b/src/proguard/optimize/info/ReadWriteFieldMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/SideEffectInstructionChecker.java b/src/proguard/optimize/info/SideEffectInstructionChecker.java
index 8be9dc1..91f1f02 100644
--- a/src/proguard/optimize/info/SideEffectInstructionChecker.java
+++ b/src/proguard/optimize/info/SideEffectInstructionChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,11 +29,14 @@ import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.*;
+import java.util.*;
+
/**
- * This class can tell whether an instruction has any side effects. Return
- * instructions can be included or not.
+ * This class can tell whether an instruction has any side effects outside of
+ * its method. Return instructions can be included or not.
*
* @see ReadWriteFieldMarker
+ * @see StaticInitializerContainingClassMarker
* @see NoSideEffectMethodMarker
* @see SideEffectMethodMarker
* @author Eric Lafortune
@@ -44,23 +47,38 @@ implements InstructionVisitor,
ConstantVisitor,
MemberVisitor
{
+ private static final boolean OPTIMIZE_CONSERVATIVELY = System.getProperty("optimize.conservatively") != null;
+
+
private final boolean includeReturnInstructions;
+ private final boolean includeLocalFieldAccess;
// A return value for the visitor methods.
+ private Clazz referencingClass;
private boolean hasSideEffects;
- public SideEffectInstructionChecker(boolean includeReturnInstructions)
+ public SideEffectInstructionChecker(boolean includeReturnInstructions,
+ boolean includeLocalFieldAccess)
{
this.includeReturnInstructions = includeReturnInstructions;
+ this.includeLocalFieldAccess = includeLocalFieldAccess;
}
- public boolean hasSideEffects(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ /**
+ * Returns whether the given instruction has side effects outside of its
+ * method.
+ */
+ public boolean hasSideEffects(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction)
{
hasSideEffects = false;
- instruction.accept(clazz, method, codeAttribute, offset, this);
+ instruction.accept(clazz, method, codeAttribute, offset, this);
return hasSideEffects;
}
@@ -76,29 +94,46 @@ implements InstructionVisitor,
byte opcode = simpleInstruction.opcode;
// Check for instructions that might cause side effects.
- if (opcode == InstructionConstants.OP_IASTORE ||
- opcode == InstructionConstants.OP_LASTORE ||
- opcode == InstructionConstants.OP_FASTORE ||
- opcode == InstructionConstants.OP_DASTORE ||
- opcode == InstructionConstants.OP_AASTORE ||
- opcode == InstructionConstants.OP_BASTORE ||
- opcode == InstructionConstants.OP_CASTORE ||
- opcode == InstructionConstants.OP_SASTORE ||
- opcode == InstructionConstants.OP_ATHROW ||
- opcode == InstructionConstants.OP_MONITORENTER ||
- opcode == InstructionConstants.OP_MONITOREXIT ||
- (includeReturnInstructions &&
- (opcode == InstructionConstants.OP_IRETURN ||
- opcode == InstructionConstants.OP_LRETURN ||
- opcode == InstructionConstants.OP_FRETURN ||
- opcode == InstructionConstants.OP_DRETURN ||
- opcode == InstructionConstants.OP_ARETURN ||
- opcode == InstructionConstants.OP_RETURN)))
+ switch (opcode)
{
- // These instructions always cause a side effect.
- hasSideEffects = true;
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException, ArrayIndexOutOfBoundsException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
+
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_ATHROW :
+ case InstructionConstants.OP_MONITORENTER:
+ case InstructionConstants.OP_MONITOREXIT:
+ // These instructions always cause a side effect.
+ hasSideEffects = true;
+ break;
+
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+ // These instructions may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
}
-
}
@@ -107,10 +142,12 @@ implements InstructionVisitor,
byte opcode = variableInstruction.opcode;
// Check for instructions that might cause side effects.
- if (includeReturnInstructions &&
- opcode == InstructionConstants.OP_RET)
+ switch (opcode)
{
- hasSideEffects = true;
+ case InstructionConstants.OP_RET:
+ // This instruction may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
}
}
@@ -120,16 +157,41 @@ implements InstructionVisitor,
byte opcode = constantInstruction.opcode;
// Check for instructions that might cause side effects.
- if (opcode == InstructionConstants.OP_PUTSTATIC ||
- opcode == InstructionConstants.OP_PUTFIELD ||
- opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
- opcode == InstructionConstants.OP_INVOKESPECIAL ||
- opcode == InstructionConstants.OP_INVOKESTATIC ||
- opcode == InstructionConstants.OP_INVOKEINTERFACE)
+ switch (opcode)
{
- // Check if the field is write-only or volatile, or if the invoked
- // method is causing any side effects.
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ // Check if the field is write-only or volatile, or if the
+ // invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ if (OPTIMIZE_CONSERVATIVELY)
+ {
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException).
+ hasSideEffects = true;
+ }
+ else
+ {
+ // Check if the field is write-only or volatile, or if the
+ // invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ break;
+
+ case InstructionConstants.OP_CHECKCAST:
+ // This instructions strictly taken may cause a side effect
+ // (ClassCastException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
}
}
@@ -139,59 +201,48 @@ implements InstructionVisitor,
byte opcode = branchInstruction.opcode;
// Check for instructions that might cause side effects.
- if (includeReturnInstructions &&
- (opcode == InstructionConstants.OP_JSR ||
- opcode == InstructionConstants.OP_JSR_W))
+ switch (opcode)
{
- hasSideEffects = true;
+ case InstructionConstants.OP_JSR:
+ case InstructionConstants.OP_JSR_W:
+ hasSideEffects = includeReturnInstructions;
+ break;
}
}
// Implementations for ConstantVisitor.
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+ }
+
+
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
+ // Pass the referencing class.
+ referencingClass = clazz;
+
// We'll have to assume accessing an unknown field has side effects.
hasSideEffects = true;
- // Check the referenced field.
+ // Check the referenced field, if known.
fieldrefConstant.referencedMemberAccept(this);
}
public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
{
- Member referencedMember = refConstant.referencedMember;
+ // Pass the referencing class.
+ referencingClass = clazz;
- // Do we have a reference to the method?
- if (referencedMember == null)
- {
- // We'll have to assume invoking the unknown method has side effects.
- hasSideEffects = true;
- }
- else
- {
- // First check the referenced method itself.
- refConstant.referencedMemberAccept(this);
-
- // If the result isn't conclusive, check down the hierarchy.
- if (!hasSideEffects)
- {
- Clazz referencedClass = refConstant.referencedClass;
- Method referencedMethod = (Method)referencedMember;
-
- // Check all other implementations of the method down the class
- // hierarchy.
- if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_PRIVATE) == 0)
- {
- clazz.hierarchyAccept(false, false, false, true,
- new NamedMethodVisitor(referencedMethod.getName(referencedClass),
- referencedMethod.getDescriptor(referencedClass),
- this));
- }
- }
- }
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+
+ // Check the referenced method, if known.
+ refConstant.referencedMemberAccept(this);
}
@@ -199,14 +250,25 @@ implements InstructionVisitor,
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- hasSideEffects = ReadWriteFieldMarker.isRead(programField);
+ hasSideEffects =
+ (includeLocalFieldAccess || !programClass.equals(referencingClass)) &&
+ ((ReadWriteFieldMarker.isRead(programField) &&
+ ReadWriteFieldMarker.isWritten(programField)) ||
+ ((programField.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0) ||
+ (!programClass.equals(referencingClass) &&
+ !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- hasSideEffects = hasSideEffects ||
- SideEffectMethodMarker.hasSideEffects(programMethod);
+ // Note that side effects already include synchronization of some
+ // implementation of the method.
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(programMethod) &&
+ (SideEffectMethodMarker.hasSideEffects(programMethod) ||
+ (!programClass.equals(referencingClass) &&
+ !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
}
@@ -218,7 +280,28 @@ implements InstructionVisitor,
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
{
- hasSideEffects = hasSideEffects ||
- !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ }
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
+ new SideEffectMethodFilter(
+ new MemberToClassVisitor(
+ new ClassCollector(set))))));
+
+ return set;
}
}
diff --git a/src/proguard/optimize/info/SideEffectMethodFilter.java b/src/proguard/optimize/info/SideEffectMethodFilter.java
new file mode 100644
index 0000000..52e072a
--- /dev/null
+++ b/src/proguard/optimize/info/SideEffectMethodFilter.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Method objects that are marked as having side effects.
+ *
+ * @see SideEffectMethodMarker
+ *
+ * @author Eric Lafortune
+ */
+public class SideEffectMethodFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new SideEffectMethodFilter.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public SideEffectMethodFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField) {}
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java
index 25fda72..f7953c0 100644
--- a/src/proguard/optimize/info/SideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/SideEffectMethodMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -41,8 +41,9 @@ implements ClassPoolVisitor,
MemberVisitor,
AttributeVisitor
{
- // A reusable object for checking whether instructions have side effects.
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false);
+ // Reusable objects for checking whether instructions have side effects.
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false, true);
+ private final SideEffectInstructionChecker initializerSideEffectInstructionChecker = new SideEffectInstructionChecker(false, false);
// Parameters and values for visitor methods.
private int newSideEffectCount;
@@ -130,6 +131,11 @@ implements ClassPoolVisitor,
byte[] code = codeAttribute.code;
int length = codeAttribute.u4codeLength;
+ SideEffectInstructionChecker checker =
+ method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ?
+ initializerSideEffectInstructionChecker :
+ sideEffectInstructionChecker;
+
// Go over all instructions.
int offset = 0;
do
@@ -138,11 +144,11 @@ implements ClassPoolVisitor,
Instruction instruction = InstructionFactory.create(code, offset);
// Check if it may be throwing exceptions.
- if (sideEffectInstructionChecker.hasSideEffects(clazz,
- method,
- codeAttribute,
- offset,
- instruction))
+ if (checker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction))
{
return true;
}
diff --git a/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
new file mode 100644
index 0000000..36aa392
--- /dev/null
+++ b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are instantiated.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public StaticInitializerContainingClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
new file mode 100644
index 0000000..3a7e642
--- /dev/null
+++ b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor marks all classes that contain static initializers.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassMarker
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if (clazz.findMethod(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT) != null)
+ {
+ setStaticInitializer(clazz);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setContainsStaticInitializer();
+ }
+ }
+
+
+ public static boolean containsStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.containsStaticInitializer();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/SuperInvocationMarker.java b/src/proguard/optimize/info/SuperInvocationMarker.java
index 6f3d3bd..37b118a 100644
--- a/src/proguard/optimize/info/SuperInvocationMarker.java
+++ b/src/proguard/optimize/info/SuperInvocationMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/VariableUsageMarker.java b/src/proguard/optimize/info/VariableUsageMarker.java
index 660c4ba..b189ca9 100644
--- a/src/proguard/optimize/info/VariableUsageMarker.java
+++ b/src/proguard/optimize/info/VariableUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor marks the local variables that are used in the code
* attributes that it visits.
@@ -62,14 +64,13 @@ implements AttributeVisitor,
// Try to reuse the previous array.
if (variableUsed.length < maxLocals)
{
+ // Create a new array.
variableUsed = new boolean[maxLocals];
}
else
{
- for (int index = 0; index < maxLocals; index++)
- {
- variableUsed[index] = false;
- }
+ // Reset the array.
+ Arrays.fill(variableUsed, 0, maxLocals, false);
}
codeAttribute.instructionsAccept(clazz, method, this);
diff --git a/src/proguard/optimize/peephole/BranchTargetFinder.java b/src/proguard/optimize/peephole/BranchTargetFinder.java
index 8f650bb..79499f1 100644
--- a/src/proguard/optimize/peephole/BranchTargetFinder.java
+++ b/src/proguard/optimize/peephole/BranchTargetFinder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,6 +29,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor finds all instruction offsets, branch targets, and
* exception targets in the CodeAttribute objects that it visits.
@@ -45,12 +47,15 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = System.getProperty("btf") != null;
//*/
public static final int NONE = -2;
public static final int AT_METHOD_ENTRY = -1;
+ public static final int UNKNOWN = -1;
+ public static final int NO_SUBROUTINE = -2;
+
private static final short INSTRUCTION = 1 << 0;
private static final short BRANCH_ORIGIN = 1 << 1;
private static final short BRANCH_TARGET = 1 << 2;
@@ -70,9 +75,10 @@ implements AttributeVisitor,
private int[] creationOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int[] initializationOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int superInitializationOffset;
+ private boolean containsSubroutines;
+ private boolean repeat;
private int currentSubroutineStart;
- private int currentSubroutineEnd;
private int[] recentCreationOffsets = new int[MAXIMUM_CREATION_OFFSETS];
private int recentCreationOffsetIndex;
private boolean isInitializer;
@@ -189,7 +195,7 @@ implements AttributeVisitor,
*/
public boolean isSubroutine(int offset)
{
- return subroutineStarts[offset] != NONE;
+ return subroutineStarts[offset] >= 0;
}
@@ -289,6 +295,16 @@ implements AttributeVisitor,
}
+ /**
+ * Returns whether the method contains subroutines, in the CodeAttribute
+ * that was visited most recently.
+ */
+ public boolean containsSubroutines()
+ {
+ return containsSubroutines;
+ }
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -312,106 +328,98 @@ implements AttributeVisitor,
initializationOffsets = new int[codeLength];
// Reset the arrays.
- for (int index = 0; index < codeLength; index++)
- {
- subroutineStarts[index] = NONE;
- subroutineEnds[index] = NONE;
- creationOffsets[index] = NONE;
- initializationOffsets[index] = NONE;
- }
+ Arrays.fill(subroutineStarts, 0, codeLength, UNKNOWN);
+ Arrays.fill(subroutineEnds, 0, codeLength, UNKNOWN);
+ Arrays.fill(creationOffsets, 0, codeLength, NONE);
+ Arrays.fill(initializationOffsets, 0, codeLength, NONE);
}
else
{
// Reset the arrays.
- for (int index = 0; index < codeLength; index++)
- {
- instructionMarks[index] = 0;
- subroutineStarts[index] = NONE;
- subroutineEnds[index] = NONE;
- creationOffsets[index] = NONE;
- initializationOffsets[index] = NONE;
- }
+ Arrays.fill(instructionMarks, 0, codeLength, (short)0);
+ Arrays.fill(subroutineStarts, 0, codeLength, UNKNOWN);
+ Arrays.fill(subroutineEnds, 0, codeLength, UNKNOWN);
+ Arrays.fill(creationOffsets, 0, codeLength, NONE);
+ Arrays.fill(initializationOffsets, 0, codeLength, NONE);
instructionMarks[codeLength] = 0;
}
superInitializationOffset = NONE;
+ containsSubroutines = false;
- // We're assuming all subroutines are contiguous blocks of code.
- // We're not starting in a subroutine.
- currentSubroutineStart = NONE;
- currentSubroutineEnd = NONE;
+ // Iterate until all subroutines have been fully marked.
+ do
+ {
+ repeat = false;
+ currentSubroutineStart = NO_SUBROUTINE;
+ recentCreationOffsetIndex = 0;
- recentCreationOffsetIndex = 0;
+ // Initialize the stack of 'new' instruction offsets if this method
+ // is an instance initializer.
+ if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
+ {
+ recentCreationOffsets[recentCreationOffsetIndex++] = AT_METHOD_ENTRY;
+ }
- // Initialize the stack of 'new' instruction offsets if this method is
- // an instance initializer.
- if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
- {
- recentCreationOffsets[recentCreationOffsetIndex++] = AT_METHOD_ENTRY;
+ // Mark branch targets by going over all instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
}
+ while (repeat);
// The end of the code is a branch target sentinel.
instructionMarks[codeLength] = BRANCH_TARGET;
- // Mark branch targets by going over all instructions.
- codeAttribute.instructionsAccept(clazz, method, this);
-
// Mark branch targets in the exception table.
codeAttribute.exceptionsAccept(clazz, method, this);
- // Fill out any gaps in the subroutine starts and the subroutine ends
- // and subroutine returning flags, working backward.
-
- // We're not starting in a subroutine.
- int subroutineStart = NONE;
- int subroutineEnd = codeLength;
- boolean subroutineReturning = false;
-
- for (int index = codeLength - 1; index >= 0; index--)
+ if (containsSubroutines)
{
- if (isInstruction(index))
- {
- // Are we inside a previously marked subroutine?
- if (subroutineStarts[index] != NONE)
- {
- // Update the current subroutine start.
- subroutineStart = subroutineStarts[index];
- }
- else if (subroutineStart != NONE)
- {
- // Mark the subroutine start.
- subroutineStarts[index] = subroutineStart;
- }
+ // Set the subroutine returning flag and the subroutine end at each
+ // subroutine start.
+ int previousSubroutineStart = NO_SUBROUTINE;
- // Did we reach the start of the subroutine.
- if (isSubroutineStart(index))
- {
- // Stop marking it.
- subroutineStart = NONE;
- }
-
- // Are we inside a subroutine?
- if (isSubroutine(index))
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (isInstruction(offset))
{
- // Mark the subroutine end.
- subroutineEnds[index] = subroutineEnd;
+ int subroutineStart = subroutineStarts[offset];
- // Update or mark the subroutine returning flag.
- if (isSubroutineReturning(index))
+ if (subroutineStart >= 0 &&
+ isSubroutineReturning(offset))
{
- subroutineReturning = true;
+ instructionMarks[subroutineStart] |= SUBROUTINE_RETURNING;
}
- else if (subroutineReturning)
+
+ if (previousSubroutineStart >= 0)
{
- instructionMarks[index] |= SUBROUTINE_RETURNING;
+ subroutineEnds[previousSubroutineStart] = offset;
}
+
+ previousSubroutineStart = subroutineStart;
}
- else
+ }
+
+ if (previousSubroutineStart >= 0)
+ {
+ subroutineEnds[previousSubroutineStart] = codeLength;
+ }
+
+ // Set the subroutine returning flag and the subroutine end at each
+ // subroutine instruction, based on the marks at the subroutine
+ // start.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (isSubroutine(offset))
{
- // Update the subroutine end and returning flag.
- subroutineEnd = index;
- subroutineReturning = false;
+ int subroutineStart = subroutineStarts[offset];
+
+ if (isSubroutineReturning(subroutineStart))
+ {
+ instructionMarks[offset] |= SUBROUTINE_RETURNING;
+ }
+
+ subroutineEnds[offset] = subroutineEnds[subroutineStart];
}
}
}
@@ -451,7 +459,7 @@ implements AttributeVisitor,
// Mark the instruction.
instructionMarks[offset] |= INSTRUCTION;
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
byte opcode = simpleInstruction.opcode;
@@ -476,7 +484,7 @@ implements AttributeVisitor,
// Mark the instruction.
instructionMarks[offset] |= INSTRUCTION;
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
// Check if the instruction is a 'new' instruction.
@@ -517,15 +525,18 @@ implements AttributeVisitor,
// Mark the instruction.
instructionMarks[offset] |= INSTRUCTION;
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
if (variableInstruction.opcode == InstructionConstants.OP_RET)
{
+ // Mark the method.
+ containsSubroutines = true;
+
// Mark the branch origin.
markBranchOrigin(offset);
- // Mark the regular subroutine return.
+ // Mark the subroutine return at its return instruction.
instructionMarks[offset] |= SUBROUTINE_RETURNING;
// Mark the next instruction.
@@ -536,28 +547,39 @@ implements AttributeVisitor,
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
{
+ int branchOffset = branchInstruction.branchOffset;
+ int targetOffset = offset + branchOffset;
+
// Mark the branch origin.
markBranchOrigin(offset);
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
// Mark the branch target.
- markBranchTarget(offset, branchInstruction.branchOffset);
+ markBranchTarget(offset, branchOffset);
byte opcode = branchInstruction.opcode;
if (opcode == InstructionConstants.OP_JSR ||
opcode == InstructionConstants.OP_JSR_W)
{
+ // Mark the method.
+ containsSubroutines = true;
+
// Mark the subroutine invocation.
instructionMarks[offset] |= SUBROUTINE_INVOCATION;
- // Mark the subroutine start.
- int targetOffset = offset + branchInstruction.branchOffset;
- subroutineStarts[targetOffset] = targetOffset;
+ // Mark the new subroutine start.
+ markBranchSubroutineStart(offset, branchOffset, targetOffset);
}
- else if (opcode == InstructionConstants.OP_GOTO ||
- opcode == InstructionConstants.OP_GOTO_W)
+ else if (currentSubroutineStart != UNKNOWN)
+ {
+ // Mark the continued subroutine start.
+ markBranchSubroutineStart(offset, branchOffset, currentSubroutineStart);
+ }
+
+ if (opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W)
{
// Mark the next instruction.
markAfterBranchOrigin(offset + branchInstruction.length(offset));
@@ -570,15 +592,14 @@ implements AttributeVisitor,
// Mark the branch origin.
markBranchOrigin(offset);
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
// Mark the branch targets of the default jump offset.
- markBranchTarget(offset, switchInstruction.defaultOffset);
+ markBranch(offset, switchInstruction.defaultOffset);
// Mark the branch targets of the jump offsets.
- markBranchTargets(offset,
- switchInstruction.jumpOffsets);
+ markBranches(offset, switchInstruction.jumpOffsets);
// Mark the next instruction.
markAfterBranchOrigin(offset + switchInstruction.length(offset));
@@ -610,19 +631,32 @@ implements AttributeVisitor,
// Small utility methods.
/**
- * Marks the branch targets of the given jump offsets for the instruction
- * at the given offset.
+ * Marks the branch targets and their subroutine starts at the given
+ * offsets.
*/
- private void markBranchTargets(int offset, int[] jumpOffsets)
+ private void markBranches(int offset, int[] jumpOffsets)
{
for (int index = 0; index < jumpOffsets.length; index++)
{
- markBranchTarget(offset, jumpOffsets[index]);
+ markBranch(offset, jumpOffsets[index]);
}
}
/**
+ * Marks the branch target and its subroutine start at the given offset.
+ */
+ private void markBranch(int offset, int jumpOffset)
+ {
+ markBranchTarget(offset, jumpOffset);
+
+ if (currentSubroutineStart != UNKNOWN)
+ {
+ markBranchSubroutineStart(offset, jumpOffset, currentSubroutineStart);
+ }
+ }
+
+ /**
* Marks the branch origin at the given offset.
*/
private void markBranchOrigin(int offset)
@@ -639,18 +673,37 @@ implements AttributeVisitor,
int targetOffset = offset + jumpOffset;
instructionMarks[targetOffset] |= BRANCH_TARGET;
+ }
- // Are we inside a previously marked subroutine?
- if (isSubroutine(offset))
- {
- // Mark the subroutine start of the target.
- subroutineStarts[targetOffset] = currentSubroutineStart;
- // Update the current subroutine end.
- if (currentSubroutineEnd < targetOffset)
+ /**
+ * Marks the subroutine start at the given offset, if applicable.
+ */
+ private void markBranchSubroutineStart(int offset,
+ int jumpOffset,
+ int subroutineStart)
+ {
+ int targetOffset = offset + jumpOffset;
+
+ // Are we marking a subroutine and branching to an offset that hasn't
+ // been marked yet?
+ if (subroutineStarts[targetOffset] == UNKNOWN)
+ {
+ // Is it a backward branch?
+ if (jumpOffset < 0)
{
- currentSubroutineEnd = targetOffset;
+ // Remember the smallest subroutine start.
+ if (subroutineStart > targetOffset)
+ {
+ subroutineStart = targetOffset;
+ }
+
+ // We'll have to go over all instructions again.
+ repeat = true;
}
+
+ // Mark the subroutine start of the target.
+ subroutineStarts[targetOffset] = subroutineStart;
}
}
@@ -662,12 +715,8 @@ implements AttributeVisitor,
{
instructionMarks[nextOffset] |= AFTER_BRANCH;
- // Are we at the end of the current subroutine?
- if (currentSubroutineEnd <= nextOffset)
- {
- // Reset the subroutine start.
- currentSubroutineStart = NONE;
- }
+ // Stop marking a subroutine.
+ currentSubroutineStart = UNKNOWN;
}
@@ -677,15 +726,23 @@ implements AttributeVisitor,
private void checkSubroutine(int offset)
{
// Are we inside a previously marked subroutine?
- if (isSubroutine(offset))
+ if (subroutineStarts[offset] != UNKNOWN)
{
- // Update the current subroutine start.
+ // Start marking a subroutine.
currentSubroutineStart = subroutineStarts[offset];
}
- else
+
+ // Are we marking a subroutine?
+ else if (currentSubroutineStart != UNKNOWN)
{
- // Mark the subroutine start (or NONE).
+ // Mark the subroutine start.
subroutineStarts[offset] = currentSubroutineStart;
+
+ if (currentSubroutineStart >= 0)
+ {
+ // Mark the subroutine end at the subroutine start.
+ subroutineEnds[currentSubroutineStart] = offset;
+ }
}
}
}
diff --git a/src/proguard/optimize/peephole/ClassFinalizer.java b/src/proguard/optimize/peephole/ClassFinalizer.java
index b5e54f8..378f972 100644
--- a/src/proguard/optimize/peephole/ClassFinalizer.java
+++ b/src/proguard/optimize/peephole/ClassFinalizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/ClassMerger.java b/src/proguard/optimize/peephole/ClassMerger.java
index 1e1a950..aa40c75 100644
--- a/src/proguard/optimize/peephole/ClassMerger.java
+++ b/src/proguard/optimize/peephole/ClassMerger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,7 @@
package proguard.optimize.peephole;
import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeNameFilter;
import proguard.classfile.constant.visitor.*;
import proguard.classfile.editor.*;
import proguard.classfile.util.*;
@@ -50,7 +51,7 @@ implements ClassVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = System.getProperty("cm") != null;
//*/
@@ -59,6 +60,8 @@ implements ClassVisitor,
private final boolean mergeInterfacesAggressively;
private final ClassVisitor extraClassVisitor;
+ private final MemberVisitor fieldOptimizationInfoCopier = new FieldOptimizationInfoCopier();
+
/**
* Creates a new ClassMerger that will merge classes into the given target
@@ -151,7 +154,7 @@ implements ClassVisitor,
// infinite recursion.
(programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_ANNOTATTION) == 0 &&
- // Only merge classes if we can change the access permissioms, or
+ // Only merge classes if we can change the access permissions, or
// if they are in the same package, or
// if they are public and don't contain or invoke package visible
// class members.
@@ -196,12 +199,19 @@ implements ClassVisitor,
!(DotClassMarker.isDotClassed(programClass) &&
DotClassMarker.isDotClassed(targetClass)) &&
+ // The classes must not have clashing fields.
+ !haveAnyIdenticalFields(programClass, targetClass) &&
+
// The two classes must not introduce any unwanted fields.
!introducesUnwantedFields(programClass, targetClass) &&
!introducesUnwantedFields(targetClass, programClass) &&
- // The classes must not have clashing constructors.
- !haveAnyIdenticalInitializers(programClass, targetClass) &&
+ // The two classes must not shadow each others fields.
+ !shadowsAnyFields(programClass, targetClass) &&
+ !shadowsAnyFields(targetClass, programClass) &&
+
+ // The classes must not have clashing methods.
+ !haveAnyIdenticalMethods(programClass, targetClass) &&
// The classes must not introduce abstract methods, unless
// explicitly allowed.
@@ -226,6 +236,10 @@ implements ClassVisitor,
System.out.println(" Target subclasses ["+targetClass.subClasses+"]");
System.out.println(" Source superclass ["+programClass.getSuperClass().getName()+"]");
System.out.println(" Target superclass ["+targetClass.getSuperClass().getName()+"]");
+
+ //System.out.println("=== Before ===");
+ //programClass.accept(new ClassPrinter());
+ //targetClass.accept(new ClassPrinter());
}
// Combine the access flags.
@@ -235,11 +249,12 @@ implements ClassVisitor,
targetClass.u2accessFlags =
((targetAccessFlags &
sourceAccessFlags) &
- (ClassConstants.INTERNAL_ACC_INTERFACE |
+ (ClassConstants.INTERNAL_ACC_INTERFACE |
ClassConstants.INTERNAL_ACC_ABSTRACT)) |
((targetAccessFlags |
sourceAccessFlags) &
- (ClassConstants.INTERNAL_ACC_PUBLIC |
+ (ClassConstants.INTERNAL_ACC_PUBLIC |
+ ClassConstants.INTERNAL_ACC_SUPER |
ClassConstants.INTERNAL_ACC_ANNOTATTION |
ClassConstants.INTERNAL_ACC_ENUM));
@@ -260,14 +275,18 @@ implements ClassVisitor,
// Copy over the class members.
MemberAdder memberAdder =
- new MemberAdder(targetClass);
+ new MemberAdder(targetClass, fieldOptimizationInfoCopier);
programClass.fieldsAccept(memberAdder);
programClass.methodsAccept(memberAdder);
// Copy over the other attributes.
programClass.attributesAccept(
- new AttributeAdder(targetClass, true));
+ new AttributeNameFilter(new NotMatcher(new OrMatcher(new OrMatcher(
+ new FixedStringMatcher(ClassConstants.ATTR_SourceFile),
+ new FixedStringMatcher(ClassConstants.ATTR_InnerClasses)),
+ new FixedStringMatcher(ClassConstants.ATTR_EnclosingMethod))),
+ new AttributeAdder(targetClass, true)));
// Update the optimization information of the target class.
ClassOptimizationInfo info =
@@ -280,6 +299,12 @@ implements ClassVisitor,
// Remember to replace the inlined class by the target class.
setTargetClass(programClass, targetClass);
+ //if (DEBUG)
+ //{
+ // System.out.println("=== After ====");
+ // targetClass.accept(new ClassPrinter());
+ //}
+
// Visit the merged class, if required.
if (extraClassVisitor != null)
{
@@ -336,10 +361,8 @@ implements ClassVisitor,
// Visit all superclasses and interfaces, collecting the ones that have
// static initializers.
clazz.hierarchyAccept(true, true, true, false,
- new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
- ClassConstants.INTERNAL_METHOD_TYPE_INIT,
- new MemberToClassVisitor(
- new ClassCollector(set))));
+ new StaticInitializerContainingClassFilter(
+ new ClassCollector(set)));
return set;
}
@@ -368,9 +391,16 @@ implements ClassVisitor,
*/
private Set caughtSuperClasses(Clazz clazz)
{
+ // Don't bother if this isn't an exception at all.
+ if (!clazz.extends_(ClassConstants.INTERNAL_NAME_JAVA_LANG_THROWABLE))
+ {
+ return Collections.EMPTY_SET;
+ }
+
+ // Visit all superclasses, collecting the ones that are caught
+ // (plus java.lang.Object, in the current implementation).
Set set = new HashSet();
- // Visit all superclasses, collecting the ones that are caught.
clazz.hierarchyAccept(true, true, false, false,
new CaughtClassFilter(
new ClassCollector(set)));
@@ -380,38 +410,82 @@ implements ClassVisitor,
/**
+ * Returns whether the two given classes have class members with the same
+ * name and descriptor.
+ */
+ private boolean haveAnyIdenticalFields(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all fields, counting the with the same name and descriptor in
+ // the target class.
+ clazz.fieldsAccept(new SimilarMemberVisitor(targetClass, true, false, false, false,
+ counter));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
* Returns whether the given class would introduce any unwanted fields
* in the target class.
*/
private boolean introducesUnwantedFields(ProgramClass programClass,
ProgramClass targetClass)
{
- // The class must not have any fields, or it must not be instantiated,
- // without any other subclasses.
- return
- programClass.u2fieldsCount != 0 &&
- (InstantiationClassMarker.isInstantiated(targetClass) ||
- (targetClass.subClasses != null &&
- !isOnlySubClass(programClass, targetClass)));
+ // It's ok if the target class is never instantiated, without any other
+ // subclasses except for maybe the source class.
+ if (!InstantiationClassMarker.isInstantiated(targetClass) &&
+ (targetClass.subClasses == null ||
+ isOnlySubClass(programClass, targetClass)))
+ {
+ return false;
+ }
+
+ MemberCounter counter = new MemberCounter();
+
+ // Count all non-static fields in the the source class.
+ programClass.fieldsAccept(new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_STATIC,
+ counter));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
+ * Returns whether the given class or its subclasses shadow any fields in
+ * the given target class.
+ */
+ private boolean shadowsAnyFields(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all fields, counting the ones that are shadowing non-private
+ // fields in the class hierarchy of the target class.
+ clazz.hierarchyAccept(true, false, false, true,
+ new AllFieldVisitor(
+ new SimilarMemberVisitor(targetClass, true, true, true, false,
+ new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
+ counter))));
+
+ return counter.getCount() > 0;
}
/**
- * Returns whether the two given classes have initializers with the same
- * descriptors.
+ * Returns whether the two given classes have class members with the same
+ * name and descriptor.
*/
- private boolean haveAnyIdenticalInitializers(Clazz clazz, Clazz targetClass)
+ private boolean haveAnyIdenticalMethods(Clazz clazz, Clazz targetClass)
{
MemberCounter counter = new MemberCounter();
- // TODO: Currently checking shared methods, not just initializers.
- // TODO: Allow identical methods.
- // Visit all methods, counting the ones that are also present in the
- // target class.
- clazz.methodsAccept(//new MemberNameFilter(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT),
+ // Visit all non-abstract methods, counting the ones that are also
+ // present in the target class.
+ clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_ABSTRACT,
new SimilarMemberVisitor(targetClass, true, false, false, false,
new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_ABSTRACT,
- counter)));
+ counter))));
return counter.getCount() > 0;
}
@@ -538,4 +612,30 @@ implements ClassVisitor,
targetClass = clazz;
}
}
+
+
+ /**
+ * This MemberVisitor copies field optimization info from copied fields.
+ */
+ private static class FieldOptimizationInfoCopier
+ extends SimplifiedVisitor
+ implements MemberVisitor
+ {
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Copy the optimization info from the field that was just copied.
+ ProgramField copiedField = (ProgramField)programField.getVisitorInfo();
+ Object info = copiedField.getVisitorInfo();
+
+ programField.setVisitorInfo(info instanceof FieldOptimizationInfo ?
+ new FieldOptimizationInfo((FieldOptimizationInfo)info) :
+ info);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Linked methods share their optimization info.
+ }
+ }
} \ No newline at end of file
diff --git a/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java b/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
index 4833275..3bfd98c 100644
--- a/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
+++ b/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -50,7 +50,7 @@ implements AttributeVisitor,
private final InstructionVisitor extraInstructionVisitor;
private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(true, false);
/**
@@ -123,10 +123,7 @@ implements AttributeVisitor,
int deleteOffset = offset - delta;
if (branchTargetFinder.isInstruction(deleteOffset))
{
- codeAttributeEditor.replaceInstruction( deleteOffset, (Instruction)null);
- codeAttributeEditor.insertBeforeInstruction(deleteOffset, (Instruction)null);
- codeAttributeEditor.insertAfterInstruction( deleteOffset, (Instruction)null);
-
+ codeAttributeEditor.clearModifications(deleteOffset);
codeAttributeEditor.deleteInstruction(deleteOffset);
}
}
@@ -136,7 +133,7 @@ implements AttributeVisitor,
if (newBranchOffset != branchInstruction.length(offset))
{
Instruction newGotoInstruction =
- new BranchInstruction(opcode, newBranchOffset);
+ new BranchInstruction(opcode, newBranchOffset).shrink();
codeAttributeEditor.replaceInstruction(offset,
newGotoInstruction);
}
diff --git a/src/proguard/optimize/peephole/GotoGotoReplacer.java b/src/proguard/optimize/peephole/GotoGotoReplacer.java
index 7d7e66c..4a490a1 100644
--- a/src/proguard/optimize/peephole/GotoGotoReplacer.java
+++ b/src/proguard/optimize/peephole/GotoGotoReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -84,8 +84,9 @@ implements InstructionVisitor
int branchOffset = branchInstruction.branchOffset;
int targetOffset = offset + branchOffset;
- if (branchOffset != branchInstruction.length(offset) &&
- !codeAttributeEditor.isModified(offset) &&
+ if (branchOffset != 0 &&
+ branchOffset != branchInstruction.length(offset) &&
+ !codeAttributeEditor.isModified(offset) &&
!codeAttributeEditor.isModified(targetOffset))
{
Instruction targetInstruction =
diff --git a/src/proguard/optimize/peephole/GotoReturnReplacer.java b/src/proguard/optimize/peephole/GotoReturnReplacer.java
index 5c3eb77..b6deec8 100644
--- a/src/proguard/optimize/peephole/GotoReturnReplacer.java
+++ b/src/proguard/optimize/peephole/GotoReturnReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/HorizontalClassMerger.java b/src/proguard/optimize/peephole/HorizontalClassMerger.java
index a37b9a5..31d3d33 100644
--- a/src/proguard/optimize/peephole/HorizontalClassMerger.java
+++ b/src/proguard/optimize/peephole/HorizontalClassMerger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/InstructionSequenceConstants.java b/src/proguard/optimize/peephole/InstructionSequenceConstants.java
index b33204b..4ab9056 100644
--- a/src/proguard/optimize/peephole/InstructionSequenceConstants.java
+++ b/src/proguard/optimize/peephole/InstructionSequenceConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,81 +20,207 @@
*/
package proguard.optimize.peephole;
+import proguard.classfile.*;
import proguard.classfile.constant.*;
import proguard.classfile.instruction.*;
-import proguard.classfile.util.InstructionSequenceMatcher;
+import proguard.classfile.visitor.ClassPrinter;
/**
* This class contains a set of instruction sequences and their suggested
* replacements.
*
* @see InstructionSequencesReplacer
+ * @see InstructionSequenceReplacer
* @author Eric Lafortune
*/
public class InstructionSequenceConstants
{
- public static final int X = InstructionSequenceMatcher.X;
- public static final int Y = InstructionSequenceMatcher.Y;
- public static final int Z = InstructionSequenceMatcher.Z;
+ private static final int X = InstructionSequenceReplacer.X;
+ private static final int Y = InstructionSequenceReplacer.Y;
+ private static final int Z = InstructionSequenceReplacer.Z;
- public static final int A = InstructionSequenceMatcher.A;
- public static final int B = InstructionSequenceMatcher.B;
- public static final int C = InstructionSequenceMatcher.C;
- public static final int D = InstructionSequenceMatcher.D;
+ private static final int A = InstructionSequenceReplacer.A;
+ private static final int B = InstructionSequenceReplacer.B;
+ private static final int C = InstructionSequenceReplacer.C;
+ private static final int D = InstructionSequenceReplacer.D;
+ private static final int STRING_A_LENGTH = InstructionSequenceReplacer.STRING_A_LENGTH;
+ private static final int BOOLEAN_A_STRING = InstructionSequenceReplacer.BOOLEAN_A_STRING;
+ private static final int CHAR_A_STRING = InstructionSequenceReplacer.CHAR_A_STRING;
+ private static final int INT_A_STRING = InstructionSequenceReplacer.INT_A_STRING;
+ private static final int LONG_A_STRING = InstructionSequenceReplacer.LONG_A_STRING;
+ private static final int FLOAT_A_STRING = InstructionSequenceReplacer.FLOAT_A_STRING;
+ private static final int DOUBLE_A_STRING = InstructionSequenceReplacer.DOUBLE_A_STRING;
+ private static final int STRING_A_STRING = InstructionSequenceReplacer.STRING_A_STRING;
+ private static final int BOOLEAN_B_STRING = InstructionSequenceReplacer.BOOLEAN_B_STRING;
+ private static final int CHAR_B_STRING = InstructionSequenceReplacer.CHAR_B_STRING;
+ private static final int INT_B_STRING = InstructionSequenceReplacer.INT_B_STRING;
+ private static final int LONG_B_STRING = InstructionSequenceReplacer.LONG_B_STRING;
+ private static final int FLOAT_B_STRING = InstructionSequenceReplacer.FLOAT_B_STRING;
+ private static final int DOUBLE_B_STRING = InstructionSequenceReplacer.DOUBLE_B_STRING;
+ private static final int STRING_B_STRING = InstructionSequenceReplacer.STRING_B_STRING;
- private static final int I_32768 = 0;
- private static final int I_65536 = 1;
- private static final int I_16777216 = 2;
+ private static final int I_32768 = 0;
+ private static final int I_65536 = 1;
+ private static final int I_16777216 = 2;
// private static final int I_0x000000ff
- private static final int I_0x0000ff00 = 3;
- private static final int I_0x00ff0000 = 4;
- private static final int I_0xff000000 = 5;
- private static final int I_0x0000ffff = 6;
- private static final int I_0xffff0000 = 7;
+ private static final int I_0x0000ff00 = 3;
+ private static final int I_0x00ff0000 = 4;
+ private static final int I_0xff000000 = 5;
+ private static final int I_0x0000ffff = 6;
+ private static final int I_0xffff0000 = 7;
- private static final int L_M1 = 8;
- private static final int L_2 = 9;
- private static final int L_4 = 10;
- private static final int L_8 = 11;
- private static final int L_16 = 12;
- private static final int L_32 = 13;
- private static final int L_64 = 14;
- private static final int L_128 = 15;
- private static final int L_256 = 16;
- private static final int L_512 = 17;
- private static final int L_1024 = 18;
- private static final int L_2048 = 19;
- private static final int L_4096 = 20;
- private static final int L_8192 = 21;
- private static final int L_16384 = 22;
- private static final int L_32768 = 23;
- private static final int L_65536 = 24;
- private static final int L_16777216 = 25;
- private static final int L_4294967296 = 26;
+ private static final int L_M1 = 8;
+ private static final int L_2 = 9;
+ private static final int L_4 = 10;
+ private static final int L_8 = 11;
+ private static final int L_16 = 12;
+ private static final int L_32 = 13;
+ private static final int L_64 = 14;
+ private static final int L_128 = 15;
+ private static final int L_256 = 16;
+ private static final int L_512 = 17;
+ private static final int L_1024 = 18;
+ private static final int L_2048 = 19;
+ private static final int L_4096 = 20;
+ private static final int L_8192 = 21;
+ private static final int L_16384 = 22;
+ private static final int L_32768 = 23;
+ private static final int L_65536 = 24;
+ private static final int L_16777216 = 25;
+ private static final int L_4294967296 = 26;
- private static final int L_0x00000000ffffffff = 27;
- private static final int L_0xffffffff00000000 = 28;
+ private static final int L_0x00000000ffffffff = 27;
+ private static final int L_0xffffffff00000000 = 28;
- private static final int F_M1 = 29;
+ private static final int F_M1 = 29;
- private static final int D_M1 = 30;
+ private static final int D_M1 = 30;
- private static final int FIELD_I = 31;
- private static final int FIELD_L = 32;
- private static final int FIELD_F = 33;
- private static final int FIELD_D = 34;
+ private static final int STRING_EMPTY = 31;
- private static final int NAME_AND_TYPE_I = 35;
- private static final int NAME_AND_TYPE_L = 36;
- private static final int NAME_AND_TYPE_F = 37;
- private static final int NAME_AND_TYPE_D = 38;
+ private static final int FIELD_I = 32; // Implicitly uses X and Y.
+ private static final int FIELD_L = 33; // Implicitly uses X and Y.
+ private static final int FIELD_F = 34; // Implicitly uses X and Y.
+ private static final int FIELD_D = 35; // Implicitly uses X and Y.
- private static final int TYPE_I = 39;
- private static final int TYPE_L = 40;
- private static final int TYPE_F = 41;
- private static final int TYPE_D = 42;
+ private static final int METHOD_STRING_EQUALS = 36;
+ private static final int METHOD_STRING_LENGTH = 37;
+ private static final int METHOD_STRING_VALUEOF_Z = 38;
+ private static final int METHOD_STRING_VALUEOF_C = 39;
+ private static final int METHOD_STRING_VALUEOF_I = 40;
+ private static final int METHOD_STRING_VALUEOF_J = 41;
+ private static final int METHOD_STRING_VALUEOF_F = 42;
+ private static final int METHOD_STRING_VALUEOF_D = 43;
+ private static final int METHOD_STRING_VALUEOF_OBJECT = 44;
+ private static final int METHOD_STRINGBUFFER_INIT = 45;
+ private static final int METHOD_STRINGBUFFER_INIT_STRING = 46;
+ private static final int METHOD_STRINGBUFFER_APPEND_Z = 47;
+ private static final int METHOD_STRINGBUFFER_APPEND_C = 48;
+ private static final int METHOD_STRINGBUFFER_APPEND_I = 49;
+ private static final int METHOD_STRINGBUFFER_APPEND_J = 50;
+ private static final int METHOD_STRINGBUFFER_APPEND_F = 51;
+ private static final int METHOD_STRINGBUFFER_APPEND_D = 52;
+ private static final int METHOD_STRINGBUFFER_APPEND_STRING = 53;
+ private static final int METHOD_STRINGBUFFER_APPEND_OBJECT = 54;
+ private static final int METHOD_STRINGBUFFER_LENGTH = 55;
+ private static final int METHOD_STRINGBUFFER_TOSTRING = 56;
+ private static final int METHOD_STRINGBUILDER_INIT = 57;
+ private static final int METHOD_STRINGBUILDER_INIT_STRING = 58;
+ private static final int METHOD_STRINGBUILDER_APPEND_Z = 59;
+ private static final int METHOD_STRINGBUILDER_APPEND_C = 60;
+ private static final int METHOD_STRINGBUILDER_APPEND_I = 61;
+ private static final int METHOD_STRINGBUILDER_APPEND_J = 62;
+ private static final int METHOD_STRINGBUILDER_APPEND_F = 63;
+ private static final int METHOD_STRINGBUILDER_APPEND_D = 64;
+ private static final int METHOD_STRINGBUILDER_APPEND_STRING = 65;
+ private static final int METHOD_STRINGBUILDER_APPEND_OBJECT = 66;
+ private static final int METHOD_STRINGBUILDER_LENGTH = 67;
+ private static final int METHOD_STRINGBUILDER_TOSTRING = 68;
+
+ private static final int CLASS_STRING = 69;
+ private static final int CLASS_STRINGBUFFER = 70;
+ private static final int CLASS_STRINGBUILDER = 71;
+
+ private static final int NAME_AND_TYPE_I = 72; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_L = 73; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_F = 74; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_D = 75; // Implicitly uses Y.
+
+ private static final int NAME_AND_TYPE_EQUALS = 76;
+ private static final int NAME_AND_TYPE_LENGTH = 77;
+ private static final int NAME_AND_TYPE_VALUEOF_Z = 78;
+ private static final int NAME_AND_TYPE_VALUEOF_C = 79;
+ private static final int NAME_AND_TYPE_VALUEOF_I = 80;
+ private static final int NAME_AND_TYPE_VALUEOF_J = 81;
+ private static final int NAME_AND_TYPE_VALUEOF_F = 82;
+ private static final int NAME_AND_TYPE_VALUEOF_D = 83;
+ private static final int NAME_AND_TYPE_VALUEOF_OBJECT = 84;
+ private static final int NAME_AND_TYPE_INIT = 85;
+ private static final int NAME_AND_TYPE_INIT_STRING = 86;
+ private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUFFER = 87;
+ private static final int NAME_AND_TYPE_APPEND_C_STRINGBUFFER = 88;
+ private static final int NAME_AND_TYPE_APPEND_I_STRINGBUFFER = 89;
+ private static final int NAME_AND_TYPE_APPEND_J_STRINGBUFFER = 90;
+ private static final int NAME_AND_TYPE_APPEND_F_STRINGBUFFER = 91;
+ private static final int NAME_AND_TYPE_APPEND_D_STRINGBUFFER = 92;
+ private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUFFER = 93;
+ private static final int NAME_AND_TYPE_APPEND_OBJECT_STRINGBUFFER = 94;
+ private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUILDER = 95;
+ private static final int NAME_AND_TYPE_APPEND_C_STRINGBUILDER = 96;
+ private static final int NAME_AND_TYPE_APPEND_I_STRINGBUILDER = 97;
+ private static final int NAME_AND_TYPE_APPEND_J_STRINGBUILDER = 98;
+ private static final int NAME_AND_TYPE_APPEND_F_STRINGBUILDER = 99;
+ private static final int NAME_AND_TYPE_APPEND_D_STRINGBUILDER = 100;
+ private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUILDER = 101;
+ private static final int NAME_AND_TYPE_APPEND_OBJECT_STRINGBUILDER = 102;
+ private static final int NAME_AND_TYPE_TOSTRING = 103;
+
+ private static final int UTF8_EMPTY = 104;
+ private static final int UTF8_I = 105;
+ private static final int UTF8_L = 106;
+ private static final int UTF8_F = 107;
+ private static final int UTF8_D = 108;
+ private static final int UTF8_STRING = 109;
+ private static final int UTF8_STRINGBUFFER = 110;
+ private static final int UTF8_STRINGBUILDER = 111;
+ private static final int UTF8_EQUALS = 112;
+ private static final int UTF8_OBJECT_Z = 113;
+ private static final int UTF8_LENGTH = 114;
+ private static final int UTF8__I = 115;
+ private static final int UTF8_VALUEOF = 116;
+ private static final int UTF8_Z_STRING = 117;
+ private static final int UTF8_C_STRING = 118;
+ private static final int UTF8_I_STRING = 119;
+ private static final int UTF8_J_STRING = 120;
+ private static final int UTF8_F_STRING = 121;
+ private static final int UTF8_D_STRING = 122;
+ private static final int UTF8_OBJECT_STRING = 123;
+ private static final int UTF8_INIT = 124;
+ private static final int UTF8__VOID = 125;
+ private static final int UTF8_STRING_VOID = 126;
+ private static final int UTF8_TOSTRING = 127;
+ private static final int UTF8__STRING = 128;
+ private static final int UTF8_APPEND = 129;
+ private static final int UTF8_Z_STRINGBUFFER = 130;
+ private static final int UTF8_C_STRINGBUFFER = 131;
+ private static final int UTF8_I_STRINGBUFFER = 132;
+ private static final int UTF8_J_STRINGBUFFER = 133;
+ private static final int UTF8_F_STRINGBUFFER = 134;
+ private static final int UTF8_D_STRINGBUFFER = 135;
+ private static final int UTF8_STRING_STRINGBUFFER = 136;
+ private static final int UTF8_OBJECT_STRINGBUFFER = 137;
+ private static final int UTF8_Z_STRINGBUILDER = 138;
+ private static final int UTF8_C_STRINGBUILDER = 139;
+ private static final int UTF8_I_STRINGBUILDER = 140;
+ private static final int UTF8_J_STRINGBUILDER = 141;
+ private static final int UTF8_F_STRINGBUILDER = 142;
+ private static final int UTF8_D_STRINGBUILDER = 143;
+ private static final int UTF8_STRING_STRINGBUILDER = 144;
+ private static final int UTF8_OBJECT_STRINGBUILDER = 145;
+
+ private static final int SENTINEL = 146;
public static final Constant[] CONSTANTS = new Constant[]
@@ -136,23 +262,128 @@ public class InstructionSequenceConstants
new DoubleConstant(-1d),
+ new StringConstant(UTF8_EMPTY, null, null),
+
new FieldrefConstant(X, NAME_AND_TYPE_I, null, null),
new FieldrefConstant(X, NAME_AND_TYPE_L, null, null),
new FieldrefConstant(X, NAME_AND_TYPE_F, null, null),
new FieldrefConstant(X, NAME_AND_TYPE_D, null, null),
- new NameAndTypeConstant(Y, TYPE_I),
- new NameAndTypeConstant(Y, TYPE_L),
- new NameAndTypeConstant(Y, TYPE_F),
- new NameAndTypeConstant(Y, TYPE_D),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_EQUALS, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_Z, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_C, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_I, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_J, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_F, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_D, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_OBJECT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_INIT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_INIT_STRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_Z_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_C_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_I_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_J_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_F_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_D_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_STRING_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_OBJECT_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_TOSTRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_INIT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_INIT_STRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_Z_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_C_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_I_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_J_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_F_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_D_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_STRING_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_OBJECT_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_TOSTRING, null, null),
+
+ new ClassConstant(UTF8_STRING, null),
+ new ClassConstant(UTF8_STRINGBUFFER, null),
+ new ClassConstant(UTF8_STRINGBUILDER, null),
+ new NameAndTypeConstant(Y, UTF8_I),
+ new NameAndTypeConstant(Y, UTF8_L),
+ new NameAndTypeConstant(Y, UTF8_F),
+ new NameAndTypeConstant(Y, UTF8_D),
+ new NameAndTypeConstant(UTF8_EQUALS, UTF8_OBJECT_Z),
+ new NameAndTypeConstant(UTF8_LENGTH, UTF8__I),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_Z_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_C_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_I_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_J_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_F_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_D_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_OBJECT_STRING),
+ new NameAndTypeConstant(UTF8_INIT, UTF8__VOID),
+ new NameAndTypeConstant(UTF8_INIT, UTF8_STRING_VOID),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_Z_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_C_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_I_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_J_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_F_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_D_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_STRING_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_OBJECT_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_Z_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_C_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_I_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_J_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_F_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_D_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_STRING_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_OBJECT_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_TOSTRING, UTF8__STRING),
+
+ new Utf8Constant(""),
new Utf8Constant("I"),
new Utf8Constant("J"),
new Utf8Constant("F"),
new Utf8Constant("D"),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_EQUALS),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_EQUALS),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_LENGTH),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_LENGTH),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_VALUEOF),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_BOOLEAN),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_CHAR),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_INT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_LONG),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_FLOAT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_DOUBLE),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_OBJECT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_INIT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_INIT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_STRING_VOID),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_TOSTRING),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_TOSTRING),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_APPEND),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CHAR_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_INT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_LONG_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_FLOAT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_STRING_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_OBJECT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CHAR_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_INT_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_LONG_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_FLOAT_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_STRING_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_OBJECT_STRING_BUILDER),
};
-
public static final Instruction[][][] VARIABLE = new Instruction[][][]
{
{ // nop = nothing
@@ -237,7 +468,7 @@ public class InstructionSequenceConstants
{ // a = a = nothing
{
new VariableInstruction(InstructionConstants.OP_ALOAD, X),
- new SimpleInstruction(InstructionConstants.OP_POP),
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
},{
// Nothing.
},
@@ -382,12 +613,12 @@ public class InstructionSequenceConstants
},
{ // c * i = i * c
{
- new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
new VariableInstruction(InstructionConstants.OP_ILOAD, X),
new SimpleInstruction(InstructionConstants.OP_IMUL),
},{
new VariableInstruction(InstructionConstants.OP_ILOAD, X),
- new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
new SimpleInstruction(InstructionConstants.OP_IMUL),
},
},
@@ -548,7 +779,7 @@ public class InstructionSequenceConstants
{ // i = i + c = i += c
{
new VariableInstruction(InstructionConstants.OP_ILOAD, X),
- new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
new SimpleInstruction(InstructionConstants.OP_IADD),
new VariableInstruction(InstructionConstants.OP_ISTORE, X),
},{
@@ -651,22 +882,23 @@ public class InstructionSequenceConstants
// Nothing.
},
},
- { // ... + 0f = ...
- {
- new SimpleInstruction(InstructionConstants.OP_FCONST_0),
- new SimpleInstruction(InstructionConstants.OP_FADD),
- },{
- // Nothing.
- },
- },
- { // ... + 0d = ...
- {
- new SimpleInstruction(InstructionConstants.OP_DCONST_0),
- new SimpleInstruction(InstructionConstants.OP_DADD),
- },{
- // Nothing.
- },
- },
+ // Not valid for -0.0.
+// { // ... + 0f = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_FADD),
+// },{
+// // Nothing.
+// },
+// },
+// { // ... + 0d = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_DADD),
+// },{
+// // Nothing.
+// },
+// },
{ // ... - 0 = ...
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -1072,7 +1304,8 @@ public class InstructionSequenceConstants
new SimpleInstruction(InstructionConstants.OP_FNEG),
},
},
-// { // ... * 0f = 0f (or NaN)
+ // Not valid for -0.0 and for NaN.
+// { // ... * 0f = 0f
// {
// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
// new SimpleInstruction(InstructionConstants.OP_FMUL),
@@ -1097,7 +1330,8 @@ public class InstructionSequenceConstants
new SimpleInstruction(InstructionConstants.OP_DNEG),
},
},
-// { // ... * 0d = 0d (or NaN)
+ // Not valid for -0.0 and for NaN.
+// { // ... * 0d = 0d
// {
// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
// new SimpleInstruction(InstructionConstants.OP_DMUL),
@@ -1504,6 +1738,7 @@ public class InstructionSequenceConstants
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
},
},
+ // Not valid for negative values.
// { // ... % 2 = ... & 0x1
// {
// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
@@ -3348,4 +3583,1508 @@ public class InstructionSequenceConstants
// },
// }
};
-} \ No newline at end of file
+
+ public static final Instruction[][][] STRING = new Instruction[][][]
+ {
+ { // "...".equals("...") = true
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRING_EQUALS),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ },
+ },
+ { // "...".length() = ...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRING_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // String.valueOf(Z) = "....
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ },
+ },
+ { // String.valueOf(C) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ },
+ },
+ { // String.valueOf(Cc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ },
+ },
+ { // String.valueOf(I) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ },
+ },
+ { // String.valueOf(Ic) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ },
+ },
+ { // String.valueOf(J) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ },
+ },
+ { // String.valueOf(Jc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ },
+ },
+ { // String.valueOf(F) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ },
+ },
+ { // String.valueOf(Fc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ },
+ },
+ { // String.valueOf(D) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ },
+ },
+ { // String.valueOf(Dc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ },
+ },
+
+ { // new StringBuffer("...").toString() = "..." (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ },
+ },
+ { // new StringBuffer(string).toString() = string (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuffer("...").length() = length
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // new StringBuffer() (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...") (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer()/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...")/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(z)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(c)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(i)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(l)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(f)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(d)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(s)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // StringBuffer#toString()/pop = pop
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // StringBuffer#append("") = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_EMPTY),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer().append(Z) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(C) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Cc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(I) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Ic) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(J) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Jc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(F) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Fc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(D) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Dc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append("...") = new StringBuffer("...")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Z) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(C) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Cc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(I) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Ic) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(J) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Jc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(F) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Fc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(D) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Dc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append("...") = new StringBuffer("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Z) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(C) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Cc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(I) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Ic) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(J) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Jc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(F) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Fc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(D) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Dc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append("...") = StringBuffer#append("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // new StringBuffer().append(z).toString() = String.valueOf(z)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },
+ },
+ { // new StringBuffer().append(c).toString() = String.valueOf(c)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },
+ },
+ { // new StringBuffer().append(i).toString() = String.valueOf(i)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },
+ },
+ { // new StringBuffer().append(j).toString() = String.valueOf(j)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },
+ },
+ { // new StringBuffer().append(f).toString() = String.valueOf(f)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },
+ },
+ { // new StringBuffer().append(d).toString() = String.valueOf(d)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },
+ },
+ { // new StringBuffer().append(string).toString() = string
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuffer().append(object).toString() = String.valueOf(object)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_OBJECT),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_OBJECT),
+ },
+ },
+
+ { // new StringBuilder("...").toString() = "..." (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ },
+ },
+ { // new StringBuilder(string).toString() = string (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuilder("...").length() = length
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // new StringBuilder() (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...") (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder()/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...")/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(z)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(c)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(i)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(l)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(f)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(d)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(s)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // StringBuilder#toString()/pop = pop
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // StringBuilder#append("") = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_EMPTY),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder().append(Z) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(C) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Cc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(I) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Ic) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(J) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Jc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(F) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Fc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(D) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Dc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append("...") = new StringBuilder("...")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Z) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(C) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Cc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(I) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Ic) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(J) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Jc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(F) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Fc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(D) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Dc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append("...") = new StringBuilder("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Z) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(C) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Cc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(I) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Ic) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(J) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Jc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(F) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Fc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(D) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Dc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append("...") = StringBuilder#append("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // new StringBuilder().append(z).toString() = String.valueOf(z)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },
+ },
+ { // new StringBuilder().append(c).toString() = String.valueOf(c)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },
+ },
+ { // new StringBuilder().append(i).toString() = String.valueOf(i)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },
+ },
+ { // new StringBuilder().append(j).toString() = String.valueOf(j)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },
+ },
+ { // new StringBuilder().append(f).toString() = String.valueOf(f)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },
+ },
+ { // new StringBuilder().append(d).toString() = String.valueOf(d)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },
+ },
+ { // new StringBuilder().append(string).toString() = string
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuilder().append(object).toString() = String.valueOf(object)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_OBJECT),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_OBJECT),
+ },
+ },
+ };
+
+
+ /**
+ * Prints out the constants and the instruction sequences.
+ */
+ public static void main(String[] args)
+ {
+ ProgramClass clazz = new ProgramClass();
+ clazz.constantPool = CONSTANTS;
+
+ ClassPrinter printer = new ClassPrinter();
+
+ for (int index = 0; index < CONSTANTS.length; index++)
+ {
+ System.out.print("["+index+"] ");
+ try
+ {
+ CONSTANTS[index].accept(clazz, printer);
+ }
+ catch (Exception e)
+ {
+ System.out.println("("+e.getClass().getName()+")");
+ }
+ }
+
+ if (CONSTANTS.length != SENTINEL)
+ {
+ throw new IllegalStateException("Constants length ["+CONSTANTS.length+"] different from number of constant names ["+SENTINEL+"]");
+ }
+
+ Instruction[][][] sequences = STRING;
+
+ for (int sequence = 0; sequence < sequences.length; sequence++)
+ {
+ System.out.println();
+ Instruction[] instructions = sequences[sequence][0];
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+ try
+ {
+ instruction.accept(clazz, null, null, index, new ClassPrinter());
+ }
+ catch (Exception e) {}
+ }
+
+ System.out.println("=>");
+ instructions = sequences[sequence][1];
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+ try
+ {
+ instruction.accept(clazz, null, null, index, new ClassPrinter());
+ }
+ catch (Exception e) {}
+ }
+ }
+ }
+}
diff --git a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
index bce06e2..7ec1a95 100644
--- a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
+++ b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,9 +22,9 @@ package proguard.optimize.peephole;
import proguard.classfile.*;
import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
-import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.editor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
@@ -42,10 +42,48 @@ extends SimplifiedVisitor
implements InstructionVisitor,
ConstantVisitor
{
+ //*
private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = true;
+ //*/
+
+ public static final int X = InstructionSequenceMatcher.X;
+ public static final int Y = InstructionSequenceMatcher.Y;
+ public static final int Z = InstructionSequenceMatcher.Z;
+
+ public static final int A = InstructionSequenceMatcher.A;
+ public static final int B = InstructionSequenceMatcher.B;
+ public static final int C = InstructionSequenceMatcher.C;
+ public static final int D = InstructionSequenceMatcher.D;
+
+ private static final int BOOLEAN_STRING = 0x1;
+ private static final int CHAR_STRING = 0x2;
+ private static final int INT_STRING = 0x3;
+ private static final int LONG_STRING = 0x4;
+ private static final int FLOAT_STRING = 0x5;
+ private static final int DOUBLE_STRING = 0x6;
+ private static final int STRING_STRING = 0x7;
+
+ public static final int STRING_A_LENGTH = 0x20000000;
+ public static final int BOOLEAN_A_STRING = 0x20000001;
+ public static final int CHAR_A_STRING = 0x20000002;
+ public static final int INT_A_STRING = 0x20000003;
+ public static final int LONG_A_STRING = 0x20000004;
+ public static final int FLOAT_A_STRING = 0x20000005;
+ public static final int DOUBLE_A_STRING = 0x20000006;
+ public static final int STRING_A_STRING = 0x20000007;
+ public static final int BOOLEAN_B_STRING = 0x20000010;
+ public static final int CHAR_B_STRING = 0x20000020;
+ public static final int INT_B_STRING = 0x20000030;
+ public static final int LONG_B_STRING = 0x20000040;
+ public static final int FLOAT_B_STRING = 0x20000050;
+ public static final int DOUBLE_B_STRING = 0x20000060;
+ public static final int STRING_B_STRING = 0x20000070;
private final InstructionSequenceMatcher instructionSequenceMatcher;
+ private final Constant[] patternConstants;
private final Instruction[] replacementInstructions;
private final BranchTargetFinder branchTargetFinder;
private final CodeAttributeEditor codeAttributeEditor;
@@ -101,6 +139,7 @@ implements InstructionVisitor,
InstructionVisitor extraInstructionVisitor)
{
this.instructionSequenceMatcher = new InstructionSequenceMatcher(patternConstants, patternInstructions);
+ this.patternConstants = patternConstants;
this.replacementInstructions = replacementInstructions;
this.branchTargetFinder = branchTargetFinder;
this.codeAttributeEditor = codeAttributeEditor;
@@ -140,7 +179,7 @@ implements InstructionVisitor,
for (int index = 0; index < replacementInstructions.length; index++)
{
int matchedOffset = instructionSequenceMatcher.matchedInstructionOffset(index);
- System.out.println(" "+replacementInstructionFactory.create(index).shrink().toString(matchedOffset));
+ System.out.println(" "+replacementInstructionFactory.create(clazz, index).shrink().toString(matchedOffset));
}
}
@@ -148,7 +187,7 @@ implements InstructionVisitor,
for (int index = 0; index < replacementInstructions.length; index++)
{
codeAttributeEditor.replaceInstruction(instructionSequenceMatcher.matchedInstructionOffset(index),
- replacementInstructionFactory.create(index).shrink());
+ replacementInstructionFactory.create(clazz, index));
}
// Delete any remaining instructions in the from sequence.
@@ -204,17 +243,17 @@ implements InstructionVisitor,
* Creates the replacement instruction for the given index in the
* instruction sequence.
*/
- public Instruction create(int index)
+ public Instruction create(Clazz clazz, int index)
{
// Create the instruction.
- replacementInstructions[index].accept(null,
+ replacementInstructions[index].accept(clazz,
null,
null,
instructionSequenceMatcher.matchedInstructionOffset(index),
this);
// Return it.
- return replacementInstruction.shrink();
+ return replacementInstruction;
}
@@ -224,7 +263,7 @@ implements InstructionVisitor,
{
replacementInstruction =
new SimpleInstruction(simpleInstruction.opcode,
- instructionSequenceMatcher.matchedArgument(simpleInstruction.constant));
+ matchedArgument(clazz, simpleInstruction.constant));
}
@@ -241,7 +280,8 @@ implements InstructionVisitor,
{
replacementInstruction =
new ConstantInstruction(constantInstruction.opcode,
- instructionSequenceMatcher.matchedConstantIndex(constantInstruction.constantIndex),
+ matchedConstantIndex((ProgramClass)clazz,
+ constantInstruction.constantIndex),
instructionSequenceMatcher.matchedArgument(constantInstruction.constant));
}
@@ -250,7 +290,8 @@ implements InstructionVisitor,
{
replacementInstruction =
new BranchInstruction(branchInstruction.opcode,
- instructionSequenceMatcher.matchedBranchOffset(offset, branchInstruction.branchOffset));
+ instructionSequenceMatcher.matchedBranchOffset(offset,
+ branchInstruction.branchOffset));
}
@@ -261,7 +302,8 @@ implements InstructionVisitor,
instructionSequenceMatcher.matchedBranchOffset(offset, tableSwitchInstruction.defaultOffset),
instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.lowCase),
instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.highCase),
- instructionSequenceMatcher.matchedJumpOffsets(offset, tableSwitchInstruction.jumpOffsets));
+ instructionSequenceMatcher.matchedJumpOffsets(offset,
+ tableSwitchInstruction.jumpOffsets));
}
@@ -274,5 +316,105 @@ implements InstructionVisitor,
instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases),
instructionSequenceMatcher.matchedJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets));
}
+
+
+ /**
+ * Returns the matched argument for the given pattern argument.
+ */
+ private int matchedArgument(Clazz clazz, int argument)
+ {
+ // Special case: do we have to compute the string length?
+ if (argument == STRING_A_LENGTH)
+ {
+ // Return the string length.
+ return clazz.getStringString(instructionSequenceMatcher.matchedArgument(A)).length();
+ }
+
+ // Otherwise, just return the matched argument.
+ return instructionSequenceMatcher.matchedArgument(argument);
+ }
+
+
+ /**
+ * Returns the matched or newly created constant index for the given
+ * pattern constant index.
+ */
+ private int matchedConstantIndex(ProgramClass programClass, int constantIndex)
+ {
+ // Special case: do we have to create a concatenated string?
+ if (constantIndex >= BOOLEAN_A_STRING &&
+ constantIndex <= (STRING_A_STRING | STRING_B_STRING))
+ {
+ // Create a new string constant and return its index.
+ return new ConstantPoolEditor(programClass).addStringConstant(
+ argumentAsString(programClass, constantIndex & 0xf, A) +
+ argumentAsString(programClass, (constantIndex >>> 4) & 0xf, B),
+ null,
+ null);
+ }
+
+ int matchedConstantIndex =
+ instructionSequenceMatcher.matchedConstantIndex(constantIndex);
+
+ // Do we have a matched constant index?
+ if (matchedConstantIndex > 0)
+ {
+ // Return its index.
+ return matchedConstantIndex;
+ }
+
+ // Otherwise, we still have to create a new constant.
+ // This currently only works for constants without any wildcards.
+ ProgramClass dummyClass = new ProgramClass();
+ dummyClass.constantPool = patternConstants;
+
+ return new ConstantAdder(programClass).addConstant(dummyClass, constantIndex);
+ }
+
+
+ private String argumentAsString(ProgramClass programClass,
+ int valueType,
+ int argument)
+ {
+ switch (valueType)
+ {
+ case BOOLEAN_STRING:
+ return Boolean.toString((instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument)) != 0);
+
+ case CHAR_STRING:
+ return Character.toString((char)(instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument)));
+
+ case INT_STRING:
+ return Integer.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case LONG_STRING:
+ return Long.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((LongConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case FLOAT_STRING:
+ return Float.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((FloatConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case DOUBLE_STRING:
+ return Double.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((DoubleConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case STRING_STRING:
+ return
+ programClass.getStringString(instructionSequenceMatcher.matchedConstantIndex(argument));
+
+ default:
+ return "";
+ }
+ }
}
}
diff --git a/src/proguard/optimize/peephole/InstructionSequencesReplacer.java b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
index f12b51a..22fb6cd 100644
--- a/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
+++ b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MemberPrivatizer.java b/src/proguard/optimize/peephole/MemberPrivatizer.java
index 55b2f31..f57281c 100644
--- a/src/proguard/optimize/peephole/MemberPrivatizer.java
+++ b/src/proguard/optimize/peephole/MemberPrivatizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MethodFinalizer.java b/src/proguard/optimize/peephole/MethodFinalizer.java
index af1811b..89174ac 100644
--- a/src/proguard/optimize/peephole/MethodFinalizer.java
+++ b/src/proguard/optimize/peephole/MethodFinalizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MethodInliner.java b/src/proguard/optimize/peephole/MethodInliner.java
index 55f9ccb..947cd43 100644
--- a/src/proguard/optimize/peephole/MethodInliner.java
+++ b/src/proguard/optimize/peephole/MethodInliner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,10 +29,11 @@ import proguard.classfile.editor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
-import proguard.classfile.visitor.MemberVisitor;
+import proguard.classfile.visitor.*;
+import proguard.optimize.*;
import proguard.optimize.info.*;
-import java.util.Stack;
+import java.util.*;
/**
* This AttributeVisitor inlines short methods or methods that are only invoked
@@ -48,10 +49,8 @@ implements AttributeVisitor,
MemberVisitor
{
private static final int MAXIMUM_INLINED_CODE_LENGTH = Integer.parseInt(System.getProperty("maximum.inlined.code.length", "8"));
- private static final int MAXIMUM_RESULTING_CODE_LENGTH_JSE = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "8000"));
+ private static final int MAXIMUM_RESULTING_CODE_LENGTH_JSE = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "7000"));
private static final int MAXIMUM_RESULTING_CODE_LENGTH_JME = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "2000"));
- private static final int MAXIMUM_CODE_EXPANSION = 2;
- private static final int MAXIMUM_EXTRA_CODE_LENGTH = 128;
//*
private static final boolean DEBUG = false;
@@ -138,6 +137,42 @@ implements AttributeVisitor,
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
+ // TODO: Remove this when the method inliner has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while inlining method:");
+ System.err.println(" Target class = ["+targetClass.getName()+"]");
+ System.err.println(" Target method = ["+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
+ if (inlining)
+ {
+ System.err.println(" Inlined class = ["+clazz.getName()+"]");
+ System.err.println(" Inlined method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+ System.err.println("Not inlining this method");
+
+ if (DEBUG)
+ {
+ targetMethod.accept(targetClass, new ClassPrinter());
+ if (inlining)
+ {
+ method.accept(clazz, new ClassPrinter());
+ }
+
+ throw ex;
+ }
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
if (!inlining)
{
// codeAttributeComposer.DEBUG = DEBUG =
@@ -278,7 +313,7 @@ implements AttributeVisitor,
}
codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
- new VariableInstruction(opcode, variableOffset + parameterOffset + parameterIndex).shrink());
+ new VariableInstruction(opcode, variableOffset + parameterOffset + parameterIndex));
}
}
@@ -286,7 +321,7 @@ implements AttributeVisitor,
if (!isStatic)
{
codeAttributeComposer.appendInstruction(parameterSize,
- new VariableInstruction(InstructionConstants.OP_ASTORE, variableOffset).shrink());
+ new VariableInstruction(InstructionConstants.OP_ASTORE, variableOffset));
}
codeAttributeComposer.endCodeFragment();
@@ -305,12 +340,12 @@ implements AttributeVisitor,
// Copy the instructions.
codeAttribute.instructionsAccept(clazz, method, this);
- // Copy the exceptions.
- codeAttribute.exceptionsAccept(clazz, method, exceptionInfoAdder);
-
// Append a label just after the code.
codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+ // Copy the exceptions.
+ codeAttribute.exceptionsAccept(clazz, method, exceptionInfoAdder);
+
codeAttributeComposer.endCodeFragment();
}
@@ -319,7 +354,7 @@ implements AttributeVisitor,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
- codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, instruction);
}
@@ -346,7 +381,7 @@ implements AttributeVisitor,
codeAttribute.u4codeLength - offset);
codeAttributeComposer.appendInstruction(offset,
- branchInstruction.shrink());
+ branchInstruction);
}
else
{
@@ -359,7 +394,7 @@ implements AttributeVisitor,
}
}
- codeAttributeComposer.appendInstruction(offset, simpleInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, simpleInstruction);
}
@@ -372,7 +407,7 @@ implements AttributeVisitor,
variableInstruction.variableIndex += variableOffset;
}
- codeAttributeComposer.appendInstruction(offset, variableInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, variableInstruction);
}
@@ -430,7 +465,7 @@ implements AttributeVisitor,
constantAdder.addConstant(clazz, constantInstruction.constantIndex);
}
- codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, constantInstruction);
}
@@ -454,45 +489,48 @@ implements AttributeVisitor,
{
int accessFlags = programMethod.getAccessFlags();
- if (// Only inline the method if it is private, static, or final.
+ if (// Don't inline methods that must be preserved.
+ !KeepMarker.isKept(programMethod) &&
+
+ // Only inline the method if it is private, static, or final.
(accessFlags & (ClassConstants.INTERNAL_ACC_PRIVATE |
ClassConstants.INTERNAL_ACC_STATIC |
- ClassConstants.INTERNAL_ACC_FINAL)) != 0 &&
+ ClassConstants.INTERNAL_ACC_FINAL)) != 0 &&
// Only inline the method if it is not synchronized, etc.
(accessFlags & (ClassConstants.INTERNAL_ACC_SYNCHRONIZED |
ClassConstants.INTERNAL_ACC_NATIVE |
ClassConstants.INTERNAL_ACC_INTERFACE |
- ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 &&
+ ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 &&
// Don't inline an <init> method, except in an <init> method in the
// same class.
// (!programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ||
// (programClass.equals(targetClass) &&
// targetMethod.getName(targetClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))) &&
- !programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) &&
+ !programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) &&
// Don't inline a method into itself.
(!programMethod.equals(targetMethod) ||
- !programClass.equals(targetClass)) &&
+ !programClass.equals(targetClass)) &&
// Only inline the method if it isn't recursing.
- !inliningMethods.contains(programMethod) &&
+ !inliningMethods.contains(programMethod) &&
// Only inline the method if its target class has at least the
// same version number as the source class, in order to avoid
// introducing incompatible constructs.
- targetClass.u4version >= programClass.u4version &&
+ targetClass.u4version >= programClass.u4version &&
// Only inline the method if it doesn't invoke a super method, or if
// it is in the same class.
(!SuperInvocationMarker.invokesSuperMethods(programMethod) ||
- programClass.equals(targetClass)) &&
+ programClass.equals(targetClass)) &&
// Only inline the method if it doesn't branch backward while there
// are uninitialized objects.
(!BackwardBranchMarker.branchesBackward(programMethod) ||
- uninitializedObjectCount == 0) &&
+ uninitializedObjectCount == 0) &&
// Only inline if the code access of the inlined method allows it.
(allowAccessModification ||
@@ -501,47 +539,24 @@ implements AttributeVisitor,
(!AccessMethodMarker.accessesPackageCode(programMethod) ||
ClassUtil.internalPackageName(programClass.getName()).equals(
- ClassUtil.internalPackageName(targetClass.getName()))))) &&
+ ClassUtil.internalPackageName(targetClass.getName()))))) &&
// (!AccessMethodMarker.accessesProtectedCode(programMethod) ||
// targetClass.extends_(programClass) ||
// targetClass.implements_(programClass)) ||
(!AccessMethodMarker.accessesProtectedCode(programMethod) ||
- programClass.equals(targetClass)) &&
+ programClass.equals(targetClass)) &&
// Only inline the method if it doesn't catch exceptions, or if it
// is invoked with an empty stack.
(!CatchExceptionMarker.catchesExceptions(programMethod) ||
- emptyInvokingStack) &&
+ emptyInvokingStack) &&
- // Only inline the method if it comes from the same class or from
- // a class with a static initializer.
+ // Only inline the method if it comes from the a class with at most
+ // a subset of the initialized superclasses.
(programClass.equals(targetClass) ||
- programClass.findMethod(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
- ClassConstants.INTERNAL_METHOD_TYPE_CLINIT) == null))
- {
-// System.out.print("MethodInliner: inlining ");
-// programMethod.accept(programClass, new SimpleClassPrinter(true));
-// System.out.print(" in ");
-// targetMethod.accept(targetClass, new SimpleClassPrinter(true));
-//
-// System.out.println(" Private: "+
-// (!AccessMethodMarker.accessesPrivateCode(programMethod) ||
-// programClass.equals(targetClass)));
-//
-// System.out.println(" Package: "+
-// (!AccessMethodMarker.accessesPackageCode(programMethod) ||
-// ClassUtil.internalPackageName(programClass.getName()).equals(
-// ClassUtil.internalPackageName(targetClass.getName()))));
-//
-// System.out.println(" Protected: "+
-// ((!AccessMethodMarker.accessesProtectedCode(programMethod) ||
-// targetClass.extends_(programClass) ||
-// targetClass.implements_(programClass)) ||
-// ClassUtil.internalPackageName(programClass.getName()).equals(
-// ClassUtil.internalPackageName(targetClass.getName()))));
-
- boolean oldInlining = inlining;
+ initializedSuperClasses(targetClass).containsAll(initializedSuperClasses(programClass))))
+ { boolean oldInlining = inlining;
inlining = true;
inliningMethods.push(programMethod);
@@ -564,4 +579,21 @@ implements AttributeVisitor,
uninitializedObjectCount--;
}
}
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new ClassCollector(set)));
+
+ return set;
+ }
}
diff --git a/src/proguard/optimize/peephole/NopRemover.java b/src/proguard/optimize/peephole/NopRemover.java
index 69adb30..9396c40 100644
--- a/src/proguard/optimize/peephole/NopRemover.java
+++ b/src/proguard/optimize/peephole/NopRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/PeepholeOptimizer.java b/src/proguard/optimize/peephole/PeepholeOptimizer.java
index 98f8e8d..2a602ee 100644
--- a/src/proguard/optimize/peephole/PeepholeOptimizer.java
+++ b/src/proguard/optimize/peephole/PeepholeOptimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/ReachableCodeMarker.java b/src/proguard/optimize/peephole/ReachableCodeMarker.java
index d9dbf2d..b6fcf18 100644
--- a/src/proguard/optimize/peephole/ReachableCodeMarker.java
+++ b/src/proguard/optimize/peephole/ReachableCodeMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor finds all instruction offsets, branch targets, and
* exception targets in the CodeAttribute objects that it visits.
@@ -91,10 +93,7 @@ implements AttributeVisitor,
else
{
// Reset the array.
- for (int index = 0; index < codeLength; index++)
- {
- isReachable[index] = false;
- }
+ Arrays.fill(isReachable, 0, codeLength, false);
}
// Mark the code, starting at the entry point.
diff --git a/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
index 6707a12..a67c6ff 100644
--- a/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
+++ b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,6 +28,8 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
+import java.util.Arrays;
+
/**
* This ClassVisitor removes InnerClasses and EnclosingMethod attributes in
* classes that are retargeted or that refer to classes that are retargeted.
@@ -70,12 +72,9 @@ implements ClassVisitor,
}
// Clean up any remaining array elements.
- for (int index = newAtributesCount; index < attributesCount; index++)
- {
- attributes[index] = null;
- }
+ Arrays.fill(attributes, newAtributesCount, attributesCount, null);
- // Update the number of attribuets.
+ // Update the number of attributes.
programClass.u2attributesCount = newAtributesCount;
}
@@ -90,8 +89,39 @@ implements ClassVisitor,
// Check whether the class itself is retargeted.
checkTarget(clazz);
- // Check whether the referenced classes are retargeted.
- innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ if (!retargeted)
+ {
+ // Check whether the referenced classes are retargeted.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ int classesCount = innerClassesAttribute.u2classesCount;
+ InnerClassesInfo[] classes = innerClassesAttribute.classes;
+
+ int newClassesCount = 0;
+
+ // Copy over all non-retargeted attributes.
+ for (int index = 0; index < classesCount; index++)
+ {
+ InnerClassesInfo classInfo = classes[index];
+
+ // Check if the outer class or inner class is a retargeted class.
+ retargeted = false;
+ classInfo.outerClassConstantAccept(clazz, this);
+ classInfo.innerClassConstantAccept(clazz, this);
+ if (!retargeted)
+ {
+ classes[newClassesCount++] = classInfo;
+ }
+ }
+
+ // Clean up any remaining array elements.
+ Arrays.fill(classes, newClassesCount, classesCount, null);
+
+ // Update the number of classes.
+ innerClassesAttribute.u2classesCount = newClassesCount;
+
+ // Remove the attribute altogether if it's empty.
+ retargeted = newClassesCount == 0;
+ }
}
diff --git a/src/proguard/optimize/peephole/TargetClassChanger.java b/src/proguard/optimize/peephole/TargetClassChanger.java
index 22fd83d..f997e03 100644
--- a/src/proguard/optimize/peephole/TargetClassChanger.java
+++ b/src/proguard/optimize/peephole/TargetClassChanger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -51,13 +51,13 @@ implements ClassVisitor,
AnnotationVisitor,
ElementValueVisitor
{
+ private static final boolean DEBUG = false;
+
+
// Implementations for ClassVisitor.
public void visitProgramClass(ProgramClass programClass)
{
- Clazz superClass = null;
- Clazz[] interfaceClasses = null;
-
// Change the references of the constant pool.
programClass.constantPoolEntriesAccept(this);
@@ -80,34 +80,39 @@ implements ClassVisitor,
programClass.getName(),
programClass);
+ // This class will loose all its interfaces.
+ programClass.u2interfacesCount = 0;
+
// This class will loose all its subclasses.
programClass.subClasses = null;
}
-
- // Remove interface classes that are pointing to this class.
- int newInterfacesCount = 0;
- for (int index = 0; index < programClass.u2interfacesCount; index++)
+ else
{
- Clazz interfaceClass = programClass.getInterface(index);
- if (!programClass.equals(interfaceClass))
+ // Remove interface classes that are pointing to this class.
+ int newInterfacesCount = 0;
+ for (int index = 0; index < programClass.u2interfacesCount; index++)
{
- programClass.u2interfaces[newInterfacesCount++] =
- programClass.u2interfaces[index];
+ Clazz interfaceClass = programClass.getInterface(index);
+ if (!programClass.equals(interfaceClass))
+ {
+ programClass.u2interfaces[newInterfacesCount++] =
+ programClass.u2interfaces[index];
+ }
}
- }
- programClass.u2interfacesCount = newInterfacesCount;
+ programClass.u2interfacesCount = newInterfacesCount;
- // Update the subclasses of the superclass and interfaces of the
- // target class.
- ConstantVisitor subclassAdder =
- new ReferencedClassVisitor(
- new SubclassFilter(programClass,
- new SubclassAdder(programClass)));
+ // Update the subclasses of the superclass and interfaces of the
+ // target class.
+ ConstantVisitor subclassAdder =
+ new ReferencedClassVisitor(
+ new SubclassFilter(programClass,
+ new SubclassAdder(programClass)));
- programClass.superClassConstantAccept(subclassAdder);
- programClass.interfaceConstantsAccept(subclassAdder);
+ programClass.superClassConstantAccept(subclassAdder);
+ programClass.interfaceConstantsAccept(subclassAdder);
- // TODO: Maybe restore private method references.
+ // TODO: Maybe restore private method references.
+ }
}
@@ -188,6 +193,12 @@ implements ClassVisitor,
Clazz newReferencedClass = updateReferencedClass(referencedClass);
if (referencedClass != newReferencedClass)
{
+ if (DEBUG)
+ {
+ System.out.println("TargetClassChanger:");
+ System.out.println(" ["+clazz.getName()+"] changing reference from ["+refConstant.referencedClass+"."+refConstant.referencedMember.getName(refConstant.referencedClass)+refConstant.referencedMember.getDescriptor(refConstant.referencedClass)+"]");
+ }
+
// Change the referenced class.
refConstant.referencedClass = newReferencedClass;
@@ -197,6 +208,11 @@ implements ClassVisitor,
refConstant.getName(clazz),
refConstant.getType(clazz),
newReferencedClass);
+
+ if (DEBUG)
+ {
+ System.out.println(" ["+clazz.getName()+"] to ["+refConstant.referencedClass+"."+refConstant.referencedMember.getName(refConstant.referencedClass)+refConstant.referencedMember.getDescriptor(refConstant.referencedClass)+"]");
+ }
}
}
diff --git a/src/proguard/optimize/peephole/UnreachableCodeRemover.java b/src/proguard/optimize/peephole/UnreachableCodeRemover.java
index e8a99ab..570b3ca 100644
--- a/src/proguard/optimize/peephole/UnreachableCodeRemover.java
+++ b/src/proguard/optimize/peephole/UnreachableCodeRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/UnreachableExceptionRemover.java b/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
index 048f5e3..8e77716 100644
--- a/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
+++ b/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/VariableShrinker.java b/src/proguard/optimize/peephole/VariableShrinker.java
index 45b694f..6c05944 100644
--- a/src/proguard/optimize/peephole/VariableShrinker.java
+++ b/src/proguard/optimize/peephole/VariableShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/VerticalClassMerger.java b/src/proguard/optimize/peephole/VerticalClassMerger.java
index 29ed6ff..825de94 100644
--- a/src/proguard/optimize/peephole/VerticalClassMerger.java
+++ b/src/proguard/optimize/peephole/VerticalClassMerger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/preverify/CodePreverifier.java b/src/proguard/preverify/CodePreverifier.java
index fa60b9a..7c38259 100644
--- a/src/proguard/preverify/CodePreverifier.java
+++ b/src/proguard/preverify/CodePreverifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -42,8 +42,7 @@ import java.util.*;
*/
public class CodePreverifier
extends SimplifiedVisitor
-implements MemberVisitor,
- AttributeVisitor
+implements AttributeVisitor
{
//*
private static final boolean DEBUG = false;
@@ -54,8 +53,9 @@ implements MemberVisitor,
private final boolean microEdition;
- private final PartialEvaluator partialEvaluator = new PartialEvaluator();
- private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer(partialEvaluator);
+ private final PartialEvaluator partialEvaluator = new PartialEvaluator();
+ private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer(partialEvaluator);
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
/**
@@ -102,18 +102,27 @@ implements MemberVisitor,
ProgramClass programClass = (ProgramClass)clazz;
ProgramMethod programMethod = (ProgramMethod)method;
+ int codeLength = codeAttribute.u4codeLength;
+
// Evaluate the method.
//partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
livenessAnalyzer.visitCodeAttribute(clazz, method, codeAttribute);
+ // We may have to remove unreachable code.
+ codeAttributeEditor.reset(codeLength);
+
// Collect the stack map frames.
List stackMapFrameList = new ArrayList();
- for (int offset = 0; offset < codeAttribute.u4codeLength; offset++)
+ for (int offset = 0; offset < codeLength; offset++)
{
// Only store frames at the beginning of code blocks.
- if (partialEvaluator.isTraced(offset) &&
- partialEvaluator.isBranchOrExceptionTarget(offset))
+ if (!partialEvaluator.isTraced(offset))
+ {
+ // Mark the unreachable instruction for deletion.
+ codeAttributeEditor.deleteInstruction(offset);
+ }
+ else if (partialEvaluator.isBranchOrExceptionTarget(offset))
{
// Convert the variable values to types.
VerificationType[] variableTypes =
@@ -235,6 +244,9 @@ implements MemberVisitor,
stackMapAttribute.accept(programClass, programMethod, codeAttribute, new ClassPrinter());
}
}
+
+ // Apply code modifications, deleting unreachable code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
}
@@ -433,7 +445,7 @@ implements MemberVisitor,
isDupOrSwap(codeAttribute.code[producerOffset]))
{
producers = partialEvaluator.getStackBefore(producerOffset).getTopProducerValue(0).instructionOffsetValue();
- producerOffset = producers.instructionOffset(0);
+ producerOffset = producers.minimumValue();
}
// Are we in an instance initialization method,
diff --git a/src/proguard/preverify/CodeSubroutineInliner.java b/src/proguard/preverify/CodeSubroutineInliner.java
index 603eb75..c1549a3 100644
--- a/src/proguard/preverify/CodeSubroutineInliner.java
+++ b/src/proguard/preverify/CodeSubroutineInliner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -45,12 +45,12 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = System.getProperty("csi") != null;
//*/
private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
- private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(true);
+ private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(true, true);
private ExceptionInfoVisitor subroutineExceptionInliner = this;
private int clipStart = 0;
@@ -67,6 +67,7 @@ implements AttributeVisitor,
// DEBUG =
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
+// CodeAttributeComposer.DEBUG = DEBUG;
// TODO: Remove this when the subroutine inliner has stabilized.
// Catch any unexpected exceptions from the actual visiting method.
@@ -97,7 +98,7 @@ implements AttributeVisitor,
branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);
// Don't bother if there aren't any subroutines anyway.
- if (!containsSubroutines(codeAttribute))
+ if (!branchTargetFinder.containsSubroutines())
{
return;
}
@@ -161,23 +162,6 @@ implements AttributeVisitor,
/**
- * Returns whether the given code attribute contains any subroutines.
- */
- private boolean containsSubroutines(CodeAttribute codeAttribute)
- {
- for (int offset = 0; offset < codeAttribute.u4codeLength; offset++)
- {
- if (branchTargetFinder.isSubroutineInvocation(offset))
- {
- return true;
- }
- }
-
- return false;
- }
-
-
- /**
* Appends the specified subroutine.
*/
private void inlineSubroutine(Clazz clazz,
@@ -245,7 +229,7 @@ implements AttributeVisitor,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
// Append the instruction.
- codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, instruction);
}
@@ -275,7 +259,7 @@ implements AttributeVisitor,
// Replace the instruction by a branch.
Instruction replacementInstruction =
new BranchInstruction(InstructionConstants.OP_GOTO,
- branchTargetFinder.subroutineEnd(offset) - offset).shrink();
+ branchTargetFinder.subroutineEnd(offset) - offset);
codeAttributeComposer.appendInstruction(offset, replacementInstruction);
}
@@ -331,7 +315,7 @@ implements AttributeVisitor,
// Replace the subroutine invocation by a simple branch.
Instruction replacementInstruction =
new BranchInstruction(InstructionConstants.OP_GOTO,
- branchOffset).shrink();
+ branchOffset);
codeAttributeComposer.appendInstruction(offset, replacementInstruction);
}
diff --git a/src/proguard/preverify/Preverifier.java b/src/proguard/preverify/Preverifier.java
index e071c5c..da9649b 100644
--- a/src/proguard/preverify/Preverifier.java
+++ b/src/proguard/preverify/Preverifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -59,13 +59,12 @@ public class Preverifier
new AllAttributeVisitor(
new CodePreverifier(configuration.microEdition)));
- // In Java Standard Edition, only class files from Java 6 or higher
- // should be preverified.
+ // Classes from Java 6 may optionally be preverified.
+ // Classes from Java 7 or higher must be preverified.
if (!configuration.microEdition)
{
preverifier =
new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_6,
- Integer.MAX_VALUE,
preverifier);
}
diff --git a/src/proguard/preverify/SubroutineInliner.java b/src/proguard/preverify/SubroutineInliner.java
index e28512f..e21c469 100644
--- a/src/proguard/preverify/SubroutineInliner.java
+++ b/src/proguard/preverify/SubroutineInliner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -65,7 +65,6 @@ public class SubroutineInliner
{
inliner =
new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_6,
- Integer.MAX_VALUE,
inliner);
}
diff --git a/src/proguard/retrace/ReTrace.java b/src/proguard/retrace/ReTrace.java
index bf6a145..91ab2a7 100644
--- a/src/proguard/retrace/ReTrace.java
+++ b/src/proguard/retrace/ReTrace.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -40,17 +40,14 @@ implements MappingProcessor
private static final String REGEX_OPTION = "-regex";
private static final String VERBOSE_OPTION = "-verbose";
- // BEGIN android-changed
- // Use regex from latest version (4.9) because it is
- // able to handle Android Bugreport format
+
public static final String STACK_TRACE_EXPRESSION = "(?:.*?\\bat\\s+%c.%m\\s*\\(.*?(?::%l)?\\)\\s*)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)";
- // END android-changed
private static final String REGEX_CLASS = "\\b(?:[A-Za-z0-9_$]+\\.)*[A-Za-z0-9_$]+\\b";
private static final String REGEX_CLASS_SLASH = "\\b(?:[A-Za-z0-9_$]+/)*[A-Za-z0-9_$]+\\b";
private static final String REGEX_LINE_NUMBER = "\\b[0-9]+\\b";
private static final String REGEX_TYPE = REGEX_CLASS + "(?:\\[\\])*";
- private static final String REGEX_MEMBER = "\\b[A-Za-z0-9_$]+\\b";
+ private static final String REGEX_MEMBER = "<?\\b[A-Za-z0-9_$]+\\b>?";
private static final String REGEX_ARGUMENTS = "(?:" + REGEX_TYPE + "(?:\\s*,\\s*" + REGEX_TYPE + ")*)?";
// The class settings.
diff --git a/src/proguard/shrink/AnnotationUsageMarker.java b/src/proguard/shrink/AnnotationUsageMarker.java
index 9aaae34..b9051a0 100644
--- a/src/proguard/shrink/AnnotationUsageMarker.java
+++ b/src/proguard/shrink/AnnotationUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -52,8 +52,7 @@ implements AttributeVisitor,
// Fields acting as a return parameters for several methods.
private boolean attributeUsed;
private boolean annotationUsed;
- private boolean elementValueUsed;
- private boolean classUsed;
+ private boolean allClassesUsed;
private boolean methodUsed;
@@ -151,9 +150,6 @@ implements AttributeVisitor,
markConstant(clazz, constantElementValue.u2elementNameIndex);
markConstant(clazz, constantElementValue.u2constantValueIndex);
-
- // The return value.
- elementValueUsed = true;
}
}
@@ -163,10 +159,10 @@ implements AttributeVisitor,
if (isReferencedMethodUsed(enumConstantElementValue))
{
// Check the referenced classes.
- classUsed = true;
- enumConstantElementValue.referencedClassesAccept(usageMarker);
+ allClassesUsed = true;
+ enumConstantElementValue.referencedClassesAccept(this);
- if (classUsed)
+ if (allClassesUsed)
{
// Mark the element value as being used.
usageMarker.markAsUsed(enumConstantElementValue);
@@ -174,9 +170,6 @@ implements AttributeVisitor,
markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
-
- // The return value.
- elementValueUsed = true;
}
}
}
@@ -186,21 +179,16 @@ implements AttributeVisitor,
{
if (isReferencedMethodUsed(classElementValue))
{
- // Check the referenced classes.
- classUsed = true;
- classElementValue.referencedClassesAccept(usageMarker);
-
- if (classUsed)
- {
- // Mark the element value as being used.
- usageMarker.markAsUsed(classElementValue);
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(classElementValue);
- markConstant(clazz, classElementValue.u2elementNameIndex);
- markConstant(clazz, classElementValue.u2classInfoIndex);
+ markConstant(clazz, classElementValue.u2elementNameIndex);
+ markConstant(clazz, classElementValue.u2classInfoIndex);
- // The return value.
- elementValueUsed = true;
- }
+ // Mark the referenced classes, since they can be retrieved from
+ // the annotation and then used.
+ // TODO: This could mark more annotation methods, affecting other annotations.
+ classElementValue.referencedClassesAccept(usageMarker);
}
}
@@ -221,9 +209,6 @@ implements AttributeVisitor,
usageMarker.markAsUsed(annotationElementValue);
markConstant(clazz, annotationElementValue.u2elementNameIndex);
-
- // The return value.
- elementValueUsed = true;
}
annotationUsed = oldAnnotationUsed;
@@ -235,26 +220,13 @@ implements AttributeVisitor,
{
if (isReferencedMethodUsed(arrayElementValue))
{
- boolean oldelementValueUsed = elementValueUsed;
-
// Check and mark the contained element values.
- elementValueUsed = false;
arrayElementValue.elementValuesAccept(clazz, annotation, this);
- if (elementValueUsed)
- {
- // Mark the element value as being used.
- usageMarker.markAsUsed(arrayElementValue);
-
- markConstant(clazz, arrayElementValue.u2elementNameIndex);
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(arrayElementValue);
- // The return value.
- //elementValueUsed = true;
- }
- else
- {
- elementValueUsed = oldelementValueUsed;
- }
+ markConstant(clazz, arrayElementValue.u2elementNameIndex);
}
}
@@ -269,17 +241,15 @@ implements AttributeVisitor,
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
- classUsed = usageMarker.isUsed(classConstant);
-
// Is the class constant marked as being used?
- if (!classUsed)
+ if (!usageMarker.isUsed(classConstant))
{
// Check the referenced class.
- classUsed = true;
+ allClassesUsed = true;
classConstant.referencedClassAccept(this);
// Is the referenced class marked as being used?
- if (classUsed)
+ if (allClassesUsed)
{
// Mark the class constant and its Utf8 constant.
usageMarker.markAsUsed(classConstant);
@@ -294,13 +264,12 @@ implements AttributeVisitor,
public void visitProgramClass(ProgramClass programClass)
{
- classUsed = usageMarker.isUsed(programClass);
+ allClassesUsed &= usageMarker.isUsed(programClass);
}
public void visitLibraryClass(LibraryClass libraryClass)
{
- classUsed = true;
}
@@ -314,7 +283,6 @@ implements AttributeVisitor,
public void visitLibraryMethod(LibraryClass LibraryClass, LibraryMethod libraryMethod)
{
- classUsed = true;
}
@@ -326,10 +294,10 @@ implements AttributeVisitor,
private boolean isReferencedClassUsed(Annotation annotation)
{
// Check if the referenced class is being used.
- classUsed = true;
+ allClassesUsed = true;
annotation.referencedClassAccept(this);
- return classUsed;
+ return allClassesUsed;
}
diff --git a/src/proguard/shrink/ClassShrinker.java b/src/proguard/shrink/ClassShrinker.java
index 0b5c5b7..f590c63 100644
--- a/src/proguard/shrink/ClassShrinker.java
+++ b/src/proguard/shrink/ClassShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,15 +24,17 @@ import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
import proguard.classfile.attribute.annotation.visitor.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.editor.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
+import java.util.Arrays;
+
/**
- * This ClassVisitor removes constant pool entries and class members that
- * are not marked as being used.
+ * This ClassVisitor removes constant pool entries, class members, and other
+ * class elements that are not marked as being used.
*
* @see UsageMarker
*
@@ -48,8 +50,7 @@ implements ClassVisitor,
{
private final UsageMarker usageMarker;
- private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
-
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
@@ -76,7 +77,7 @@ implements ClassVisitor,
programClass.u2interfacesCount);
// Shrinking the constant pool also sets up an index map.
- programClass.u2constantPoolCount =
+ int newConstantPoolCount =
shrinkConstantPool(programClass.constantPool,
programClass.u2constantPoolCount);
@@ -98,9 +99,15 @@ implements ClassVisitor,
programClass.methodsAccept(this);
programClass.attributesAccept(this);
- // Remap all constant pool references.
- constantPoolRemapper.setConstantIndexMap(constantIndexMap);
- constantPoolRemapper.visitProgramClass(programClass);
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
// Remove the unused interfaces from the class signature.
programClass.attributesAccept(new SignatureShrinker());
@@ -140,6 +147,15 @@ implements ClassVisitor,
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Shrink the array of BootstrapMethodInfo objects.
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount =
+ shrinkArray(bootstrapMethodsAttribute.bootstrapMethods,
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount);
+ }
+
+
public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
{
// Shrink the array of InnerClassesInfo objects.
@@ -173,6 +189,27 @@ implements ClassVisitor,
codeAttribute.u2attributesCount =
shrinkArray(codeAttribute.attributes,
codeAttribute.u2attributesCount);
+
+ // Shrink the attributes themselves.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Shrink the local variable info array.
+ localVariableTableAttribute.u2localVariableTableLength =
+ shrinkArray(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Shrink the local variable type info array.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength =
+ shrinkArray(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength);
}
@@ -349,10 +386,7 @@ implements ClassVisitor,
}
// Clear the remaining constant pool elements.
- for (int index = counter; index < length; index++)
- {
- constantPool[index] = null;
- }
+ Arrays.fill(constantPool, counter, length, null);
return counter;
}
@@ -377,10 +411,7 @@ implements ClassVisitor,
}
// Clear the remaining array elements.
- for (int index = counter; index < length; index++)
- {
- array[index] = 0;
- }
+ Arrays.fill(array, counter, length, 0);
return counter;
}
@@ -437,10 +468,10 @@ implements ClassVisitor,
}
}
- // Clear the remaining array elements.
- for (int index = counter; index < length; index++)
+ // Clear any remaining array elements.
+ if (counter < length)
{
- array[index] = null;
+ Arrays.fill(array, counter, length, null);
}
return counter;
diff --git a/src/proguard/shrink/InnerUsageMarker.java b/src/proguard/shrink/InnerUsageMarker.java
index b8ca801..6d77e81 100644
--- a/src/proguard/shrink/InnerUsageMarker.java
+++ b/src/proguard/shrink/InnerUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/InterfaceUsageMarker.java b/src/proguard/shrink/InterfaceUsageMarker.java
index 7599898..240838e 100644
--- a/src/proguard/shrink/InterfaceUsageMarker.java
+++ b/src/proguard/shrink/InterfaceUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/LocalVariableTypeUsageMarker.java b/src/proguard/shrink/LocalVariableTypeUsageMarker.java
new file mode 100644
index 0000000..573d8f6
--- /dev/null
+++ b/src/proguard/shrink/LocalVariableTypeUsageMarker.java
@@ -0,0 +1,178 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This AttributeVisitor recursively marks all information that points to used
+ * classes, in the LocalVariableTable and LocalVariableTypeTable attributes that
+ * it visits.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTypeUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ ClassVisitor,
+ ConstantVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as a return parameters for several methods.
+ private boolean tableUsed;
+ private boolean variableInfoUsed;
+
+
+ /**
+ * Creates a new LocalVariableTypeUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public LocalVariableTypeUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Check and mark the individual entries.
+ tableUsed = false;
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Mark the table if any of the entries is marked.
+ if (tableUsed)
+ {
+ usageMarker.markAsUsed(localVariableTableAttribute);
+
+ markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Check and mark the individual entries.
+ tableUsed = false;
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Mark the table if any of the entries is marked.
+ if (tableUsed)
+ {
+ usageMarker.markAsUsed(localVariableTypeTableAttribute);
+
+ markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Only keep the local variable info if all of its classes are used.
+ variableInfoUsed = true;
+ localVariableInfo.referencedClassAccept(this);
+
+ if (variableInfoUsed)
+ {
+ // We got a positive used flag, so the local variable info is useful.
+ usageMarker.markAsUsed(localVariableInfo);
+
+ markConstant(clazz, localVariableInfo.u2nameIndex);
+ markConstant(clazz, localVariableInfo.u2descriptorIndex);
+
+ tableUsed = true;
+ }
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Only keep the local variable info if all of its classes are used.
+ variableInfoUsed = true;
+ localVariableTypeInfo.referencedClassesAccept(this);
+
+ if (variableInfoUsed)
+ {
+ // We got a positive used flag, so the local variable info is useful.
+ usageMarker.markAsUsed(localVariableTypeInfo);
+
+ markConstant(clazz, localVariableTypeInfo.u2nameIndex);
+ markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
+
+ tableUsed = true;
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Don't keep the local variable info if one of its classes is not used.
+ if (!usageMarker.isUsed(programClass))
+ {
+ variableInfoUsed = false;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ usageMarker.markAsUsed(constant);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+}
diff --git a/src/proguard/shrink/ShortestUsageMark.java b/src/proguard/shrink/ShortestUsageMark.java
index 757c713..e2df7fa 100644
--- a/src/proguard/shrink/ShortestUsageMark.java
+++ b/src/proguard/shrink/ShortestUsageMark.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/ShortestUsageMarker.java b/src/proguard/shrink/ShortestUsageMarker.java
index da8fad3..1ac6e7e 100644
--- a/src/proguard/shrink/ShortestUsageMarker.java
+++ b/src/proguard/shrink/ShortestUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/ShortestUsagePrinter.java b/src/proguard/shrink/ShortestUsagePrinter.java
index db42fe1..8740b9f 100644
--- a/src/proguard/shrink/ShortestUsagePrinter.java
+++ b/src/proguard/shrink/ShortestUsagePrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,7 +21,9 @@
package proguard.shrink;
import proguard.classfile.*;
-import proguard.classfile.util.ClassUtil;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
import java.io.PrintStream;
@@ -36,8 +38,10 @@ import java.io.PrintStream;
* @author Eric Lafortune
*/
public class ShortestUsagePrinter
+extends SimplifiedVisitor
implements ClassVisitor,
- MemberVisitor
+ MemberVisitor,
+ AttributeVisitor
{
private final ShortestUsageMarker shortestUsageMarker;
private final boolean verbose;
@@ -117,8 +121,7 @@ implements ClassVisitor,
ps.println(ClassUtil.externalClassName(programClass.getName()) +
(verbose ?
": " + ClassUtil.externalFullFieldDescription(0, name, type):
- "." + name) +
- lineNumberRange(programClass, programField));
+ "." + name));
// Print the reason for keeping this method.
printReason(programField);
@@ -131,11 +134,12 @@ implements ClassVisitor,
String name = programMethod.getName(programClass);
String type = programMethod.getDescriptor(programClass);
- ps.println(ClassUtil.externalClassName(programClass.getName()) +
- (verbose ?
- ": " + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, name, type):
- "." + name) +
- lineNumberRange(programClass, programMethod));
+ ps.print(ClassUtil.externalClassName(programClass.getName()) +
+ (verbose ?
+ ": " + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, name, type):
+ "." + name));
+ programMethod.attributesAccept(programClass, this);
+ ps.println();
// Print the reason for keeping this method.
printReason(programMethod);
@@ -174,6 +178,25 @@ implements ClassVisitor,
}
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ ps.print(" (" +
+ lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ")");
+ }
+
+
// Small utility methods.
private void printReason(VisitorAccepter visitorAccepter)
@@ -194,17 +217,4 @@ implements ClassVisitor,
ps.println(" is not being kept.\n");
}
}
-
-
- /**
- * Returns the line number range of the given class member, followed by a
- * colon, or just an empty String if no range is available.
- */
- private static String lineNumberRange(ProgramClass programClass, ProgramMember programMember)
- {
- String range = programMember.getLineNumberRange(programClass);
- return range != null ?
- (" (" + range + ")") :
- "";
- }
}
diff --git a/src/proguard/shrink/Shrinker.java b/src/proguard/shrink/Shrinker.java
index edbc27f..0472c3d 100644
--- a/src/proguard/shrink/Shrinker.java
+++ b/src/proguard/shrink/Shrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,7 +21,7 @@
package proguard.shrink;
import proguard.*;
-import proguard.classfile.ClassPool;
+import proguard.classfile.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.visitor.*;
@@ -67,9 +67,20 @@ public class Shrinker
new UsageMarker() :
new ShortestUsageMarker();
+ // Automatically mark the parameterless constructors of seed classes,
+ // mainly for convenience and for backward compatibility.
+ ClassVisitor classUsageMarker =
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ usageMarker,
+ new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_INIT,
+ usageMarker)
+ });
+
ClassPoolVisitor classPoolvisitor =
ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
- usageMarker,
+ classUsageMarker,
usageMarker,
true,
false,
@@ -89,6 +100,8 @@ public class Shrinker
{
new InnerUsageMarker(usageMarker),
new AnnotationUsageMarker(usageMarker),
+ new SignatureUsageMarker(usageMarker),
+ new LocalVariableTypeUsageMarker(usageMarker)
}))));
// Should we explain ourselves?
@@ -113,15 +126,21 @@ public class Shrinker
if (configuration.printUsage != null)
{
- PrintStream ps = isFile(configuration.printUsage) ?
- new PrintStream(new BufferedOutputStream(new FileOutputStream(configuration.printUsage))) :
- System.out;
+ PrintStream ps =
+ configuration.printUsage == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(configuration.printUsage)));
// Print out items that will be removed.
programClassPool.classesAcceptAlphabetically(
new UsagePrinter(usageMarker, true, ps));
- if (ps != System.out)
+ if (ps == System.out)
+ {
+ ps.flush();
+ }
+ else
{
ps.close();
}
@@ -157,14 +176,4 @@ public class Shrinker
return newProgramClassPool;
}
-
-
- /**
- * Returns whether the given file is actually a file, or just a placeholder
- * for the standard output.
- */
- private boolean isFile(File file)
- {
- return file.getPath().length() > 0;
- }
}
diff --git a/src/proguard/shrink/SignatureUsageMarker.java b/src/proguard/shrink/SignatureUsageMarker.java
new file mode 100644
index 0000000..9c5cd4d
--- /dev/null
+++ b/src/proguard/shrink/SignatureUsageMarker.java
@@ -0,0 +1,117 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This AttributeVisitor recursively marks all Signature attributes that it
+ * visits and that point to used classes.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class SignatureUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ ClassVisitor,
+ ConstantVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as a return parameters for several methods.
+ private boolean attributeUsed;
+
+
+ /**
+ * Creates a new SignatureUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public SignatureUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Only keep the signature if all of its classes are used.
+ attributeUsed = true;
+ signatureAttribute.referencedClassesAccept(this);
+
+ if (attributeUsed)
+ {
+ // We got a positive used flag, so the signature is useful.
+ usageMarker.markAsUsed(signatureAttribute);
+
+ markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ markConstant(clazz, signatureAttribute.u2signatureIndex);
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Don't keep the signature if one of its classes is not used.
+ if (!usageMarker.isUsed(programClass))
+ {
+ attributeUsed = false;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ usageMarker.markAsUsed(constant);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+}
diff --git a/src/proguard/shrink/UsageMarker.java b/src/proguard/shrink/UsageMarker.java
index e913046..51210b5 100644
--- a/src/proguard/shrink/UsageMarker.java
+++ b/src/proguard/shrink/UsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,10 +27,10 @@ import proguard.classfile.attribute.preverification.*;
import proguard.classfile.attribute.preverification.visitor.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.constant.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
@@ -65,18 +65,15 @@ implements ClassVisitor,
private static final Object USED = new Object();
- private final MyInterfaceUsageMarker interfaceUsageMarker = new MyInterfaceUsageMarker();
- private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker = new MyPossiblyUsedMemberUsageMarker();
-// private ClassVisitor dynamicClassMarker =
-// new MultiClassVisitor(
-// new ClassVisitor[]
-// {
-// this,
-// new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,
-// ClassConstants.INTERNAL_METHOD_TYPE_INIT,
-// this)
-// });
-
+ private final MyInterfaceUsageMarker interfaceUsageMarker = new MyInterfaceUsageMarker();
+ private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker = new MyPossiblyUsedMemberUsageMarker();
+ private final MemberVisitor nonEmptyMethodUsageMarker = new AllAttributeVisitor(
+ new MyNonEmptyMethodUsageMarker());
+ private final ConstantVisitor parameterlessConstructorMarker = new ConstantTagFilter(new int[] { ClassConstants.CONSTANT_String, ClassConstants.CONSTANT_Class },
+ new ReferencedClassVisitor(
+ new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_INIT,
+ this)));
// Implementations for ClassVisitor.
@@ -107,15 +104,10 @@ implements ClassVisitor,
programClass.hierarchyAccept(false, false, true, false,
interfaceUsageMarker);
- // Explicitly mark the <clinit> method.
+ // Explicitly mark the <clinit> method, if it's not empty.
programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
- this);
-
- // Explicitly mark the parameterless <init> method.
- programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT,
- ClassConstants.INTERNAL_METHOD_TYPE_INIT,
- this);
+ nonEmptyMethodUsageMarker);
// Process all class members that have already been marked as possibly used.
programClass.fieldsAccept(possiblyUsedMemberUsageMarker);
@@ -187,6 +179,10 @@ implements ClassVisitor,
}
+ /**
+ * This MemberVisitor marks ProgramField and ProgramMethod objects that
+ * have already been marked as possibly used.
+ */
private class MyPossiblyUsedMemberUsageMarker
extends SimplifiedVisitor
implements MemberVisitor
@@ -230,6 +226,28 @@ implements ClassVisitor,
}
+ /**
+ * This AttributeVisitor marks ProgramMethod objects of non-empty methods.
+ */
+ private class MyNonEmptyMethodUsageMarker
+ extends SimplifiedVisitor
+ implements AttributeVisitor
+ {
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (codeAttribute.u4codeLength > 1)
+ {
+ method.accept(clazz, UsageMarker.this);
+ }
+ }
+ }
+
+
// Implementations for MemberVisitor.
public void visitProgramField(ProgramClass programClass, ProgramField programField)
@@ -335,15 +353,26 @@ implements ClassVisitor,
*/
protected void markMethodHierarchy(Clazz clazz, Method method)
{
- if ((method.getAccessFlags() &
+ int accessFlags = method.getAccessFlags();
+ if ((accessFlags &
(ClassConstants.INTERNAL_ACC_PRIVATE |
- ClassConstants.INTERNAL_ACC_STATIC)) == 0)
+ ClassConstants.INTERNAL_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.INTERNAL_ACC_PRIVATE |
+ ClassConstants.INTERNAL_ACC_STATIC |
+ ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0 ? 0 :
+ ClassConstants.INTERNAL_ACC_ABSTRACT);
+
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,
+ new MemberAccessFilter(0, requiredUnsetAccessFlags,
this)))));
}
}
@@ -395,11 +424,7 @@ implements ClassVisitor,
markConstant(clazz, stringConstant.u2stringIndex);
- // Mark the referenced class and its parameterless constructor,
- // if the string is being used in a Class.forName construct.
- //stringConstant.referencedClassAccept(dynamicClassMarker);
-
- // Mark the referenced class or class member, if any.
+ // Mark the referenced class and class member, if any.
stringConstant.referencedClassAccept(this);
stringConstant.referencedMemberAccept(this);
}
@@ -415,6 +440,31 @@ implements 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 void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ if (shouldBeMarkedAsUsed(methodHandleConstant))
+ {
+ markAsUsed(methodHandleConstant);
+
+ markConstant(clazz, methodHandleConstant.u2referenceIndex);
+ }
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
if (shouldBeMarkedAsUsed(refConstant))
@@ -450,6 +500,17 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ if (shouldBeMarkedAsUsed(methodTypeConstant))
+ {
+ markAsUsed(methodTypeConstant);
+
+ markConstant(clazz, methodTypeConstant.u2descriptorIndex);
+ }
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
if (shouldBeMarkedAsUsed(nameAndTypeConstant))
@@ -462,6 +523,58 @@ implements ClassVisitor,
}
+ /**
+ * This AttributeVisitor marks the bootstrap methods attributes, their
+ * method entries, their method handles, and their arguments.
+ */
+ private class MyBootStrapMethodUsageMarker
+ extends SimplifiedVisitor
+ implements AttributeVisitor,
+ BootstrapMethodInfoVisitor
+ {
+ private int bootstrapMethodIndex;
+
+
+ private MyBootStrapMethodUsageMarker(int bootstrapMethodIndex)
+ {
+ this.bootstrapMethodIndex = bootstrapMethodIndex;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (shouldBeMarkedAsUsed(bootstrapMethodsAttribute))
+ {
+ markAsUsed(bootstrapMethodsAttribute);
+
+ markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
+ bootstrapMethodIndex,
+ this);
+ }
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ markAsUsed(bootstrapMethodInfo);
+
+ markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Mark the constant pool entries referenced by the arguments.
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, UsageMarker.this);
+ }
+ }
+
+
// Implementations for AttributeVisitor.
// Note that attributes are typically only referenced once, so we don't
// test if they have been marked already.
@@ -475,6 +588,13 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Don't mark the attribute and its name here. We may mark it in
+ // MyBootStrapMethodsAttributeUsageMarker.
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
markAsUsed(sourceFileAttribute);
@@ -538,10 +658,12 @@ implements ClassVisitor,
public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
{
- markAsUsed(signatureAttribute);
-
- markConstant(clazz, signatureAttribute.u2attributeNameIndex);
- markConstant(clazz, signatureAttribute.u2signatureIndex);
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in SignatureUsageMarker.
+ //markAsUsed(signatureAttribute);
+ //
+ //markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ //markConstant(clazz, signatureAttribute.u2signatureIndex);
}
@@ -611,23 +733,27 @@ implements ClassVisitor,
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
{
- markAsUsed(localVariableTableAttribute);
-
- markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
-
- // Mark the constant pool entries referenced by the local variables.
- localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in LocalVariableTypeUsageMarker.
+ //markAsUsed(localVariableTableAttribute);
+ //
+ //markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the local variables.
+ //localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
}
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
{
- markAsUsed(localVariableTypeTableAttribute);
-
- markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
-
- // Mark the constant pool entries referenced by the local variable types.
- localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in LocalVariableTypeUsageMarker.
+ //markAsUsed(localVariableTypeTableAttribute);
+ //
+ //markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the local variable types.
+ //localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
}
@@ -635,12 +761,12 @@ implements ClassVisitor,
{
// Don't mark the attribute and its contents yet. We may mark them later,
// in AnnotationUsageMarker.
-// markAsUsed(annotationsAttribute);
-//
-// markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
-//
-// // Mark the constant pool entries referenced by the annotations.
-// annotationsAttribute.annotationsAccept(clazz, this);
+ //markAsUsed(annotationsAttribute);
+ //
+ //markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the annotations.
+ //annotationsAttribute.annotationsAccept(clazz, this);
}
@@ -648,12 +774,12 @@ implements ClassVisitor,
{
// Don't mark the attribute and its contents yet. We may mark them later,
// in AnnotationUsageMarker.
-// markAsUsed(parameterAnnotationsAttribute);
-//
-// markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
-//
-// // Mark the constant pool entries referenced by the annotations.
-// parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ //markAsUsed(parameterAnnotationsAttribute);
+ //
+ //markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the annotations.
+ //parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
}
@@ -837,6 +963,12 @@ implements ClassVisitor,
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);
}
@@ -915,6 +1047,6 @@ implements ClassVisitor,
*/
private void markConstant(Clazz clazz, int index)
{
- clazz.constantPoolEntryAccept(index, this);
+ clazz.constantPoolEntryAccept(index, this);
}
}
diff --git a/src/proguard/shrink/UsagePrinter.java b/src/proguard/shrink/UsagePrinter.java
index 294b9e1..69df7fa 100644
--- a/src/proguard/shrink/UsagePrinter.java
+++ b/src/proguard/shrink/UsagePrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,8 @@
package proguard.shrink;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
@@ -38,7 +40,8 @@ import java.io.PrintStream;
public class UsagePrinter
extends SimplifiedVisitor
implements ClassVisitor,
- MemberVisitor
+ MemberVisitor,
+ AttributeVisitor
{
private final UsageMarker usageMarker;
private final boolean printUnusedItems;
@@ -121,7 +124,6 @@ implements ClassVisitor,
printClassNameHeader();
ps.println(" " +
- lineNumberRange(programClass, programField) +
ClassUtil.externalFullFieldDescription(
programField.getAccessFlags(),
programField.getName(programClass),
@@ -136,9 +138,10 @@ implements ClassVisitor,
{
printClassNameHeader();
- ps.println(" " +
- lineNumberRange(programClass, programMethod) +
- ClassUtil.externalFullMethodDescription(
+ ps.print("====");
+ ps.print(" ");
+ programMethod.attributesAccept(programClass, this);
+ ps.println(ClassUtil.externalFullMethodDescription(
programClass.getName(),
programMethod.getAccessFlags(),
programMethod.getName(programClass),
@@ -147,6 +150,24 @@ implements ClassVisitor,
}
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ ps.print(lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ":");
+ }
+
+
// Small utility methods.
/**
@@ -161,17 +182,4 @@ implements ClassVisitor,
className = null;
}
}
-
-
- /**
- * Returns the line number range of the given class member, followed by a
- * colon, or just an empty String if no range is available.
- */
- private static String lineNumberRange(ProgramClass programClass, ProgramMember programMember)
- {
- String range = programMember.getLineNumberRange(programClass);
- return range != null ?
- (range + ":") :
- "";
- }
}
diff --git a/src/proguard/shrink/UsedClassFilter.java b/src/proguard/shrink/UsedClassFilter.java
index ec180bd..7630b0b 100644
--- a/src/proguard/shrink/UsedClassFilter.java
+++ b/src/proguard/shrink/UsedClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/UsedMemberFilter.java b/src/proguard/shrink/UsedMemberFilter.java
index 755cfd1..f1a9c75 100644
--- a/src/proguard/shrink/UsedMemberFilter.java
+++ b/src/proguard/shrink/UsedMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,7 +39,7 @@ implements MemberVisitor
/**
- * Creates a new UsedClassFilter.
+ * Creates a new UsedMemberFilter.
* @param usageMarker the usage marker that is used to mark the classes
* and class members.
* @param memberVisitor the member visitor to which the visiting will be
diff --git a/src/proguard/util/AndMatcher.java b/src/proguard/util/AndMatcher.java
index 94a37e5..1aa3726 100644
--- a/src/proguard/util/AndMatcher.java
+++ b/src/proguard/util/AndMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ArrayUtil.java b/src/proguard/util/ArrayUtil.java
new file mode 100644
index 0000000..8584700
--- /dev/null
+++ b/src/proguard/util/ArrayUtil.java
@@ -0,0 +1,960 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+
+/**
+ * This class contains utility methods operating on arrays.
+ */
+public class ArrayUtil
+{
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(byte[] array1, byte[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(short[] array1, short[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(int[] array1, int[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(Object[] array1, Object[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (!array1[index].equals(array2[index]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(byte[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(short[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(int[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(Object[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index].hashCode();
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(byte[] array1, int size1,
+ byte[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(short[] array1, int size1,
+ short[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(int[] array1, int size1,
+ int[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(Comparable[] array1, int size1,
+ Comparable[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ int comparison = ObjectUtil.compare(array1[index], array2[index]);
+ if (comparison != 0)
+ {
+ return comparison;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static boolean[] extendArray(boolean[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ boolean[] newArray = new boolean[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static boolean[] ensureArraySize(boolean[] array,
+ int size,
+ boolean initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new boolean[size];
+
+ if (initialValue)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] add(byte[] array, int size, byte element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] insert(byte[] array, int size, int index, byte element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(byte[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] extendArray(byte[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ byte[] newArray = new byte[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static byte[] ensureArraySize(byte[] array,
+ int size,
+ byte initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new byte[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] add(short[] array, int size, short element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] insert(short[] array, int size, int index, short element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(short[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] extendArray(short[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ short[] newArray = new short[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static short[] ensureArraySize(short[] array,
+ int size,
+ short initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new short[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] add(int[] array, int size, int element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] insert(int[] array, int size, int index, int element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(int[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] extendArray(int[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ int[] newArray = new int[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static int[] ensureArraySize(int[] array,
+ int size,
+ int initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new int[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] add(long[] array, int size, long element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] insert(long[] array, int size, int index, long element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(long[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] extendArray(long[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ long[] newArray = new long[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static long[] ensureArraySize(long[] array,
+ int size,
+ long initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new long[size];
+
+ if (initialValue != 0L)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] add(Object[] array, int size, Object element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] insert(Object[] array, int size, int index, Object element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(Object[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = null;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] extendArray(Object[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ Object[] newArray = (Object[])Array.newInstance(array.getClass().getComponentType(), size);
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static Object[] ensureArraySize(Object[] array,
+ int size,
+ Object initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = (Object[])Array.newInstance(array.getClass().getComponentType(), size);
+
+ if (initialValue != null)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+}
diff --git a/src/proguard/util/ClassNameParser.java b/src/proguard/util/ClassNameParser.java
index ee972f0..22a0703 100644
--- a/src/proguard/util/ClassNameParser.java
+++ b/src/proguard/util/ClassNameParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ConstantMatcher.java b/src/proguard/util/ConstantMatcher.java
index 1764caa..8c0f1e1 100644
--- a/src/proguard/util/ConstantMatcher.java
+++ b/src/proguard/util/ConstantMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/EmptyStringMatcher.java b/src/proguard/util/EmptyStringMatcher.java
index 543f446..f07c666 100644
--- a/src/proguard/util/EmptyStringMatcher.java
+++ b/src/proguard/util/EmptyStringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ExtensionMatcher.java b/src/proguard/util/ExtensionMatcher.java
index 5a9f658..eeb627a 100644
--- a/src/proguard/util/ExtensionMatcher.java
+++ b/src/proguard/util/ExtensionMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/FileNameParser.java b/src/proguard/util/FileNameParser.java
index 913f22d..9ec6d22 100644
--- a/src/proguard/util/FileNameParser.java
+++ b/src/proguard/util/FileNameParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/FixedStringMatcher.java b/src/proguard/util/FixedStringMatcher.java
index c1eb3f4..2f02271 100644
--- a/src/proguard/util/FixedStringMatcher.java
+++ b/src/proguard/util/FixedStringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ListMatcher.java b/src/proguard/util/ListMatcher.java
index b2559c8..e07bff0 100644
--- a/src/proguard/util/ListMatcher.java
+++ b/src/proguard/util/ListMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ListParser.java b/src/proguard/util/ListParser.java
index cec803b..b3b4518 100644
--- a/src/proguard/util/ListParser.java
+++ b/src/proguard/util/ListParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -68,7 +68,7 @@ public class ListParser implements StringParser
// Loop over all simple regular expressions, backward, creating a
// linked list of matchers.
- for (int index = regularExpressions.size()-1; index >=0; index--)
+ for (int index = regularExpressions.size()-1; index >= 0; index--)
{
String regularExpression = (String)regularExpressions.get(index);
diff --git a/src/proguard/util/ListUtil.java b/src/proguard/util/ListUtil.java
index 570dbe8..18bdce2 100644
--- a/src/proguard/util/ListUtil.java
+++ b/src/proguard/util/ListUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -34,7 +34,7 @@ public class ListUtil
/**
* Creates a comma-separated String from the given List of String objects.
*/
- public static String commaSeparatedString(List list)
+ public static String commaSeparatedString(List list, boolean quoteStrings)
{
if (list == null)
{
@@ -50,7 +50,14 @@ public class ListUtil
buffer.append(',');
}
- buffer.append(quotedString((String)list.get(index)));
+ String string = (String)list.get(index);
+
+ if (quoteStrings)
+ {
+ string = quotedString(string);
+ }
+
+ buffer.append(string);
}
return buffer.toString();
@@ -165,7 +172,7 @@ public class ListUtil
System.out.println("["+list.get(index)+"]");
}
- String string = commaSeparatedString(list);
+ String string = commaSeparatedString(list, true);
System.out.println("Resulting string: ["+string+"]");
}
diff --git a/src/proguard/util/NameParser.java b/src/proguard/util/NameParser.java
index e311fbf..f25d52e 100644
--- a/src/proguard/util/NameParser.java
+++ b/src/proguard/util/NameParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/NotMatcher.java b/src/proguard/util/NotMatcher.java
index f2a9a51..af539d0 100644
--- a/src/proguard/util/NotMatcher.java
+++ b/src/proguard/util/NotMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ObjectUtil.java b/src/proguard/util/ObjectUtil.java
new file mode 100644
index 0000000..c5de36a
--- /dev/null
+++ b/src/proguard/util/ObjectUtil.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package proguard.util;
+
+/**
+ * This class contains utility methods operating on objects.
+ */
+public class ObjectUtil
+{
+ /**
+ * Returns whether the given objects are the same.
+ * @param object1 the first object, may be null.
+ * @param object2 the second object, may be null.
+ * @return whether the objects are the same.
+ */
+ public static boolean equal(Object object1, Object object2)
+ {
+ return object1 == null ?
+ object2 == null :
+ object1.equals(object2);
+ }
+
+
+ /**
+ * Returns the hash code of the given object, or 0 if it is null.
+ * @param object the object, may be null.
+ * @return the hash code.
+ */
+ public static int hashCode(Object object)
+ {
+ return object == null ? 0 : object.hashCode();
+ }
+
+
+ /**
+ * Returns a comparison of the two given objects.
+ * @param object1 the first object, may be null.
+ * @param object2 the second object, may be null.
+ * @return -1, 0, or 1.
+ * @see Comparable#compareTo(Object)
+ */
+ public static int compare(Comparable object1, Comparable object2)
+ {
+ return object1 == null ?
+ object2 == null ? 0 : -1 :
+ object2 == null ? 1 : object1.compareTo(object2);
+ }
+}
diff --git a/src/proguard/util/OrMatcher.java b/src/proguard/util/OrMatcher.java
index 097c6c6..7ad85c4 100644
--- a/src/proguard/util/OrMatcher.java
+++ b/src/proguard/util/OrMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/SettableMatcher.java b/src/proguard/util/SettableMatcher.java
index 9557f62..8650ccc 100644
--- a/src/proguard/util/SettableMatcher.java
+++ b/src/proguard/util/SettableMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/StringMatcher.java b/src/proguard/util/StringMatcher.java
index bd66dcc..146dbfc 100644
--- a/src/proguard/util/StringMatcher.java
+++ b/src/proguard/util/StringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/StringParser.java b/src/proguard/util/StringParser.java
index 29f4f16..39d04d5 100644
--- a/src/proguard/util/StringParser.java
+++ b/src/proguard/util/StringParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/VariableStringMatcher.java b/src/proguard/util/VariableStringMatcher.java
index 1e41323..5a07c2a 100644
--- a/src/proguard/util/VariableStringMatcher.java
+++ b/src/proguard/util/VariableStringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/wtk/ProGuardObfuscator.java b/src/proguard/wtk/ProGuardObfuscator.java
index 4618437..b6f9ace 100644
--- a/src/proguard/wtk/ProGuardObfuscator.java
+++ b/src/proguard/wtk/ProGuardObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -71,7 +71,8 @@ public class ProGuardObfuscator implements Obfuscator
Configuration configuration = new Configuration();
// Parse the default configuration file.
- ConfigurationParser parser = new ConfigurationParser(this.getClass().getResource(DEFAULT_CONFIGURATION));
+ ConfigurationParser parser = new ConfigurationParser(this.getClass().getResource(DEFAULT_CONFIGURATION),
+ System.getProperties());
try
{