From cfead78069f3dc32998dc118ee08cab3867acea2 Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Mon, 27 Feb 2012 10:21:35 -0800 Subject: Upgrade from Progaurd 4.4 to 4.7. Change-Id: Ie185d0be411a80cc6a330cafa8547252a7dc1d9c You can find the changelog here http://proguard.sourceforge.net/#downloads.html --- src/proguard/ArgumentWordReader.java | 7 +- src/proguard/ClassPath.java | 2 +- src/proguard/ClassPathEntry.java | 137 ++- src/proguard/ClassSpecification.java | 2 +- src/proguard/ClassSpecificationVisitorFactory.java | 5 +- src/proguard/Configuration.java | 11 +- src/proguard/ConfigurationConstants.java | 4 +- src/proguard/ConfigurationParser.java | 172 +-- src/proguard/ConfigurationWriter.java | 44 +- src/proguard/DataEntryReaderFactory.java | 24 +- src/proguard/DataEntryWriterFactory.java | 26 +- src/proguard/DescriptorKeepChecker.java | 62 +- src/proguard/DuplicateClassPrinter.java | 2 +- src/proguard/FileWordReader.java | 52 +- src/proguard/FullyQualifiedClassNameChecker.java | 9 +- src/proguard/GPL.java | 14 +- src/proguard/Initializer.java | 23 +- src/proguard/InputReader.java | 4 +- src/proguard/KeepClassMemberChecker.java | 87 ++ src/proguard/KeepClassSpecification.java | 2 +- src/proguard/LineWordReader.java | 74 ++ src/proguard/MemberSpecification.java | 2 +- src/proguard/OutputWriter.java | 66 +- src/proguard/ParseException.java | 2 +- src/proguard/ProGuard.java | 51 +- src/proguard/SeedPrinter.java | 97 ++ src/proguard/SubclassedClassFilter.java | 2 +- src/proguard/Targeter.java | 2 +- src/proguard/UpToDateChecker.java | 219 ++-- src/proguard/WordReader.java | 127 +- src/proguard/ant/ClassPathElement.java | 2 +- src/proguard/ant/ClassSpecificationElement.java | 3 +- src/proguard/ant/ConfigurationElement.java | 2 +- src/proguard/ant/ConfigurationTask.java | 5 +- src/proguard/ant/FilterElement.java | 2 +- src/proguard/ant/KeepSpecificationElement.java | 2 +- src/proguard/ant/MemberSpecificationElement.java | 5 +- src/proguard/ant/ProGuardTask.java | 38 +- src/proguard/classfile/ClassConstants.java | 103 +- src/proguard/classfile/ClassPool.java | 19 +- src/proguard/classfile/Clazz.java | 31 +- src/proguard/classfile/Field.java | 2 +- src/proguard/classfile/LibraryClass.java | 61 +- src/proguard/classfile/LibraryField.java | 2 +- src/proguard/classfile/LibraryMember.java | 2 +- src/proguard/classfile/LibraryMethod.java | 2 +- src/proguard/classfile/Member.java | 2 +- src/proguard/classfile/Method.java | 2 +- src/proguard/classfile/ProgramClass.java | 92 +- src/proguard/classfile/ProgramField.java | 2 +- src/proguard/classfile/ProgramMember.java | 2 +- src/proguard/classfile/ProgramMethod.java | 2 +- src/proguard/classfile/VisitorAccepter.java | 2 +- src/proguard/classfile/attribute/Attribute.java | 2 +- .../classfile/attribute/BootstrapMethodInfo.java | 89 ++ .../attribute/BootstrapMethodsAttribute.java | 95 ++ .../classfile/attribute/CodeAttribute.java | 2 +- .../attribute/ConstantValueAttribute.java | 2 +- .../classfile/attribute/DeprecatedAttribute.java | 2 +- .../attribute/EnclosingMethodAttribute.java | 2 +- .../classfile/attribute/ExceptionInfo.java | 2 +- .../classfile/attribute/ExceptionsAttribute.java | 8 +- .../classfile/attribute/InnerClassesAttribute.java | 2 +- .../classfile/attribute/InnerClassesInfo.java | 11 +- .../classfile/attribute/LineNumberInfo.java | 2 +- .../attribute/LineNumberTableAttribute.java | 2 +- .../classfile/attribute/LocalVariableInfo.java | 20 +- .../attribute/LocalVariableTableAttribute.java | 2 +- .../classfile/attribute/LocalVariableTypeInfo.java | 20 +- .../attribute/LocalVariableTypeTableAttribute.java | 2 +- .../classfile/attribute/SignatureAttribute.java | 2 +- .../classfile/attribute/SourceDirAttribute.java | 2 +- .../classfile/attribute/SourceFileAttribute.java | 2 +- .../classfile/attribute/SyntheticAttribute.java | 2 +- .../classfile/attribute/UnknownAttribute.java | 2 +- .../classfile/attribute/annotation/Annotation.java | 2 +- .../annotation/AnnotationDefaultAttribute.java | 2 +- .../annotation/AnnotationElementValue.java | 2 +- .../attribute/annotation/AnnotationsAttribute.java | 2 +- .../attribute/annotation/ArrayElementValue.java | 2 +- .../attribute/annotation/ClassElementValue.java | 2 +- .../attribute/annotation/ConstantElementValue.java | 2 +- .../attribute/annotation/ElementValue.java | 2 +- .../annotation/EnumConstantElementValue.java | 2 +- .../annotation/ParameterAnnotationsAttribute.java | 2 +- .../RuntimeInvisibleAnnotationsAttribute.java | 2 +- ...timeInvisibleParameterAnnotationsAttribute.java | 2 +- .../RuntimeVisibleAnnotationsAttribute.java | 2 +- ...untimeVisibleParameterAnnotationsAttribute.java | 2 +- .../annotation/visitor/AllAnnotationVisitor.java | 2 +- .../annotation/visitor/AnnotatedClassVisitor.java | 2 +- .../visitor/AnnotationToMemberVisitor.java | 2 +- .../annotation/visitor/AnnotationTypeFilter.java | 2 +- .../annotation/visitor/AnnotationVisitor.java | 2 +- .../annotation/visitor/ElementValueVisitor.java | 2 +- .../attribute/preverification/DoubleType.java | 2 +- .../attribute/preverification/FloatType.java | 2 +- .../attribute/preverification/FullFrame.java | 2 +- .../attribute/preverification/IntegerType.java | 2 +- .../attribute/preverification/LessZeroFrame.java | 2 +- .../attribute/preverification/LongType.java | 2 +- .../attribute/preverification/MoreZeroFrame.java | 2 +- .../attribute/preverification/NullType.java | 2 +- .../attribute/preverification/ObjectType.java | 2 +- .../attribute/preverification/SameOneFrame.java | 2 +- .../attribute/preverification/SameZeroFrame.java | 2 +- .../preverification/StackMapAttribute.java | 2 +- .../attribute/preverification/StackMapFrame.java | 2 +- .../preverification/StackMapTableAttribute.java | 2 +- .../attribute/preverification/TopType.java | 2 +- .../preverification/UninitializedThisType.java | 2 +- .../preverification/UninitializedType.java | 2 +- .../preverification/VerificationType.java | 2 +- .../preverification/VerificationTypeFactory.java | 2 +- .../visitor/StackMapFrameVisitor.java | 2 +- .../visitor/VerificationTypeVisitor.java | 2 +- .../attribute/visitor/AllAttributeVisitor.java | 2 +- .../visitor/AllBootstrapMethodInfoVisitor.java | 55 + .../attribute/visitor/AllExceptionInfoVisitor.java | 2 +- .../visitor/AllInnerClassesInfoVisitor.java | 55 + .../attribute/visitor/AttributeNameFilter.java | 29 +- .../attribute/visitor/AttributeVisitor.java | 13 +- .../visitor/BootstrapMethodInfoVisitor.java | 40 + .../attribute/visitor/ExceptionInfoVisitor.java | 2 +- .../attribute/visitor/InnerClassesInfoVisitor.java | 2 +- .../attribute/visitor/LineNumberInfoVisitor.java | 2 +- .../visitor/LocalVariableInfoVisitor.java | 2 +- .../visitor/LocalVariableTypeInfoVisitor.java | 2 +- .../attribute/visitor/MultiAttributeVisitor.java | 11 +- .../attribute/visitor/NonEmptyAttributeFilter.java | 293 +++++ .../attribute/visitor/RequiredAttributeFilter.java | 11 +- .../attribute/visitor/StackSizeComputer.java | 9 +- src/proguard/classfile/constant/ClassConstant.java | 2 +- src/proguard/classfile/constant/Constant.java | 2 +- .../classfile/constant/DoubleConstant.java | 2 +- .../classfile/constant/FieldrefConstant.java | 2 +- src/proguard/classfile/constant/FloatConstant.java | 2 +- .../classfile/constant/IntegerConstant.java | 2 +- .../constant/InterfaceMethodrefConstant.java | 2 +- .../classfile/constant/InvokeDynamicConstant.java | 148 +++ src/proguard/classfile/constant/LongConstant.java | 2 +- .../classfile/constant/MethodHandleConstant.java | 124 ++ .../classfile/constant/MethodTypeConstant.java | 93 ++ .../classfile/constant/MethodrefConstant.java | 2 +- .../classfile/constant/NameAndTypeConstant.java | 2 +- src/proguard/classfile/constant/RefConstant.java | 2 +- .../classfile/constant/StringConstant.java | 2 +- src/proguard/classfile/constant/Utf8Constant.java | 2 +- .../constant/visitor/AllConstantVisitor.java | 2 +- .../visitor/BootstrapMethodHandleTraveler.java | 100 ++ .../constant/visitor/ConstantTagFilter.java | 86 ++ .../constant/visitor/ConstantVisitor.java | 5 +- .../visitor/ExceptClassConstantFilter.java | 12 +- .../constant/visitor/MethodrefTraveler.java | 60 + src/proguard/classfile/editor/AccessFixer.java | 28 +- src/proguard/classfile/editor/AnnotationAdder.java | 2 +- .../editor/AnnotationsAttributeEditor.java | 2 +- src/proguard/classfile/editor/AttributeAdder.java | 4 +- src/proguard/classfile/editor/AttributeSorter.java | 2 +- .../classfile/editor/AttributesEditor.java | 2 +- .../classfile/editor/BridgeMethodFixer.java | 117 ++ src/proguard/classfile/editor/ClassEditor.java | 2 +- .../classfile/editor/ClassElementSorter.java | 2 +- .../classfile/editor/ClassMemberSorter.java | 2 +- .../classfile/editor/ClassReferenceFixer.java | 2 +- .../classfile/editor/CodeAttributeComposer.java | 48 +- .../classfile/editor/CodeAttributeEditor.java | 161 +-- .../editor/CodeAttributeEditorResetter.java | 2 +- .../classfile/editor/ComparableConstant.java | 83 +- src/proguard/classfile/editor/ConstantAdder.java | 47 +- .../classfile/editor/ConstantPoolEditor.java | 119 +- .../classfile/editor/ConstantPoolRemapper.java | 105 +- .../classfile/editor/ConstantPoolShrinker.java | 578 +++++++++ .../classfile/editor/ConstantPoolSorter.java | 7 +- .../classfile/editor/ElementValueAdder.java | 2 +- .../classfile/editor/ElementValuesEditor.java | 2 +- src/proguard/classfile/editor/ExceptionAdder.java | 2 +- .../classfile/editor/ExceptionInfoAdder.java | 2 +- .../editor/ExceptionsAttributeEditor.java | 2 +- .../classfile/editor/InnerClassesAccessFixer.java | 83 ++ .../classfile/editor/InstructionAdder.java | 2 +- .../classfile/editor/InstructionWriter.java | 2 +- src/proguard/classfile/editor/InterfaceAdder.java | 2 +- src/proguard/classfile/editor/InterfaceSorter.java | 119 +- .../classfile/editor/InterfacesEditor.java | 2 +- .../classfile/editor/LineNumberInfoAdder.java | 2 +- .../editor/LineNumberTableAttributeEditor.java | 2 +- .../classfile/editor/LocalVariableInfoAdder.java | 2 +- .../editor/LocalVariableTableAttributeEditor.java | 2 +- .../editor/LocalVariableTypeInfoAdder.java | 2 +- .../LocalVariableTypeTableAttributeEditor.java | 2 +- src/proguard/classfile/editor/MemberAdder.java | 49 +- .../classfile/editor/MemberReferenceFixer.java | 37 +- .../classfile/editor/MethodInvocationFixer.java | 57 +- .../classfile/editor/NameAndTypeShrinker.java | 188 +++ .../classfile/editor/NamedAttributeDeleter.java | 2 +- .../ParameterAnnotationsAttributeEditor.java | 2 +- .../classfile/editor/StackSizeUpdater.java | 2 +- src/proguard/classfile/editor/SubclassAdder.java | 2 +- src/proguard/classfile/editor/SubclassToAdder.java | 2 +- src/proguard/classfile/editor/Utf8Shrinker.java | 455 ++++++++ src/proguard/classfile/editor/VariableCleaner.java | 204 +++- src/proguard/classfile/editor/VariableEditor.java | 11 +- .../classfile/editor/VariableRemapper.java | 75 +- .../classfile/editor/VariableSizeUpdater.java | 13 +- .../classfile/instruction/BranchInstruction.java | 2 +- .../classfile/instruction/ConstantInstruction.java | 34 +- .../classfile/instruction/Instruction.java | 8 +- .../instruction/InstructionConstants.java | 36 +- .../classfile/instruction/InstructionFactory.java | 3 +- .../classfile/instruction/InstructionUtil.java | 2 +- .../instruction/LookUpSwitchInstruction.java | 2 +- .../classfile/instruction/SimpleInstruction.java | 2 +- .../classfile/instruction/SwitchInstruction.java | 2 +- .../instruction/TableSwitchInstruction.java | 2 +- .../classfile/instruction/VariableInstruction.java | 2 +- .../instruction/visitor/AllInstructionVisitor.java | 2 +- .../instruction/visitor/InstructionCounter.java | 2 +- .../instruction/visitor/InstructionVisitor.java | 2 +- .../visitor/MultiInstructionVisitor.java | 2 +- src/proguard/classfile/io/LibraryClassReader.java | 25 +- src/proguard/classfile/io/ProgramClassReader.java | 79 +- src/proguard/classfile/io/ProgramClassWriter.java | 53 +- src/proguard/classfile/io/RuntimeDataInput.java | 2 +- src/proguard/classfile/io/RuntimeDataOutput.java | 2 +- src/proguard/classfile/util/AccessUtil.java | 2 +- .../classfile/util/ClassReferenceInitializer.java | 108 +- .../util/ClassSubHierarchyInitializer.java | 2 +- .../util/ClassSuperHierarchyInitializer.java | 7 +- src/proguard/classfile/util/ClassUtil.java | 85 +- .../classfile/util/DescriptorClassEnumeration.java | 2 +- .../util/DynamicClassReferenceInitializer.java | 21 +- .../util/DynamicMemberReferenceInitializer.java | 484 ++++++-- .../classfile/util/ExternalTypeEnumeration.java | 2 +- .../classfile/util/InstructionSequenceMatcher.java | 182 ++- .../classfile/util/InternalTypeEnumeration.java | 2 +- src/proguard/classfile/util/MemberFinder.java | 2 +- src/proguard/classfile/util/MethodLinker.java | 19 +- src/proguard/classfile/util/SimplifiedVisitor.java | 28 +- .../classfile/util/StringReferenceInitializer.java | 5 +- src/proguard/classfile/util/StringSharer.java | 21 +- src/proguard/classfile/util/WarningPrinter.java | 2 +- .../classfile/visitor/AllClassVisitor.java | 2 +- .../classfile/visitor/AllFieldVisitor.java | 2 +- .../classfile/visitor/AllMemberVisitor.java | 2 +- .../classfile/visitor/AllMethodVisitor.java | 2 +- .../classfile/visitor/BottomClassFilter.java | 2 +- .../classfile/visitor/ClassAccessFilter.java | 2 +- src/proguard/classfile/visitor/ClassCleaner.java | 2 +- src/proguard/classfile/visitor/ClassCollector.java | 2 +- src/proguard/classfile/visitor/ClassCounter.java | 2 +- .../visitor/ClassForNameClassVisitor.java | 66 -- .../classfile/visitor/ClassHierarchyTraveler.java | 2 +- .../classfile/visitor/ClassNameFilter.java | 2 +- .../classfile/visitor/ClassPoolFiller.java | 2 +- .../classfile/visitor/ClassPoolVisitor.java | 2 +- .../classfile/visitor/ClassPresenceFilter.java | 2 +- src/proguard/classfile/visitor/ClassPrinter.java | 69 +- .../classfile/visitor/ClassVersionFilter.java | 15 +- .../classfile/visitor/ClassVersionSetter.java | 2 +- src/proguard/classfile/visitor/ClassVisitor.java | 2 +- .../visitor/ConcreteClassDownTraveler.java | 2 +- .../classfile/visitor/DotClassClassVisitor.java | 4 +- .../classfile/visitor/ExceptClassFilter.java | 2 +- .../classfile/visitor/ExceptClassesFilter.java | 2 +- .../classfile/visitor/ExceptionCounter.java | 2 +- .../visitor/ExceptionExcludedOffsetFilter.java | 2 +- .../visitor/ExceptionHandlerConstantVisitor.java | 2 +- .../classfile/visitor/ExceptionHandlerFilter.java | 2 +- .../classfile/visitor/ExceptionOffsetFilter.java | 2 +- .../classfile/visitor/ExceptionRangeFilter.java | 2 +- .../visitor/ImplementedClassConstantFilter.java | 2 +- .../classfile/visitor/ImplementedClassFilter.java | 2 +- .../visitor/ImplementingClassConstantFilter.java | 2 +- .../classfile/visitor/LibraryClassFilter.java | 2 +- .../classfile/visitor/LibraryMemberFilter.java | 2 +- .../classfile/visitor/MemberAccessFilter.java | 2 +- .../classfile/visitor/MemberClassAccessFilter.java | 2 +- .../classfile/visitor/MemberCollector.java | 2 +- src/proguard/classfile/visitor/MemberCounter.java | 2 +- .../classfile/visitor/MemberDescriptorFilter.java | 2 +- .../classfile/visitor/MemberNameFilter.java | 2 +- .../classfile/visitor/MemberToClassVisitor.java | 2 +- src/proguard/classfile/visitor/MemberVisitor.java | 2 +- .../visitor/MethodImplementationFilter.java | 2 +- .../visitor/MethodImplementationTraveler.java | 2 +- .../classfile/visitor/MultiClassPoolVisitor.java | 2 +- .../classfile/visitor/MultiClassVisitor.java | 2 +- .../classfile/visitor/MultiMemberVisitor.java | 2 +- .../classfile/visitor/NamedClassVisitor.java | 2 +- .../classfile/visitor/NamedFieldVisitor.java | 2 +- .../classfile/visitor/NamedMethodVisitor.java | 2 +- .../classfile/visitor/ProgramClassFilter.java | 2 +- .../classfile/visitor/ProgramMemberFilter.java | 2 +- .../classfile/visitor/ReferencedClassVisitor.java | 9 +- .../classfile/visitor/ReferencedMemberVisitor.java | 2 +- .../classfile/visitor/SimilarMemberVisitor.java | 2 +- .../classfile/visitor/SimpleClassPrinter.java | 2 +- src/proguard/classfile/visitor/SubclassFilter.java | 2 +- .../classfile/visitor/SubclassTraveler.java | 2 +- .../classfile/visitor/VariableClassVisitor.java | 2 +- .../classfile/visitor/VariableMemberVisitor.java | 2 +- src/proguard/evaluation/BasicBranchUnit.java | 2 +- src/proguard/evaluation/BasicInvocationUnit.java | 47 +- src/proguard/evaluation/BranchUnit.java | 2 +- .../evaluation/ClassConstantValueFactory.java | 53 + src/proguard/evaluation/ConstantValueFactory.java | 113 ++ src/proguard/evaluation/InvocationUnit.java | 2 +- src/proguard/evaluation/Processor.java | 101 +- src/proguard/evaluation/Stack.java | 9 +- src/proguard/evaluation/TracedStack.java | 2 +- src/proguard/evaluation/TracedVariables.java | 32 +- src/proguard/evaluation/Variables.java | 9 +- src/proguard/evaluation/value/Category1Value.java | 2 +- src/proguard/evaluation/value/Category2Value.java | 2 +- src/proguard/evaluation/value/ComparisonValue.java | 10 +- .../evaluation/value/CompositeDoubleValue.java | 2 +- .../evaluation/value/CompositeFloatValue.java | 10 +- .../evaluation/value/CompositeIntegerValue.java | 2 +- .../evaluation/value/CompositeLongValue.java | 2 +- .../evaluation/value/ConvertedByteValue.java | 2 +- .../evaluation/value/ConvertedCharacterValue.java | 2 +- .../evaluation/value/ConvertedDoubleValue.java | 2 +- .../evaluation/value/ConvertedFloatValue.java | 2 +- .../evaluation/value/ConvertedIntegerValue.java | 2 +- .../evaluation/value/ConvertedLongValue.java | 2 +- .../evaluation/value/ConvertedShortValue.java | 2 +- src/proguard/evaluation/value/DoubleValue.java | 7 +- src/proguard/evaluation/value/FloatValue.java | 2 +- .../evaluation/value/IdentifiedDoubleValue.java | 2 +- .../evaluation/value/IdentifiedFloatValue.java | 2 +- .../evaluation/value/IdentifiedIntegerValue.java | 2 +- .../evaluation/value/IdentifiedLongValue.java | 2 +- .../evaluation/value/IdentifiedReferenceValue.java | 13 +- .../evaluation/value/IdentifiedValueFactory.java | 2 +- .../evaluation/value/InstructionOffsetValue.java | 2 +- src/proguard/evaluation/value/IntegerValue.java | 2 +- src/proguard/evaluation/value/LongValue.java | 2 +- .../evaluation/value/NegatedDoubleValue.java | 2 +- .../evaluation/value/NegatedFloatValue.java | 2 +- .../evaluation/value/NegatedIntegerValue.java | 2 +- .../evaluation/value/NegatedLongValue.java | 2 +- .../evaluation/value/ParticularDoubleValue.java | 14 +- .../evaluation/value/ParticularFloatValue.java | 14 +- .../evaluation/value/ParticularIntegerValue.java | 2 +- .../evaluation/value/ParticularLongValue.java | 2 +- src/proguard/evaluation/value/ReferenceValue.java | 40 +- .../evaluation/value/SpecificDoubleValue.java | 11 +- .../evaluation/value/SpecificFloatValue.java | 11 +- .../evaluation/value/SpecificIntegerValue.java | 2 +- .../evaluation/value/SpecificLongValue.java | 2 +- .../evaluation/value/SpecificValueFactory.java | 14 +- src/proguard/evaluation/value/TopValue.java | 2 +- .../evaluation/value/UnknownDoubleValue.java | 2 +- .../evaluation/value/UnknownFloatValue.java | 2 +- .../evaluation/value/UnknownIntegerValue.java | 2 +- .../evaluation/value/UnknownLongValue.java | 2 +- src/proguard/evaluation/value/Value.java | 2 +- src/proguard/evaluation/value/ValueFactory.java | 2 +- src/proguard/gui/ClassPathPanel.java | 8 +- src/proguard/gui/ClassSpecificationDialog.java | 22 +- src/proguard/gui/ClassSpecificationsPanel.java | 2 +- src/proguard/gui/ExtensionFileFilter.java | 2 +- src/proguard/gui/FilterBuilder.java | 2 +- src/proguard/gui/FilterDialog.java | 12 +- src/proguard/gui/GUIResources.java | 2 +- src/proguard/gui/GUIResources.properties | 46 +- src/proguard/gui/KeepSpecificationsPanel.java | 2 +- src/proguard/gui/ListPanel.java | 2 +- src/proguard/gui/MemberSpecificationDialog.java | 14 +- src/proguard/gui/MemberSpecificationsPanel.java | 2 +- src/proguard/gui/MessageDialogRunnable.java | 2 +- src/proguard/gui/OptimizationsDialog.java | 2 +- src/proguard/gui/ProGuardGUI.java | 173 +-- src/proguard/gui/ProGuardRunnable.java | 2 +- src/proguard/gui/ReTraceRunnable.java | 2 +- src/proguard/gui/SwingUtil.java | 2 +- src/proguard/gui/TabbedPane.java | 2 +- src/proguard/gui/TextAreaOutputStream.java | 2 +- src/proguard/gui/splash/BufferedSprite.java | 2 +- src/proguard/gui/splash/CircleSprite.java | 2 +- src/proguard/gui/splash/ClipSprite.java | 2 +- src/proguard/gui/splash/ColorSprite.java | 2 +- src/proguard/gui/splash/CompositeSprite.java | 2 +- src/proguard/gui/splash/ConstantColor.java | 2 +- src/proguard/gui/splash/ConstantDouble.java | 2 +- src/proguard/gui/splash/ConstantFont.java | 2 +- src/proguard/gui/splash/ConstantInt.java | 2 +- src/proguard/gui/splash/ConstantString.java | 2 +- src/proguard/gui/splash/ConstantTiming.java | 2 +- src/proguard/gui/splash/FontSprite.java | 2 +- src/proguard/gui/splash/ImageSprite.java | 2 +- src/proguard/gui/splash/LinearColor.java | 2 +- src/proguard/gui/splash/LinearDouble.java | 2 +- src/proguard/gui/splash/LinearInt.java | 2 +- src/proguard/gui/splash/LinearTiming.java | 2 +- src/proguard/gui/splash/OverrideGraphics2D.java | 2 +- src/proguard/gui/splash/RectangleSprite.java | 2 +- src/proguard/gui/splash/SawToothTiming.java | 2 +- src/proguard/gui/splash/ShadowedSprite.java | 2 +- src/proguard/gui/splash/SineTiming.java | 2 +- src/proguard/gui/splash/SmoothTiming.java | 2 +- src/proguard/gui/splash/SplashPanel.java | 2 +- src/proguard/gui/splash/Sprite.java | 2 +- src/proguard/gui/splash/TextSprite.java | 2 +- src/proguard/gui/splash/TimeSwitchSprite.java | 2 +- src/proguard/gui/splash/Timing.java | 2 +- src/proguard/gui/splash/TypeWriterString.java | 2 +- src/proguard/gui/splash/VariableColor.java | 2 +- src/proguard/gui/splash/VariableDouble.java | 2 +- src/proguard/gui/splash/VariableFont.java | 2 +- src/proguard/gui/splash/VariableInt.java | 2 +- src/proguard/gui/splash/VariableSizeFont.java | 2 +- src/proguard/gui/splash/VariableString.java | 2 +- src/proguard/io/CascadingDataEntryWriter.java | 2 +- src/proguard/io/ClassFilter.java | 2 +- src/proguard/io/ClassReader.java | 4 +- src/proguard/io/ClassRewriter.java | 2 +- src/proguard/io/DataEntry.java | 2 +- src/proguard/io/DataEntryClassWriter.java | 85 ++ src/proguard/io/DataEntryCopier.java | 2 +- src/proguard/io/DataEntryDirectoryFilter.java | 2 +- src/proguard/io/DataEntryFilter.java | 2 +- src/proguard/io/DataEntryNameFilter.java | 2 +- src/proguard/io/DataEntryObfuscator.java | 47 +- src/proguard/io/DataEntryParentFilter.java | 2 +- src/proguard/io/DataEntryPump.java | 2 +- src/proguard/io/DataEntryReader.java | 2 +- src/proguard/io/DataEntryRenamer.java | 6 +- src/proguard/io/DataEntryRewriter.java | 2 +- src/proguard/io/DataEntryWriter.java | 2 +- src/proguard/io/DirectoryFilter.java | 2 +- src/proguard/io/DirectoryPump.java | 2 +- src/proguard/io/DirectoryWriter.java | 2 +- src/proguard/io/FileDataEntry.java | 2 +- src/proguard/io/FilteredDataEntryReader.java | 2 +- src/proguard/io/FilteredDataEntryWriter.java | 2 +- src/proguard/io/Finisher.java | 2 +- src/proguard/io/JarReader.java | 2 +- src/proguard/io/JarWriter.java | 2 +- src/proguard/io/ManifestRewriter.java | 2 +- src/proguard/io/NameFilter.java | 2 +- src/proguard/io/ParentDataEntryWriter.java | 2 +- src/proguard/io/RenamedDataEntry.java | 2 +- src/proguard/io/ZipDataEntry.java | 2 +- src/proguard/obfuscate/AttributeShrinker.java | 9 +- src/proguard/obfuscate/AttributeUsageMarker.java | 4 +- src/proguard/obfuscate/ClassObfuscator.java | 16 +- src/proguard/obfuscate/ClassRenamer.java | 2 +- src/proguard/obfuscate/DictionaryNameFactory.java | 2 +- src/proguard/obfuscate/MapCleaner.java | 2 +- src/proguard/obfuscate/MappingKeeper.java | 2 +- src/proguard/obfuscate/MappingPrinter.java | 2 +- src/proguard/obfuscate/MappingProcessor.java | 2 +- src/proguard/obfuscate/MappingReader.java | 2 +- src/proguard/obfuscate/MemberNameCleaner.java | 2 +- src/proguard/obfuscate/MemberNameCollector.java | 2 +- .../obfuscate/MemberNameConflictFixer.java | 2 +- src/proguard/obfuscate/MemberNameFilter.java | 120 ++ src/proguard/obfuscate/MemberObfuscator.java | 2 +- .../obfuscate/MemberSpecialNameFilter.java | 12 +- src/proguard/obfuscate/MultiMappingProcessor.java | 2 +- src/proguard/obfuscate/NameAndTypeShrinker.java | 112 -- src/proguard/obfuscate/NameAndTypeUsageMarker.java | 135 --- src/proguard/obfuscate/NameFactory.java | 2 +- src/proguard/obfuscate/NameFactoryResetter.java | 2 +- src/proguard/obfuscate/NameMarker.java | 2 +- src/proguard/obfuscate/NumericNameFactory.java | 2 +- src/proguard/obfuscate/Obfuscator.java | 44 +- src/proguard/obfuscate/ParameterNameMarker.java | 128 ++ src/proguard/obfuscate/SimpleNameFactory.java | 2 +- src/proguard/obfuscate/SourceFileRenamer.java | 2 +- src/proguard/obfuscate/SpecialNameFactory.java | 2 +- src/proguard/obfuscate/Utf8Shrinker.java | 110 -- src/proguard/obfuscate/Utf8UsageMarker.java | 392 ------- .../optimize/BootstrapMethodArgumentShrinker.java | 103 ++ src/proguard/optimize/ChangedCodePrinter.java | 8 +- src/proguard/optimize/ConstantMemberFilter.java | 2 +- src/proguard/optimize/ConstantParameterFilter.java | 2 +- .../optimize/DuplicateInitializerFixer.java | 34 +- .../DuplicateInitializerInvocationFixer.java | 37 +- src/proguard/optimize/KeepMarker.java | 2 +- src/proguard/optimize/KeptClassFilter.java | 69 ++ src/proguard/optimize/KeptMemberFilter.java | 88 ++ .../optimize/MemberDescriptorSpecializer.java | 4 +- .../optimize/MethodDescriptorShrinker.java | 12 +- src/proguard/optimize/MethodStaticizer.java | 2 +- .../optimize/OptimizationInfoMemberFilter.java | 2 +- src/proguard/optimize/Optimizer.java | 197 +++- src/proguard/optimize/ParameterShrinker.java | 4 +- src/proguard/optimize/TailRecursionSimplifier.java | 101 +- src/proguard/optimize/WriteOnlyFieldFilter.java | 2 +- .../optimize/evaluation/EvaluationShrinker.java | 290 ++++- .../optimize/evaluation/EvaluationSimplifier.java | 15 +- .../optimize/evaluation/LivenessAnalyzer.java | 12 +- .../optimize/evaluation/LoadingInvocationUnit.java | 20 +- .../optimize/evaluation/PartialEvaluator.java | 141 ++- .../optimize/evaluation/StoringInvocationUnit.java | 2 +- .../optimize/evaluation/TracedBranchUnit.java | 2 +- .../optimize/evaluation/VariableOptimizer.java | 127 +- src/proguard/optimize/info/AccessMethodMarker.java | 19 +- .../optimize/info/BackwardBranchMarker.java | 2 +- .../optimize/info/CatchExceptionMarker.java | 2 +- src/proguard/optimize/info/CaughtClassFilter.java | 2 +- src/proguard/optimize/info/CaughtClassMarker.java | 7 +- .../optimize/info/ClassOptimizationInfo.java | 16 +- .../optimize/info/ClassOptimizationInfoSetter.java | 2 +- src/proguard/optimize/info/DotClassFilter.java | 2 +- src/proguard/optimize/info/DotClassMarker.java | 2 +- .../optimize/info/ExceptionInstructionChecker.java | 104 +- .../optimize/info/FieldOptimizationInfo.java | 56 +- .../optimize/info/InstanceofClassFilter.java | 2 +- .../optimize/info/InstanceofClassMarker.java | 2 +- .../optimize/info/InstantiationClassFilter.java | 2 +- .../optimize/info/InstantiationClassMarker.java | 2 +- .../info/MemberOptimizationInfoSetter.java | 18 +- .../optimize/info/MethodInvocationMarker.java | 2 +- .../optimize/info/MethodOptimizationInfo.java | 6 +- .../optimize/info/NoSideEffectMethodMarker.java | 2 +- .../optimize/info/NonPrivateMemberMarker.java | 16 +- .../PackageVisibleMemberContainingClassMarker.java | 28 +- .../PackageVisibleMemberInvokingClassMarker.java | 72 +- .../optimize/info/ParameterUsageMarker.java | 8 +- .../optimize/info/ReadWriteFieldMarker.java | 2 +- .../info/SideEffectInstructionChecker.java | 109 +- .../optimize/info/SideEffectMethodMarker.java | 2 +- .../StaticInitializerContainingClassFilter.java | 62 + .../StaticInitializerContainingClassMarker.java | 65 ++ .../optimize/info/SuperInvocationMarker.java | 2 +- .../optimize/info/VariableUsageMarker.java | 11 +- .../optimize/peephole/BranchTargetFinder.java | 28 +- src/proguard/optimize/peephole/ClassFinalizer.java | 2 +- src/proguard/optimize/peephole/ClassMerger.java | 57 +- .../optimize/peephole/GotoCommonCodeReplacer.java | 2 +- .../optimize/peephole/GotoGotoReplacer.java | 7 +- .../optimize/peephole/GotoReturnReplacer.java | 2 +- .../optimize/peephole/HorizontalClassMerger.java | 2 +- .../peephole/InstructionSequenceConstants.java | 1233 ++++++++++++++++++-- .../peephole/InstructionSequenceReplacer.java | 164 ++- .../peephole/InstructionSequencesReplacer.java | 2 +- .../optimize/peephole/MemberPrivatizer.java | 2 +- .../optimize/peephole/MethodFinalizer.java | 2 +- src/proguard/optimize/peephole/MethodInliner.java | 120 +- src/proguard/optimize/peephole/NopRemover.java | 2 +- .../optimize/peephole/PeepholeOptimizer.java | 2 +- .../optimize/peephole/ReachableCodeMarker.java | 9 +- .../RetargetedInnerClassAttributeRemover.java | 44 +- .../optimize/peephole/TargetClassChanger.java | 62 +- .../optimize/peephole/UnreachableCodeRemover.java | 2 +- .../peephole/UnreachableExceptionRemover.java | 2 +- .../optimize/peephole/VariableShrinker.java | 2 +- .../optimize/peephole/VerticalClassMerger.java | 2 +- src/proguard/preverify/CodePreverifier.java | 2 +- src/proguard/preverify/CodeSubroutineInliner.java | 3 +- src/proguard/preverify/Preverifier.java | 7 +- src/proguard/preverify/SubroutineInliner.java | 3 +- src/proguard/retrace/ReTrace.java | 4 +- src/proguard/shrink/AnnotationUsageMarker.java | 38 +- src/proguard/shrink/ClassShrinker.java | 52 +- src/proguard/shrink/InnerUsageMarker.java | 2 +- src/proguard/shrink/InterfaceUsageMarker.java | 2 +- src/proguard/shrink/ShortestUsageMark.java | 2 +- src/proguard/shrink/ShortestUsageMarker.java | 2 +- src/proguard/shrink/ShortestUsagePrinter.java | 2 +- src/proguard/shrink/Shrinker.java | 17 +- src/proguard/shrink/UsageMarker.java | 174 ++- src/proguard/shrink/UsagePrinter.java | 2 +- src/proguard/shrink/UsedClassFilter.java | 2 +- src/proguard/shrink/UsedMemberFilter.java | 4 +- src/proguard/util/AndMatcher.java | 2 +- src/proguard/util/ClassNameParser.java | 2 +- src/proguard/util/ConstantMatcher.java | 2 +- src/proguard/util/EmptyStringMatcher.java | 2 +- src/proguard/util/ExtensionMatcher.java | 2 +- src/proguard/util/FileNameParser.java | 2 +- src/proguard/util/FixedStringMatcher.java | 2 +- src/proguard/util/ListMatcher.java | 2 +- src/proguard/util/ListParser.java | 2 +- src/proguard/util/ListUtil.java | 15 +- src/proguard/util/NameParser.java | 2 +- src/proguard/util/NotMatcher.java | 2 +- src/proguard/util/OrMatcher.java | 2 +- src/proguard/util/SettableMatcher.java | 2 +- src/proguard/util/StringMatcher.java | 2 +- src/proguard/util/StringParser.java | 2 +- src/proguard/util/VariableStringMatcher.java | 2 +- src/proguard/wtk/ProGuardObfuscator.java | 2 +- 587 files changed, 10341 insertions(+), 3374 deletions(-) create mode 100644 src/proguard/KeepClassMemberChecker.java create mode 100644 src/proguard/LineWordReader.java create mode 100644 src/proguard/SeedPrinter.java create mode 100755 src/proguard/classfile/attribute/BootstrapMethodInfo.java create mode 100755 src/proguard/classfile/attribute/BootstrapMethodsAttribute.java create mode 100644 src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java create mode 100644 src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java create mode 100755 src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java create mode 100644 src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java create mode 100755 src/proguard/classfile/constant/InvokeDynamicConstant.java create mode 100755 src/proguard/classfile/constant/MethodHandleConstant.java create mode 100644 src/proguard/classfile/constant/MethodTypeConstant.java create mode 100644 src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java create mode 100644 src/proguard/classfile/constant/visitor/ConstantTagFilter.java create mode 100644 src/proguard/classfile/constant/visitor/MethodrefTraveler.java create mode 100644 src/proguard/classfile/editor/BridgeMethodFixer.java create mode 100644 src/proguard/classfile/editor/ConstantPoolShrinker.java create mode 100644 src/proguard/classfile/editor/InnerClassesAccessFixer.java create mode 100644 src/proguard/classfile/editor/NameAndTypeShrinker.java create mode 100644 src/proguard/classfile/editor/Utf8Shrinker.java delete mode 100644 src/proguard/classfile/visitor/ClassForNameClassVisitor.java create mode 100644 src/proguard/evaluation/ClassConstantValueFactory.java create mode 100644 src/proguard/evaluation/ConstantValueFactory.java create mode 100644 src/proguard/io/DataEntryClassWriter.java create mode 100644 src/proguard/obfuscate/MemberNameFilter.java delete mode 100644 src/proguard/obfuscate/NameAndTypeShrinker.java delete mode 100644 src/proguard/obfuscate/NameAndTypeUsageMarker.java create mode 100644 src/proguard/obfuscate/ParameterNameMarker.java delete mode 100644 src/proguard/obfuscate/Utf8Shrinker.java delete mode 100644 src/proguard/obfuscate/Utf8UsageMarker.java create mode 100644 src/proguard/optimize/BootstrapMethodArgumentShrinker.java create mode 100644 src/proguard/optimize/KeptClassFilter.java create mode 100644 src/proguard/optimize/KeptMemberFilter.java create mode 100644 src/proguard/optimize/info/StaticInitializerContainingClassFilter.java create mode 100644 src/proguard/optimize/info/StaticInitializerContainingClassMarker.java (limited to 'src/proguard') diff --git a/src/proguard/ArgumentWordReader.java b/src/proguard/ArgumentWordReader.java index 89f3824..eb0e642 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..6851a84 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..17f1f54 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..eb52fc3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..042a367 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..2a39870 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 @@ 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 @@ -236,6 +236,13 @@ 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. */ diff --git a/src/proguard/ConfigurationConstants.java b/src/proguard/ConfigurationConstants.java index 694e006..0da4b5d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..0a6e296 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +58,21 @@ public class ConfigurationParser public ConfigurationParser(String[] args, File baseDir) throws IOException { - reader = new ArgumentWordReader(args, baseDir); + this(new ArgumentWordReader(args, baseDir)); + } - readNextWord(); + + /** + * Creates a new ConfigurationParser for the given lines, + * with the given base directory. + */ + public ConfigurationParser(String lines, + String description, + File baseDir) throws IOException + { + this(new LineWordReader(new LineNumberReader(new StringReader(lines)), + description, + baseDir)); } @@ -69,9 +81,7 @@ public class ConfigurationParser */ public ConfigurationParser(File file) throws IOException { - reader = new FileWordReader(file); - - readNextWord(); + this(new FileWordReader(file)); } @@ -80,7 +90,16 @@ public class ConfigurationParser */ public ConfigurationParser(URL url) throws IOException { - reader = new FileWordReader(url); + this(new FileWordReader(url)); + } + + + /** + * Creates a new ConfigurationParser for the given word reader. + */ + public ConfigurationParser(WordReader reader) throws IOException + { + this.reader = reader; readNextWord(); } @@ -110,6 +129,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 +144,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 +152,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 +166,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 +211,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 +225,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 +246,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 +266,7 @@ public class ConfigurationParser { // Read the filter. filters[counter++] = - parseCommaSeparatedList("filter", true, false, true, false, true, false, false, null); + parseCommaSeparatedList("filter", true, false, true, true, false, true, false, false, null); } while (counter < filters.length && ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord)); @@ -343,7 +364,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,7 +379,7 @@ public class ConfigurationParser throws ParseException, IOException { // Read the optional file name. - readNextWord(); + readNextWord(true); // Didn't the user specify a file name? if (configurationEnd()) @@ -386,11 +407,11 @@ public class ConfigurationParser return ""; } - String fileName = nextWord; + String argument = nextWord; readNextWord(); - return fileName; + return argument; } @@ -431,7 +452,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 +513,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()); @@ -512,30 +535,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 +557,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 +570,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 +589,6 @@ public class ConfigurationParser requiredUnsetClassAccessFlags |= accessFlag; } - if ((requiredSetClassAccessFlags & requiredUnsetClassAccessFlags) != 0) { @@ -585,16 +604,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 +636,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 +644,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 +683,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 +722,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 +740,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 +902,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)) { @@ -921,6 +948,7 @@ public class ConfigurationParser boolean readFirstWord, boolean allowEmptyList, boolean expectClosingParenthesis, + boolean isFileName, boolean checkJavaIdentifiers, boolean replaceSystemProperties, boolean replaceExternalClassNames, @@ -938,12 +966,12 @@ public class ConfigurationParser if (expectClosingParenthesis || !allowEmptyList) { // Read the first list entry. - readNextWord(expectedDescription); + readNextWord(expectedDescription, isFileName, false); } else { // Read the first list entry, if there is any. - readNextWord(); + readNextWord(isFileName); // Check if the list is empty. if (configurationEnd() || @@ -1005,7 +1033,7 @@ public class ConfigurationParser } // Read the next list entry. - readNextWord(expectedDescription); + readNextWord(expectedDescription, isFileName, false); } return list; @@ -1035,16 +1063,6 @@ 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; } @@ -1096,7 +1114,7 @@ public class ConfigurationParser private void readNextWord(String expectedDescription) throws ParseException, IOException { - readNextWord(expectedDescription, false); + readNextWord(expectedDescription, false, false); } @@ -1105,10 +1123,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 +1141,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); } diff --git a/src/proguard/ConfigurationWriter.java b/src/proguard/ConfigurationWriter.java index 5d112d6..cd83515 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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)); } } } @@ -584,6 +575,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..5b9c711 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..0da890b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..7849693 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..9ade21b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e0325b7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..7534fb4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..9327b8b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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."); } } @@ -165,9 +166,14 @@ public class GPL packageName.startsWith("org.apache.tools.maven") || packageName.startsWith("org.eclipse") || packageName.startsWith("org.netbeans") || + packageName.startsWith("com.android") || packageName.startsWith("com.sun.kvem") || packageName.startsWith("net.certiv.proguarddt") || + 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..dc17b00 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -60,6 +60,11 @@ public class Initializer { int originalLibraryClassPoolSize = libraryClassPool.size(); + // Perform a basic check on the keep options in the configuration. + WarningPrinter keepClassMemberNotePrinter = new WarningPrinter(System.out, configuration.note); + + 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 @@ -275,8 +280,12 @@ 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 specify additional library jars (using '-libraryjars')."); + + if (configuration.skipNonPublicLibraryClasses) + { + System.err.println(" You may also have to remove the option '-skipnonpubliclibraryclasses'."); + } } int dependencyWarningCount = dependencyWarningPrinter.getWarningCount(); @@ -295,9 +304,13 @@ public class Initializer " 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(" 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'."); + } } if ((classReferenceWarningCount > 0 || diff --git a/src/proguard/InputReader.java b/src/proguard/InputReader.java index c088324..9ee1314 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -227,7 +227,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..a6546d9 --- /dev/null +++ b/src/proguard/KeepClassMemberChecker.java @@ -0,0 +1,87 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 (className != null && + notePrinter.accepts(className)) + { + notePrinter.print(className, + "Note: the configuration doesn't specify which class members to keep for class '" + + ClassUtil.externalClassName(className) + "'"); + } + } + } + } + } +} diff --git a/src/proguard/KeepClassSpecification.java b/src/proguard/KeepClassSpecification.java index 29c0d3c..c30538a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b8c9126 --- /dev/null +++ b/src/proguard/LineWordReader.java @@ -0,0 +1,74 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 WordReader 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..025f3b8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..39dd1ad 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 '-dontusemixedclassnames'."); + + 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..2f3af01 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..913207a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +24,7 @@ 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; @@ -37,7 +37,7 @@ import java.io.*; */ public class ProGuard { - public static final String VERSION = "ProGuard, version 4.4"; + public static final String VERSION = "ProGuard, version 4.7"; private final Configuration configuration; private ClassPool programClassPool = new ClassPool(); @@ -77,7 +77,8 @@ public class ProGuard readInput(); - if (configuration.shrink || + if (configuration.printSeeds != null || + configuration.shrink || configuration.optimize || configuration.obfuscate || configuration.preverify) @@ -236,30 +237,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 { @@ -445,14 +426,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"; + if (isFile(file)) + { + try + { + return file.getCanonicalPath(); + } + catch (IOException ex) + { + return file.getPath(); + } + } + else + { + return "standard output"; + } } diff --git a/src/proguard/SeedPrinter.java b/src/proguard/SeedPrinter.java new file mode 100644 index 0000000..aee8f60 --- /dev/null +++ b/src/proguard/SeedPrinter.java @@ -0,0 +1,97 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..78afb7f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..16583bf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c743af9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..4e7a511 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..53084d3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..81b0c1b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..f283b8d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ConfigurationTask.java b/src/proguard/ant/ConfigurationTask.java index 0d2f04f..6c4d48a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -293,7 +293,8 @@ public class ConfigurationTask extends Task { String arg = getProject().replaceProperties(text); - ConfigurationParser parser = new ConfigurationParser(new String[] { arg }, + ConfigurationParser parser = new ConfigurationParser(arg, + "embedded configuration", getProject().getBaseDir()); try diff --git a/src/proguard/ant/FilterElement.java b/src/proguard/ant/FilterElement.java index d792c5d..1174bd5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2ac61e8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/MemberSpecificationElement.java b/src/proguard/ant/MemberSpecificationElement.java index d4bb4a9..789cc5e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -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..982c2dd 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -215,6 +215,12 @@ public class ProGuardTask extends ConfigurationTask } + public void setKeepparameternames(boolean keepParameterNames) + { + configuration.keepParameterNames = keepParameterNames; + } + + public void setRenamesourcefileattribute(String newSourceFileAttribute) { configuration.newSourceFileAttribute = newSourceFileAttribute; @@ -241,13 +247,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(); + } } diff --git a/src/proguard/classfile/ClassConstants.java b/src/proguard/classfile/ClassConstants.java index 3b243e0..081305b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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"; @@ -179,32 +201,48 @@ 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 = ""; public static final String INTERNAL_METHOD_TYPE_INIT = "()V"; public static final String INTERNAL_METHOD_NAME_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;"; @@ -214,6 +252,29 @@ public interface ClassConstants 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_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_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_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..c5defe8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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(); /** @@ -66,11 +68,11 @@ public class ClassPool /** * Returns a Clazz from the class pool based on its name. Returns * null 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 +124,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..3dfdcd0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. @@ -115,6 +125,13 @@ 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. @@ -122,6 +139,13 @@ public interface Clazz extends VisitorAccepter */ 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..c30321d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..625d088 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..e9c8469 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ef5a4d7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..cd95ea6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2e984c2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ec8f2b5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e3caddb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..761fe95 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..86d12d9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ProgramMethod.java b/src/proguard/classfile/ProgramMethod.java index 943c3d6..39e720f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..551d025 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0eaafbb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c593251 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..b8ec9bd --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..9d5a254 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..737ade0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d440242 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..befd585 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5f605cf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8dfd096 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..135c61c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..87f9768 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..6ad7ed2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b9056d9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/LocalVariableInfo.java b/src/proguard/classfile/attribute/LocalVariableInfo.java index 4e54c22..589bb7a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.visitor.ClassVisitor; * * @author Eric Lafortune */ -public class LocalVariableInfo +public class LocalVariableInfo implements Comparable { public int u2startPC; public int u2length; @@ -80,4 +80,20 @@ public class LocalVariableInfo referencedClass.accept(classVisitor); } } + + + // Implementations for Comparable. + + public int compareTo(Object object) + { + LocalVariableInfo other = (LocalVariableInfo)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.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..02eae2a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3a77e3d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.visitor.ClassVisitor; * * @author Eric Lafortune */ -public class LocalVariableTypeInfo +public class LocalVariableTypeInfo implements Comparable { public int u2startPC; public int u2length; @@ -88,4 +88,20 @@ public class LocalVariableTypeInfo } } } + + + // 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..3a2ab75 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2b59775 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f9e4005 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b28e139 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..cbb7e30 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..11f6029 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..248c8f3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..9ac7eae 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0cfefac 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/AnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java index 8117077..1786f15 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f2bf911 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ClassElementValue.java b/src/proguard/classfile/attribute/annotation/ClassElementValue.java index ba51641..b174695 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ConstantElementValue.java b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java index 3ebe5e5..f8bfc7f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ElementValue.java b/src/proguard/classfile/attribute/annotation/ElementValue.java index 39f8953..415aa6a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/EnumConstantElementValue.java b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java index d46bb7f..c6fbb52 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java index 3c700c8..0aca20f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4494b4c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5696a37 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e25d868 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..722792e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4af6946 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/AnnotatedClassVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java index 7a1d7c6..4582728 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c3e5eb0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6068dfb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/AnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java index 16b2a56..b079628 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0f89b06 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4cc614d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2559d53 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..39cc7f6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3dc6382 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e995346 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a2f3eaa 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1a375f1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4832751 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..acc45e1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7d5db73 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ffde7f5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..fe0e010 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..999863b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7a2be14 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..27321bc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1a9bf83 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4b2963c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..720f221 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c99ee7d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1b4ffad 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..703e8c4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8c4555d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..fbc9189 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..e502123 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3e1f0a7 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..9906483 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +24,7 @@ import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; import proguard.classfile.attribute.preverification.*; -import proguard.util.StringMatcher; +import proguard.util.*; /** * This AttributeVisitor delegates its visits another AttributeVisitor, but @@ -41,7 +41,21 @@ implements AttributeVisitor /** - * Creates a new AttributeNameFilter. + * Creates a new AttributeNameFilter based on a given name. + * @param name the string matcher that will check the attribute + * names. + * @param attributeVisitor the AttributeVisitor to which + * visits will be delegated. + */ + public AttributeNameFilter(String name, + AttributeVisitor attributeVisitor) + { + this(new FixedStringMatcher(name), attributeVisitor); + } + + + /** + * Creates a new AttributeNameFilter based on a given string matcher. * @param stringMatcher the string matcher that will check the attribute * names. * @param attributeVisitor the AttributeVisitor to which @@ -66,6 +80,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)) diff --git a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java index e8f226b..bb7ee34 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..4828d7f --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 + * BootstrapMethodInfo objects. Note that there is only a single + * implementation of BootstrapMethodInfo, 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..a96d4bf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8f033bf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..32efa63 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d00e184 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7018fea 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4156654 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..1b0460f --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 AttributeVisitor 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..e392ee7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -80,6 +80,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) diff --git a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java index 401f188..c4711d1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..b9089d2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ec25a67 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..08827c2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ddd6fb1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e98aec2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..bd6afa0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..80fe817 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..bbff88d --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 {@link + * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}. + * 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..2d55e6a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c2e068e --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 {@link + * proguard.classfile.util.ClassReferenceInitializer + * ClassReferenceInitializer}.. + */ + 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..29f79d7 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 {@link + * proguard.classfile.util.ClassReferenceInitializer + * ClassReferenceInitializer}.. + */ + 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..a69c04e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f8f814a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c0531f6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..923c6dd 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..27ef218 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2b89657 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6b02b73 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..bfa7149 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 ConstantVisitor 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 ConstantVisitor 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 ConstantVisitor 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..2cec804 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..0477631 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 ConstantVisitor 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/constant/visitor/MethodrefTraveler.java b/src/proguard/classfile/constant/visitor/MethodrefTraveler.java new file mode 100644 index 0000000..49c0917 --- /dev/null +++ b/src/proguard/classfile/constant/visitor/MethodrefTraveler.java @@ -0,0 +1,60 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.attribute.*; +import proguard.classfile.constant.*; +import proguard.classfile.util.SimplifiedVisitor; + +/** + * 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 MethodrefTraveler +extends SimplifiedVisitor +implements ConstantVisitor +{ + private ConstantVisitor methodrefConstantVisitor; + + + /** + * Creates a new v that will delegate to the given constant visitor. + */ + public MethodrefTraveler(ConstantVisitor methodrefConstantVisitor) + { + this.methodrefConstantVisitor = methodrefConstantVisitor; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) + { + clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, + methodrefConstantVisitor); + } +} diff --git a/src/proguard/classfile/editor/AccessFixer.java b/src/proguard/classfile/editor/AccessFixer.java index 7d6274e..8ff08f3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..3c35608 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5537f5e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a7f8dc3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -256,7 +256,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..dcae85e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..91c0080 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..010c8a2 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..f51ae45 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c5eb366 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..61d69b2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..808d339 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a645f57 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 accumulates instructions and exceptions, and then * copies them into code attributes that it visits. @@ -49,7 +51,7 @@ implements AttributeVisitor, //* private static final boolean DEBUG = false; /*/ - public static boolean DEBUG = true; + public static boolean DEBUG = false; //*/ @@ -313,7 +315,7 @@ implements AttributeVisitor, int handlerPC = -exceptionInfo.u2handlerPC; if (handlerPC > 0) { - if (remappableInstructionOffset(handlerPC)) + if (remappableExceptionHandler(handlerPC)) { exceptionInfo.u2handlerPC = remapInstructionOffset(handlerPC); } @@ -490,7 +492,7 @@ implements AttributeVisitor, int handlerPC = exceptionInfo.u2handlerPC; exceptionInfo.u2handlerPC = !allowExternalExceptionHandlers || - remappableInstructionOffset(handlerPC) ? + remappableExceptionHandler(handlerPC) ? remapInstructionOffset(handlerPC) : -handlerPC; } @@ -674,13 +676,21 @@ 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; + if (oldInstructionOffset > codeFragmentLengths[level]) + { + return false; + } + + int newInstructionOffset = + instructionOffsetMap[level][oldInstructionOffset]; + + return newInstructionOffset > INVALID && + newInstructionOffset < codeLength; } @@ -703,10 +713,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 +741,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 +768,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 +795,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..82ed29e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ 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 java.util.Arrays; /** * This AttributeVisitor accumulates specified changes to code, and then applies @@ -105,13 +106,10 @@ 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); } modified = false; @@ -328,52 +326,51 @@ implements AttributeVisitor, { if (DEBUG) { - System.out.println("CodeAttributeEditor: ["+clazz.getName()+"."+method.getName(clazz)+"]"); + System.out.println("CodeAttributeEditor: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)); } - // Avoid doing any work if nothing is changing anyway. - if (!modified) + // Do we have to update the code? + if (modified) { - return; - } - - // 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); + // Remap 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); + // Remap 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); @@ -415,12 +412,6 @@ implements AttributeVisitor, { // Remap 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); } @@ -428,12 +419,6 @@ implements AttributeVisitor, { // Remap 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); } @@ -912,10 +897,12 @@ 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); + int newStartPC = remapInstructionOffset(localVariableInfo.u2startPC); + int newEndPC = remapInstructionOffset(localVariableInfo.u2startPC + + localVariableInfo.u2length); + + localVariableInfo.u2length = newEndPC - newStartPC; + localVariableInfo.u2startPC = newStartPC; } @@ -924,10 +911,12 @@ 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); + int newStartPC = remapInstructionOffset(localVariableTypeInfo.u2startPC); + int newEndPC = remapInstructionOffset(localVariableTypeInfo.u2startPC + + localVariableTypeInfo.u2length); + + localVariableTypeInfo.u2length = newEndPC - newStartPC; + localVariableTypeInfo.u2startPC = newStartPC; } @@ -1017,54 +1006,6 @@ 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. - */ - 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..eedc045 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ba5f3b1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..14edbce 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..6ba4857 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -198,6 +198,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. @@ -562,6 +649,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. diff --git a/src/proguard/classfile/editor/ConstantPoolRemapper.java b/src/proguard/classfile/editor/ConstantPoolRemapper.java index 7430d3d..7677218 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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); 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) diff --git a/src/proguard/classfile/editor/ConstantPoolShrinker.java b/src/proguard/classfile/editor/ConstantPoolShrinker.java new file mode 100644 index 0000000..8c8e5d6 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..8e18865 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..895fd68 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ce9352a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ee0fb52 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5fd98a8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d49658a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1d991df --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..34fb63b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/InstructionWriter.java b/src/proguard/classfile/editor/InstructionWriter.java index d842358..b7da62f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/InterfaceAdder.java b/src/proguard/classfile/editor/InterfaceAdder.java index e095af6..9c11d97 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..176e13e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..59cdd6a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b0db7fb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7497458 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0f47933 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8bb051d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a1c1379 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..9b1ebd5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7791e3b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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); @@ -150,6 +169,12 @@ implements MemberVisitor // Add the completed field. classEditor.addField(newProgramField); + + // Visit the newly added field, if necessary. + if (extraMemberVisitor != null) + { + extraMemberVisitor.visitProgramField(targetClass, newProgramField); + } } @@ -240,6 +265,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..6d665c1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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); } } } @@ -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..f33ef1d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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; @@ -168,6 +166,7 @@ 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. @@ -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/classfile/editor/NameAndTypeShrinker.java b/src/proguard/classfile/editor/NameAndTypeShrinker.java new file mode 100644 index 0000000..f316884 --- /dev/null +++ b/src/proguard/classfile/editor/NameAndTypeShrinker.java @@ -0,0 +1,188 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.editor.ConstantPoolRemapper; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.ClassVisitor; + +import java.util.Arrays; + + +/** + * This ClassVisitor removes NameAndType constant pool entries that are not + * used. + * + * @author Eric Lafortune + */ +public class NameAndTypeShrinker +extends SimplifiedVisitor +implements ClassVisitor, + ConstantVisitor, + AttributeVisitor +{ + // 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. + + public void visitProgramClass(ProgramClass programClass) + { + // Mark the NameAndType entries referenced by all other constant pool + // entries. + programClass.constantPoolEntriesAccept(this); + + // 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); + + // 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 ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + markNameAndTypeConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex); + } + + + public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) + { + markNameAndTypeConstant(clazz, refConstant.u2nameAndTypeIndex); + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) + { + if (enclosingMethodAttribute.u2nameAndTypeIndex != 0) + { + markNameAndTypeConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex); + } + } + + + // Small utility methods. + + /** + * Marks the given UTF-8 constant pool entry of the given class. + */ + private void markNameAndTypeConstant(Clazz clazz, int index) + { + markAsUsed((NameAndTypeConstant)((ProgramClass)clazz).getConstant(index)); + } + + + /** + * Marks the given VisitorAccepter as being used. + * In this context, the VisitorAccepter will be a NameAndTypeConstant object. + */ + private void markAsUsed(VisitorAccepter visitorAccepter) + { + visitorAccepter.setVisitorInfo(USED); + } + + + /** + * Returns whether the given VisitorAccepter has been marked as being used. + * In this context, the VisitorAccepter will be a NameAndTypeConstant object. + */ + 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..5ae950d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c97e2c8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..cc743b1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f944ef8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f4cdd70 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/Utf8Shrinker.java b/src/proguard/classfile/editor/Utf8Shrinker.java new file mode 100644 index 0000000..b9dac44 --- /dev/null +++ b/src/proguard/classfile/editor/Utf8Shrinker.java @@ -0,0 +1,455 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.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 removes UTF-8 constant pool entries that are not used. + * + * @author Eric Lafortune + */ +public class Utf8Shrinker +extends SimplifiedVisitor +implements ClassVisitor, + MemberVisitor, + ConstantVisitor, + AttributeVisitor, + InnerClassesInfoVisitor, + LocalVariableInfoVisitor, + LocalVariableTypeInfoVisitor, + AnnotationVisitor, + ElementValueVisitor +{ + // 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. + + public void visitProgramClass(ProgramClass programClass) + { + // Mark the UTF-8 entries referenced by the other constant pool entries. + programClass.constantPoolEntriesAccept(this); + + // Mark the UTF-8 entries referenced by the fields and methods. + programClass.fieldsAccept(this); + programClass.methodsAccept(this); + + // 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); + } + } + + + // Implementations for MemberVisitor. + + public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) + { + // Mark the name and descriptor UTF-8 entries. + markCpUtf8Entry(programClass, programMember.u2nameIndex); + markCpUtf8Entry(programClass, programMember.u2descriptorIndex); + + // Mark the UTF-8 entries referenced by the attributes. + programMember.attributesAccept(programClass, this); + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + { + markCpUtf8Entry(clazz, stringConstant.u2stringIndex); + } + + + public void visitClassConstant(Clazz clazz, ClassConstant classConstant) + { + markCpUtf8Entry(clazz, classConstant.u2nameIndex); + } + + + public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) + { + markCpUtf8Entry(clazz, nameAndTypeConstant.u2nameIndex); + markCpUtf8Entry(clazz, nameAndTypeConstant.u2descriptorIndex); + } + + + // Implementations for AttributeVisitor. + + public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) + { + // This is the best we can do for unknown attributes. + markCpUtf8Entry(clazz, unknownAttribute.u2attributeNameIndex); + } + + + public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) + { + markCpUtf8Entry(clazz, sourceFileAttribute.u2attributeNameIndex); + + markCpUtf8Entry(clazz, sourceFileAttribute.u2sourceFileIndex); + } + + + public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) + { + markCpUtf8Entry(clazz, sourceDirAttribute.u2attributeNameIndex); + + markCpUtf8Entry(clazz, sourceDirAttribute.u2sourceDirIndex); + } + + + public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) + { + markCpUtf8Entry(clazz, innerClassesAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the inner classes. + innerClassesAttribute.innerClassEntriesAccept(clazz, this); + } + + + public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) + { + markCpUtf8Entry(clazz, enclosingMethodAttribute.u2attributeNameIndex); + + // These entries have already been marked in the constant pool. + //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2classIndex); + //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2nameAndTypeIndex); + } + + + public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) + { + markCpUtf8Entry(clazz, deprecatedAttribute.u2attributeNameIndex); + } + + + public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) + { + markCpUtf8Entry(clazz, syntheticAttribute.u2attributeNameIndex); + } + + + public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) + { + markCpUtf8Entry(clazz, signatureAttribute.u2attributeNameIndex); + + markCpUtf8Entry(clazz, signatureAttribute.u2signatureIndex); + } + + + public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) + { + markCpUtf8Entry(clazz, constantValueAttribute.u2attributeNameIndex); + } + + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) + { + markCpUtf8Entry(clazz, exceptionsAttribute.u2attributeNameIndex); + } + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + markCpUtf8Entry(clazz, codeAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the attributes. + codeAttribute.attributesAccept(clazz, method, this); + } + + + public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) + { + markCpUtf8Entry(clazz, stackMapAttribute.u2attributeNameIndex); + } + + + public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) + { + markCpUtf8Entry(clazz, stackMapTableAttribute.u2attributeNameIndex); + } + + + public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) + { + markCpUtf8Entry(clazz, lineNumberTableAttribute.u2attributeNameIndex); + } + + + public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) + { + markCpUtf8Entry(clazz, localVariableTableAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the local variables. + localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); + } + + + public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) + { + markCpUtf8Entry(clazz, localVariableTypeTableAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the local variable types. + localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); + } + + + public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) + { + markCpUtf8Entry(clazz, annotationsAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the annotations. + annotationsAttribute.annotationsAccept(clazz, this); + } + + + public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) + { + markCpUtf8Entry(clazz, parameterAnnotationsAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the annotations. + parameterAnnotationsAttribute.annotationsAccept(clazz, method, this); + } + + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) + { + markCpUtf8Entry(clazz, annotationDefaultAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the element value. + annotationDefaultAttribute.defaultValueAccept(clazz, this); + } + + + // Implementations for InnerClassesInfoVisitor. + + public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) + { + if (innerClassesInfo.u2innerNameIndex != 0) + { + markCpUtf8Entry(clazz, innerClassesInfo.u2innerNameIndex); + } + } + + + // Implementations for LocalVariableInfoVisitor. + + public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) + { + markCpUtf8Entry(clazz, localVariableInfo.u2nameIndex); + markCpUtf8Entry(clazz, localVariableInfo.u2descriptorIndex); + } + + + // Implementations for LocalVariableTypeInfoVisitor. + + public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) + { + markCpUtf8Entry(clazz, localVariableTypeInfo.u2nameIndex); + markCpUtf8Entry(clazz, localVariableTypeInfo.u2signatureIndex); + } + + + // Implementations for AnnotationVisitor. + + public void visitAnnotation(Clazz clazz, Annotation annotation) + { + markCpUtf8Entry(clazz, annotation.u2typeIndex); + + // Mark the UTF-8 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) + { + markCpUtf8Entry(clazz, constantElementValue.u2elementNameIndex); + } + + // Only the string constant element value refers to a UTF-8 entry. + if (constantElementValue.u1tag == ClassConstants.ELEMENT_VALUE_STRING_CONSTANT) + { + markCpUtf8Entry(clazz, constantElementValue.u2constantValueIndex); + } + } + + + public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) + { + if (enumConstantElementValue.u2elementNameIndex != 0) + { + markCpUtf8Entry(clazz, enumConstantElementValue.u2elementNameIndex); + } + + markCpUtf8Entry(clazz, enumConstantElementValue.u2typeNameIndex); + markCpUtf8Entry(clazz, enumConstantElementValue.u2constantNameIndex); + } + + + public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) + { + if (classElementValue.u2elementNameIndex != 0) + { + markCpUtf8Entry(clazz, classElementValue.u2elementNameIndex); + } + + markCpUtf8Entry(clazz, classElementValue.u2classInfoIndex); + } + + + public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) + { + if (annotationElementValue.u2elementNameIndex != 0) + { + markCpUtf8Entry(clazz, annotationElementValue.u2elementNameIndex); + } + + // Mark the UTF-8 entries referenced by the annotation. + annotationElementValue.annotationAccept(clazz, this); + } + + + public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) + { + if (arrayElementValue.u2elementNameIndex != 0) + { + markCpUtf8Entry(clazz, arrayElementValue.u2elementNameIndex); + } + + // Mark the UTF-8 entries referenced by the element values. + arrayElementValue.elementValuesAccept(clazz, annotation, this); + } + + + // Small utility methods. + + /** + * Marks the given UTF-8 constant pool entry of the given class. + */ + private void markCpUtf8Entry(Clazz clazz, int index) + { + markAsUsed((Utf8Constant)((ProgramClass)clazz).getConstant(index)); + } + + + /** + * Marks the given VisitorAccepter as being used. + * In this context, the VisitorAccepter will be a Utf8Constant object. + */ + private void markAsUsed(VisitorAccepter visitorAccepter) + { + visitorAccepter.setVisitorInfo(USED); + } + + + /** + * Returns whether the given VisitorAccepter has been marked as being used. + * In this context, the VisitorAccepter will be a Utf8Constant object. + */ + 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..af51403 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,28 @@ 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. 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.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 +156,112 @@ 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. 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.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..8c99ff8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..df26534 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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); } @@ -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..bb87151 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..54f583b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ConstantInstruction.java b/src/proguard/classfile/instruction/ConstantInstruction.java index 6c2d1a3..900a8d5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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)); @@ -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..77b0e20 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 diff --git a/src/proguard/classfile/instruction/InstructionConstants.java b/src/proguard/classfile/instruction/InstructionConstants.java index 78730b3..8ca03cc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..288acc2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..12d4d05 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2da639b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..83499dc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/SwitchInstruction.java b/src/proguard/classfile/instruction/SwitchInstruction.java index b98c2fb..11f05c4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a5e8c5e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6cbd3de 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/AllInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java index 71b2cde..c355433 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/InstructionCounter.java b/src/proguard/classfile/instruction/visitor/InstructionCounter.java index 1d10980..64c0f65 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d7d1b24 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..160ccd7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..32bb569 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..01f057f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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(): diff --git a/src/proguard/classfile/io/ProgramClassWriter.java b/src/proguard/classfile/io/ProgramClassWriter.java index e56f08a..53995d4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..7225ec9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..75d0642 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..068a89e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e7709ab 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -166,17 +166,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 +207,7 @@ 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. missingMemberWarningPrinter.print(clazz.getName(), className, "Warning: " + @@ -216,7 +229,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 +237,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 +256,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. + missingMemberWarningPrinter.print(className, + enclosingClassName, + "Warning: " + + ClassUtil.externalClassName(className) + + ": can't find enclosing method '" + + ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) + + "' in class " + + ClassUtil.externalClassName(enclosingClassName)); + } + } } - - // Save the references. - enclosingMethodAttribute.referencedClass = referencedClass; - enclosingMethodAttribute.referencedMethod = referencedMethod; } @@ -501,11 +509,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..304efd7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..de95250 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..e92a022 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. "java.lang.Object[][]" + * @return the external base type, + * e.g. "java.lang.Object". + */ + 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. "java.lang.Object" * @return the external short class name, @@ -409,6 +432,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. "". + * @return whether the method name refers to an initializer, + * e.g. true. + */ + 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, @@ -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..bb08f08 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..bdf2102 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..110dc43 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,14 +55,20 @@ implements InstructionVisitor, 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 +91,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 +131,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 +221,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 +235,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 +323,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 +336,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 +375,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 +423,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 +443,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 +491,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 +538,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 +657,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 +692,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 +734,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 +755,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 +789,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 +802,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 +817,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 +840,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 +852,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 +865,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 +911,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 +937,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/ExternalTypeEnumeration.java b/src/proguard/classfile/util/ExternalTypeEnumeration.java index 6371888..7edfbc9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..51eb7bc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..8658be3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/MemberFinder.java b/src/proguard/classfile/util/MemberFinder.java index 0fdeec0..6108b6d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8aed77a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. - *

- * As a MemberVisitor, it links all corresponding class members that it visits, - * including fields and private class members. - *

- * 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..55b3848 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..aff9b9f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..04dc1d0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..de66bd6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ea6272d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..40af76c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2a6f34e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2526a6a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6f442ac 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..cab208f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4dd1790 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..07c6a15 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3c2dac7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ClassForNameClassVisitor.java b/src/proguard/classfile/visitor/ClassForNameClassVisitor.java deleted file mode 100644 index ee028f8..0000000 --- a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java +++ /dev/null @@ -1,66 +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.classfile.visitor; - -import proguard.classfile.Clazz; -import proguard.classfile.constant.*; -import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.util.SimplifiedVisitor; - - -/** - * This ConstantVisitor lets a given ClassVisitor visit all - * constant classes involved in any Class.forName constructs that - * it visits. - * - * @see DotClassClassVisitor - * - * @author Eric Lafortune - */ -public class ClassForNameClassVisitor -extends SimplifiedVisitor -implements ConstantVisitor -{ - private final ClassVisitor classVisitor; - - - /** - * Creates a new ClassHierarchyTraveler. - * @param classVisitor the ClassVisitor to which visits will - * be delegated. - */ - public ClassForNameClassVisitor(ClassVisitor classVisitor) - { - this.classVisitor = classVisitor; - } - - - // Implementations for ConstantVisitor. - - public void visitAnyConstant(Clazz clazz, Constant constant) {} - - - public void visitStringConstant(Clazz clazz, StringConstant stringConstant) - { - // Visit the referenced class from the Class.forName construct, if any. - stringConstant.referencedClassAccept(classVisitor); - } -} diff --git a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java index 2e1755e..116b0bf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..64f5a61 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ClassPoolFiller.java b/src/proguard/classfile/visitor/ClassPoolFiller.java index e1773de..c9efaa0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..da2876f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..bb90e22 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8d35ab7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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; /** @@ -222,10 +224,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 +278,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 +390,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 +635,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 +658,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 +873,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 +885,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..4400ea3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 +36,19 @@ public class ClassVersionFilter implements ClassVisitor private final ClassVisitor classVisitor; + /** + * Creates a new ClassVersionFilter. + * @param minimumClassVersion the minimum class version number. + * @param classVisitor the ClassVisitor 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. diff --git a/src/proguard/classfile/visitor/ClassVersionSetter.java b/src/proguard/classfile/visitor/ClassVersionSetter.java index 34dfbc1..4090d44 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..989910c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0c8a9bc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8289f42 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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, .class constructs are actually * compiled differently, using Class.forName 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..c9694e6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ae70ffe 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e750b69 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..27e1159 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c77fb83 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..74ccbe5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d9fa3c7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b094907 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..574bbf1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d2b5ce0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d052916 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1d00e1d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d006d8d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..baf5173 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0c5bfdd 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1373409 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f6f1204 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..81251e0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f638f09 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/MemberToClassVisitor.java b/src/proguard/classfile/visitor/MemberToClassVisitor.java index a405cfc..b5b0385 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c0d48cb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c4af8b0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d696215 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a52c1d6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d8ac3d7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..609b6a9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a0d9fc5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7ccf0fe 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3f94680 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..98e4e15 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..dd21cea 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5b4ee20 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..762cb06 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..9df79cb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b025ebf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..cecb0b6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..505510d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b9a40f1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7b93a62 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1c01888 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..33b0d0c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..1493b6f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8214eea --- /dev/null +++ b/src/proguard/evaluation/ClassConstantValueFactory.java @@ -0,0 +1,53 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..e76b869 --- /dev/null +++ b/src/proguard/evaluation/ConstantValueFactory.java @@ -0,0 +1,113 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..a8809ee 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b694d66 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..46c1b40 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 Value * 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..3c3def4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5f58f97 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. - *

- * 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; /** @@ -77,24 +73,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. @@ -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..0cf2584 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 Value * 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..0d5650b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..dde0625 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..55c942c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..d183dee 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ecc32bb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..a042fcf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d4fa331 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..115e7d1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..88e0e25 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..943e2a5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..df4994d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..23ec03f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..026bd5b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c209d44 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..48d8f11 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..3783096 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..86393a7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..363530b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..57e73cb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a0c4636 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1514d4d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..f2a3cab 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..93d0380 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6a0775d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1d8f413 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6409f8c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f0f7e40 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..74b857c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3f97fd0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..383cae3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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) diff --git a/src/proguard/evaluation/value/ParticularFloatValue.java b/src/proguard/evaluation/value/ParticularFloatValue.java index 59e4357..335765c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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) diff --git a/src/proguard/evaluation/value/ParticularIntegerValue.java b/src/proguard/evaluation/value/ParticularIntegerValue.java index 8a4ac1d..d6906e7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..22d9d1a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..084a1a4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..ea4ecc4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..1e55c23 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..45eb013 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..32302a4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..145ff55 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..ecd182e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..96bf06a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..14469f8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/UnknownIntegerValue.java b/src/proguard/evaluation/value/UnknownIntegerValue.java index be5e79d..94fcf60 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f183447 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b4f1c6a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2b9e7f1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ClassPathPanel.java b/src/proguard/gui/ClassPathPanel.java index 95f3d1b..6fa6154 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..a9493c9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..50fd87b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..581e889 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..33a8527 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e65620a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..b190119 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..705079e 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-2011 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.7 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\ + ProGuard is a free class file shrinker, optimizer, obfuscator, and preverifier.\ +

\ + With this GUI, you can create, load, modify, and save ProGuard configurations.\ +
\ 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.\ +

\ With the ReTrace part of this GUI you can de-obfuscate your stack traces.\ - \n\n\ +

\ ProGuard and ReTrace are written and maintained by Eric Lafortune.\ - \n\n\ +

\ + Official site at Sourceforge: \ + http://proguard.sourceforge.net/\ +
\ + Professional support by Saikoa: \ + http://www.saikoa.com/\ +

\ Distributed under the GNU General Public License.\ - \n\ - Copyright (c) 2002-2009. +
\ + Copyright © 2002-2011. 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,8 +122,8 @@ 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 @@ -209,6 +216,9 @@ attributesTip = \

  • "*Annotations*" is necessary for preserving annotations.\ \ The wildcard * and the negator ! are allowed. +keepParameterNamesTip = \ + Keep parameter names and types in "LocalVariable*Table" attributes
    \ + in methods that are not obfuscated. renameSourceFileAttributeTip = \ Put the given string in the "SourceFile" attribute of the processed class files.
    \ It will appear as the file name of the classes in stack traces. @@ -246,12 +256,12 @@ noteTip = \ noteFilterTip = \ A filter matching classes for which no notes should be printed. warnTip = \ - Print out warnings about possibly erronous input.
    \ + Print out warnings about possibly erroneous input.
    \ Only unset this option if you know what you're doing! warnFilterTip = \ A filter matching classes for which no warnings should be printed. ignoreWarningsTip = \ - Ignore any warnings about possibly erronous input.
    \ + Ignore any warnings about possibly erroneous input.
    \ Only set this option if you know what you're doing! skipNonPublicLibraryClassesTip = \ Skip reading non-public library classes, for efficiency.
    \ @@ -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..9834894 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..292b838 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f260b8b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..4e0a5f4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7dddae5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1dbbd1c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7ff9086 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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); @@ -1019,6 +1021,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 +1044,26 @@ 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 +1190,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; @@ -1436,13 +1445,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 +1476,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 +1609,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 +1648,37 @@ 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 (isFile(file)) + { + try + { + return file.getCanonicalPath(); + } + catch (IOException ex) + { + return file.getPath(); + } + } + else + { + return ""; + } + } + + + /** + * Returns whether the given file is actually a file, or just a placeholder + * for the standard output. + */ + private boolean isFile(File file) + { + return file != null && + file.getPath().length() > 0; } @@ -1693,46 +1726,52 @@ 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(); + 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) + { + 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..2a898d9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..fb1f325 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f6d2d34 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..033b039 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..da263a5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/BufferedSprite.java b/src/proguard/gui/splash/BufferedSprite.java index 8427832..c82c511 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6512495 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6a8e5fe 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1e633fa 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e82f524 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..85ca451 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e903c9b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c7fd8f5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c9e80a8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e67db5c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..9b0a01c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..19882d4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..28bb05f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..cdd8d11 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..249b8de 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7ee7c32 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..13799fc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6d70049 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6f702f7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..eef8995 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e048c9f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..56779ef 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..22e90fc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..00ac82a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..79a2747 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..131b94c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f8501de 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1256a6f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..53540de 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..7fc4b4d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..dcde0bc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..12fe09e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..148cf56 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..eaef2c9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..73d01f2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..9bd657f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..fe35d8f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c049ea0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..613bb89 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..bc61704 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4cd46ff --- /dev/null +++ b/src/proguard/io/DataEntryClassWriter.java @@ -0,0 +1,85 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..76d5bdd 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/DataEntryDirectoryFilter.java b/src/proguard/io/DataEntryDirectoryFilter.java index bb36f3e..036347d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..92ff83e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..86a736f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1009548 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..cf44b65 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a54038b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6d24b42 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..89e006a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..d7852a5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6db918e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f99a6c2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..35d5a76 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c74d503 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1a2d2d3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b03dd6f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..795e8c8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..164ef58 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..60a1d6d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..946b5b8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b28dd8d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/NameFilter.java b/src/proguard/io/NameFilter.java index 2a9fbc3..f36d663 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..528bb39 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..71b7fac 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3e19db1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..ee9bc4b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..297b540 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..446b158 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -469,13 +469,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..a967d36 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..393c648 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d6ca5f6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d02d7bc 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c004b73 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/MappingProcessor.java b/src/proguard/obfuscate/MappingProcessor.java index 01c1809..7c9103a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0798a4d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0d5a519 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..92ec589 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..22de855 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1447a25 --- /dev/null +++ b/src/proguard/obfuscate/MemberNameFilter.java @@ -0,0 +1,120 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 MemberVisitor delegates its visits to another given + * MemberVisitor, 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 MemberSpecialNameFilter. + * @param memberVisitor the MemberVisitor 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; + } +} \ No newline at end of file diff --git a/src/proguard/obfuscate/MemberObfuscator.java b/src/proguard/obfuscate/MemberObfuscator.java index 332b849..7b30596 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6da56da 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..8b67bb6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/NameAndTypeUsageMarker.java b/src/proguard/obfuscate/NameAndTypeUsageMarker.java deleted file mode 100644 index cc779f0..0000000 --- a/src/proguard/obfuscate/NameAndTypeUsageMarker.java +++ /dev/null @@ -1,135 +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.attribute.*; -import proguard.classfile.attribute.visitor.AttributeVisitor; -import proguard.classfile.constant.*; -import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.util.SimplifiedVisitor; -import proguard.classfile.visitor.ClassVisitor; - -/** - * This ClassVisitor marks all NameAndType constant pool entries that are - * being used in the program classes it visits. - * - * @see NameAndTypeShrinker - * - * @author Eric Lafortune - */ -public class NameAndTypeUsageMarker -extends SimplifiedVisitor -implements ClassVisitor, - ConstantVisitor, - AttributeVisitor -{ - // A visitor info flag to indicate the NameAndType constant pool entry is being used. - private static final Object USED = new Object(); - - - // Implementations for ClassVisitor. - - public void visitProgramClass(ProgramClass programClass) - { - // Mark the NameAndType entries referenced by all other constant pool - // entries. - programClass.constantPoolEntriesAccept(this); - - // Mark the NameAndType entries referenced by all EnclosingMethod - // attributes. - programClass.attributesAccept(this); - } - - - // Implementations for ConstantVisitor. - - public void visitAnyConstant(Clazz clazz, Constant constant) {} - - - public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) - { - visitRefConstant(clazz, fieldrefConstant); - } - - - public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) - { - visitRefConstant(clazz, interfaceMethodrefConstant); - } - - - public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) - { - visitRefConstant(clazz, methodrefConstant); - } - - - private void visitRefConstant(Clazz clazz, RefConstant refConstant) - { - markNameAndTypeConstant(clazz, refConstant.u2nameAndTypeIndex); - } - - - // Implementations for AttributeVisitor. - - public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} - - - public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) - { - if (enclosingMethodAttribute.u2nameAndTypeIndex != 0) - { - markNameAndTypeConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex); - } - } - - - // Small utility methods. - - /** - * Marks the given UTF-8 constant pool entry of the given class. - */ - private void markNameAndTypeConstant(Clazz clazz, int index) - { - markAsUsed((NameAndTypeConstant)((ProgramClass)clazz).getConstant(index)); - } - - - /** - * Marks the given VisitorAccepter as being used. - * In this context, the VisitorAccepter will be a NameAndTypeConstant object. - */ - private static void markAsUsed(VisitorAccepter visitorAccepter) - { - visitorAccepter.setVisitorInfo(USED); - } - - - /** - * 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) - { - return visitorAccepter.getVisitorInfo() == USED; - } -} diff --git a/src/proguard/obfuscate/NameFactory.java b/src/proguard/obfuscate/NameFactory.java index c64d1ad..9585381 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f3e889d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..130260c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5a6e3b4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5f58a83 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. @@ -398,23 +409,28 @@ 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()); + // 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..2c3a3db --- /dev/null +++ b/src/proguard/obfuscate/ParameterNameMarker.java @@ -0,0 +1,128 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..d9b770b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8805b08 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..07c1674 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/obfuscate/Utf8UsageMarker.java b/src/proguard/obfuscate/Utf8UsageMarker.java deleted file mode 100644 index c59ebb8..0000000 --- a/src/proguard/obfuscate/Utf8UsageMarker.java +++ /dev/null @@ -1,392 +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.attribute.*; -import proguard.classfile.attribute.annotation.*; -import proguard.classfile.attribute.annotation.visitor.*; -import proguard.classfile.attribute.preverification.*; -import proguard.classfile.attribute.visitor.*; -import proguard.classfile.constant.*; -import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.util.SimplifiedVisitor; -import proguard.classfile.visitor.*; - -/** - * This ClassVisitor marks all UTF-8 constant pool entries that are - * being used in the program classes it visits. - * - * @see Utf8Shrinker - * - * @author Eric Lafortune - */ -public class Utf8UsageMarker -extends SimplifiedVisitor -implements ClassVisitor, - MemberVisitor, - ConstantVisitor, - AttributeVisitor, - InnerClassesInfoVisitor, - LocalVariableInfoVisitor, - LocalVariableTypeInfoVisitor, - AnnotationVisitor, - ElementValueVisitor -{ - // A visitor info flag to indicate the UTF-8 constant pool entry is being used. - private static final Object USED = new Object(); - - - // Implementations for ClassVisitor. - - public void visitProgramClass(ProgramClass programClass) - { - // Mark the UTF-8 entries referenced by the other constant pool entries. - programClass.constantPoolEntriesAccept(this); - - // Mark the UTF-8 entries referenced by the fields and methods. - programClass.fieldsAccept(this); - programClass.methodsAccept(this); - - // Mark the UTF-8 entries referenced by the attributes. - programClass.attributesAccept(this); - } - - - // Implementations for MemberVisitor. - - public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) - { - // Mark the name and descriptor UTF-8 entries. - markCpUtf8Entry(programClass, programMember.u2nameIndex); - markCpUtf8Entry(programClass, programMember.u2descriptorIndex); - - // Mark the UTF-8 entries referenced by the attributes. - programMember.attributesAccept(programClass, this); - } - - - // Implementations for ConstantVisitor. - - public void visitAnyConstant(Clazz clazz, Constant constant) {} - - - public void visitStringConstant(Clazz clazz, StringConstant stringConstant) - { - markCpUtf8Entry(clazz, stringConstant.u2stringIndex); - } - - - public void visitClassConstant(Clazz clazz, ClassConstant classConstant) - { - markCpUtf8Entry(clazz, classConstant.u2nameIndex); - } - - - public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) - { - markCpUtf8Entry(clazz, nameAndTypeConstant.u2nameIndex); - markCpUtf8Entry(clazz, nameAndTypeConstant.u2descriptorIndex); - } - - - // Implementations for AttributeVisitor. - - public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) - { - // This is the best we can do for unknown attributes. - markCpUtf8Entry(clazz, unknownAttribute.u2attributeNameIndex); - } - - - public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) - { - markCpUtf8Entry(clazz, sourceFileAttribute.u2attributeNameIndex); - - markCpUtf8Entry(clazz, sourceFileAttribute.u2sourceFileIndex); - } - - - public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) - { - markCpUtf8Entry(clazz, sourceDirAttribute.u2attributeNameIndex); - - markCpUtf8Entry(clazz, sourceDirAttribute.u2sourceDirIndex); - } - - - public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) - { - markCpUtf8Entry(clazz, innerClassesAttribute.u2attributeNameIndex); - - // Mark the UTF-8 entries referenced by the inner classes. - innerClassesAttribute.innerClassEntriesAccept(clazz, this); - } - - - public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) - { - markCpUtf8Entry(clazz, enclosingMethodAttribute.u2attributeNameIndex); - - // These entries have already been marked in the constant pool. - //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2classIndex); - //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2nameAndTypeIndex); - } - - - public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) - { - markCpUtf8Entry(clazz, deprecatedAttribute.u2attributeNameIndex); - } - - - public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) - { - markCpUtf8Entry(clazz, syntheticAttribute.u2attributeNameIndex); - } - - - public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) - { - markCpUtf8Entry(clazz, signatureAttribute.u2attributeNameIndex); - - markCpUtf8Entry(clazz, signatureAttribute.u2signatureIndex); - } - - - public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) - { - markCpUtf8Entry(clazz, constantValueAttribute.u2attributeNameIndex); - } - - - public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) - { - markCpUtf8Entry(clazz, exceptionsAttribute.u2attributeNameIndex); - } - - - public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) - { - markCpUtf8Entry(clazz, codeAttribute.u2attributeNameIndex); - - // Mark the UTF-8 entries referenced by the attributes. - codeAttribute.attributesAccept(clazz, method, this); - } - - - public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) - { - markCpUtf8Entry(clazz, stackMapAttribute.u2attributeNameIndex); - } - - - public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) - { - markCpUtf8Entry(clazz, stackMapTableAttribute.u2attributeNameIndex); - } - - - public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) - { - markCpUtf8Entry(clazz, lineNumberTableAttribute.u2attributeNameIndex); - } - - - public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) - { - markCpUtf8Entry(clazz, localVariableTableAttribute.u2attributeNameIndex); - - // Mark the UTF-8 entries referenced by the local variables. - localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); - } - - - public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) - { - markCpUtf8Entry(clazz, localVariableTypeTableAttribute.u2attributeNameIndex); - - // Mark the UTF-8 entries referenced by the local variable types. - localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); - } - - - public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) - { - markCpUtf8Entry(clazz, annotationsAttribute.u2attributeNameIndex); - - // Mark the UTF-8 entries referenced by the annotations. - annotationsAttribute.annotationsAccept(clazz, this); - } - - - public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) - { - markCpUtf8Entry(clazz, parameterAnnotationsAttribute.u2attributeNameIndex); - - // Mark the UTF-8 entries referenced by the annotations. - parameterAnnotationsAttribute.annotationsAccept(clazz, method, this); - } - - - public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) - { - markCpUtf8Entry(clazz, annotationDefaultAttribute.u2attributeNameIndex); - - // Mark the UTF-8 entries referenced by the element value. - annotationDefaultAttribute.defaultValueAccept(clazz, this); - } - - - // Implementations for InnerClassesInfoVisitor. - - public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) - { - if (innerClassesInfo.u2innerNameIndex != 0) - { - markCpUtf8Entry(clazz, innerClassesInfo.u2innerNameIndex); - } - } - - - // Implementations for LocalVariableInfoVisitor. - - public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) - { - markCpUtf8Entry(clazz, localVariableInfo.u2nameIndex); - markCpUtf8Entry(clazz, localVariableInfo.u2descriptorIndex); - } - - - // Implementations for LocalVariableTypeInfoVisitor. - - public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) - { - markCpUtf8Entry(clazz, localVariableTypeInfo.u2nameIndex); - markCpUtf8Entry(clazz, localVariableTypeInfo.u2signatureIndex); - } - - - // Implementations for AnnotationVisitor. - - public void visitAnnotation(Clazz clazz, Annotation annotation) - { - markCpUtf8Entry(clazz, annotation.u2typeIndex); - - // Mark the UTF-8 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) - { - markCpUtf8Entry(clazz, constantElementValue.u2elementNameIndex); - } - - // Only the string constant element value refers to a UTF-8 entry. - if (constantElementValue.u1tag == ClassConstants.ELEMENT_VALUE_STRING_CONSTANT) - { - markCpUtf8Entry(clazz, constantElementValue.u2constantValueIndex); - } - } - - - public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) - { - if (enumConstantElementValue.u2elementNameIndex != 0) - { - markCpUtf8Entry(clazz, enumConstantElementValue.u2elementNameIndex); - } - - markCpUtf8Entry(clazz, enumConstantElementValue.u2typeNameIndex); - markCpUtf8Entry(clazz, enumConstantElementValue.u2constantNameIndex); - } - - - public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) - { - if (classElementValue.u2elementNameIndex != 0) - { - markCpUtf8Entry(clazz, classElementValue.u2elementNameIndex); - } - - markCpUtf8Entry(clazz, classElementValue.u2classInfoIndex); - } - - - public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) - { - if (annotationElementValue.u2elementNameIndex != 0) - { - markCpUtf8Entry(clazz, annotationElementValue.u2elementNameIndex); - } - - // Mark the UTF-8 entries referenced by the annotation. - annotationElementValue.annotationAccept(clazz, this); - } - - - public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) - { - if (arrayElementValue.u2elementNameIndex != 0) - { - markCpUtf8Entry(clazz, arrayElementValue.u2elementNameIndex); - } - - // Mark the UTF-8 entries referenced by the element values. - arrayElementValue.elementValuesAccept(clazz, annotation, this); - } - - - // Small utility methods. - - /** - * Marks the given UTF-8 constant pool entry of the given class. - */ - private void markCpUtf8Entry(Clazz clazz, int index) - { - markAsUsed((Utf8Constant)((ProgramClass)clazz).getConstant(index)); - } - - - /** - * Marks the given VisitorAccepter as being used. - * In this context, the VisitorAccepter will be a Utf8Constant object. - */ - private static void markAsUsed(VisitorAccepter visitorAccepter) - { - visitorAccepter.setVisitorInfo(USED); - } - - - /** - * 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) - { - return visitorAccepter.getVisitorInfo() == USED; - } -} diff --git a/src/proguard/optimize/BootstrapMethodArgumentShrinker.java b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java new file mode 100644 index 0000000..70d031d --- /dev/null +++ b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java @@ -0,0 +1,103 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..e0d00b8 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..d3a8207 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6920990 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..07b7d82 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..e900232 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..f8087be 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/KeptClassFilter.java b/src/proguard/optimize/KeptClassFilter.java new file mode 100644 index 0000000..4b9d090 --- /dev/null +++ b/src/proguard/optimize/KeptClassFilter.java @@ -0,0 +1,69 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..5b25425 --- /dev/null +++ b/src/proguard/optimize/KeptMemberFilter.java @@ -0,0 +1,88 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..7f051f5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..f4667ee 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..9bd7b2a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a6d3cc7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c5db18b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..2021861 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..f01dcd9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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); + } + } } @@ -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)); } @@ -227,19 +220,52 @@ implements AttributeVisitor, } - // 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; diff --git a/src/proguard/optimize/WriteOnlyFieldFilter.java b/src/proguard/optimize/WriteOnlyFieldFilter.java index 578beb2..4a0e095 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..bc5f658 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. @@ -55,13 +57,14 @@ implements AttributeVisitor 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); + 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); 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]; @@ -276,18 +279,10 @@ implements AttributeVisitor if (partialEvaluator.isTraced(offset) && !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); - } + Instruction instruction = InstructionFactory.create(codeAttribute.code, + offset); + + instruction.accept(clazz, method, codeAttribute, offset, variableInitializationMarker); } } if (DEBUG) System.out.println(); @@ -467,7 +462,9 @@ implements AttributeVisitor */ private class MyUnusedParameterSimplifier extends SimplifiedVisitor - implements InstructionVisitor, ConstantVisitor, MemberVisitor + implements InstructionVisitor, + ConstantVisitor, + MemberVisitor { private int invocationOffset; private ConstantInstruction invocationInstruction; @@ -656,6 +653,40 @@ 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) + { + if (!variableInstruction.isLoad()) + { + int variableIndex = variableInstruction.variableIndex; + + if (isVariableInitialization(offset, + variableIndex) && + isVariableInitializationNecessary(clazz, + method, + codeAttribute, + offset, + variableIndex)) + { + markInstruction(offset); + } + } + } + } + + /** * This InstructionVisitor fixes instructions locally, popping any unused * produced stack entries after marked instructions, and popping produced @@ -687,12 +718,23 @@ implements AttributeVisitor int requiredPushCount = 0; for (int stackIndex = 0; stackIndex < popCount; stackIndex++) { - // Is the stack entry required by other consumers? - if (!isStackSimplifiedBefore(offset, top - stackIndex) && - !isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex)) + InstructionOffsetValue producerOffsets = + tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(); + + if (!isStackSimplifiedBefore(offset, top - stackIndex)) { - // Remember to push it. - requiredPushCount++; + // Is the stack entry pushed by any producer, + // because it is required by other consumers? + if (isAnyStackEntryNecessaryAfter(producerOffsets, top - stackIndex)) + { + // Make sure it is pushed after all producers. + markStackEntriesAfter(producerOffsets, top - stackIndex); + } + else + { + // Remember to push it. + requiredPushCount++; + } } } @@ -757,9 +799,16 @@ implements AttributeVisitor int expectedPopCount = 0; for (int stackIndex = 0; stackIndex < popCount; stackIndex++) { - // Is the stack entry required by other consumers? - if (isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex)) + InstructionOffsetValue producerOffsets = + tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(); + + // Is the stack entry pushed by any producer, + // because it is required by other consumers? + if (isAnyStackEntryNecessaryAfter(producerOffsets, top - stackIndex)) { + // Make sure it is pushed after all producers. + markStackEntriesAfter(producerOffsets, top - stackIndex); + // Remember to pop it. expectedPopCount++; } @@ -1052,6 +1101,7 @@ implements AttributeVisitor byte oldOpcode = instruction.opcode; byte newOpcode = 0; + byte addOpcode = 0; // Simplify the popping instruction if possible. switch (oldOpcode) @@ -1232,9 +1282,20 @@ implements AttributeVisitor stackEntryPresent1) { // Will both elements be present? - if (stackEntryPresent0 && - stackEntryPresent1) + if (!stackEntryPresent1) { + // Pop the original top element (later bottom element). + newOpcode = InstructionConstants.OP_POP; + } + else if (!stackEntryPresent0) + { + // Swap both elements and pop the top one. + newOpcode = InstructionConstants.OP_SWAP; + addOpcode = InstructionConstants.OP_POP; + } + else + { + // Just swap both elements. newOpcode = InstructionConstants.OP_SWAP; } } @@ -1242,6 +1303,7 @@ implements AttributeVisitor } } + // Is there a replacement opcode? if (newOpcode == 0) { // Delete the instruction. @@ -1270,6 +1332,21 @@ implements AttributeVisitor if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString()); } + + // Is there an additional opcode? + if (addOpcode != 0) + { + // Add the instruction. + Instruction additionalInstruction = new SimpleInstruction(addOpcode); + codeAttributeEditor.insertAfterInstruction(dupOffset, additionalInstruction); + + if (extraAddedInstructionVisitor != null) + { + extraAddedInstructionVisitor.visitSimpleInstruction(null, null, null, dupOffset, null); + } + + if (DEBUG) System.out.println(" Adding instruction "+additionalInstruction.toString(dupOffset)); + } } @@ -1596,10 +1673,7 @@ implements AttributeVisitor { for (int offset = 0; offset < codeLength; offset++) { - for (int index = 0; index < maxLocals; index++) - { - variablesNecessaryAfter[offset][index] = false; - } + Arrays.fill(variablesNecessaryAfter[offset], 0, maxLocals, false); } } @@ -1612,10 +1686,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 +1699,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,10 +1709,7 @@ implements AttributeVisitor } else { - for (int index = 0; index < codeLength; index++) - { - instructionsNecessary[index] = false; - } + Arrays.fill(instructionsNecessary, 0, codeLength, false); } } @@ -1669,6 +1734,34 @@ implements AttributeVisitor } + /** + * Returns whether the specified variable is initialized at the specified + * offset. + */ + private boolean isVariableInitialization(int instructionOffset, + int variableIndex) + { + // Wasn't the variable set yet? + Value valueBefore = partialEvaluator.getVariablesBefore(instructionOffset).getValue(variableIndex); + if (valueBefore == null) + { + return true; + } + + // Is the computational type different now? + Value valueAfter = partialEvaluator.getVariablesAfter(instructionOffset).getValue(variableIndex); + if (valueAfter.computationalType() != valueBefore.computationalType()) + { + return true; + } + + // 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; + } + + /** * Returns whether the specified variable must be initialized at the * specified offset, according to the verifier of the JVM. @@ -1686,8 +1779,8 @@ implements AttributeVisitor { 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. + // Lazily perform simple partial evaluation, the way the JVM + // verifier would do it. simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); if (DEBUG) System.out.println("End of simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]"); @@ -1695,7 +1788,7 @@ implements AttributeVisitor // Check if the variable is necessary elsewhere. for (int offset = 0; offset < codeLength; offset++) { - if (isInstructionNecessary(offset)) + if (partialEvaluator.isTraced(offset)) { Value producer = partialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex); if (producer != null) @@ -1708,16 +1801,22 @@ implements AttributeVisitor 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)) + if (DEBUG) { - // Then the initialization is necessary. + System.out.println(" ["+offset+"] producers ["+producerOffsets+"], simple producers ["+simpleProducerOffsets+"]"); + } + + // Is the variable being used without all of its + // immediate simple producers being marked? + if (isVariableNecessaryAfterAny(producerOffsets, variableIndex) && + !isVariableNecessaryAfterAll(simpleProducerOffsets, variableIndex)) + { + if (DEBUG) + { + System.out.println(" => initialization of variable v"+variableIndex+" at ["+initializationOffset+"] necessary"); + } + + // Then the initialization may be necessary. return true; } } @@ -1726,6 +1825,11 @@ implements AttributeVisitor } } + if (DEBUG) + { + System.out.println(" => initialization of variable v"+variableIndex+" at ["+initializationOffset+"] not necessary"); + } + return false; } @@ -1749,7 +1853,7 @@ implements AttributeVisitor /** * Returns whether the specified variable is ever necessary after any - * instruction in the specified block. + * instructions in the specified block. */ private boolean isVariableNecessaryAfterAny(int startOffset, int endOffset, @@ -1769,7 +1873,7 @@ implements AttributeVisitor /** * Returns whether the specified variable is ever necessary after any - * instruction in the specified set of instructions offsets. + * instructions in the specified set of instructions offsets. */ private boolean isVariableNecessaryAfterAny(InstructionOffsetValue instructionOffsetValue, int variableIndex) @@ -1789,6 +1893,28 @@ implements AttributeVisitor } + /** + * Returns whether the specified variable is ever necessary after all + * instructions in the specified set of instructions offsets. + */ + private boolean isVariableNecessaryAfterAll(InstructionOffsetValue instructionOffsetValue, + int variableIndex) + { + int count = instructionOffsetValue.instructionOffsetCount(); + + for (int index = 0; index < count; index++) + { + if (!isVariableNecessaryAfter(instructionOffsetValue.instructionOffset(index), + variableIndex)) + { + return false; + } + } + + return true; + } + + private boolean isVariableNecessaryAfter(int instructionOffset, int variableIndex) { @@ -1797,6 +1923,36 @@ implements AttributeVisitor } + /** + * Marks the stack entries after the given offsets. + * @param instructionOffsets the offsets of the stack entries to be marked. + * @param stackIndex the index of the stack entries to be marked + * (counting from the bottom). + */ + private void markStackEntriesAfter(InstructionOffsetValue instructionOffsets, + int stackIndex) + { + if (instructionOffsets != null) + { + int offsetCount = instructionOffsets.instructionOffsetCount(); + for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) + { + // Make sure the stack entry and the instruction are marked + // at the producing offset. + int offset = instructionOffsets.instructionOffset(offsetIndex); + + markStackEntryAfter(offset, stackIndex); + } + } + } + + + /** + * 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) { @@ -1814,6 +1970,13 @@ implements AttributeVisitor } + /** + * 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 +1994,13 @@ implements AttributeVisitor } + /** + * Returns whether any of the stack entries after the given offset are + * 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) { diff --git a/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationSimplifier.java index 0c3a9c7..b207108 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 @@ extends SimplifiedVisitor implements AttributeVisitor, InstructionVisitor { + private static int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f); + private static long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0); + //* private static final boolean DEBUG = false; /*/ @@ -559,10 +562,11 @@ implements AttributeVisitor, Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); if (pushedValue.isParticular()) { + // 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, @@ -627,8 +631,9 @@ implements AttributeVisitor, Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); if (pushedValue.isParticular()) { + // 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, diff --git a/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/src/proguard/optimize/evaluation/LivenessAnalyzer.java index 9915027..747f993 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -78,6 +78,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..578ece5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..b2776d1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 NONE 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(); @@ -896,11 +917,7 @@ implements AttributeVisitor, subroutinePartialEvaluator = new PartialEvaluator(this); - subroutinePartialEvaluator.initializeVariables(clazz, - method, - codeAttribute, - variables, - stack); + subroutinePartialEvaluator.initializeArrays(codeAttribute); } // Evaluate the subroutine. @@ -952,13 +969,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 +984,6 @@ implements AttributeVisitor, stacksAfter[offset] .generalize(other.stacksAfter[offset]); //generalizedContexts[offset] evaluationCounts[offset] += other.evaluationCounts[offset]; - //initializedVariables[offset] } } } @@ -1094,11 +1109,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 +1117,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 +1157,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..010dab0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b7dd469 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a824481 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,59 @@ 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); + + localVariableInfo.u2startPC = startPC; + localVariableInfo.u2length = endPC - startPC; + } + + + // 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); + + localVariableTypeInfo.u2startPC = startPC; + localVariableTypeInfo.u2length = endPC - startPC; } @@ -241,4 +298,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..8d758ce 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..d53a5b2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5d74047 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4f7caff 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5a60aaf 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..e440eef 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..bc58f2d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..c55925c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..2819441 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..40287f3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..6797a14 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..955fe9e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..6d2f8aa 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..e67e0b5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..dc623c2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d222d81 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..9d573b7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..dd76f97 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..2e0516b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/NonPrivateMemberMarker.java b/src/proguard/optimize/info/NonPrivateMemberMarker.java index d451643..23e33a9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..85ff4b9 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..42cc14f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..abae946 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..236cb17 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..1444e5a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. * * @see ReadWriteFieldMarker + * @see StaticInitializerContainingClassMarker * @see NoSideEffectMethodMarker * @see SideEffectMethodMarker * @author Eric Lafortune @@ -47,6 +50,7 @@ implements InstructionVisitor, private final boolean includeReturnInstructions; // A return value for the visitor methods. + private Clazz referencingClass; private boolean hasSideEffects; @@ -60,7 +64,7 @@ implements InstructionVisitor, { hasSideEffects = false; - instruction.accept(clazz, method, codeAttribute, offset, this); + instruction.accept(clazz, method, codeAttribute, offset, this); return hasSideEffects; } @@ -118,14 +122,16 @@ implements InstructionVisitor, public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) { 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) + 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_INVOKEDYNAMIC) { // Check if the field is write-only or volatile, or if the invoked // method is causing any side effects. @@ -150,48 +156,36 @@ implements InstructionVisitor, // 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 +193,24 @@ implements InstructionVisitor, public void visitProgramField(ProgramClass programClass, ProgramField programField) { - hasSideEffects = ReadWriteFieldMarker.isRead(programField); + hasSideEffects = + (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 +222,24 @@ 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 ClassCollector(set))); + + return set; } } diff --git a/src/proguard/optimize/info/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java index 25fda72..d73179e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/StaticInitializerContainingClassFilter.java b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java new file mode 100644 index 0000000..197668d --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..a121250 --- /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-2011 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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..07e33bb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..a1c6a9a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..7e5a11f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. @@ -312,25 +314,19 @@ 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, NONE); + Arrays.fill(subroutineEnds, 0, codeLength, NONE); + 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, NONE); + Arrays.fill(subroutineEnds, 0, codeLength, NONE); + Arrays.fill(creationOffsets, 0, codeLength, NONE); + Arrays.fill(initializationOffsets, 0, codeLength, NONE); instructionMarks[codeLength] = 0; } diff --git a/src/proguard/optimize/peephole/ClassFinalizer.java b/src/proguard/optimize/peephole/ClassFinalizer.java index b5e54f8..063f254 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4971cab 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.constant.ClassConstant; import proguard.classfile.constant.visitor.*; import proguard.classfile.editor.*; import proguard.classfile.util.*; @@ -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. @@ -235,11 +238,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,7 +264,7 @@ implements ClassVisitor, // Copy over the class members. MemberAdder memberAdder = - new MemberAdder(targetClass); + new MemberAdder(targetClass, fieldOptimizationInfoCopier); programClass.fieldsAccept(memberAdder); programClass.methodsAccept(memberAdder); @@ -336,10 +340,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,12 +370,19 @@ 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))); + new ClassCollector(set))); return set; } @@ -538,4 +547,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..0dd93b1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/GotoGotoReplacer.java b/src/proguard/optimize/peephole/GotoGotoReplacer.java index 7d7e66c..d05d7b6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..cafda92 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d12c2c0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..eb24061 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,179 @@ */ 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; + private static final int FIELD_L = 33; + private static final int FIELD_F = 34; + private static final int FIELD_D = 35; - 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_STRINGBUFFER_INIT = 38; + private static final int METHOD_STRINGBUFFER_INIT_STRING = 39; + private static final int METHOD_STRINGBUFFER_APPEND_BOOLEAN = 40; + private static final int METHOD_STRINGBUFFER_APPEND_CHAR = 41; + private static final int METHOD_STRINGBUFFER_APPEND_INTEGER = 42; + private static final int METHOD_STRINGBUFFER_APPEND_LONG = 43; + private static final int METHOD_STRINGBUFFER_APPEND_FLOAT = 44; + private static final int METHOD_STRINGBUFFER_APPEND_DOUBLE = 45; + private static final int METHOD_STRINGBUFFER_APPEND_STRING = 46; + private static final int METHOD_STRINGBUFFER_LENGTH = 47; + private static final int METHOD_STRINGBUFFER_TOSTRING = 48; + private static final int METHOD_STRINGBUILDER_INIT = 49; + private static final int METHOD_STRINGBUILDER_INIT_STRING = 50; + private static final int METHOD_STRINGBUILDER_APPEND_BOOLEAN = 51; + private static final int METHOD_STRINGBUILDER_APPEND_CHAR = 52; + private static final int METHOD_STRINGBUILDER_APPEND_INTEGER = 53; + private static final int METHOD_STRINGBUILDER_APPEND_LONG = 54; + private static final int METHOD_STRINGBUILDER_APPEND_FLOAT = 55; + private static final int METHOD_STRINGBUILDER_APPEND_DOUBLE = 56; + private static final int METHOD_STRINGBUILDER_APPEND_STRING = 57; + private static final int METHOD_STRINGBUILDER_LENGTH = 58; + private static final int METHOD_STRINGBUILDER_TOSTRING = 59; + + private static final int CLASS_STRING = 60; + private static final int CLASS_STRINGBUFFER = 61; + private static final int CLASS_STRINGBUILDER = 62; + + private static final int NAME_AND_TYPE_I = 63; + private static final int NAME_AND_TYPE_L = 64; + private static final int NAME_AND_TYPE_F = 65; + private static final int NAME_AND_TYPE_D = 66; + + private static final int NAME_AND_TYPE_EQUALS = 67; + private static final int NAME_AND_TYPE_LENGTH = 68; + private static final int NAME_AND_TYPE_INIT = 69; + private static final int NAME_AND_TYPE_INIT_STRING = 70; + private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUFFER = 71; + private static final int NAME_AND_TYPE_APPEND_C_STRINGBUFFER = 72; + private static final int NAME_AND_TYPE_APPEND_I_STRINGBUFFER = 73; + private static final int NAME_AND_TYPE_APPEND_J_STRINGBUFFER = 74; + private static final int NAME_AND_TYPE_APPEND_F_STRINGBUFFER = 75; + private static final int NAME_AND_TYPE_APPEND_D_STRINGBUFFER = 76; + private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUFFER = 77; + private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUILDER = 78; + private static final int NAME_AND_TYPE_APPEND_C_STRINGBUILDER = 79; + private static final int NAME_AND_TYPE_APPEND_I_STRINGBUILDER = 80; + private static final int NAME_AND_TYPE_APPEND_J_STRINGBUILDER = 81; + private static final int NAME_AND_TYPE_APPEND_F_STRINGBUILDER = 82; + private static final int NAME_AND_TYPE_APPEND_D_STRINGBUILDER = 83; + private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUILDER = 84; + private static final int NAME_AND_TYPE_TOSTRING = 85; + + private static final int UTF8_EMPTY = 86; + private static final int UTF8_I = 87; + private static final int UTF8_L = 88; + private static final int UTF8_F = 89; + private static final int UTF8_D = 90; + private static final int UTF8_STRING = 91; + private static final int UTF8_STRINGBUFFER = 92; + private static final int UTF8_STRINGBUILDER = 93; + private static final int UTF8_EQUALS = 94; + private static final int UTF8_OBJECT_Z = 95; + private static final int UTF8_LENGTH = 96; + private static final int UTF8__I = 97; + private static final int UTF8_INIT = 98; + private static final int UTF8__VOID = 99; + private static final int UTF8_STRING_VOID = 100; + private static final int UTF8_TOSTRING = 101; + private static final int UTF8__STRING = 102; + private static final int UTF8_APPEND = 103; + private static final int UTF8_Z_STRINGBUFFER = 104; + private static final int UTF8_C_STRINGBUFFER = 105; + private static final int UTF8_I_STRINGBUFFER = 106; + private static final int UTF8_J_STRINGBUFFER = 107; + private static final int UTF8_F_STRINGBUFFER = 108; + private static final int UTF8_D_STRINGBUFFER = 109; + private static final int UTF8_STRING_STRINGBUFFER = 110; + private static final int UTF8_Z_STRINGBUILDER = 111; + private static final int UTF8_C_STRINGBUILDER = 112; + private static final int UTF8_I_STRINGBUILDER = 113; + private static final int UTF8_J_STRINGBUILDER = 114; + private static final int UTF8_F_STRINGBUILDER = 115; + private static final int UTF8_D_STRINGBUILDER = 116; + private static final int UTF8_STRING_STRINGBUILDER = 117; + + private static final int SENTINEL = 118; public static final Constant[] CONSTANTS = new Constant[] @@ -136,23 +234,100 @@ 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_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_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_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_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_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_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_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_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), }; - public static final Instruction[][][] VARIABLE = new Instruction[][][] { { // nop = nothing @@ -237,7 +412,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 +557,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 +723,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 +826,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 +1248,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 +1274,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 +1682,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 +3527,898 @@ 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), + }, + }, + + { // 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("...").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), + }, + }, + { // 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_BOOLEAN), + },{ + 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_CHAR), + },{ + 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_CHAR), + },{ + 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_INTEGER), + },{ + 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_INTEGER), + },{ + 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_LONG), + },{ + 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_LONG), + },{ + 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_FLOAT), + },{ + 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_FLOAT), + },{ + 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_DOUBLE), + },{ + 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_DOUBLE), + },{ + 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, STRING_A_STRING), + 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_BOOLEAN), + },{ + 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_CHAR), + },{ + 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_CHAR), + },{ + 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_INTEGER), + },{ + 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_INTEGER), + },{ + 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_LONG), + },{ + 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_LONG), + },{ + 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_FLOAT), + },{ + 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_FLOAT), + },{ + 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_DOUBLE), + },{ + 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_DOUBLE), + },{ + 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_BOOLEAN), + },{ + 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_CHAR), + },{ + 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_CHAR), + },{ + 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_INTEGER), + },{ + 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_INTEGER), + },{ + 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_LONG), + },{ + 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_LONG), + },{ + 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_FLOAT), + },{ + 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_FLOAT), + },{ + 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_DOUBLE), + },{ + 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_DOUBLE), + },{ + 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 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("...").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), + }, + }, + { // 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_BOOLEAN), + },{ + 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_CHAR), + },{ + 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_CHAR), + },{ + 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_INTEGER), + },{ + 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_INTEGER), + },{ + 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_LONG), + },{ + 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_LONG), + },{ + 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_FLOAT), + },{ + 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_FLOAT), + },{ + 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_DOUBLE), + },{ + 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_DOUBLE), + },{ + 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, STRING_A_STRING), + 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_BOOLEAN), + },{ + 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_CHAR), + },{ + 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_CHAR), + },{ + 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_INTEGER), + },{ + 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_INTEGER), + },{ + 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_LONG), + },{ + 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_LONG), + },{ + 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_FLOAT), + },{ + 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_FLOAT), + },{ + 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_DOUBLE), + },{ + 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_DOUBLE), + },{ + 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_BOOLEAN), + },{ + 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_CHAR), + },{ + 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_CHAR), + },{ + 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_INTEGER), + },{ + 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_INTEGER), + },{ + 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_LONG), + },{ + 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_LONG), + },{ + 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_FLOAT), + },{ + 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_FLOAT), + },{ + 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_DOUBLE), + },{ + 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_DOUBLE), + },{ + 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), + }, + }, + }; + + /* + static + { + 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[] instructions = STRING[2][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(" "+instruction.toString(offset)); + } + } + } + //*/ +} diff --git a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java index bce06e2..be65b53 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 { + /* + public static boolean DEBUG = true; + /*/ private static final boolean DEBUG = false; + //*/ + + 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).shrink()); } // Delete any remaining instructions in the from sequence. @@ -204,10 +243,10 @@ 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), @@ -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..72fc334 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..254e968 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..140a114 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..8857202 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,10 @@ 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.info.*; -import java.util.Stack; +import java.util.*; /** * This AttributeVisitor inlines short methods or methods that are only invoked @@ -48,7 +48,7 @@ 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; @@ -137,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) { @@ -305,12 +341,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(); } @@ -457,42 +493,42 @@ implements AttributeVisitor, if (// 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 method, except in an 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 +537,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 +577,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..4c99f3a 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d865638 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..cac1965 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..254f748 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,10 +72,7 @@ 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. 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..5fa4fac 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..fcb8914 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..f3ecf0b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..55f42ca 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..721f2a5 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..670f26e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/CodeSubroutineInliner.java b/src/proguard/preverify/CodeSubroutineInliner.java index 603eb75..9012b05 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,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. diff --git a/src/proguard/preverify/Preverifier.java b/src/proguard/preverify/Preverifier.java index e071c5c..3cbd930 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..38a824e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 97ab27b..183d9a0 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 @@ implements MappingProcessor 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 = "?"; 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..0b2fd91 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +52,6 @@ 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 methodUsed; @@ -151,9 +150,6 @@ implements AttributeVisitor, markConstant(clazz, constantElementValue.u2elementNameIndex); markConstant(clazz, constantElementValue.u2constantValueIndex); - - // The return value. - elementValueUsed = true; } } @@ -164,7 +160,7 @@ implements AttributeVisitor, { // Check the referenced classes. classUsed = true; - enumConstantElementValue.referencedClassesAccept(usageMarker); + enumConstantElementValue.referencedClassesAccept(this); if (classUsed) { @@ -174,9 +170,6 @@ implements AttributeVisitor, markConstant(clazz, enumConstantElementValue.u2elementNameIndex); markConstant(clazz, enumConstantElementValue.u2typeNameIndex); markConstant(clazz, enumConstantElementValue.u2constantNameIndex); - - // The return value. - elementValueUsed = true; } } } @@ -188,7 +181,7 @@ implements AttributeVisitor, { // Check the referenced classes. classUsed = true; - classElementValue.referencedClassesAccept(usageMarker); + classElementValue.referencedClassesAccept(this); if (classUsed) { @@ -197,9 +190,6 @@ implements AttributeVisitor, markConstant(clazz, classElementValue.u2elementNameIndex); markConstant(clazz, classElementValue.u2classInfoIndex); - - // The return value. - elementValueUsed = true; } } } @@ -221,9 +211,6 @@ implements AttributeVisitor, usageMarker.markAsUsed(annotationElementValue); markConstant(clazz, annotationElementValue.u2elementNameIndex); - - // The return value. - elementValueUsed = true; } annotationUsed = oldAnnotationUsed; @@ -235,26 +222,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); } } diff --git a/src/proguard/shrink/ClassShrinker.java b/src/proguard/shrink/ClassShrinker.java index 0b5c5b7..f40e3ce 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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. @@ -349,10 +365,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 +390,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 +447,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..c95bc64 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..065745d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ShortestUsageMark.java b/src/proguard/shrink/ShortestUsageMark.java index 757c713..a2ff762 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..3f2cf94 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..4f12e87 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/Shrinker.java b/src/proguard/shrink/Shrinker.java index edbc27f..66ca161 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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, diff --git a/src/proguard/shrink/UsageMarker.java b/src/proguard/shrink/UsageMarker.java index e913046..a1b2f53 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 method. + // Explicitly mark the method, if it's not empty. programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, - this); - - // Explicitly mark the parameterless 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) @@ -337,7 +355,8 @@ implements ClassVisitor, { if ((method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC)) == 0) + ClassConstants.INTERNAL_ACC_STATIC)) == 0 && + !ClassUtil.isInitializer(method.getName(clazz))) { clazz.accept(new ConcreteClassDownTraveler( new ClassHierarchyTraveler(true, true, false, true, @@ -395,11 +414,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 +430,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 +490,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 +513,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 +578,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); @@ -837,6 +947,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 +1031,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..53f7bc2 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/UsedClassFilter.java b/src/proguard/shrink/UsedClassFilter.java index ec180bd..b5a77fb 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..0034ce7 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..ae70e5d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ClassNameParser.java b/src/proguard/util/ClassNameParser.java index ee972f0..fd12475 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..90e5a0c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..5e56147 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..9e3fd65 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..d5cbdf3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..570b70e 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..30f1a9b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..b8f075d 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ListUtil.java b/src/proguard/util/ListUtil.java index 570dbe8..71556f3 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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..6bbf4f6 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..53b87ae 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/OrMatcher.java b/src/proguard/util/OrMatcher.java index 097c6c6..70b849b 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..48f01e1 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..571ee7f 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..541d30c 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..9b296d4 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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..da957ed 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-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free -- cgit v1.2.3