[proguard] 01/02: Imported Upstream version 4.4
Emmanuel Bourg
ebourg-guest at moszumanska.debian.org
Thu Apr 10 09:00:42 UTC 2014
This is an automated email from the git hooks/post-receive script.
ebourg-guest pushed a commit to annotated tag debian/4.4-1
in repository proguard.
commit 37e94f0a7dbd79b3e4b7545819ad227053e6b599
Author: Sam Clegg <samo at debian.org>
Date: Thu Apr 10 10:42:01 2014 +0200
Imported Upstream version 4.4
---
README | 2 +-
build/README | 34 -
build/build.sh | 18 +-
build/build.xml | 5 +
build/makefile | 4 +-
docs/FAQ.html | 2 +-
docs/GPL_exception.html | 3 +-
docs/acknowledgements.html | 5 +-
docs/alternatives.html | 12 +-
docs/downloads.html | 47 +-
docs/feedback.html | 2 +-
docs/index.html | 2 +-
docs/license.html | 11 +-
docs/main.html | 2 +-
docs/manual/ant.html | 75 +-
docs/manual/examples.html | 318 ++-
docs/manual/gui.html | 6 +-
docs/manual/index.html | 2 +-
docs/manual/introduction.html | 2 +-
docs/manual/limitations.html | 2 +-
docs/manual/optimizations.html | 158 ++
docs/manual/refcard.html | 42 +-
docs/manual/retrace/examples.html | 2 +-
docs/manual/retrace/index.html | 2 +-
docs/manual/retrace/introduction.html | 2 +-
docs/manual/retrace/usage.html | 87 +-
docs/manual/style.css | 6 +
docs/manual/troubleshooting.html | 35 +-
docs/manual/usage.html | 276 ++-
docs/manual/wtk.html | 2 +-
docs/quality.html | 2 +-
docs/results.html | 2 +-
docs/screenshots.html | 2 +-
docs/sections.html | 4 +
docs/sflogo.png | Bin 1299 -> 469 bytes
docs/testimonials.html | 2 +-
docs/title.html | 2 +-
examples/annotations/examples/Applet.java | 6 +-
examples/annotations/examples/Application.java | 6 +-
examples/annotations/examples/Bean.java | 6 +-
examples/annotations/examples/NativeCallBack.java | 6 +-
examples/annotations/lib/annotations.jar | Bin 6123 -> 6123 bytes
examples/ant/proguard.xml | 1 +
lib/proguard.jar | Bin 0 -> 664512 bytes
lib/proguardgui.jar | Bin 0 -> 137516 bytes
lib/retrace.jar | Bin 0 -> 6888 bytes
src/proguard/ArgumentWordReader.java | 2 +-
src/proguard/ClassPath.java | 2 +-
src/proguard/ClassPathEntry.java | 71 +-
src/proguard/ClassSpecification.java | 28 +-
src/proguard/ClassSpecificationVisitorFactory.java | 52 +-
src/proguard/Configuration.java | 50 +-
src/proguard/ConfigurationConstants.java | 6 +-
src/proguard/ConfigurationParser.java | 92 +-
src/proguard/ConfigurationWriter.java | 105 +-
src/proguard/DataEntryReaderFactory.java | 16 +-
src/proguard/DataEntryWriterFactory.java | 16 +-
src/proguard/DescriptorKeepChecker.java | 6 +-
src/proguard/DuplicateClassPrinter.java | 8 +-
src/proguard/FileWordReader.java | 2 +-
src/proguard/FullyQualifiedClassNameChecker.java | 8 +-
src/proguard/GPL.java | 3 +-
src/proguard/Initializer.java | 282 +--
src/proguard/InputReader.java | 87 +-
...cification.java => KeepClassSpecification.java} | 35 +-
src/proguard/MemberSpecification.java | 2 +-
src/proguard/OutputWriter.java | 93 +-
src/proguard/ParseException.java | 2 +-
src/proguard/ProGuard.java | 4 +-
src/proguard/SubclassedClassFilter.java | 2 +-
src/proguard/Targeter.java | 4 +-
src/proguard/UpToDateChecker.java | 2 +-
src/proguard/WordReader.java | 2 +-
src/proguard/ant/ClassPathElement.java | 13 +-
src/proguard/ant/ClassSpecificationElement.java | 4 +-
src/proguard/ant/ConfigurationElement.java | 2 +-
src/proguard/ant/ConfigurationTask.java | 142 +-
src/proguard/ant/FilterElement.java | 20 +-
src/proguard/ant/KeepAttributeElement.java | 70 -
src/proguard/ant/KeepSpecificationElement.java | 10 +-
src/proguard/ant/MemberSpecificationElement.java | 2 +-
src/proguard/ant/ProGuardTask.java | 7 +-
src/proguard/classfile/ClassConstants.java | 2 +-
src/proguard/classfile/ClassPool.java | 2 +-
src/proguard/classfile/Clazz.java | 2 +-
src/proguard/classfile/Field.java | 2 +-
src/proguard/classfile/LibraryClass.java | 2 +-
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 | 2 +-
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/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 | 2 +-
.../classfile/attribute/InnerClassesAttribute.java | 2 +-
.../classfile/attribute/InnerClassesInfo.java | 2 +-
.../classfile/attribute/LineNumberInfo.java | 12 +-
.../attribute/LineNumberTableAttribute.java | 2 +-
.../classfile/attribute/LocalVariableInfo.java | 27 +-
.../attribute/LocalVariableTableAttribute.java | 2 +-
.../classfile/attribute/LocalVariableTypeInfo.java | 27 +-
.../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/AllExceptionInfoVisitor.java} | 17 +-
.../attribute/visitor/AttributeNameFilter.java | 2 +-
.../attribute/visitor/AttributeVisitor.java | 2 +-
.../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 | 2 +-
.../attribute/visitor/RequiredAttributeFilter.java | 2 +-
.../attribute/visitor/StackSizeComputer.java | 4 +-
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 +-
src/proguard/classfile/constant/LongConstant.java | 2 +-
.../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 | 134 +-
.../constant/visitor/AllConstantVisitor.java | 2 +-
.../constant/visitor/ConstantVisitor.java | 2 +-
.../visitor/ExceptClassConstantFilter.java | 2 +-
src/proguard/classfile/editor/AccessFixer.java | 2 +-
src/proguard/classfile/editor/AnnotationAdder.java | 69 +-
.../editor/AnnotationsAttributeEditor.java | 2 +-
src/proguard/classfile/editor/AttributeAdder.java | 85 +-
src/proguard/classfile/editor/AttributeSorter.java | 2 +-
.../classfile/editor/AttributesEditor.java | 2 +-
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 | 69 +-
.../classfile/editor/CodeAttributeEditor.java | 200 +-
.../editor/CodeAttributeEditorResetter.java | 2 +-
.../classfile/editor/ComparableConstant.java | 2 +-
src/proguard/classfile/editor/ConstantAdder.java | 2 +-
.../classfile/editor/ConstantPoolEditor.java | 2 +-
.../classfile/editor/ConstantPoolRemapper.java | 2 +-
.../classfile/editor/ConstantPoolSorter.java | 2 +-
.../classfile/editor/ElementValueAdder.java | 3 +-
.../classfile/editor/ElementValuesEditor.java | 2 +-
src/proguard/classfile/editor/ExceptionAdder.java | 2 +-
.../classfile/editor/ExceptionInfoAdder.java | 2 +-
.../editor/ExceptionsAttributeEditor.java | 2 +-
.../classfile/editor/InstructionAdder.java | 2 +-
.../classfile/editor/InstructionWriter.java | 2 +-
src/proguard/classfile/editor/InterfaceAdder.java | 2 +-
src/proguard/classfile/editor/InterfaceSorter.java | 2 +-
.../classfile/editor/InterfacesEditor.java | 2 +-
.../classfile/editor/LineNumberInfoAdder.java | 59 +
.../editor/LineNumberTableAttributeEditor.java | 67 +
.../classfile/editor/LocalVariableInfoAdder.java | 67 +
.../editor/LocalVariableTableAttributeEditor.java | 67 +
.../editor/LocalVariableTypeInfoAdder.java | 68 +
.../LocalVariableTypeTableAttributeEditor.java | 68 +
src/proguard/classfile/editor/MemberAdder.java | 4 +-
.../classfile/editor/MemberReferenceFixer.java | 6 +-
.../classfile/editor/MethodInvocationFixer.java | 2 +-
.../classfile/editor/NamedAttributeDeleter.java | 2 +-
.../ParameterAnnotationsAttributeEditor.java | 71 +
.../classfile/editor/StackSizeUpdater.java | 2 +-
src/proguard/classfile/editor/SubclassAdder.java | 2 +-
src/proguard/classfile/editor/SubclassToAdder.java | 2 +-
src/proguard/classfile/editor/VariableCleaner.java | 135 ++
src/proguard/classfile/editor/VariableEditor.java | 2 +-
.../classfile/editor/VariableRemapper.java | 2 +-
.../classfile/editor/VariableSizeUpdater.java | 2 +-
.../classfile/instruction/BranchInstruction.java | 2 +-
.../classfile/instruction/ConstantInstruction.java | 2 +-
.../classfile/instruction/Instruction.java | 4 +-
.../instruction/InstructionConstants.java | 2 +-
.../classfile/instruction/InstructionFactory.java | 2 +-
.../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 | 21 +-
.../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 | 2 +-
src/proguard/classfile/io/ProgramClassReader.java | 2 +-
src/proguard/classfile/io/ProgramClassWriter.java | 6 +-
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 | 88 +-
.../util/ClassSubHierarchyInitializer.java | 2 +-
.../util/ClassSuperHierarchyInitializer.java | 10 +-
src/proguard/classfile/util/ClassUtil.java | 2 +-
.../classfile/util/DescriptorClassEnumeration.java | 20 +-
.../util/DynamicClassReferenceInitializer.java | 19 +-
.../util/DynamicMemberReferenceInitializer.java | 62 +-
.../classfile/util/ExternalTypeEnumeration.java | 2 +-
.../classfile/util/InstructionSequenceMatcher.java | 26 +-
.../classfile/util/InternalTypeEnumeration.java | 2 +-
src/proguard/classfile/util/MemberFinder.java | 2 +-
src/proguard/classfile/util/MethodLinker.java | 2 +-
src/proguard/classfile/util/SimplifiedVisitor.java | 2 +-
.../classfile/util/StringReferenceInitializer.java | 89 +
src/proguard/classfile/util/StringSharer.java | 2 +-
src/proguard/classfile/util/WarningPrinter.java | 72 +-
.../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 | 2 +-
.../classfile/visitor/ClassHierarchyTraveler.java | 2 +-
.../classfile/visitor/ClassNameFilter.java | 19 +-
.../classfile/visitor/ClassPoolFiller.java | 2 +-
.../classfile/visitor/ClassPoolVisitor.java | 2 +-
.../classfile/visitor/ClassPresenceFilter.java | 2 +-
src/proguard/classfile/visitor/ClassPrinter.java | 17 +-
.../classfile/visitor/ClassVersionFilter.java | 2 +-
.../classfile/visitor/ClassVersionSetter.java | 2 +-
src/proguard/classfile/visitor/ClassVisitor.java | 2 +-
.../visitor/ConcreteClassDownTraveler.java | 2 +-
.../classfile/visitor/DotClassClassVisitor.java | 2 +-
.../classfile/visitor/ExceptClassFilter.java | 2 +-
.../classfile/visitor/ExceptClassesFilter.java | 2 +-
.../classfile/visitor/ExceptionCounter.java | 2 +-
.../visitor/ExceptionExcludedOffsetFilter.java | 4 +-
...r.java => ExceptionHandlerConstantVisitor.java} | 28 +-
...angeFilter.java => ExceptionHandlerFilter.java} | 24 +-
.../classfile/visitor/ExceptionOffsetFilter.java | 4 +-
.../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 | 5 +-
.../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 | 6 +-
src/proguard/evaluation/BranchUnit.java | 2 +-
src/proguard/evaluation/InvocationUnit.java | 2 +-
src/proguard/evaluation/Processor.java | 2 +-
src/proguard/evaluation/Stack.java | 2 +-
src/proguard/evaluation/TracedStack.java | 2 +-
src/proguard/evaluation/TracedVariables.java | 2 +-
src/proguard/evaluation/Variables.java | 2 +-
src/proguard/evaluation/value/Category1Value.java | 2 +-
src/proguard/evaluation/value/Category2Value.java | 2 +-
src/proguard/evaluation/value/ComparisonValue.java | 4 +-
.../evaluation/value/CompositeDoubleValue.java | 2 +-
.../evaluation/value/CompositeFloatValue.java | 2 +-
.../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 | 2 +-
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 | 2 +-
.../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 | 2 +-
.../evaluation/value/ParticularFloatValue.java | 2 +-
.../evaluation/value/ParticularIntegerValue.java | 2 +-
.../evaluation/value/ParticularLongValue.java | 2 +-
src/proguard/evaluation/value/ReferenceValue.java | 4 +-
.../evaluation/value/SpecificDoubleValue.java | 2 +-
.../evaluation/value/SpecificFloatValue.java | 2 +-
.../evaluation/value/SpecificIntegerValue.java | 2 +-
.../evaluation/value/SpecificLongValue.java | 2 +-
.../evaluation/value/SpecificValueFactory.java | 2 +-
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 | 15 +-
src/proguard/gui/ClassSpecificationDialog.java | 34 +-
src/proguard/gui/ClassSpecificationsPanel.java | 2 +-
src/proguard/gui/ExtensionFileFilter.java | 2 +-
src/proguard/gui/FilterBuilder.java | 208 ++
src/proguard/gui/FilterDialog.java | 45 +-
src/proguard/gui/GUIResources.java | 2 +-
src/proguard/gui/GUIResources.properties | 210 +-
src/proguard/gui/KeepSpecificationsPanel.java | 8 +-
src/proguard/gui/ListPanel.java | 2 +-
src/proguard/gui/MemberSpecificationDialog.java | 8 +-
src/proguard/gui/MemberSpecificationsPanel.java | 2 +-
src/proguard/gui/MessageDialogRunnable.java | 18 +-
src/proguard/gui/OptimizationsDialog.java | 251 ++
src/proguard/gui/ProGuardGUI.java | 270 ++-
src/proguard/gui/ProGuardRunnable.java | 2 +-
src/proguard/gui/ReTraceRunnable.java | 5 +-
src/proguard/gui/SwingUtil.java | 6 +-
src/proguard/gui/TabbedPane.java | 19 +-
src/proguard/gui/TextAreaOutputStream.java | 14 +-
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 | 8 +-
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/gui/vtitle.gif | Bin 26541 -> 0 bytes
src/proguard/gui/vtitle.png | Bin 0 -> 23313 bytes
src/proguard/io/CascadingDataEntryWriter.java | 12 +-
src/proguard/io/ClassFilter.java | 25 +-
src/proguard/io/ClassReader.java | 5 +-
src/proguard/io/ClassRewriter.java | 2 +-
src/proguard/io/DataEntry.java | 11 +-
src/proguard/io/DataEntryCopier.java | 31 +-
...ryReader.java => DataEntryDirectoryFilter.java} | 24 +-
src/proguard/io/DataEntryFilter.java | 2 +-
src/proguard/io/DataEntryNameFilter.java | 2 +-
...aEntryRenamer.java => DataEntryObfuscator.java} | 52 +-
src/proguard/io/DataEntryParentFilter.java | 2 +-
src/proguard/io/DataEntryPump.java | 2 +-
src/proguard/io/DataEntryReader.java | 2 +-
src/proguard/io/DataEntryRenamer.java | 113 +-
src/proguard/io/DataEntryRewriter.java | 58 +-
src/proguard/io/DataEntryWriter.java | 10 +-
.../io/{ClassFilter.java => DirectoryFilter.java} | 38 +-
src/proguard/io/DirectoryPump.java | 9 +-
src/proguard/io/DirectoryWriter.java | 28 +-
src/proguard/io/FileDataEntry.java | 8 +-
src/proguard/io/FilteredDataEntryReader.java | 2 +-
src/proguard/io/FilteredDataEntryWriter.java | 15 +-
src/proguard/io/Finisher.java | 2 +-
src/proguard/io/JarReader.java | 13 +-
src/proguard/io/JarWriter.java | 108 +-
src/proguard/io/ManifestRewriter.java | 216 ++
src/proguard/io/NameFilter.java | 83 +
src/proguard/io/ParentDataEntryWriter.java | 9 +-
src/proguard/io/RenamedDataEntry.java | 8 +-
src/proguard/io/ZipDataEntry.java | 21 +-
src/proguard/obfuscate/AttributeShrinker.java | 2 +-
src/proguard/obfuscate/AttributeUsageMarker.java | 2 +-
src/proguard/obfuscate/ClassObfuscator.java | 145 +-
src/proguard/obfuscate/ClassRenamer.java | 2 +-
src/proguard/obfuscate/DictionaryNameFactory.java | 2 +-
src/proguard/obfuscate/MapCleaner.java | 2 +-
src/proguard/obfuscate/MappingKeeper.java | 23 +-
src/proguard/obfuscate/MappingPrinter.java | 2 +-
src/proguard/obfuscate/MappingProcessor.java | 23 +-
src/proguard/obfuscate/MappingReader.java | 67 +-
src/proguard/obfuscate/MemberNameCleaner.java | 2 +-
src/proguard/obfuscate/MemberNameCollector.java | 2 +-
.../obfuscate/MemberNameConflictFixer.java | 5 +-
src/proguard/obfuscate/MemberObfuscator.java | 2 +-
.../obfuscate/MemberSpecialNameFilter.java | 2 +-
src/proguard/obfuscate/MultiMappingProcessor.java | 8 +-
src/proguard/obfuscate/NameAndTypeShrinker.java | 2 +-
src/proguard/obfuscate/NameAndTypeUsageMarker.java | 2 +-
src/proguard/obfuscate/NameFactory.java | 2 +-
src/proguard/obfuscate/NameFactoryResetter.java | 2 +-
src/proguard/obfuscate/NameMarker.java | 2 +-
.../{NameFactory.java => NumericNameFactory.java} | 29 +-
src/proguard/obfuscate/Obfuscator.java | 97 +-
src/proguard/obfuscate/SimpleNameFactory.java | 2 +-
src/proguard/obfuscate/SourceFileRenamer.java | 8 +-
src/proguard/obfuscate/SpecialNameFactory.java | 2 +-
src/proguard/obfuscate/Utf8Shrinker.java | 2 +-
src/proguard/obfuscate/Utf8UsageMarker.java | 2 +-
src/proguard/optimize/ChangedCodePrinter.java | 2 +-
src/proguard/optimize/ConstantMemberFilter.java | 4 +-
src/proguard/optimize/ConstantParameterFilter.java | 79 +
.../optimize/DuplicateInitializerFixer.java | 2 +-
.../DuplicateInitializerInvocationFixer.java | 2 +-
src/proguard/optimize/KeepMarker.java | 2 +-
.../optimize/MemberDescriptorSpecializer.java | 2 +-
.../optimize/MethodDescriptorShrinker.java | 17 +-
src/proguard/optimize/MethodStaticizer.java | 2 +-
.../optimize/OptimizationInfoMemberFilter.java | 2 +-
src/proguard/optimize/Optimizer.java | 978 +++++---
src/proguard/optimize/ParameterShrinker.java | 40 +-
src/proguard/optimize/TailRecursionSimplifier.java | 10 +-
src/proguard/optimize/WriteOnlyFieldFilter.java | 2 +-
...tionSimplifier.java => EvaluationShrinker.java} | 1128 ++-------
.../optimize/evaluation/EvaluationSimplifier.java | 2564 ++++----------------
.../optimize/evaluation/LivenessAnalyzer.java | 8 +-
.../optimize/evaluation/LoadingInvocationUnit.java | 88 +-
.../optimize/evaluation/PartialEvaluator.java | 555 +++--
.../optimize/evaluation/StoringInvocationUnit.java | 62 +-
.../optimize/evaluation/TracedBranchUnit.java | 2 +-
.../optimize/evaluation/VariableOptimizer.java | 33 +-
src/proguard/optimize/info/AccessMethodMarker.java | 2 +-
.../optimize/info/BackwardBranchMarker.java | 2 +-
.../optimize/info/CatchExceptionMarker.java | 2 +-
...{DotClassFilter.java => CaughtClassFilter.java} | 14 +-
...{DotClassFilter.java => CaughtClassMarker.java} | 34 +-
.../optimize/info/ClassOptimizationInfo.java | 26 +-
.../optimize/info/ClassOptimizationInfoSetter.java | 2 +-
src/proguard/optimize/info/DotClassFilter.java | 2 +-
src/proguard/optimize/info/DotClassMarker.java | 4 +-
.../optimize/info/ExceptionInstructionChecker.java | 2 +-
.../optimize/info/FieldOptimizationInfo.java | 2 +-
.../optimize/info/InstanceofClassFilter.java | 2 +-
.../optimize/info/InstanceofClassMarker.java | 4 +-
.../optimize/info/InstantiationClassFilter.java | 2 +-
.../optimize/info/InstantiationClassMarker.java | 4 +-
.../info/MemberOptimizationInfoSetter.java | 2 +-
.../optimize/info/MethodInvocationMarker.java | 2 +-
.../optimize/info/MethodOptimizationInfo.java | 31 +-
.../optimize/info/NoSideEffectMethodMarker.java | 2 +-
.../optimize/info/NonPrivateMemberMarker.java | 2 +-
.../PackageVisibleMemberContainingClassMarker.java | 4 +-
.../PackageVisibleMemberInvokingClassMarker.java | 4 +-
.../optimize/info/ParameterUsageMarker.java | 170 +-
.../optimize/info/ReadWriteFieldMarker.java | 6 +-
.../info/SideEffectInstructionChecker.java | 2 +-
.../optimize/info/SideEffectMethodMarker.java | 2 +-
.../optimize/info/SuperInvocationMarker.java | 2 +-
.../optimize/info/VariableUsageMarker.java | 2 +-
.../optimize/peephole/BranchTargetFinder.java | 2 +-
src/proguard/optimize/peephole/ClassFinalizer.java | 63 +-
src/proguard/optimize/peephole/ClassMerger.java | 58 +-
.../optimize/peephole/GotoCommonCodeReplacer.java | 8 +-
.../optimize/peephole/GotoGotoReplacer.java | 2 +-
.../optimize/peephole/GotoReturnReplacer.java | 2 +-
.../optimize/peephole/HorizontalClassMerger.java | 2 +-
.../peephole/InstructionSequenceConstants.java | 255 +-
.../peephole/InstructionSequenceReplacer.java | 2 +-
.../peephole/InstructionSequencesReplacer.java | 2 +-
.../optimize/peephole/LoadStoreRemover.java | 123 -
.../optimize/peephole/MemberPrivatizer.java | 33 +-
.../{ClassFinalizer.java => MethodFinalizer.java} | 54 +-
src/proguard/optimize/peephole/MethodInliner.java | 15 +-
src/proguard/optimize/peephole/NopRemover.java | 2 +-
.../optimize/peephole/PeepholeOptimizer.java | 2 +-
src/proguard/optimize/peephole/PushPopRemover.java | 168 --
.../optimize/peephole/ReachableCodeMarker.java | 2 +-
.../RetargetedInnerClassAttributeRemover.java | 2 +-
.../optimize/peephole/StoreLoadReplacer.java | 141 --
.../optimize/peephole/TargetClassChanger.java | 2 +-
.../optimize/peephole/UnreachableCodeRemover.java | 2 +-
.../peephole/UnreachableExceptionRemover.java | 2 +-
.../optimize/peephole/VariableShrinker.java | 4 +-
.../optimize/peephole/VerticalClassMerger.java | 2 +-
src/proguard/preverify/CodePreverifier.java | 38 +-
src/proguard/preverify/CodeSubroutineInliner.java | 42 +-
src/proguard/preverify/Preverifier.java | 2 +-
src/proguard/preverify/SubroutineInliner.java | 2 +-
src/proguard/retrace/ReTrace.java | 664 ++++-
src/proguard/retrace/StackTrace.java | 178 --
src/proguard/retrace/StackTraceItem.java | 291 ---
src/proguard/shrink/AnnotationUsageMarker.java | 2 +-
src/proguard/shrink/ClassShrinker.java | 2 +-
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 | 2 +-
src/proguard/shrink/UsageMarker.java | 2 +-
src/proguard/shrink/UsagePrinter.java | 2 +-
src/proguard/shrink/UsedClassFilter.java | 2 +-
src/proguard/shrink/UsedMemberFilter.java | 2 +-
src/proguard/util/AndMatcher.java | 2 +-
src/proguard/util/ClassNameParser.java | 2 +-
.../util/{NotMatcher.java => ConstantMatcher.java} | 20 +-
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 | 14 +-
src/proguard/util/ListUtil.java | 100 +-
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 +-
611 files changed, 8643 insertions(+), 6954 deletions(-)
diff --git a/README b/README
index 6946bd0..8766da5 100644
--- a/README
+++ b/README
@@ -30,4 +30,4 @@ Enjoy!
http://proguard.sourceforge.net/
-Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
diff --git a/build/README b/build/README
deleted file mode 100644
index fa5f5a4..0000000
--- a/build/README
+++ /dev/null
@@ -1,34 +0,0 @@
-ProGuard, Java class file shrinker, optimizer, obfuscator, and preverifier
-==========================================================================
-
-This directory contains a number of alternative ways to build ProGuard:
-
-- build.sh : a shell script for GNU/Linux
-- makefile : a makefile for GNU/Linux
-- build.xml : an Ant build file for all platforms
-
-- As a final alternative, you can also easily compile the code from the
- command line:
-
- mkdir classes
- javac -sourcepath src -d classes src/proguard/ProGuard.java
- javac -sourcepath src -d classes src/proguard/gui/ProGuardGUI.java
- javac -sourcepath src -d classes src/proguard/retrace/ReTrace.java
-
- For the ProGuard Ant task:
-
- javac -sourcepath src -d classes -classpath lib/ant.jar \
- src/proguard/ant/ProGuardTask.java
-
- For the Java Micro Edition Wireless Tool Kit (JME WTK) obfuscator plug-in:
-
- javac -sourcepath src -d classes -classpath wtklib/kenv.zip \
- src/proguard/wtk/ProGuardObfuscator.java
-
-Note that you'll have to install Ant and the JME WTK yourself.
-
-Enjoy!
-
-http://proguard.sourceforge.net/
-
-Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
diff --git a/build/build.sh b/build/build.sh
index b829aa1..eb5fcf7 100755
--- a/build/build.sh
+++ b/build/build.sh
@@ -2,6 +2,10 @@
#
# GNU/Linux build script for ProGuard.
+#
+# Configuration.
+#
+
ANT_HOME=${ANT_HOME:-/usr/local/java/ant}
WTK_HOME=${WTK_HOME:-/usr/local/java/wtk}
@@ -23,12 +27,16 @@ ANT_TASK=proguard/ant/ProGuardTask
WTK_PLUGIN=proguard/wtk/ProGuardObfuscator
ANT_JAR=$ANT_HOME/lib/ant.jar
-WTK_JAR=$WTK_HOME/wtklib/kenv.jar
+WTK_JAR=$WTK_HOME/wtklib/kenv.zip
PROGUARD_JAR=$LIB/proguard.jar
PROGUARD_GUI_JAR=$LIB/proguardgui.jar
RETRACE_JAR=$LIB/retrace.jar
+#
+# Function definitions.
+#
+
function compile {
# Compile java source files.
echo "Compiling ${1//\//.} ..."
@@ -38,7 +46,7 @@ function compile {
# Copy resource files.
(cd "$SRC"; find $(dirname $1) -maxdepth 1 \
- \( -name \*.properties -o -name \*.gif -o -name \*.pro \) \
+ \( -name \*.properties -o -name \*.png -o -name \*.gif -o -name \*.pro \) \
-exec cp --parents {} "../$CLASSES" \; )
}
@@ -52,6 +60,12 @@ function updatejar {
jar -uf "$PROGUARD_JAR" -C "$CLASSES" $(dirname $1)
}
+#
+# Main script body.
+#
+
+mkdir -p "$CLASSES"
+
compile $PROGUARD
createjar $PROGUARD "$PROGUARD_JAR"
diff --git a/build/build.xml b/build/build.xml
index 3b5dd71..a592945 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -28,6 +28,7 @@
<copy todir = "${classes}">
<fileset dir = "${src}">
<include name = "proguard/*.properties"/>
+ <include name = "proguard/*.png"/>
<include name = "proguard/*.gif"/>
<include name = "proguard/*.pro"/>
</fileset>
@@ -51,6 +52,7 @@
<copy todir = "${classes}">
<fileset dir = "${src}">
<include name = "proguard/gui/*.properties"/>
+ <include name = "proguard/gui/*.png"/>
<include name = "proguard/gui/*.gif"/>
<include name = "proguard/gui/*.pro"/>
</fileset>
@@ -74,6 +76,7 @@
<copy todir = "${classes}">
<fileset dir = "${src}">
<include name = "proguard/retrace/*.properties"/>
+ <include name = "proguard/retrace/*.png"/>
<include name = "proguard/retrace/*.gif"/>
<include name = "proguard/retrace/*.pro"/>
</fileset>
@@ -106,6 +109,7 @@
<copy todir = "${classes}">
<fileset dir = "${src}">
<include name = "proguard/ant/*.properties"/>
+ <include name = "proguard/ant/*.png"/>
<include name = "proguard/ant/*.gif"/>
<include name = "proguard/ant/*.pro"/>
</fileset>
@@ -138,6 +142,7 @@
<copy todir = "${classes}">
<fileset dir = "${src}">
<include name = "proguard/wtk/*.properties"/>
+ <include name = "proguard/wtk/*.png"/>
<include name = "proguard/wtk/*.gif"/>
<include name = "proguard/wtk/*.pro"/>
</fileset>
diff --git a/build/makefile b/build/makefile
index bb4af4f..0508eb4 100644
--- a/build/makefile
+++ b/build/makefile
@@ -66,7 +66,7 @@ clean:
define RESOURCES
- $(shell find $(SRC)/$(dir $(1)) -maxdepth 1 \( -name \*.properties -o -name \*.gif -o -name \*.pro \) -printf $(CLASSES)/$(dir $(1))%P\\n)
+ $(shell find $(SRC)/$(dir $(1)) -maxdepth 1 \( -name \*.properties -o -name \*.png -o -name \*.gif -o -name \*.pro \) -printf $(CLASSES)/$(dir $(1))%P\\n)
endef
define TARGETRULE
@@ -81,7 +81,7 @@ $(CLASSES) $(LIB):
$(CLASSES)/%.class: $(SRC)/%.java
javac $(JAVAC_OPTIONS) $^
-$(CLASSES)/%.properties $(CLASSES)/%.gif $(CLASSES)/%.pro:
+$(CLASSES)/%.properties $(CLASSES)/%.png $(CLASSES)/%.gif $(CLASSES)/%.pro:
cp $(subst $(CLASSES),$(SRC),$@) $@
%.jar %.zip:
diff --git a/docs/FAQ.html b/docs/FAQ.html
index 04897dc..8f19b15 100644
--- a/docs/FAQ.html
+++ b/docs/FAQ.html
@@ -247,7 +247,7 @@ Manual</a> for more details.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/GPL_exception.html b/docs/GPL_exception.html
index 0955cf8..0a44d66 100644
--- a/docs/GPL_exception.html
+++ b/docs/GPL_exception.html
@@ -7,7 +7,7 @@
<H1>Special Exception to the GNU General Public License</H1>
<P>
-Copyright © 2002-2008 Eric Lafortune
+Copyright © 2002-2009 Eric Lafortune
</P>
<P>
@@ -35,6 +35,7 @@ the code of this program with the following stand-alone applications:
<ul>
<li>Apache Ant,
<li>Apache Maven,
+<li>the Eclipse ProGuardDT GUI,
<li>the EclipseME JME IDE,
<li>the Sun NetBeans Java IDE,
<li>the Sun JME Wireless Toolkit, and
diff --git a/docs/acknowledgements.html b/docs/acknowledgements.html
index 5713ae1..af19461 100644
--- a/docs/acknowledgements.html
+++ b/docs/acknowledgements.html
@@ -32,7 +32,8 @@ Sherington, David Sitsky, James Manning, Ptolemy Oberin, Frank-Michael Moser,
QZ Shines, Thomas Singer, Michele Puccini, Roman Bednarek, Natalia Pujol,
Daniel Sjöblom, Jan Filipsky, Charles Smith, Gerrit Telkamp, Noel
Grandin, Torbjörn Söderstedt, Clemens Eisserer, Clark Bassett,
-Eduard Welch, Dawid Weiss, Andrew Wilson, Sean Owen, Niels Gron,
+Eduard Welch, Dawid Weiss, Andrew Wilson, Sean Owen, Niels Gron, Ishan Mehta,
+Steven Adams, Xavier Kral,
and many others. Thanks! Your feedback has been invaluable.
<p>
@@ -59,7 +60,7 @@ href="http://www.javadocking.com/" target="other">Java Docking Library</a>.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
diff --git a/docs/alternatives.html b/docs/alternatives.html
index 7a09b34..fa5db0c 100644
--- a/docs/alternatives.html
+++ b/docs/alternatives.html
@@ -214,6 +214,16 @@ below is incorrect.
</tr>
<tr>
+<td><a target="other" rel="nofollow" href="http://www.sable.mcgill.ca/">Sable</a></td>
+<td><a target="other" href="http://www.sable.mcgill.ca/JBCO/">JBCO</a></td>
+<td align="center"><br></td>
+<td align="center"><br></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
+<td align="center"><br></td>
+<td>Free (LGPL)</td>
+</tr>
+
+<tr>
<td><a target="other" rel="nofollow" href="http://sourceforge.net/users/glurk/">Thorsten Heit</a></td>
<td><a target="other" href="http://sourceforge.net/projects/javaguard/">JavaGuard</a></td>
<td align="center"><br></td>
@@ -639,7 +649,7 @@ All trademarks are property of their respective holders.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
diff --git a/docs/downloads.html b/docs/downloads.html
index dfaee8d..ebd1b28 100644
--- a/docs/downloads.html
+++ b/docs/downloads.html
@@ -15,7 +15,8 @@
License. Please consult the <a href="license.html">license page</a> for more
details.
<p>
-<b>ProGuard</b> is written in Java. It requires a Java 2 runtime environment.
+<b>ProGuard</b> is written in Java, so it requires a Java Runtime Environment
+ (JRE 1.4 or higher).
<p>
You can download the latest release (containing the program jar, the
documentation you're reading now, examples, and the source code) from this
@@ -43,12 +44,52 @@ interest too, because they typically contain any less urgent bug fixes
collected since the previous release.
<p>
+<h3><div>Jul 2009</div> Version 4.4</h3>
+<ul>
+<li>Added new peephole optimizations.
+<li>Added option <code>-optimizations</code> for fine-grained configuration of
+ optimizations.
+<li>Added option <code>-adaptclassstrings</code> for adapting string constants
+ that correspond to obfuscated classes.
+<li>Added option <code>-keeppackagenames</code> for keeping specified package
+ names from being obfuscated.
+<li>Added option <code>-keepdirectories</code> for keeping specified directory
+ entries in output jars.
+<li>Extended options <code>-dontnote</code> and <code>-dontwarn</code> for
+ fine-grained configuration of notes and warnings.
+<li>Added option <code>-regex</code> in ReTrace, for specifying alternative
+ regular expressions to parse stack traces.
+<li>Extended renaming of resource files based on obfuscation.
+<li>Improved inlining of constant parameters and removal of unused parameters.
+<li>Avoiding bug in IBM's JVM for JSE, in optimization step.
+<li>Avoiding ArrayIndexOutOfBoundsException in optimization step.
+<li>Fixed configuration with annotations that are not preserved themselves.
+<li>Fixed preverification of invocations of super constructors with arguments
+ containing ternary operators.
+<li>Fixed processing of unreachable exception handlers.
+<li>Fixed merging of exception classes.
+<li>Fixed repeated method inlining.
+<li>Fixed inlining of finally blocks surrounded by large try blocks, compiled
+ with JDK 1.4 or earlier.
+<li>Fixed optimization of complex finally blocks, compiled with JDK 1.4 or
+ earlier.
+<li>Fixed obfuscation of anonymous class names, if <code>EnclosingMethod</code>
+ attributes are being kept.
+<li>Fixed obfuscation of inner class names in generic types.
+<li>Fixed decoding of UTF-8 strings containing special characters.
+<li>Fixed copying of debug information and annotations when merging classes.
+<li>Fixed writing out of unknown attributes.
+<li>Fixed updating manifest files with split lines.
+<li>Updated documentation and examples.
+</ul>
+
<h3><div>Dec 2008</div> Version 4.3</h3>
<ul>
<li>Added class merging.
<li>Added static single assignment analysis.
<li>Added support for annotation and enumeration class types in configuration.
-<li>Refined shrinking of fields in case of unusual -keepclassmembers options.
+<li>Refined shrinking of fields in case of unusual
+ <code>-keepclassmembers</code> options.
<li>Added simplification of tail recursion calls.
<li>Added new peephole optimizations.
<li>Fixed optimization of unused variable initializations causing negative
@@ -472,7 +513,7 @@ Upgrade considerations:
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
diff --git a/docs/feedback.html b/docs/feedback.html
index 60bc4a9..a7e770b 100644
--- a/docs/feedback.html
+++ b/docs/feedback.html
@@ -98,7 +98,7 @@ projects.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
diff --git a/docs/index.html b/docs/index.html
index 8787906..771bb6a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -64,7 +64,7 @@ You can go straight to the <a href="main.html">main page</a>.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/license.html b/docs/license.html
index b393294..b4654fd 100644
--- a/docs/license.html
+++ b/docs/license.html
@@ -26,11 +26,12 @@ the complete source code available as well. If you develop a program that is
linked with
<b>ProGuard</b>, the program as a whole has to be distributed at no charge
under the GPL. I am granting a <a href="GPL_exception.html">special
-exception</a> to the latter clause (in wording suggested by the <a
-href="http://www.gnu.org/copyleft/gpl-faq.html#GPLIncompatibleLibs"
+exception</a> to the latter clause (in wording suggested by
+the <a href="http://www.gnu.org/copyleft/gpl-faq.html#GPLIncompatibleLibs"
target="other">FSF</a>), for combinations with the following stand-alone
-applications: Apache Ant, Apache Maven, the EclipseME JME IDE, the Sun NetBeans
-Java IDE, the Sun JME Wireless Toolkit, and the Javaground Tools.
+applications: Apache Ant, Apache Maven, the Eclipse ProGuardDT GUI, the
+EclipseME JME IDE, the Sun NetBeans Java IDE, the Sun JME Wireless Toolkit,
+and the Javaground Tools.
<p>
The <b>ProGuard user documentation</b> represents an important part of this
@@ -39,7 +40,7 @@ version of the code.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/main.html b/docs/main.html
index 2e4e117..e988c79 100644
--- a/docs/main.html
+++ b/docs/main.html
@@ -85,7 +85,7 @@ The following sections provide more detailed information:
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/ant.html b/docs/manual/ant.html
index 6088991..bc3a3b4 100644
--- a/docs/manual/ant.html
+++ b/docs/manual/ant.html
@@ -102,7 +102,7 @@ If you really prefer a full-blown XML configuration, you can replace the
ProGuard configuration options by XML configuration tags. The resulting
configuration will be equivalent, but much more verbose and difficult to read,
as XML goes. The remainder of this page presents the supported tags. For a
-more extensive discussion of their meaning, please refer to the traditional <a
+more extensive discussion of their meaning, please consult the traditional <a
href="usage.html">Usage</a> section. You can find some sample configuration
files in the <code>examples/ant</code> directory of the ProGuard distribution.
<p>
@@ -169,7 +169,7 @@ elements:
<dt><a href="usage.html#optimizationpasses"><code><b>optimizationpasses</b></code></a>
= "<i>n</i>"
(default = 1)</dt>
-<dd>The number of optimization passes to be performed.
+<dd>The number of optimization passes to be performed.</dd>
<dt><a href="usage.html#allowaccessmodification"><code><b>allowaccessmodification</b></code></a>
= "<i>boolean</i>"
@@ -267,13 +267,16 @@ elements:
<dt><a href="usage.html#dontnote"><code><b>note</b></code></a>
= "<i>boolean</i>"
(default = true)</dt>
-<dd>Print notes about potential mistakes or omissions in the
- configuration.</dd>
+<dd>Print notes about potential mistakes or omissions in the configuration.
+ Use the nested element <a href="#dontnote">dontnote</a> for more
+ fine-grained control.</dd>
<dt><a href="usage.html#dontwarn"><code><b>warn</b></code></a>
= "<i>boolean</i>"
(default = true)</dt>
-<dd>Warn about unresolved references at all.</dd>
+<dd>Print warnings about unresolved references. Use the nested
+ element <a href="#dontwarn">dontwarn</a> for more fine-grained
+ control. <i>Only use this option if you know what you're doing!</i></dd>
<dt><a href="usage.html#ignorewarnings"><code><b>ignorewarnings</b></code></a>
= "<i>boolean</i>"
@@ -310,6 +313,13 @@ elements:
<code><b>/></b></code></dt>
<dd>Specifies the library jars (or wars, ears, zips, or directories).</dd>
+<dt><a href="usage.html#keepdirectories"><code><b><keepdirectory name = </b></code></a>"<i>directory_name</i>"
+ <code><b>/></b></code><br/>
+ <a href="usage.html#keepdirectories"><code><b><keepdirectories filter = </b></code></a>"<a href="usage.html#filefilters"><i>directory_filter</i></a>"
+ <code><b>/></b></code></dt>
+<dd>Keep the specified directories in the output jars (or wars, ears, zips, or
+ directories).</dd>
+
<dt><a href="usage.html#keep"><code><b><keep</b></code></a>
<a href="#keepmodifier"><i>modifiers</i></a>
<a href="#classspecification"><i>class_specification</i></a>
@@ -375,22 +385,55 @@ elements:
<a href="#classmemberspecification"><i>class_member_specifications</i></a>
<code><b></assumenosideeffects></b></code></dt>
<dd>Assume that the specified methods don't have any side effects, while
- optimizing.</dd>
+ optimizing. <i>Only use this option if you know what you're
+ doing!</i></dd>
+
+<dt><a href="usage.html#optimizations"><code><b><optimization name = </b></code></a>"<a href="optimizations.html"><i>optimization_name</i></a>"
+ <code><b>/></b></code><br/>
+ <a href="usage.html#optimizations"><code><b><optimizations filter = </b></code></a>""<a href="optimizations.html"><i>optimization_filter</i></a>"
+ <code><b>/></b></code></dt>
+<dd>Perform only the specified optimizations.</dd>
+
+<dt><a href="usage.html#keeppackagenames"><code><b><keeppackagename name = </b></code></a>"<i>package_name</i>"
+ <code><b>/></b></code><br/>
+ <a href="usage.html#keeppackagenames"><code><b><keeppackagenames filter = </b></code></a>"<a href="usage.html#filters"><i>package_filter</i></a>"
+ <code><b>/></b></code></dt>
+<dd>Keep the specified package names from being obfuscated. If no name is
+ given, all package names are preserved.</dd>
<dt><a href="usage.html#keepattributes"><code><b><keepattribute name = </b></code></a>"<i>attribute_name</i>"
+ <code><b>/></b></code><br/>
+ <a href="usage.html#keepattributes"><code><b><keepattributes filter = </b></code></a>"<a href="usage.html#filters"><i>attribute_filter</i></a>"
<code><b>/></b></code></dt>
-<dd>Preserve the given optional Java bytecode attribute, with optional
+<dd>Preserve the specified optional Java bytecode attributes, with optional
wildcards. If no name is given, all attributes are preserved.</dd>
-<dt><a href="usage.html#adaptresourcefilenames"><code><b><adaptresourcefilenames filter = </b></code></a>"<a href="usage.html#filters"><i>filter</i></a>"
+<dt><a href="usage.html#adaptclassstrings"><code><b><adaptclassstrings filter = </b></code></a>"<a href="usage.html#filters"><i>class_filter</i></a>"
+ <code><b>/></b></code></dt>
+<dd>Adapt string constants in the specified classes, based on the obfuscated
+ names of any corresponding classes.</dd>
+
+<dt><a href="usage.html#adaptresourcefilenames"><code><b><adaptresourcefilenames filter = </b></code></a>"<a href="usage.html#filefilters"><i>file_filter</i></a>"
<code><b>/></b></code></dt>
<dd>Rename the specified resource files, based on the obfuscated names of the
corresponding class files.</dd>
-<dt><a href="usage.html#adaptresourcefilecontents"><code><b><adaptresourcefilecontents filter = </b></code></a>"<a href="usage.html#filters"><i>filter</i></a>"
+<dt><a href="usage.html#adaptresourcefilecontents"><code><b><adaptresourcefilecontents filter = </b></code></a>"<a href="usage.html#filefilters"><i>file_filter</i></a>"
<code><b>/></b></code></dt>
<dd>Update the contents of the specified resource files, based on the
- obfuscated names of the class files.</dd>
+ obfuscated names of the processed classes.</dd>
+
+<dt><a name="dontnote" />
+ <a href="usage.html#dontnote"><code><b><dontnote filter = </b></code></a>"<a href="usage.html#filters"><i>class_filter</i></a>"
+ <code><b>/></b></code></dt>
+<dd>Don't print notes about classes matching the specified class name
+ filter.</dd>
+
+<dt><a name="dontwarn" />
+ <a href="usage.html#dontwarn"><code><b><dontwarn filter = </b></code></a>"<a href="usage.html#filters"><i>class_filter</i></a>"
+ <code><b>/></b></code></dt>
+<dd>Don't print warnings about classes matching the specified class name
+ filter. <i>Only use this option if you know what you're doing!</i></dd>
<dt><a name="configuration_element"><code><b><configuration refid = </b></code></a>"<i>ref_id</i>"
<code><b>/></b></code></dt>
@@ -434,24 +477,24 @@ In addition, the jar tags can have ProGuard-style filter attributes:
<dl>
<dt><code><b>filter</b></code> =
- "<a href="usage.html#filters"><i>filter</i></a>"</dt>
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
<dd>An optional filter for all class file names and resource file names that
are encountered.</dd>
<dt><code><b>jarfilter</b></code> =
- "<a href="usage.html#filters"><i>filter</i></a>"</dt>
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
<dd>An optional filter for all jar names that are encountered.</dd>
<dt><code><b>warfilter</b></code> =
- "<a href="usage.html#filters"><i>filter</i></a>"</dt>
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
<dd>An optional filter for all war names that are encountered.</dd>
<dt><code><b>earfilter</b></code> =
- "<a href="usage.html#filters"><i>filter</i></a>"</dt>
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
<dd>An optional filter for all ear names that are encountered.</dd>
<dt><code><b>zipfilter</b></code> =
- "<a href="usage.html#filters"><i>filter</i></a>"</dt>
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
<dd>An optional filter for all zip names that are encountered.</dd>
</dl>
@@ -560,7 +603,7 @@ attributes:
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/examples.html b/docs/manual/examples.html
index 33a8ecc..3f47fca 100644
--- a/docs/manual/examples.html
+++ b/docs/manual/examples.html
@@ -15,11 +15,17 @@ Some typical useful configurations:
<li><a href="#application">A typical application</a>
<li><a href="#applet">A typical applet</a>
<li><a href="#midlet">A typical midlet</a>
+<li><a href="#jcapplet">A typical Java Card applet</a>
+<li><a href="#xlet">A typical xlet</a>
+<li><a href="#androidapplication">A typical Android application</a>
+<li><a href="#library">A typical library</a>
<li><a href="#applications">All possible applications in the input jars</a>
<li><a href="#applets">All possible applets in the input jars</a>
<li><a href="#midlets">All possible midlets in the input jars</a>
+<li><a href="#jcapplets">All possible Java Card applets in the input jars</a>
+<li><a href="#xlets">All possible xlets in the input jars</a>
+<li><a href="#androidapplications">All possible Android applications in the input jars</a>
<li><a href="#servlets">All possible servlets in the input jars</a>
-<li><a href="#library">A typical library</a>
<li><a href="#native">Processing native methods</a>
<li><a href="#callback">Processing callback methods</a>
<li><a href="#enumerations">Processing enumeration classes</a>
@@ -162,6 +168,153 @@ option.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a> and <a href="#resourcefiles">resource files</a>.
+<p>
+Note that you will still have to adapt the midlet jar size in the
+corresponding jad file; ProGuard doesn't do that for you.
+
+<a name="jcapplet"> </a>
+<h3>A typical Java Card applet</h3>
+These options shrink, optimize, and obfuscate the Java Card applet
+<code>mypackage.MyApplet</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/javacard2.2.2/lib/api.jar
+-dontwarn java.lang.Class
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+
+-keep public class mypackage.MyApplet
+</pre>
+<p>
+The configuration is very similar to the configuration for midlets, except that
+it now targets the Java Card run-time environment. This environment doesn't
+have java.lang.Class, so we're telling ProGuard not to worry about it.
+
+<a name="xlet"> </a>
+<h3>A typical xlet</h3>
+These options shrink, optimize, and obfuscate the xlet
+<code>mypackage.MyXlet</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/jtv1.1/javatv.jar
+-libraryjars /usr/local/java/cdc1.1/lib/cdc.jar
+-libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+
+-keep public class mypackage.MyXlet
+</pre>
+<p>
+The configuration is very similar to the configuration for midlets, except that
+it now targets the CDC run-time environment with the Java TV API.
+
+<a name="androidapplication"> </a>
+<h3>A typical Android application</h3>
+These options shrink, optimize, and obfuscate the simple Android application
+based on a single activity <code>mypackage.MyActivity</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/android-1.5_r1/platforms/android-1.5/android.jar
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-optimizations !code/simplification/arithmetic
+
+-keep public class mypackage.MyActivity
+</pre>
+<p>
+The configuration is very similar to the configuration for midlets, except that
+it now targets the Android run-time environment.
+<p>
+The <a href="usage.html#optimizations"><code>-optimizations</code></a> option
+disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, and <a
+href="#resourcefiles">resource files</a>.
+
+<a name="library"> </a>
+<h3>A typical library</h3>
+These options shrink, optimize, and obfuscate an entire library, keeping all
+public and protected classes and class members, native method names, and
+serialization code:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars <java.home>/lib/rt.jar
+-printmapping out.map
+
+-renamesourcefileattribute SourceFile
+-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
+ SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
+
+-keep public class * {
+ public protected *;
+}
+
+-keepclassmembernames class * {
+ java.lang.Class class$(java.lang.String);
+ java.lang.Class class$(java.lang.String, boolean);
+}
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+</pre>
+<p>
+This configuration should preserve everything we'll ever want to access in the
+library. Only if there are any other non-public classes or methods that are
+invoked dynamically, they should be specified using additional <a
+href="usage.html#keep"><code>-keep</code></a> options.
+<p>
+The <a
+href="usage.html#keepclassmembernames"><code>-keepclassmembernames</code></a>
+option for the <code>class$</code> methods is not strictly necessary. These
+methods are inserted by the <code>javac</code> compiler and the
+<code>jikes</code> compiler respectively, to implement the <code>.class</code>
+construct. ProGuard will automatically detect them and deal with them, even
+when their names have been obfuscated. However, older versions of ProGuard and
+other obfuscators may rely on the original method names. It may therefore be
+helpful to preserve them, in case these other obfuscators are ever used for
+further obfuscation of the library.
+<p>
+The "Exceptions" attribute has to be preserved, so the compiler knows which
+exceptions methods may throw.
+<p>
+The "InnerClasses" attribute (or more precisely, its source name part) has to
+be preserved too, for any inner classes that can be referenced from outside the
+library. The <code>javac</code> compiler would be unable to find the inner
+classes otherwise.
+<p>
+The "Signature" attribute is required to be able to access generic types when
+compiling in JDK 5.0 and higher.
+<p>
+Finally, we're keeping the "Deprecated" attribute and the attributes for
+producing <a href="#stacktrace">useful stack traces</a>.
+<p>
+We've also added some options for for processing <a href="#native">native
+methods</a>, <a href="#enumerations">enumerations</a>, <a
+href="#serializable">serializable classes</a>, and <a
+href="#annotations">annotations</a>, which are all discussed in their
+respective examples.
<a name="applications"> </a>
<h3>All possible applications in the input jars</h3>
@@ -255,6 +408,85 @@ out which midlets exactly will be preserved.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a> and <a href="#resourcefiles">resource files</a>.
+<p>
+Note that you will still have to adapt the midlet jar size in the
+corresponding jad file; ProGuard doesn't do that for you.
+
+<a name="jcapplets"> </a>
+<h3>All possible Java Card applets in the input jars</h3>
+These options shrink, optimize, and obfuscate all public Java Card applets in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/javacard2.2.2/lib/api.jar
+-dontwarn java.lang.Class
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-printseeds
+
+-keep public class * implements javacard.framework.Applet
+</pre>
+<p>
+We're simply keeping all classes that implement the <code>Applet</code>
+interface.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which applets exactly will be preserved.
+
+<a name="xlets"> </a>
+<h3>All possible xlets in the input jars</h3>
+These options shrink, optimize, and obfuscate all public xlets in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/jtv1.1/javatv.jar
+-libraryjars /usr/local/java/cdc1.1/lib/cdc.jar
+-libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-printseeds
+
+-keep public class * implements javax.tv.xlet.Xlet
+</pre>
+<p>
+We're simply keeping all classes that implement the <code>Xlet</code> interface.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which xlets exactly will be preserved.
+
+<a name="androidapplications"> </a>
+<h3>All possible Android applications in the input jars</h3>
+These options shrink, optimize, and obfuscate all public activities, services,
+broadcast receivers, and content providers in <code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/android-1.5_r1/platforms/android-1.5/android.jar
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-optimizations !code/simplification/arithmetic
+-printseeds
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+</pre>
+<p>
+We're keeping all classes that extend the base classes that may be referenced
+by the <code>AndroidManifest.xml</code> file of the application.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which implementations exactly will be preserved.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, and <a
+href="#resourcefiles">resource files</a>.
<a name="servlets"> </a>
<h3>All possible servlets in the input jars</h3>
@@ -289,84 +521,6 @@ classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
-<a name="library"> </a>
-<h3>A typical library</h3>
-These options shrink, optimize, and obfuscate an entire library, keeping all
-public and protected classes and class members, native method names, and
-serialization code:
-<pre>
--injars in.jar
--outjars out.jar
--libraryjars <java.home>/lib/rt.jar
--printmapping out.map
-
--renamesourcefileattribute SourceFile
--keepattributes Exceptions,InnerClasses,Signature,Deprecated,
- SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-
--keep public class * {
- public protected *;
-}
-
--keepclassmembernames class * {
- java.lang.Class class$(java.lang.String);
- java.lang.Class class$(java.lang.String, boolean);
-}
-
--keepclasseswithmembernames class * {
- native <methods>;
-}
-
--keepclassmembers enum * {
- public static **[] values();
- public static ** valueOf(java.lang.String);
-}
-
--keepclassmembers class * implements java.io.Serializable {
- static final long serialVersionUID;
- private void writeObject(java.io.ObjectOutputStream);
- private void readObject(java.io.ObjectInputStream);
- java.lang.Object writeReplace();
- java.lang.Object readResolve();
-}
-</pre>
-<p>
-This configuration should preserve everything we'll ever want to access in the
-library. Only if there are any other non-public classes or methods that are
-invoked dynamically, they should be specified using additional <a
-href="usage.html#keep"><code>-keep</code></a> options.
-<p>
-The <a
-href="usage.html#keepclassmembernames"><code>-keepclassmembernames</code></a>
-option for the <code>class$</code> methods is not strictly necessary. These
-methods are inserted by the <code>javac</code> compiler and the
-<code>jikes</code> compiler respectively, to implement the <code>.class</code>
-construct. ProGuard will automatically detect them and deal with them, even
-when their names have been obfuscated. However, older versions of ProGuard and
-other obfuscators may rely on the original method names. It may therefore be
-helpful to preserve them, in case these other obfuscators are ever used for
-further obfuscation of the library.
-<p>
-The "Exceptions" attribute has to be preserved, so the compiler knows which
-exceptions methods may throw.
-<p>
-The "InnerClasses" attribute (or more precisely, its source name part) has to
-be preserved too, for any inner classes that can be referenced from outside the
-library. The <code>javac</code> compiler would be unable to find the inner
-classes otherwise.
-<p>
-The "Signature" attribute is required to be able to access generic types when
-compiling in JDK 5.0 and higher.
-<p>
-Finally, we're keeping the "Deprecated" attribute and the attributes for
-producing <a href="#stacktrace">useful stack traces</a>.
-<p>
-We've also added some options for for processing <a href="#native">native
-methods</a>, <a href="#enumerations">enumerations</a>, <a
-href="#serializable">serializable classes</a>, and <a
-href="#annotations">annotations</a>, which are all discussed in their
-respective examples.
-
<a name="native"> </a>
<h3>Processing native methods</h3>
If your application, applet, servlet, library, etc., contains native methods,
@@ -662,9 +816,7 @@ any). The <a
href="usage.html#adaptresourcefilecontents">-adaptresourcefilecontents</a>
option looks for class names in properties files and in the manifest file, and
replaces these names by the obfuscated names (if any). You'll probably want to
-adapt the filters to suit your application. Note that package names of
-resource files that don't have corresponding class files are not updated in
-the current implementation.
+adapt the filters to suit your application.
<a name="stacktrace"> </a>
<h3>Producing useful obfuscated stack traces</h3>
@@ -1143,7 +1295,7 @@ illustrate some of the possibilities.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/gui.html b/docs/manual/gui.html
index 033fcd8..37684a6 100644
--- a/docs/manual/gui.html
+++ b/docs/manual/gui.html
@@ -345,10 +345,12 @@ Corresponding configuration options:
<li>-<a href="usage.html#overloadaggressively">overloadaggressively</a>
<li>-<a href="usage.html#useuniqueclassmembernames">useuniqueclassmembernames</a>
<li>-<a href="usage.html#dontusemixedcaseclassnames">dontusemixedcaseclassnames</a>
+<li>-<a href="usage.html#keeppackagenames">keeppackagenames</a>
<li>-<a href="usage.html#flattenpackagehierarchy">flattenpackagehierarchy</a>
<li>-<a href="usage.html#repackageclasses">repackageclasses</a>
<li>-<a href="usage.html#keepattributes">keepattributes</a>
<li>-<a href="usage.html#renamesourcefileattribute">renamesourcefileattribute</a>
+<li>-<a href="usage.html#adaptclassstrings">adaptclassstrings</a>
<li>-<a href="usage.html#adaptresourcefilenames">adaptresourcefilenames</a>
<li>-<a href="usage.html#adaptresourcefilecontents">adaptresourcefilecontents</a>
<li>-<a href="usage.html#keepnames">keepnames</a>
@@ -374,6 +376,7 @@ href="#shrinking">Shrinking Tab</a>.
Corresponding configuration options:
<ul type="none">
<li>-<a href="usage.html#dontoptimize">dontoptimize</a>
+<li>-<a href="usage.html#optimizations">optimizations</a>
<li>-<a href="usage.html#optimizationpasses">optimizationpasses</a>
<li>-<a href="usage.html#allowaccessmodification">allowaccessmodification</a>
<li>-<a href="usage.html#mergeinterfacesaggressively">mergeinterfacesaggressively</a>
@@ -402,6 +405,7 @@ Corresponding configuration options:
<li>-<a href="usage.html#ignorewarnings">ignorewarnings</a>
<li>-<a href="usage.html#dontskipnonpubliclibraryclasses">dontskipnonpubliclibraryclasses</a>
<li>-<a href="usage.html#dontskipnonpubliclibraryclassmembers">dontskipnonpubliclibraryclassmembers</a>
+<li>-<a href="usage.html#keepdirectories">keepdirectories</a>
<li>-<a href="usage.html#forceprocessing">forceprocessing</a>
<li>-<a href="usage.html#printseeds">printseeds</a>
<li>-<a href="usage.html#printconfiguration">printconfiguration</a>
@@ -463,7 +467,7 @@ There are two buttons at the bottom:
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/index.html b/docs/manual/index.html
index 65db3c8..397b910 100644
--- a/docs/manual/index.html
+++ b/docs/manual/index.html
@@ -32,7 +32,7 @@
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/introduction.html b/docs/manual/introduction.html
index 5035057..cdab330 100644
--- a/docs/manual/introduction.html
+++ b/docs/manual/introduction.html
@@ -149,7 +149,7 @@ about the internals of the code.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/limitations.html b/docs/manual/limitations.html
index 68c27da..cfe0ff5 100644
--- a/docs/manual/limitations.html
+++ b/docs/manual/limitations.html
@@ -57,7 +57,7 @@ which are easily avoided or resolved:
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/optimizations.html b/docs/manual/optimizations.html
new file mode 100644
index 0000000..9c20571
--- /dev/null
+++ b/docs/manual/optimizations.html
@@ -0,0 +1,158 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>Optimizations</title>
+</head>
+<body>
+
+<h2>Optimizations</h2>
+
+The optimization step of ProGuard can be switched off with the
+<a href="usage.html#dontoptimize"><code>-dontoptimize</code></a> option. For
+more fine-grained control over individual optimizations, experts can use the
+<a href="usage.html#optimizations"><code>-optimizations</code></a> option,
+with a filter based on the optimization names listed below. The filter works
+like any <a href="usage.html#filters">filter</a> in ProGuard.
+<p>
+
+The following wildcards are supported:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in an optimization name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of an optimization name.</td></tr>
+</table>
+
+An optimization that is preceded by an exclamation mark '<b>!</b>' is
+<i>excluded</i> from further attempts to match with <i>subsequent</i>
+optimization names in the filter. Make sure to specify filters correctly,
+since they are not checked for potential typos.
+<p>
+
+For example,
+"<code>code/simplification/variable,code/simplification/arithmetic</code>"
+only performs the two specified peephole optimizations.
+<p>
+
+For example, "<code>!method/propagation/*</code>" performs all optimizations,
+except the ones that propagate values between methods.
+<p>
+
+For example,
+"<code>!code/simplification/advanced,code/simplification/*</code>" only
+performs all peephole optimizations.
+<p>
+Some optimizations necessarily imply other optimizations. These are then
+indicated. Note that the list is likely to change over time, as optimizations
+are added and reorganized.
+<p>
+
+<dl>
+<dt><code><b>class/marking/final</b></code></dt>
+<dd>Marks classes as final, whenever possible.</dd>
+
+<dt><code><b>class/merging/vertical</b></code></dt>
+<dd>Merges classes vertically in the class hierarchy, whenever possible.</dd>
+
+<dt><code><b>class/merging/horizontal</b></code></dt>
+<dd>Merges classes horizontally in the class hierarchy, whenever possible.</dd>
+
+<dt><div>(⇒ <code>code/removal/advanced</code>)</div>
+ <code><b>field/removal/writeonly</b></code></dt>
+<dd>Removes write-only fields.</dd>
+
+<dt><code><b>field/marking/private</b></code></dt>
+<dd>Marks fields as private, whenever possible.</dd>
+
+<dt><div>(⇒ <code>code/simplification/advanced</code>)</div>
+ <code><b>field/propagation/value</b></code></dt>
+<dd>Propagates the values of fields across methods.</dd>
+
+<dt><code><b>method/marking/private</b></code></dt>
+<dd>Marks methods as private, whenever possible (<i>devirtualization</i>).</dd>
+
+<dt><div>(⇒ <code>code/removal/advanced</code>)</div>
+ <code><b>method/marking/static</b></code></dt>
+<dd>Marks methods as static, whenever possible (<i>devirtualization</i>).</dd>
+
+<dt><code><b>method/marking/final</b></code></dt>
+<dd>Marks methods as final, whenever possible.</dd>
+
+<dt><div>(⇒ <code>code/removal/advanced</code>)</div>
+ <code><b>method/removal/parameter</b></code></dt>
+<dd>Removes unused method parameters.</dd>
+
+<dt><div>(⇒ <code>code/simplification/advanced</code>)</div>
+ <code><b>method/propagation/parameter</b></code></dt>
+<dd>Propagates the values of method parameters from method invocations to
+ the invoked methods.</dd>
+
+<dt><div>(⇒ <code>code/simplification/advanced</code>)</div>
+ <code><b>method/propagation/returnvalue</b></code></dt>
+<dd>Propagates the values of method return values from methods to their
+ invocations.</dd>
+
+<dt><code><b>method/inlining/short</b></code></dt>
+<dd>Inlines short methods.</dd>
+
+<dt><code><b>method/inlining/unique</b></code></dt>
+<dd>Inlines methods that are only called once.</dd>
+
+<dt><code><b>method/inlining/tailrecursion</b></code></dt>
+<dd>Simplifies tail recursion calls, whenever possible.</dd>
+
+<dt><code><b>code/merging</b></code></dt>
+<dd>Merges identical blocks of code by modifying branch targets.</dd>
+
+<dt><code><b>code/simplification/variable</b></code></dt>
+<dd>Performs peephole optimizations for variable loading and storing.</dd>
+
+<dt><code><b>code/simplification/arithmetic</b></code></dt>
+<dd>Performs peephole optimizations for arithmetic instructions.</dd>
+
+<dt><code><b>code/simplification/cast</b></code></dt>
+<dd>Performs peephole optimizations for casting operations.</dd>
+
+<dt><code><b>code/simplification/field</b></code></dt>
+<dd>Performs peephole optimizations for field loading and storing.</dd>
+
+<dt><div>(⇒ <code>code/removal/simple</code>)</div>
+ <code><b>code/simplification/branch</b></code></dt>
+<dd>Performs peephole optimizations for branch instructions.</dd>
+
+<dt><div>(<i>best used with</i> <code>code/removal/advanced</code>)</div>
+ <code><b>code/simplification/advanced</b></code></dt>
+<dd>Simplifies code based on control flow analysis and data flow
+ analysis.</dd>
+
+<dt><div>(⇒ <code>code/removal/exception</code>)</div>
+ <code><b>code/removal/advanced</b></code></dt>
+<dd>Removes dead code based on control flow analysis and data flow
+ analysis.</dd>
+
+<dt><div>(⇒ <code>code/removal/exception</code>)</div>
+ <code><b>code/removal/simple</b></code></dt>
+<dd>Removes dead code based on a simple control flow analysis.</dd>
+
+<dt><code><b>code/removal/variable</b></code></dt>
+<dd>Removes unused variables from the local variable frame.</dd>
+
+<dt><code><b>code/removal/exception</b></code></dt>
+<dd>Removes exceptions with empty catch blocks.</dd>
+
+<dt><code><b>code/allocation/variable</b></code></dt>
+<dd>Optimizes variable allocation on the local variable frame.</dd>
+</dl>
+<p>
+
+<hr>
+<address>
+Copyright © 2002-2009
+<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+</address>
+</body>
+</html>
diff --git a/docs/manual/refcard.html b/docs/manual/refcard.html
index 9ef9d78..236f049 100644
--- a/docs/manual/refcard.html
+++ b/docs/manual/refcard.html
@@ -73,6 +73,13 @@
</tr>
<tr>
+<td valign="top"><a href="usage.html#keepdirectories"><code><b>-keepdirectories</b></code></a>
+ [<a href="usage.html#filters"><i>directory_filter</i></a>]</td>
+<td>Keep the specified directories in the output jars (or wars, ears, zips, or
+ directories).</td>
+</tr>
+
+<tr>
<td valign="top"><a href="usage.html#target"><code><b>-target</b></code></a>
<i>version</i></td>
<td>Set the given version number in the processed classes.</td>
@@ -160,6 +167,12 @@
</tr>
<tr>
+<td valign="top"><a href="usage.html#optimizations"><code><b>-optimizations</b></code></a>
+ <a href="optimizations.html"><i>optimization_filter</i></a></td>
+<td>The optimizations to be enabled and disabled.</td>
+</tr>
+
+<tr>
<td valign="top"><a href="usage.html#optimizationpasses"><code><b>-optimizationpasses</b></code></a>
<i>n</i></td>
<td>The number of optimization passes to be performed.</td>
@@ -235,6 +248,12 @@
</tr>
<tr>
+<td valign="top"><a href="usage.html#keeppackagenames"><code><b>-keeppackagenames</b></code></a>
+ [<i><a href="usage.html#filters">package_filter</a></i>]</td>
+<td>Keep the specified package names from being obfuscated.</td>
+</tr>
+
+<tr>
<td valign="top"><a href="usage.html#flattenpackagehierarchy"><code><b>-flattenpackagehierarchy</b></code></a>
[<i>package_name</i>]</td>
<td>Repackage all packages that are renamed into the single given parent
@@ -250,7 +269,7 @@
<tr>
<td valign="top"><a href="usage.html#keepattributes"><code><b>-keepattributes</b></code></a>
- [<i>attribute_name<b>,</b>...</i>]</td>
+ [<i><a href="usage.html#filters">attribute_filter</a></i>]</td>
<td>Preserve the given optional attributes; typically
<code>Exceptions</code>, <code>InnerClasses</code>,
<code>Signature</code>, <code>Deprecated</code>,
@@ -269,17 +288,24 @@
</tr>
<tr>
+<td valign="top"><a href="usage.html#adaptclassstrings"><code><b>-adaptclassstrings</b></code></a>
+ [<a href="usage.html#filters"><i>class_filter</i></a>]</td>
+<td>Adapt string constants in the specified classes, based on the obfuscated
+ names of any corresponding classes.</td>
+</tr>
+
+<tr>
<td valign="top"><a href="usage.html#adaptresourcefilenames"><code><b>-adaptresourcefilenames</b></code></a>
- [<a href="#filters"><i>filter</i></a>]</td>
+ [<a href="usage.html#filefilters"><i>file_filter</i></a>]</td>
<td>Rename the specified resource files, based on the obfuscated names of the
corresponding class files.</td>
</tr>
<tr>
<td valign="top"><a href="usage.html#adaptresourcefilecontents"><code><b>-adaptresourcefilecontents</b></code></a>
- [<a href="#filters"><i>filter</i></a>]</td>
+ [<a href="usage.html#filefilters"><i>file_filter</i></a>]</td>
<td>Update the contents of the specified resource files, based on the
- obfuscated names of the class files.</td>
+ obfuscated names of the processed classes.</td>
</tr>
<tr>
@@ -298,13 +324,15 @@
</tr>
<tr>
-<td valign="top"><a href="usage.html#dontnote"><code><b>-dontnote</b></code></a></td>
+<td valign="top"><a href="usage.html#dontnote"><code><b>-dontnote</b></code></a>
+ [<a href="usage.html#filters"><i>class_filter</i></a>]</td>
<td>Don't print notes about potential mistakes or omissions in the
configuration.</td>
</tr>
<tr>
-<td valign="top"><a href="usage.html#dontwarn"><code><b>-dontwarn</b></code></a></td>
+<td valign="top"><a href="usage.html#dontwarn"><code><b>-dontwarn</b></code></a>
+ [<a href="usage.html#filters"><i>class_filter</i></a>]</td>
<td>Don't warn about unresolved references at all.</td>
</tr>
@@ -430,7 +458,7 @@ Notes:
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/retrace/examples.html b/docs/manual/retrace/examples.html
index 7829efb..211017b 100644
--- a/docs/manual/retrace/examples.html
+++ b/docs/manual/retrace/examples.html
@@ -328,7 +328,7 @@ Exception in thread "main" java.lang.Error: Random exception
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/retrace/index.html b/docs/manual/retrace/index.html
index d87163c..ebb23ac 100644
--- a/docs/manual/retrace/index.html
+++ b/docs/manual/retrace/index.html
@@ -18,7 +18,7 @@
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/retrace/introduction.html b/docs/manual/retrace/introduction.html
index 8be230f..19f9471 100644
--- a/docs/manual/retrace/introduction.html
+++ b/docs/manual/retrace/introduction.html
@@ -60,7 +60,7 @@ original class names and class member names to their obfuscated names.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/retrace/usage.html b/docs/manual/retrace/usage.html
index 5355fff..88587ff 100644
--- a/docs/manual/retrace/usage.html
+++ b/docs/manual/retrace/usage.html
@@ -14,37 +14,72 @@ You can find the ReTrace jar in the <code>lib</code> directory of the
ProGuard distribution. To run ReTrace, just type:
<p>
<p class="code">
-<code><b>java -jar retrace.jar [-verbose] </b></code><i>mapping_file</i>
-[<i>stacktrace_file</i>]
+<code><b>java -jar retrace.jar </b></code>[<i>options...</i>]
+ <i>mapping_file</i> [<i>stacktrace_file</i>]
</p>
-The arguments have the following meaning:
-<p>
-<table cellspacing="10">
-<tr>
-<td valign="top"><code><b>-verbose</b></code></td>
-
-<td>Optionally specifies to print out more informative stack traces that
- include not only method names, but also method return types and
- arguments.</td>
+These are the arguments:
-</tr>
-<tr>
-<td valign="top"><i>mapping_file</i></td>
+<dl>
+<dt><i>mapping_file</i></dt>
-<td>Specifies the name of the mapping file, produced by ProGuard with the
- option "<code>-printmapping</code> <i>mapping_file</i>", while obfuscating
- the application that produced the stack trace.</td>
+<dd>Specifies the name of the mapping file, produced by ProGuard with the
+ option
+ "<a href="../usage.html#printmapping"><code>-printmapping</code></a> <i>mapping_file</i>",
+ while obfuscating the application that produced the stack trace.</dd>
-</tr>
-<tr>
-<td valign="top"><i>stacktrace_file</i></td>
+<dt><i>stacktrace_file</i></dt>
-<td>Optionally specifies the name of the file containing the stack trace. If
+<dd>Optionally specifies the name of the file containing the stack trace. If
no file is specified, a stack trace is read from the standard input. Blank
- lines and unrecognized lines are ignored, as far as possible.</td>
-
-</tr>
-</table>
+ lines and unrecognized lines are ignored, as far as possible.</dd>
+</dl>
+
+The following options are supported:
+<dl>
+<dt><code><b>-verbose</b></code></dt>
+
+<dd>Specifies to print out more informative stack traces that include not only
+ method names, but also method return types and arguments.</dd>
+
+<dt><code><b>-regex</b></code> <i>regular_expression</i></dt>
+
+<dd>Specifies the regular expression that is used to parse the lines in the
+ stack trace. Specifying a different regular expression allows to
+ de-obfuscate more general types of input than just stack traces. The
+ default is suitable for stack traces produced by most JVMs:
+ <pre>
+ (?:\s*%c:.*)|(?:\s*at\s+%c.%m\s*\(.*?(?::%l)?\)\s*)
+ </pre>
+ The regular expression is a Java regular expression (cfr. the documentation
+ of <code>java.util.regex.Pattern</code>), with a few additional wildcards:
+ <table cellspacing="10">
+ <tr><td valign="top"><code><b>%c</b></code></td>
+ <td>matches a class name (e.g.
+ "<code>myapplication.MyClass</code>").</td></tr>
+ <tr><td valign="top"><code><b>%C</b></code></td>
+ <td>matches a class name with slashes (e.g.
+ "<code>myapplication/MyClass</code>").</td></tr>
+ <tr><td valign="top"><code><b>%t</b></code></td>
+ <td>matches a field type or method return type (e.g.
+ "<code>myapplication.MyClass[]</code>").</td></tr>
+ <tr><td valign="top"><code><b>%f</b></code></td>
+ <td>matches a field name (e.g.
+ "<code>myField</code>").</td></tr>
+ <tr><td valign="top"><code><b>%m</b></code></td>
+ <td>matches a method name (e.g.
+ "<code>myMethod</code>").</td></tr>
+ <tr><td valign="top"><code><b>%a</b></code></td>
+ <td>matches a list of method arguments (e.g.
+ "<code>boolean,int</code>").</td></tr>
+ <tr><td valign="top"><code><b>%l</b></code></td>
+ <td>matches a line number inside a method (e.g.
+ "<code>123</code>").</td></tr>
+ </table>
+ Elements that match these wildcards are de-obfuscated, when possible. Note
+ that regular expressions must not contain any capturing groups. Use
+ non-capturing groups instead: <code>(?:</code>...<code>)</code>
+ </dd>
+</dl>
The restored stack trace is printed to the standard output. The completeness
of the restored stack trace depends on the presence of line number tables in
@@ -74,7 +109,7 @@ will be left unchanged.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/style.css b/docs/manual/style.css
index 778e10f..28fc112 100644
--- a/docs/manual/style.css
+++ b/docs/manual/style.css
@@ -19,6 +19,12 @@ dt {
padding: 6px;
}
+dt div
+{
+ color: grey;
+ float: right;
+}
+
dd {
padding: 6px;
}
diff --git a/docs/manual/troubleshooting.html b/docs/manual/troubleshooting.html
index 68ce0f5..d3ed14e 100644
--- a/docs/manual/troubleshooting.html
+++ b/docs/manual/troubleshooting.html
@@ -22,6 +22,7 @@ few problems. The following sections discuss some common issues and solutions:
<li><a href="#duplicateclass">Note: duplicate definition of program/library class</a></li>
<li><a href="#duplicatezipentry">Warning: can't write resource ... Duplicate zip entry</a></li>
<li><a href="#unresolvedclass">Warning: can't find superclass or interface</a></li>
+<li><a href="#unresolvedclass">Warning: can't find referenced class</a></li>
<li><a href="#unresolvedclassmember">Warning: can't find referenced field/method</a></li>
<li><a href="#unresolvedenclosingmethod">Warning: can't find enclosing class/method</a></li>
<li><a href="#dependency">Warning: library class ... depends on program class ...</a></li>
@@ -143,28 +144,30 @@ ProGuard may terminate when it encounters parsing errors or I/O errors, or
some more serious warnings:
<dl>
-<dt><a name="unresolvedclass"><b>Warning: can't find superclass or interface</b></a></dt>
+<dt><a name="unresolvedclass"><b>Warning: can't find superclass or interface</b><br/><b>Warning: can't find referenced class</b></a></dt>
-<dd>If there are unresolved references to superclasses or interfaces, you most
- likely forgot to specify an essential library. All libraries that are
- referenced by your code should be specified, including the Java run-time
- library. For specifying libraries, use the <a
- href="usage.html#libraryjars"><code>-libraryjars</code></a> option.
+<dd>If there are unresolved references to classes or interfaces, you most
+ likely forgot to specify an essential library. For proper processing, all
+ libraries that are referenced by your code must be specified, including
+ the Java run-time library. For specifying libraries, use
+ the <a href="usage.html#libraryjars"><code>-libraryjars</code></a> option.
<p>
If the class that is reported as missing is a non-public library class,
you should specify the <a
href="usage.html#dontskipnonpubliclibraryclasses"><code>-dontskipnonpubliclibraryclasses</code></a>
- option. A common example is the class
- <code>java.util.zip.ZipConstants</code>, which is used as an interface
- class in some public classes, even though it is only package visible (in
- this case, the warning could also be ignored, because the class is not a
- fundamental part of the class hierarchy).
+ option. Common examples are the classes
+ <code>javax.swing.TransferHandler$HasGetTransferHandler</code> and
+ <code>java.util.zip.ZipConstants</code>, which are used as interfaces in
+ some public classes, even though they are only package visible. This
+ option is not set by default for reasons of efficiency. Setting it increases
+ the processing time a bit, but it won't hurt the output in any way.
<p>
If you're missing a library and you're absolutely sure it isn't used
anyway, you can try your luck with the <a
href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a> option,
or even the <a href="usage.html#dontwarn"><code>-dontwarn</code></a>
- option.</dd>
+ option. Only use these options if you really know what you're doing
+ though.</dd>
<dt><a name="unresolvedclassmember"><b>Warning: can't find referenced field/method</b></a></dt>
@@ -455,9 +458,9 @@ might be several reasons:
and/or <a
href="usage.html#adaptresourcefilecontents"><code>-adaptresourcefilecontents</code></a>.
<p>
- Note that directory entries in jar files aren't copied at all. If you
- refer to any directories from your code, you should add them
- manually.</dd>
+ Furthermore, directory entries in jar files aren't copied, unless you
+ specify the option <a
+ href="usage.html#keepdirectories"><code>-keepdirectories</code></a>.</dd>
<dt><a name="invalidjarfile"><b>Invalid or corrupt jarfile</b></a></dt>
@@ -582,7 +585,7 @@ might be several reasons:
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/usage.html b/docs/manual/usage.html
index 7a0a694..8be8d60 100644
--- a/docs/manual/usage.html
+++ b/docs/manual/usage.html
@@ -52,8 +52,10 @@ The sections below provide more details:
<li><a href="#optimizationoptions">Optimization Options</a>
<li><a href="#obfuscationoptions">Obfuscation Options</a>
<li><a href="#preverificationoptions">Preverification Options</a>
+<li><a href="#generaloptions">General Options</a>
<li><a href="#classpath">Class Paths</a>
<li><a href="#filename">File Names</a>
+<li><a href="#filefilters">File Filters</a>
<li><a href="#filters">Filters</a>
<li><a href="#keepoverview">Overview of <code>Keep</code> Options</a>
<li><a href="#keepoptionmodifiers">Keep Option Modifiers</a>
@@ -90,7 +92,7 @@ The sections below provide more details:
will be copied without changes. Please be aware of any temporary files
(e.g. created by IDEs), especially if you are reading your input files
straight from directories. The entries in the class path can be filtered,
- as explained in the <a href="#filters">filters</a> section. For better
+ as explained in the <a href="#filefilters">filters</a> section. For better
readability, class path entries can be specified using multiple
<code>-injars</code> options.</dd>
@@ -101,10 +103,10 @@ The sections below provide more details:
directories). The processed input of the preceding <code>-injars</code>
options will be written to the named jars. This allows you to collect the
contents of groups of input jars into corresponding groups of output jars.
- In addition, the output entries can be filtered, as explained in the <a
- href="#filters">filters</a> section. Each processed class file or resource
- file is then written to the first output entry with a matching filter,
- within the group of output jars.
+ In addition, the output entries can be filtered, as explained in
+ the <a href="#filefilters">filters</a> section. Each processed class file
+ or resource file is then written to the first output entry with a matching
+ filter, within the group of output jars.
<p>
You must avoid letting the output files overwrite any input files. For
better readability, class path entries can be specified using multiple
@@ -121,7 +123,7 @@ The sections below provide more details:
class files that are only <i>called</i> needn't be present, although their
presence can improve the results of the optimization step. The entries in
the class path can be filtered, as explained in the <a
- href="#filters">filters</a> section. For better readability, class path
+ href="#filefilters">filters</a> section. For better readability, class path
entries can be specified using multiple <code>-libraryjars</code> options.
<p>
Please note that the boot path and the class path set for running ProGuard
@@ -157,6 +159,16 @@ The sections below provide more details:
those cases, it can be useful to actually read the class members, in order
to make sure the processed code remains consistent.</dd>
+<dt><a name="keepdirectories"><code><b>-keepdirectories</b></code></a>
+ [<i><a href="#filefilters">directory_filter</a></i>]</dt>
+
+<dd>Specifies the directories to be kept in the output jars (or wars, ears, or
+ directories). By default, directory entries are removed. This reduces the
+ jar size, but it may be undesirable if the program code tries to find them
+ with constructs like "<code>MyClass.class.getResource("")</code>". If the
+ option is specified without a filter, all directories are kept. With a
+ filter, only matching directories are kept.</dd>
+
<dt><a name="target"><code><b>-target</b></code></a> <i>version</i></dt>
<dd>Specifies the version number to be set in the processed class files. The
@@ -316,6 +328,13 @@ The sections below provide more details:
<dd>Specifies not to optimize the input class files. By default, optimization
is enabled; all methods are optimized at a bytecode level.</dd>
+<dt><a name="optimizations"><code><b>-optimizations</b></code></a>
+ <a href="optimizations.html"><i>optimization_filter</i></a></dt>
+
+<dd>Specifies the optimizations to be enabled and disabled, at a more
+ fine-grained level. Only applicable when optimizing. <i>This is an expert
+ option.</i></dd>
+
<dt><a name="optimizationpasses"><code><b>-optimizationpasses</b></code></a> <i>n</i></dt>
<dd>Specifies the number of optimization passes to be performed. By default, a
@@ -353,9 +372,10 @@ The sections below provide more details:
obfuscating with the <a
href="#repackageclasses"><code>-repackageclasses</code></a> option).
<p>
- Counter-indication: you probably shouldn't use this option when processing
- code that is to be used as a library, since classes and class members that
- weren't designed to be public in the API may become public.</dd>
+ <i>Counter-indication:</i> you probably shouldn't use this option when
+ processing code that is to be used as a library, since classes and class
+ members that weren't designed to be public in the API may become
+ public.</dd>
<dt><a name="mergeinterfacesaggressively"><code><b>-mergeinterfacesaggressively</b></code></a></dt>
@@ -373,9 +393,16 @@ The sections below provide more details:
"http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#34031"
>Section 8.1.4</a>). Only applicable when optimizing.
<p>
- Counter-indication: setting this option can reduce the performance of the
- processed code on some JVMs, since advanced just-in-time compilation tend
- to favor more interfaces with fewer implementing classes.</dd>
+ <i>Counter-indication:</i> setting this option can reduce the performance
+ of the processed code on some JVMs, since advanced just-in-time
+ compilation tends to favor more interfaces with fewer implementing
+ classes. Worse, some JVMs may not be able to handle the resulting code.
+ Notably:
+ <ul>
+ <li>Sun's JRE 1.3 may throw an <code>InternalError</code> when
+ encountering more than 256 <i>Miranda</i> methods (interface methods
+ without implementations) in a class.
+ </ul></dd>
</dl>
<p>
@@ -460,7 +487,7 @@ The sections below provide more details:
make the processed code even smaller (and less comprehensible). Only
applicable when obfuscating.
<p>
- Counter-indication: the resulting class files fall within the Java
+ <i>Counter-indication:</i> the resulting class files fall within the Java
bytecode specification (cfr. <a href=
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html"
>The Java Virtual Machine Specification, Second Edition</a>, first
@@ -524,6 +551,14 @@ The sections below provide more details:
use this option to switch off this behavior. Note that the obfuscated jars
will become larger as a result. Only applicable when obfuscating.</dd>
+<dt><a name="keeppackagenames"><code><b>-keeppackagenames</b></code></a>
+ [<i><a href="#filters">package_filter</a></i>]</dt>
+
+<dd>Specifies not obfuscate the given package names. The optional filter is a
+ comma-separated list of package names. Package names can contain <b>?</b>,
+ <b>*</b>, and <b>**</b> wildcards, and they can be preceded by the
+ <b>!</b> negator. Only applicable when obfuscating.</dd>
+
<dt><a name="flattenpackagehierarchy"><code><b>-flattenpackagehierarchy</b></code></a>
[<i>package_name</i>]</dt>
@@ -548,22 +583,21 @@ The sections below provide more details:
deprecated name is <code>-defaultpackage</code>. Only applicable when
obfuscating.
<p>
- Counter-indication: classes that look for resource files in their package
- directories will no longer work properly if they are moved elsewhere. When
- in doubt, just leave the packaging untouched by not using this
- option.</dd>
+ <i>Counter-indication:</i> classes that look for resource files in their
+ package directories will no longer work properly if they are moved
+ elsewhere. When in doubt, just leave the packaging untouched by not using
+ this option.</dd>
<dt><a name="keepattributes"><code><b>-keepattributes</b></code></a>
- [<i>attribute_name<b>,</b>...</i>]</dt>
+ [<i><a href="#filters">attribute_filter</a></i>]</dt>
<dd>Specifies any optional attributes to be preserved. The attributes can be
- specified with one or more <code>-keepattributes</code> directives.
- Multiple attributes should be separated by commas. An empty list preserves
- all attributes. Attribute names can contain <b>?</b> and
- <b>*</b> wildcards, and they can be preceded by the <b>!</b> negator (much
- like file name <a href="#filters">filters</a>). Typical optional
- attributes are <code>Exceptions</code>, <code>Signature</code>,
- <code>Deprecated</code>, <code>SourceFile</code>, <code>SourceDir</code>,
+ specified with one or more <code>-keepattributes</code> directives. The
+ optional filter is a comma-separated list of attribute names. Attribute
+ names can contain <b>?</b>, <b>*</b>, and <b>**</b> wildcards, and they
+ can be preceded by the <b>!</b> negator. Typical optional attributes are
+ <code>Exceptions</code>, <code>Signature</code>, <code>Deprecated</code>,
+ <code>SourceFile</code>, <code>SourceDir</code>,
<code>LineNumberTable</code>, <code>LocalVariableTable</code>,
<code>LocalVariableTypeTable</code>, <code>Synthetic</code>,
<code>EnclosingMethod</code>, <code>RuntimeVisibleAnnotations</code>,
@@ -592,8 +626,20 @@ The sections below provide more details:
applications produce <a href="examples.html#stacktrace">useful obfuscated
stack traces</a>. Only applicable when obfuscating.</dd>
+<dt><a name="adaptclassstrings"><code><b>-adaptclassstrings</b></code></a>
+ [<i><a href="#filters">class_filter</a></i>]</dt>
+
+<dd>Specifies that string constants that correspond to class names should be
+ obfuscated as well. Without a filter, all string constants that correspond
+ to class names are adapted. With a filter, only string constants in
+ classes that match the filter are adapted. For example, if your code
+ contains a large number of hard-coded strings that refer to classes, and
+ you prefer not to keep their names, you may want to use this option.
+ Primarily applicable when obfuscating, although corresponding classes are
+ automatically kept in the shrinking step too.</dd>
+
<dt><a name="adaptresourcefilenames"><code><b>-adaptresourcefilenames</b></code></a>
- [<i><a href="#filters">filter</a></i>]</dt>
+ [<i><a href="#filefilters">file_filter</a></i>]</dt>
<dd>Specifies the resource files to be renamed, based on the obfuscated names
of the corresponding class files (if any). Without a filter, all resource
@@ -603,15 +649,18 @@ The sections below provide more details:
applicable when obfuscating.</dd>
<dt><a name="adaptresourcefilecontents"><code><b>-adaptresourcefilecontents</b></code></a>
- [<i><a href="#filters">filter</a></i>]</dt>
+ [<i><a href="#filefilters">file_filter</a></i>]</dt>
<dd>Specifies the resource files whose contents are to be updated. Any class
names mentioned in the resource files are renamed, based on the obfuscated
- names of the corresponding class files (if any). Without a filter, the
+ names of the corresponding classes (if any). Without a filter, the
contents of all resource files updated. With a filter, only matching files
- are updated. For example, see <a
- href="examples.html#resourcefiles">processing resource files</a>. Only
- applicable when obfuscating.</dd>
+ are updated. The resource files are parsed and written using the
+ platform's default character set. You can change this default character set
+ by setting the environment variable <code>LANG</code> or the Java system
+ property <code>file.encoding</code>. For an example,
+ see <a href="examples.html#resourcefiles">processing resource files</a>.
+ Only applicable when obfuscating.</dd>
</dl>
<p>
@@ -651,19 +700,24 @@ The sections below provide more details:
program terminates with an exception, this option will print out the entire
stack trace, instead of just the exception message.</dd>
-<dt><a name="dontnote"><code><b>-dontnote</b></code></a></dt>
+<dt><a name="dontnote"><code><b>-dontnote</b></code></a>
+ [<i><a href="#filters">class_filter</a></i>]</dt>
<dd>Specifies not to print notes about potential mistakes or omissions in the
- configuration, like typos in class names, or missing options that might be
- useful.</dd>
+ configuration, like typos in class names, or like missing options that
+ might be useful. The optional filter is a regular expression; ProGuard
+ doesn't print notes about classes with matching names.</dd>
-<dt><a name="dontwarn"><code><b>-dontwarn</b></code></a></dt>
+<dt><a name="dontwarn"><code><b>-dontwarn</b></code></a>
+ [<i><a href="#filters">class_filter</a></i>]</dt>
<dd>Specifies not to warn about unresolved references and other important
- problems at all. Ignoring warnings can be dangerous. For instance, if the
- unresolved classes or class members are indeed required for processing,
- the processed code will not function properly. <i>Only use this option if
- you know what you're doing!</i></dd>
+ problems at all. The optional filter is a regular expression; ProGuard
+ doesn't print warnings about classes with matching names. Ignoring
+ warnings can be dangerous. For instance, if the unresolved classes or
+ class members are indeed required for processing, the processed code will
+ not function properly. <i>Only use this option if you know what you're
+ doing!</i></dd>
<dt><a name="ignorewarnings"><code><b>-ignorewarnings</b></code></a></dt>
@@ -741,10 +795,49 @@ to <a href="examples.html#restructuring">restructure output archives</a>.
Files and directories can be specified as discussed in the section on <a
href="#filename">file names</a> below.
<p>
-In addition, the individual class patch entries and their contents can be
-filtered, as explained in the <a href="#filters">filters</a> section below.
-This allows for an almost infinite number of packaging and repackaging
-possibilities.
+In addition, ProGuard provides the possibility to filter the class path
+entries and their contents, based on their full relative file names. Each
+class path entry can be followed by up to 5 types of <a
+href="#filefilters">file filters</a> between parentheses, separated by
+semi-colons:
+<ul>
+<li>A filter for all zip names that are encountered,
+<li>A filter for all ear names that are encountered,
+<li>A filter for all war names that are encountered,
+<li>A filter for all jar names that are encountered,
+<li>A filter for all class file names and resource file names that are
+ encountered.
+</ul>
+<p>
+If fewer than 5 filters are specified, they are assumed to be the latter
+filters. Any empty filters are ignored. More formally, a filtered class path
+entry looks like this:
+<pre>
+<i>classpathentry</i><b>(</b>[[[[<i>zipfilter</i><b>;</b>]<i>earfilter</i><b>;</b>]<i>warfilter</i><b>;</b>]<i>jarfilter</i><b>;</b>]<i>filefilter</i><b>)</b>
+</pre>
+<p>
+Square brackets "[]" mean that their contents are optional.
+<p>
+For example, "<code>rt.jar(java/**.class,javax/**.class)</code>" matches all
+class files in the <code>java</code> and <code>javax</code> directories inside
+the <code>rt</code> jar.
+<p>
+For example, "<code>input.jar(!**.gif,images/**)</code>" matches all files in
+the <code>images</code> directory inside the <code>input</code> jar, except
+gif files.
+<p>
+Note that the different filters are applied to all corresponding file types,
+irrespective of their nesting levels in the input; they are orthogonal.
+<p>
+For example,
+"<code>input.war(lib/**.jar,support/**.jar;**.class,**.gif)</code>" only
+considers jar files in the <code>lib</code> and <code>support</code>
+directories in the <code>input</code> war, not any other jar files. It then
+matches all class files and gif files that are encountered.
+<p>
+The filters allow for an almost infinite number of packaging and repackaging
+possibilities. The Examples section provides a few more examples
+for <a href="examples.html#filtering">filtering input and output</a>.
<p>
<a name="filename"> </a>
@@ -779,36 +872,13 @@ For example, on the command line, you could use an option like <code>'-injars
"my program.jar":"/your directory/your program.jar"'</code>.
<p>
-<a name="filters"> </a>
-<h2>Filters</h2>
+<a name="filefilters"> </a>
+<h2>File Filters</h2>
-ProGuard provides the possibility to filter the class path entries and their
-contents, based on their full relative file names. Each class path entry can
-be followed by up to 5 types of filters between parentheses, separated by
-semi-colons:
-<ul>
-<li>A filter for all zip names that are encountered,
-<li>A filter for all ear names that are encountered,
-<li>A filter for all war names that are encountered,
-<li>A filter for all jar names that are encountered,
-<li>A filter for all class file names and resource file names that are
- encountered.
-</ul>
-<p>
-If fewer than 5 filters are specified, they are assumed to be the latter
-filters. Any empty filters are ignored. More formally, a filtered class path
-entry looks like this:
-<pre>
-<i>classpathentry</i><b>(</b>[[[[<i>zipfilter</i><b>;</b>]<i>earfilter</i><b>;</b>]<i>warfilter</i><b>;</b>]<i>jarfilter</i><b>;</b>]<i>filefilter</i><b>)</b>
-</pre>
-<p>
-Square brackets "[]" mean that their contents are optional.
-
-<p>
-A filter consists of one or more comma-separated file names that can contain
-wildcards. Only files with matching file names are read (in the case of input
-jars), or written (in the case of output jars). The following wildcards are
-supported:
+Like general <a href="#filters">filters</a>, a file filter is a
+comma-separated list of file names that can contain wildcards. Only files with
+matching file names are read (in the case of input jars), or written (in the
+case of output jars). The following wildcards are supported:
<table cellspacing="10">
<tr><td valign="top"><code><b>?</b></code></td>
@@ -821,32 +891,58 @@ supported:
directory separators.</td></tr>
</table>
-For example, "<code>rt.jar(java/**.class,javax/**.class)</code>" matches all
-class files in the <code>java</code> and <code>javax</code> directories inside
-the <code>rt</code> jar.
+For example, "<code>java/**.class,javax/**.class</code>" matches all
+class files in the <code>java</code> and <code>javax</code>.
<p>
Furthermore, a file name can be preceded by an exclamation mark '<b>!</b>' to
<i>exclude</i> the file name from further attempts to match with
-<i>subsequent</i> file names. You can think of the filtering mechanism as a
-conveyor belt, with pushers that accept or reject files as they pass by.
+<i>subsequent</i> file names.
<p>
-For example, "<code>input.jar(!**.gif,images/**)</code>" matches all files in
-the <code>images</code> directory inside the <code>input</code> jar, except
-gif files.
+For example, "<code>!**.gif,images/**</code>" matches all files in the
+<code>images</code> directory, except gif files.
<p>
+The Examples section provides a few more examples for <a
+href="examples.html#filtering">filtering input and output</a>.
-Note that the different filters are applied to all corresponding file types,
-irrespective of their nesting levels in the input; they are orthogonal.
+<a name="filters"> </a>
+<h2>Filters</h2>
+
+ProGuard offers options with filters for many different aspects of the
+configuration: names of files, directories, classes, packages, attributes,
+optimizations, etc.
<p>
-For example,
-"<code>input.war(lib/**.jar,support/**.jar;**.class,**.gif)</code>" only
-considers jar files in the <code>lib</code> and <code>support</code>
-directories in the <code>input</code> war, not any other jar files. It then
-matches all class files and gif files that are encountered.
+A filter is a list of comma-separated names that can contain wildcards. Only
+names that match an item on the list pass the filter. The supported wildcards
+depend on the type of names for which the filter is being used, but the
+following wildcards are typical:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in a name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of a name not containing the package separator or
+ directory separator.</td></tr>
+<tr><td valign="top"><code><b>**</b></code></td>
+ <td>matches any part of a name, possibly containing any number of
+ package separators or directory separators.</td></tr>
+</table>
+
+For example, "<code>foo,*bar</code>" matches the name <code>foo</code> and
+all names ending with <code>bar</code>.
+<p>
+
+Furthermore, a name can be preceded by a negating exclamation mark '<b>!</b>'
+to <i>exclude</i> the name from further attempts to match
+with <i>subsequent</i> names. So, if a name matches an item in the filter, it
+is accepted or rejected right away, depending on whether the item has a
+negator. If the name doesn't match the item, it is tested against the next
+item, and so on. It if doesn't match any items, it is accepted or rejected,
+depending on the whether the last item has a negator or not.
+<p>
+For example, "<code>!foobar,*bar</code>" matches all names ending with
+<code>bar</code>, except <code>foobar</code>.
<p>
- The Examples section provides a few more examples for <a
- href="examples.html#filtering">filtering input and output</a>.
<a name="keepoverview"> </a>
<h2>Overview of <code>Keep</code> Options</h2>
@@ -1128,7 +1224,7 @@ files.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/manual/wtk.html b/docs/manual/wtk.html
index 30fde13..b8c70b5 100644
--- a/docs/manual/wtk.html
+++ b/docs/manual/wtk.html
@@ -51,7 +51,7 @@ that's inside the <code>proguard.jar</code>.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/quality.html b/docs/quality.html
index 4a375f1..29889e3 100644
--- a/docs/quality.html
+++ b/docs/quality.html
@@ -37,7 +37,7 @@ problems as soon as possible.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/results.html b/docs/results.html
index 3ef8470..480cd4f 100644
--- a/docs/results.html
+++ b/docs/results.html
@@ -147,7 +147,7 @@ is governed by the basic java virtual machine and by the total size of the
library jars and program jars.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
diff --git a/docs/screenshots.html b/docs/screenshots.html
index 954fea0..8718839 100644
--- a/docs/screenshots.html
+++ b/docs/screenshots.html
@@ -49,7 +49,7 @@ You can click on the image to see the full-size version.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/sections.html b/docs/sections.html
index efa7012..d955d33 100644
--- a/docs/sections.html
+++ b/docs/sections.html
@@ -38,6 +38,10 @@ document.write(document.location.hostname == "proguard.sourceforge.net" ?
"http://sourceforge.net/sflogo.php?group_id=54750&type=1" :
"sflogo.png");
document.write("\" width=\"88\" height=\"31\" alt=\"SourceForge\">");
+if (document.location.hostname == "proguard.sourceforge.net") {
+ document.write("<script type=\"text/javascript\" src=\"http://sourceforge.net/apps/piwik/proguard/piwik.js\"></scri"+"pt>");
+ document.write("<script type=\"text/javascript\">piwik_log(\"\", 1, \"http://sourceforge.net/apps/piwik/proguard/piwik.php\");</scri"+"pt>");
+}
//-->
</script>
<noscript>
diff --git a/docs/sflogo.png b/docs/sflogo.png
index 1105bc7..142a6f9 100644
Binary files a/docs/sflogo.png and b/docs/sflogo.png differ
diff --git a/docs/testimonials.html b/docs/testimonials.html
index 79becde..6971617 100644
--- a/docs/testimonials.html
+++ b/docs/testimonials.html
@@ -114,7 +114,7 @@ You could've been rich.
<hr>
<address>
-Copyright © 2002-2008
+Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
diff --git a/docs/title.html b/docs/title.html
index 841d5be..33171b5 100644
--- a/docs/title.html
+++ b/docs/title.html
@@ -10,7 +10,7 @@
<div class="title">
<h1><img src="title.gif" width="154" height="29" alt="ProGuard"></h1>
-<div>Version 4.3</div>
+<div>Version 4.4</div>
</div>
</body>
diff --git a/examples/annotations/examples/Applet.java b/examples/annotations/examples/Applet.java
index 5a04887..8a5874b 100644
--- a/examples/annotations/examples/Applet.java
+++ b/examples/annotations/examples/Applet.java
@@ -3,8 +3,10 @@ import proguard.annotation.*;
/**
* This applet illustrates the use of annotations for configuring ProGuard.
*
- * After having been compiled, it can be processed using:
- * java -jar proguard.jar @examples.pro
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar Applet.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotation will preserve the class and its essential methods.
*/
diff --git a/examples/annotations/examples/Application.java b/examples/annotations/examples/Application.java
index 96ac208..f8d5060 100644
--- a/examples/annotations/examples/Application.java
+++ b/examples/annotations/examples/Application.java
@@ -3,8 +3,10 @@ import proguard.annotation.KeepApplication;
/**
* This application illustrates the use of annotations for configuring ProGuard.
*
- * After having been compiled, it can be processed using:
- * java -jar proguard.jar @examples.pro
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar Application.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotation will preserve the class and its main method.
*/
diff --git a/examples/annotations/examples/Bean.java b/examples/annotations/examples/Bean.java
index e49a88e..0544bf3 100644
--- a/examples/annotations/examples/Bean.java
+++ b/examples/annotations/examples/Bean.java
@@ -3,8 +3,10 @@ import proguard.annotation.*;
/**
* This bean illustrates the use of annotations for configuring ProGuard.
*
- * After having been compiled, it can be processed using:
- * java -jar proguard.jar @examples.pro
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar Bean.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotations will preserve the class and its public getters and setters.
*/
diff --git a/examples/annotations/examples/NativeCallBack.java b/examples/annotations/examples/NativeCallBack.java
index 9c34884..2c72f7b 100644
--- a/examples/annotations/examples/NativeCallBack.java
+++ b/examples/annotations/examples/NativeCallBack.java
@@ -3,8 +3,10 @@ import proguard.annotation.*;
/**
* This application illustrates the use of annotations for configuring ProGuard.
*
- * After having been compiled, it can be processed using:
- * java -jar proguard.jar @examples.pro
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar NativeCallBack.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotation will preserve the class and its main method.
*/
diff --git a/examples/annotations/lib/annotations.jar b/examples/annotations/lib/annotations.jar
index 8dd8fa7..967d604 100644
Binary files a/examples/annotations/lib/annotations.jar and b/examples/annotations/lib/annotations.jar differ
diff --git a/examples/ant/proguard.xml b/examples/ant/proguard.xml
index 13ca2ae..315e628 100644
--- a/examples/ant/proguard.xml
+++ b/examples/ant/proguard.xml
@@ -55,6 +55,7 @@
<!-- If we have ant.jar, we can properly process the Ant task. -->
+ <keeppackagename name="proguard.ant" />
<keep name="proguard.ant.*" allowobfuscation="true" />
<keepclassmembers access="public" name="proguard.ant.*">
<constructor parameters="org.apache.tools.ant.Project" />
diff --git a/lib/proguard.jar b/lib/proguard.jar
new file mode 100644
index 0000000..3a9aebc
Binary files /dev/null and b/lib/proguard.jar differ
diff --git a/lib/proguardgui.jar b/lib/proguardgui.jar
new file mode 100644
index 0000000..5866856
Binary files /dev/null and b/lib/proguardgui.jar differ
diff --git a/lib/retrace.jar b/lib/retrace.jar
new file mode 100644
index 0000000..8e42e5a
Binary files /dev/null and b/lib/retrace.jar differ
diff --git a/src/proguard/ArgumentWordReader.java b/src/proguard/ArgumentWordReader.java
index 4d0bc2b..89f3824 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassPath.java b/src/proguard/ClassPath.java
index 80fb1ca..f4eeaad 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e7b4240..28483be 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,7 @@
package proguard;
import java.io.*;
+import java.util.List;
/**
@@ -35,11 +36,11 @@ public class ClassPathEntry
{
private File file;
private boolean output;
- private String filter;
- private String jarFilter;
- private String warFilter;
- private String earFilter;
- private String zipFilter;
+ private List filter;
+ private List jarFilter;
+ private List warFilter;
+ private List earFilter;
+ private List zipFilter;
/**
@@ -92,85 +93,57 @@ public class ClassPathEntry
}
- public String getFilter()
+ public List getFilter()
{
return filter;
}
- public void setFilter(String filter)
+ public void setFilter(List filter)
{
- this.filter = filter == null || filter.length() == 0 ? null : filter;
+ this.filter = filter == null || filter.size() == 0 ? null : filter;
}
- public String getJarFilter()
+ public List getJarFilter()
{
return jarFilter;
}
- public void setJarFilter(String filter)
+ public void setJarFilter(List filter)
{
- this.jarFilter = filter == null || filter.length() == 0 ? null : filter;
+ this.jarFilter = filter == null || filter.size() == 0 ? null : filter;
}
- public String getWarFilter()
+ public List getWarFilter()
{
return warFilter;
}
- public void setWarFilter(String filter)
+ public void setWarFilter(List filter)
{
- this.warFilter = filter == null || filter.length() == 0 ? null : filter;
+ this.warFilter = filter == null || filter.size() == 0 ? null : filter;
}
- public String getEarFilter()
+ public List getEarFilter()
{
return earFilter;
}
- public void setEarFilter(String filter)
+ public void setEarFilter(List filter)
{
- this.earFilter = filter == null || filter.length() == 0 ? null : filter;
+ this.earFilter = filter == null || filter.size() == 0 ? null : filter;
}
- public String getZipFilter()
+ public List getZipFilter()
{
return zipFilter;
}
- public void setZipFilter(String filter)
+ public void setZipFilter(List filter)
{
- this.zipFilter = filter == null || filter.length() == 0 ? null : filter;
- }
-
-
- public String toString()
- {
- String string = getName();
-
- if (filter != null ||
- jarFilter != null ||
- warFilter != null ||
- earFilter != null ||
- zipFilter != null)
- {
- string +=
- ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
- (zipFilter != null ? zipFilter : "") +
- ConfigurationConstants.SEPARATOR_KEYWORD +
- (earFilter != null ? earFilter : "") +
- ConfigurationConstants.SEPARATOR_KEYWORD +
- (warFilter != null ? warFilter : "") +
- ConfigurationConstants.SEPARATOR_KEYWORD +
- (jarFilter != null ? jarFilter : "") +
- ConfigurationConstants.SEPARATOR_KEYWORD +
- (filter != null ? filter : "") +
- ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD;
- }
-
- return string;
+ this.zipFilter = filter == null || filter.size() == 0 ? null : filter;
}
}
diff --git a/src/proguard/ClassSpecification.java b/src/proguard/ClassSpecification.java
index cfc318b..a84e0c8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,15 +33,15 @@ import java.util.*;
public class ClassSpecification implements Cloneable
{
public final String comments;
- public int requiredSetAccessFlags;
- public int requiredUnsetAccessFlags;
+ public int requiredSetAccessFlags;
+ public int requiredUnsetAccessFlags;
public final String annotationType;
- public String className;
+ public String className;
public final String extendsAnnotationType;
public final String extendsClassName;
- public List fieldSpecifications;
- public List methodSpecifications;
+ public List fieldSpecifications;
+ public List methodSpecifications;
/**
@@ -220,15 +220,15 @@ public class ClassSpecification implements Cloneable
ClassSpecification other = (ClassSpecification)object;
return
-// (this.comments == null ? other.comments == null : this.comments.equals(other.comments) ) &&
- (this.requiredSetAccessFlags == other.requiredSetAccessFlags ) &&
- (this.requiredUnsetAccessFlags == other.requiredUnsetAccessFlags ) &&
- (this.annotationType == null ? other.annotationType == null : this.annotationType.equals(other.annotationType) ) &&
- (this.className == null ? other.className == null : this.className.equals(other.className) ) &&
+// (this.comments == null ? other.comments == null : this.comments.equals(other.comments) ) &&
+ (this.requiredSetAccessFlags == other.requiredSetAccessFlags ) &&
+ (this.requiredUnsetAccessFlags == other.requiredUnsetAccessFlags ) &&
+ (this.annotationType == null ? other.annotationType == null : this.annotationType.equals(other.annotationType) ) &&
+ (this.className == null ? other.className == null : this.className.equals(other.className) ) &&
(this.extendsAnnotationType == null ? other.extendsAnnotationType == null : this.extendsAnnotationType.equals(other.extendsAnnotationType)) &&
- (this.extendsClassName == null ? other.extendsClassName == null : this.extendsClassName.equals(other.extendsClassName) ) &&
- (this.fieldSpecifications == null ? other.fieldSpecifications == null : this.fieldSpecifications.equals(other.fieldSpecifications) ) &&
- (this.methodSpecifications == null ? other.methodSpecifications == null : this.methodSpecifications.equals(other.methodSpecifications) );
+ (this.extendsClassName == null ? other.extendsClassName == null : this.extendsClassName.equals(other.extendsClassName) ) &&
+ (this.fieldSpecifications == null ? other.fieldSpecifications == null : this.fieldSpecifications.equals(other.fieldSpecifications) ) &&
+ (this.methodSpecifications == null ? other.methodSpecifications == null : this.methodSpecifications.equals(other.methodSpecifications) );
}
public int hashCode()
diff --git a/src/proguard/ClassSpecificationVisitorFactory.java b/src/proguard/ClassSpecificationVisitorFactory.java
index 727e51b..c99ab2c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,15 +38,15 @@ public class ClassSpecificationVisitorFactory
* Constructs a ClassPoolVisitor to efficiently travel to the specified
* classes and class members.
*
- * @param keepSpecifications the list of KeepSpecification instances,
- * defining of the classes and class members to
- * visit.
- * @param classVisitor the ClassVisitor to be applied to matching
- * classes.
- * @param memberVisitor the MemberVisitor to be applied to matching
- * class members.
+ * @param keepClassSpecifications the list of KeepClassSpecification
+ * instances, defining of the classes and
+ * class members to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
*/
- public static ClassPoolVisitor createClassPoolVisitor(List keepSpecifications,
+ public static ClassPoolVisitor createClassPoolVisitor(List keepClassSpecifications,
ClassVisitor classVisitor,
MemberVisitor memberVisitor,
boolean shrinking,
@@ -55,19 +55,19 @@ public class ClassSpecificationVisitorFactory
{
MultiClassPoolVisitor multiClassPoolVisitor = new MultiClassPoolVisitor();
- if (keepSpecifications != null)
+ if (keepClassSpecifications != null)
{
- for (int index = 0; index < keepSpecifications.size(); index++)
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
{
- KeepSpecification keepSpecification =
- (KeepSpecification)keepSpecifications.get(index);
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepClassSpecifications.get(index);
- if ((shrinking && !keepSpecification.allowShrinking) ||
- (optimizing && !keepSpecification.allowOptimization) ||
- (obfuscating && !keepSpecification.allowObfuscation))
+ if ((shrinking && !keepClassSpecification.allowShrinking) ||
+ (optimizing && !keepClassSpecification.allowOptimization) ||
+ (obfuscating && !keepClassSpecification.allowObfuscation))
{
multiClassPoolVisitor.addClassPoolVisitor(
- createClassPoolVisitor(keepSpecification,
+ createClassPoolVisitor(keepClassSpecification,
classVisitor,
memberVisitor));
}
@@ -118,44 +118,44 @@ public class ClassSpecificationVisitorFactory
* Constructs a ClassPoolVisitor to efficiently travel to the specified
* classes and class members.
*
- * @param keepSpecification the specifications of the class(es) and class
+ * @param keepClassSpecification the specifications of the class(es) and class
* members to visit.
* @param classVisitor the ClassVisitor to be applied to matching
* classes.
* @param memberVisitor the MemberVisitor to be applied to matching
* class members.
*/
- private static ClassPoolVisitor createClassPoolVisitor(KeepSpecification keepSpecification,
+ private static ClassPoolVisitor createClassPoolVisitor(KeepClassSpecification keepClassSpecification,
ClassVisitor classVisitor,
MemberVisitor memberVisitor)
{
// Don't visit the classes if not specified.
- if (!keepSpecification.markClasses &&
- !keepSpecification.markConditionally)
+ if (!keepClassSpecification.markClasses &&
+ !keepClassSpecification.markConditionally)
{
classVisitor = null;
}
// If specified, let the marker visit the class and its class
// members conditionally.
- if (keepSpecification.markConditionally)
+ if (keepClassSpecification.markConditionally)
{
// Combine both visitors.
ClassVisitor composedClassVisitor =
- createCombinedClassVisitor(keepSpecification,
+ createCombinedClassVisitor(keepClassSpecification,
classVisitor,
memberVisitor);
// Replace the class visitor.
classVisitor =
- createClassMemberTester(keepSpecification,
+ createClassMemberTester(keepClassSpecification,
composedClassVisitor);
// Discard the member visitor, because it has already been included.
memberVisitor = null;
}
- return createClassPoolVisitor((ClassSpecification)keepSpecification,
+ return createClassPoolVisitor((ClassSpecification)keepClassSpecification,
classVisitor,
memberVisitor);
}
@@ -192,7 +192,7 @@ public class ClassSpecificationVisitorFactory
// If wildcarded, only visit classes with matching names.
if (className != null &&
(extendsAnnotationType != null ||
- extendsClassName != null ||
+ extendsClassName != null ||
containsWildCards(className)))
{
composedClassVisitor =
diff --git a/src/proguard/Configuration.java b/src/proguard/Configuration.java
index 473a4fb..d513e2c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +59,15 @@ public class Configuration
public boolean skipNonPublicLibraryClassMembers = true;
/**
+ * A list of <code>String</code>s specifying directories to be kept in
+ * the output directories or the output jars. A <code>null</code> list
+ * means no directories. An empty list means all directories. The directory
+ * names may contain "**", "*", or "?" wildcards, and they may be preceded
+ * by the "!" negator.
+ */
+ public List keepDirectories;
+
+ /**
* Specifies the version number of the output classes, or 0 if the version
* number can be left unchanged.
*/
@@ -78,7 +87,7 @@ public class Configuration
///////////////////////////////////////////////////////////////////////////
/**
- * A list of {@link KeepSpecification} instances, whose class names and
+ * A list of {@link KeepClassSpecification} instances, whose class names and
* class member names are to be kept from shrinking, optimization, and/or
* obfuscation.
*/
@@ -121,6 +130,14 @@ public class Configuration
public boolean optimize = true;
/**
+ * A list of <code>String</code>s specifying the optimizations to be
+ * performed. A <code>null</code> list means all optimizations. The
+ * optimization names may contain "*" or "?" wildcards, and they may
+ * be preceded by the "!" negator.
+ */
+ public List optimizations;
+
+ /**
* Specifies the number of optimization passes.
*/
public int optimizationPasses = 1;
@@ -192,6 +209,14 @@ public class Configuration
public boolean useMixedCaseClassNames = true;
/**
+ * A list of <code>String</code>s specifying package names to be kept.
+ * A <code>null</code> list means no names. An empty list means all
+ * names. The package names may contain "**", "*", or "?" wildcards, and
+ * they may be preceded by the "!" negator.
+ */
+ public List keepPackageNames;
+
+ /**
* An optional base package if the obfuscated package hierarchy is to be
* flattened, <code>null</code> otherwise.
*/
@@ -217,6 +242,13 @@ public class Configuration
public String newSourceFileAttribute;
/**
+ * A list of <code>String</code>s specifying a filter for clases whose
+ * string constants are to be adapted, based on corresponding obfuscated
+ * class names.
+ */
+ public List adaptClassStrings;
+
+ /**
* A list of <code>String</code>s specifying a filter for files whose
* names are to be adapted, based on corresponding obfuscated class names.
*/
@@ -254,14 +286,20 @@ public class Configuration
public boolean verbose = false;
/**
- * Specifies whether to print any notes.
+ * A list of <code>String</code>s specifying a filter for the classes for
+ * which not to print notes, if there are noteworthy potential problems.
+ * A <code>null</code> list means all classes. The class names may contain
+ * "**", "*", or "?" wildcards, and they may be preceded by the "!" negator.
*/
- public boolean note = true;
+ public List note = null;
/**
- * Specifies whether to print any warnings.
+ * A list of <code>String</code>s specifying a filter for the classes for
+ * which not to print warnings, if there are any problems.
+ * A <code>null</code> list means all classes. The class names may contain
+ * "**", "*", or "?" wildcards, and they may be preceded by the "!" negator.
*/
- public boolean warn = true;
+ public List warn = null;
/**
* Specifies whether to ignore any warnings.
diff --git a/src/proguard/ConfigurationConstants.java b/src/proguard/ConfigurationConstants.java
index 1baf79f..694e006 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -53,6 +53,7 @@ class ConfigurationConstants
public static final String WHY_ARE_YOU_KEEPING_OPTION = "-whyareyoukeeping";
public static final String DONT_OPTIMIZE_OPTION = "-dontoptimize";
+ public static final String OPTIMIZATIONS = "-optimizations";
public static final String OPTIMIZATION_PASSES = "-optimizationpasses";
public static final String ASSUME_NO_SIDE_EFFECTS_OPTION = "-assumenosideeffects";
public static final String ALLOW_ACCESS_MODIFICATION_OPTION = "-allowaccessmodification";
@@ -67,11 +68,13 @@ class ConfigurationConstants
public static final String OVERLOAD_AGGRESSIVELY_OPTION = "-overloadaggressively";
public static final String USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION = "-useuniqueclassmembernames";
public static final String DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION = "-dontusemixedcaseclassnames";
+ public static final String KEEP_PACKAGE_NAMES_OPTION = "-keeppackagenames";
public static final String FLATTEN_PACKAGE_HIERARCHY_OPTION = "-flattenpackagehierarchy";
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 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";
public static final String ADAPT_RESOURCE_FILE_CONTENTS_OPTION = "-adaptresourcefilecontents";
@@ -87,6 +90,7 @@ class ConfigurationConstants
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";
+ public static final String KEEP_DIRECTORIES_OPTION = "-keepdirectories";
public static final String FORCE_PROCESSING_OPTION = "-forceprocessing";
public static final String ANY_ATTRIBUTE_KEYWORD = "*";
diff --git a/src/proguard/ConfigurationParser.java b/src/proguard/ConfigurationParser.java
index 7897763..e01809e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -115,20 +115,24 @@ public class ConfigurationParser
else if (ConfigurationConstants.TARGET_OPTION .startsWith(nextWord)) configuration.targetClassVersion = parseClassVersion();
else if (ConfigurationConstants.FORCE_PROCESSING_OPTION .startsWith(nextWord)) configuration.lastModified = parseNoArgument(Long.MAX_VALUE);
- else if (ConfigurationConstants.KEEP_OPTION .startsWith(nextWord)) configuration.keep = parseKeepSpecificationArguments(configuration.keep, true, false, false);
- else if (ConfigurationConstants.KEEP_CLASS_MEMBERS_OPTION .startsWith(nextWord)) configuration.keep = parseKeepSpecificationArguments(configuration.keep, false, false, false);
- else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBERS_OPTION .startsWith(nextWord)) configuration.keep = parseKeepSpecificationArguments(configuration.keep, false, true, false);
- else if (ConfigurationConstants.KEEP_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepSpecificationArguments(configuration.keep, true, false, true);
- else if (ConfigurationConstants.KEEP_CLASS_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepSpecificationArguments(configuration.keep, false, false, true);
- else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepSpecificationArguments(configuration.keep, false, true, true);
+ else if (ConfigurationConstants.KEEP_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, true, false, false);
+ else if (ConfigurationConstants.KEEP_CLASS_MEMBERS_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, false, false);
+ else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBERS_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, true, false);
+ else if (ConfigurationConstants.KEEP_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, true, false, true);
+ else if (ConfigurationConstants.KEEP_CLASS_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, false, true);
+ else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, true, true);
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.DONT_SHRINK_OPTION .startsWith(nextWord)) configuration.shrink = parseNoArgument(false);
else if (ConfigurationConstants.PRINT_USAGE_OPTION .startsWith(nextWord)) configuration.printUsage = parseOptionalFile();
else if (ConfigurationConstants.WHY_ARE_YOU_KEEPING_OPTION .startsWith(nextWord)) configuration.whyAreYouKeeping = parseClassSpecificationArguments(configuration.whyAreYouKeeping);
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.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);
@@ -142,20 +146,22 @@ 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.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, configuration.keepAttributes);
+ 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.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION .startsWith(nextWord)) configuration.newSourceFileAttribute = parseOptionalArgument();
- else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, 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, configuration.adaptResourceFileContents);
+ 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.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 = parseNoArgument(false);
- else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseNoArgument(false);
+ 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.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();
@@ -232,16 +238,14 @@ public class ConfigurationParser
ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(nextWord))
{
// Read all filters in an array.
- String[] filters = new String[5];
+ List[] filters = new List[5];
int counter = 0;
do
{
// Read the filter.
filters[counter++] =
- ListUtil.commaSeparatedString(
- parseCommaSeparatedList("filter", true,
- false, true, false, true, null));
+ parseCommaSeparatedList("filter", true, false, true, false, true, false, false, null);
}
while (counter < filters.length &&
ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord));
@@ -406,16 +410,16 @@ public class ConfigurationParser
}
- private List parseKeepSpecificationArguments(List keepSpecifications,
- boolean markClasses,
- boolean markConditionally,
- boolean allowShrinking)
+ private List parseKeepClassSpecificationArguments(List keepClassSpecifications,
+ boolean markClasses,
+ boolean markConditionally,
+ boolean allowShrinking)
throws ParseException, IOException
{
// Create a new List if necessary.
- if (keepSpecifications == null)
+ if (keepClassSpecifications == null)
{
- keepSpecifications = new ArrayList();
+ keepClassSpecifications = new ArrayList();
}
//boolean allowShrinking = false;
@@ -465,14 +469,13 @@ public class ConfigurationParser
parseClassSpecificationArguments();
// Create and add the keep configuration.
- keepSpecifications.add(new KeepSpecification(markClasses,
- markConditionally,
- allowShrinking,
- allowOptimization,
- allowObfuscation,
- classSpecification));
-
- return keepSpecifications;
+ keepClassSpecifications.add(new KeepClassSpecification(markClasses,
+ markConditionally,
+ allowShrinking,
+ allowOptimization,
+ allowObfuscation,
+ classSpecification));
+ return keepClassSpecifications;
}
@@ -549,10 +552,9 @@ public class ConfigurationParser
{
// Parse the annotation type.
annotationType =
- ClassUtil.internalType(
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- false, false, false, true, false, null)));
+ false, false, false, true, false, false, true, null));
continue;
}
@@ -592,7 +594,7 @@ public class ConfigurationParser
String externalClassName =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("class name or interface name",
- true, false, false, true, false, null));
+ true, false, false, true, false, false, false, null));
// For backward compatibility, allow a single "*" wildcard to match any
// class.
@@ -602,7 +604,7 @@ public class ConfigurationParser
// Clear the annotation type and the class name of the extends part.
String extendsAnnotationType = null;
- String extendsClassName = null;
+ String extendsClassName = null;
if (!configurationEnd())
{
@@ -616,16 +618,15 @@ public class ConfigurationParser
if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
{
extendsAnnotationType =
- ClassUtil.internalType(
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- true, false, false, true, false, null)));
+ true, false, false, true, false, false, true, null));
}
String externalExtendsClassName =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("class name or interface name",
- false, false, false, true, false, null));
+ false, false, false, true, false, false, false, null));
extendsClassName = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalExtendsClassName) ?
null :
@@ -694,10 +695,9 @@ public class ConfigurationParser
if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
{
annotationType =
- ClassUtil.internalType(
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- true, false, false, true, false, null)));
+ true, false, false, true, false, false, true, null));
continue;
}
@@ -875,7 +875,7 @@ public class ConfigurationParser
// Parse the method arguments.
String descriptor =
ClassUtil.internalMethodDescriptor(type,
- parseCommaSeparatedList("argument", true, true, true, true, false, null));
+ parseCommaSeparatedList("argument", true, true, true, true, false, false, false, null));
if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord))
{
@@ -923,6 +923,8 @@ public class ConfigurationParser
boolean expectClosingParenthesis,
boolean checkJavaIdentifiers,
boolean replaceSystemProperties,
+ boolean replaceExternalClassNames,
+ boolean replaceExternalTypes,
List list)
throws ParseException, IOException
{
@@ -972,6 +974,16 @@ public class ConfigurationParser
nextWord = replaceSystemProperties(nextWord);
}
+ if (replaceExternalClassNames)
+ {
+ nextWord = ClassUtil.internalClassName(nextWord);
+ }
+
+ if (replaceExternalTypes)
+ {
+ nextWord = ClassUtil.internalType(nextWord);
+ }
+
list.add(nextWord);
if (expectClosingParenthesis)
diff --git a/src/proguard/ConfigurationWriter.java b/src/proguard/ConfigurationWriter.java
index 654dfec..5d112d6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -107,6 +107,7 @@ public class ConfigurationWriter
// Write the other options.
writeOption(ConfigurationConstants.DONT_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));
writeOption(ConfigurationConstants.FORCE_PROCESSING_OPTION, configuration.lastModified == Long.MAX_VALUE);
@@ -114,6 +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.OPTIMIZATION_PASSES, configuration.optimizationPasses);
writeOption(ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION, configuration.allowAccessModification);
writeOption(ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION, configuration.mergeInterfacesAggressively);
@@ -127,19 +129,21 @@ public class ConfigurationWriter
writeOption(ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION, configuration.overloadAggressively);
writeOption(ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION, configuration.useUniqueClassMemberNames);
writeOption(ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION, !configuration.useMixedCaseClassNames);
- writeOption(ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION, configuration.flattenPackageHierarchy == null ? null : ClassUtil.externalClassName(configuration.flattenPackageHierarchy));
- writeOption(ConfigurationConstants.REPACKAGE_CLASSES_OPTION, configuration.repackageClasses == null ? null : ClassUtil.externalClassName(configuration.repackageClasses));
- writeOption(ConfigurationConstants.KEEP_ATTRIBUTES_OPTION, ListUtil.commaSeparatedString(configuration.keepAttributes));
+ writeOption(ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION, configuration.keepPackageNames, true);
+ 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.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION, configuration.newSourceFileAttribute);
- writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION, ListUtil.commaSeparatedString(configuration.adaptResourceFileNames));
- writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION, ListUtil.commaSeparatedString(configuration.adaptResourceFileContents));
+ writeOption(ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION, configuration.adaptClassStrings, true);
+ writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION, configuration.adaptResourceFileNames);
+ writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION, configuration.adaptResourceFileContents);
writeOption(ConfigurationConstants.DONT_PREVERIFY_OPTION, !configuration.preverify);
writeOption(ConfigurationConstants.MICRO_EDITION_OPTION, configuration.microEdition);
writeOption(ConfigurationConstants.VERBOSE_OPTION, configuration.verbose);
- writeOption(ConfigurationConstants.DONT_NOTE_OPTION, !configuration.note);
- writeOption(ConfigurationConstants.DONT_WARN_OPTION, !configuration.warn);
+ writeOption(ConfigurationConstants.DONT_NOTE_OPTION, configuration.note, true);
+ writeOption(ConfigurationConstants.DONT_WARN_OPTION, configuration.warn, true);
writeOption(ConfigurationConstants.IGNORE_WARNINGS_OPTION, configuration.ignoreWarnings);
writeOption(ConfigurationConstants.PRINT_CONFIGURATION_OPTION, configuration.printConfiguration);
writeOption(ConfigurationConstants.DUMP_OPTION, configuration.dump);
@@ -200,7 +204,7 @@ public class ConfigurationWriter
}
- private boolean writeFilter(boolean filtered, String filter)
+ private boolean writeFilter(boolean filtered, List filter)
{
if (filtered)
{
@@ -214,7 +218,15 @@ public class ConfigurationWriter
writer.print(ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD);
}
- writer.print(quotedString(filter));
+ for (int index = 0; index < filter.size(); index++)
+ {
+ if (index > 0)
+ {
+ writer.print(ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD);
+ }
+
+ writer.print(quotedString((String)filter.get(index)));
+ }
filtered = true;
}
@@ -243,10 +255,56 @@ public class ConfigurationWriter
}
+ private void writeOption(String optionName, List arguments)
+ {
+ writeOption(optionName, arguments, false);
+ }
+
+
+ private void writeOption(String optionName,
+ List arguments,
+ boolean replaceInternalClassNames)
+ {
+ if (arguments != null)
+ {
+ if (arguments.isEmpty())
+ {
+ writer.println(optionName);
+ }
+ else
+ {
+ String argumentString = ListUtil.commaSeparatedString(arguments);
+
+ if (replaceInternalClassNames)
+ {
+ argumentString = ClassUtil.externalClassName(argumentString);
+ }
+
+ writer.print(optionName);
+ writer.print(' ');
+ writer.println(quotedString(argumentString));
+ }
+ }
+ }
+
+
private void writeOption(String optionName, String arguments)
{
+ writeOption(optionName, arguments, false);
+ }
+
+
+ private void writeOption(String optionName,
+ String arguments,
+ boolean replaceInternalClassNames)
+ {
if (arguments != null)
{
+ if (replaceInternalClassNames)
+ {
+ arguments = ClassUtil.externalClassName(arguments);
+ }
+
writer.print(optionName);
writer.print(' ');
writer.println(quotedString(arguments));
@@ -273,46 +331,46 @@ public class ConfigurationWriter
private void writeOptions(String[] optionNames,
- List keepSpecifications)
+ List keepClassSpecifications)
{
- if (keepSpecifications != null)
+ if (keepClassSpecifications != null)
{
- for (int index = 0; index < keepSpecifications.size(); index++)
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
{
- writeOption(optionNames, (KeepSpecification)keepSpecifications.get(index));
+ writeOption(optionNames, (KeepClassSpecification)keepClassSpecifications.get(index));
}
}
}
- private void writeOption(String[] optionNames,
- KeepSpecification keepSpecification)
+ private void writeOption(String[] optionNames,
+ KeepClassSpecification keepClassSpecification)
{
// Compose the option name.
- String optionName = optionNames[keepSpecification.markConditionally ? 2 :
- keepSpecification.markClasses ? 0 :
+ String optionName = optionNames[keepClassSpecification.markConditionally ? 2 :
+ keepClassSpecification.markClasses ? 0 :
1];
- if (keepSpecification.allowShrinking)
+ if (keepClassSpecification.allowShrinking)
{
optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION;
}
- if (keepSpecification.allowOptimization)
+ if (keepClassSpecification.allowOptimization)
{
optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION;
}
- if (keepSpecification.allowObfuscation)
+ if (keepClassSpecification.allowObfuscation)
{
optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION;
}
// Write out the option with the proper class specification.
- writeOption(optionName, keepSpecification);
+ writeOption(optionName, keepClassSpecification);
}
@@ -561,7 +619,8 @@ public class ConfigurationWriter
string.indexOf('(') >= 0 ||
string.indexOf(')') >= 0 ||
string.indexOf(':') >= 0 ||
- string.indexOf(';') >= 0 ? ("'" + string + "'") :
+ string.indexOf(';') >= 0 ||
+ string.indexOf(',') >= 0 ? ("'" + string + "'") :
( string );
}
diff --git a/src/proguard/DataEntryReaderFactory.java b/src/proguard/DataEntryReaderFactory.java
index 68e8eb7..a9724b5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,8 @@ package proguard;
import proguard.io.*;
import proguard.util.*;
+import java.util.List;
+
/**
* This class can create DataEntryReader instances based on class path entries.
@@ -52,11 +54,11 @@ public class DataEntryReaderFactory
boolean isEar = endsWithIgnoreCase(entryName, ".ear");
boolean isZip = endsWithIgnoreCase(entryName, ".zip");
- String filter = classPathEntry.getFilter();
- String jarFilter = classPathEntry.getJarFilter();
- String warFilter = classPathEntry.getWarFilter();
- String earFilter = classPathEntry.getEarFilter();
- String zipFilter = classPathEntry.getZipFilter();
+ List filter = classPathEntry.getFilter();
+ List jarFilter = classPathEntry.getJarFilter();
+ List warFilter = classPathEntry.getWarFilter();
+ List earFilter = classPathEntry.getEarFilter();
+ List zipFilter = classPathEntry.getZipFilter();
System.out.println(messagePrefix +
(isJar ? "jar" :
@@ -107,7 +109,7 @@ public class DataEntryReaderFactory
*/
private static DataEntryReader wrapInJarReader(DataEntryReader reader,
boolean isJar,
- String jarFilter,
+ List jarFilter,
String jarExtension)
{
// Unzip any jars, if necessary.
diff --git a/src/proguard/DataEntryWriterFactory.java b/src/proguard/DataEntryWriterFactory.java
index 1adc75f..9fbc6d0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,8 @@ package proguard;
import proguard.io.*;
import proguard.util.*;
+import java.util.List;
+
/**
* This class can create DataEntryWriter instances based on class paths. The
* writers will wrap the output in the proper jars, wars, ears, and zips.
@@ -69,11 +71,11 @@ public class DataEntryWriterFactory
boolean isEar = endsWithIgnoreCase(entryName, ".ear");
boolean isZip = endsWithIgnoreCase(entryName, ".zip");
- String filter = classPathEntry.getFilter();
- String jarFilter = classPathEntry.getJarFilter();
- String warFilter = classPathEntry.getWarFilter();
- String earFilter = classPathEntry.getEarFilter();
- String zipFilter = classPathEntry.getZipFilter();
+ List filter = classPathEntry.getFilter();
+ List jarFilter = classPathEntry.getJarFilter();
+ List warFilter = classPathEntry.getWarFilter();
+ List earFilter = classPathEntry.getEarFilter();
+ List zipFilter = classPathEntry.getZipFilter();
System.out.println("Preparing output " +
(isJar ? "jar" :
@@ -120,7 +122,7 @@ public class DataEntryWriterFactory
*/
private static DataEntryWriter wrapInJarWriter(DataEntryWriter writer,
boolean isJar,
- String jarFilter,
+ List jarFilter,
String jarExtension,
boolean dontWrap)
{
diff --git a/src/proguard/DescriptorKeepChecker.java b/src/proguard/DescriptorKeepChecker.java
index e8547f7..1dfaf1a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -139,7 +139,9 @@ implements MemberVisitor,
{
if (!KeepMarker.isKept(programClass))
{
- notePrinter.print("Note: the configuration keeps the entry point '" +
+ notePrinter.print(referencingClass.getName(),
+ programClass.getName(),
+ "Note: the configuration keeps the entry point '" +
ClassUtil.externalClassName(referencingClass.getName()) +
" { " +
(isField ?
diff --git a/src/proguard/DuplicateClassPrinter.java b/src/proguard/DuplicateClassPrinter.java
index 09a8b0c..21b6aa0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,14 +48,16 @@ public class DuplicateClassPrinter implements ClassVisitor
public void visitProgramClass(ProgramClass programClass)
{
- notePrinter.print("Note: duplicate definition of program class [" +
+ notePrinter.print(programClass.getName(),
+ "Note: duplicate definition of program class [" +
ClassUtil.externalClassName(programClass.getName()) + "]");
}
public void visitLibraryClass(LibraryClass libraryClass)
{
- notePrinter.print("Note: duplicate definition of library class [" +
+ notePrinter.print(libraryClass.getName(),
+ "Note: duplicate definition of library class [" +
ClassUtil.externalClassName(libraryClass.getName()) + "]");
}
}
diff --git a/src/proguard/FileWordReader.java b/src/proguard/FileWordReader.java
index 8ea9767..fb9fa50 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/FullyQualifiedClassNameChecker.java b/src/proguard/FullyQualifiedClassNameChecker.java
index aeb7398..06949b5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -150,9 +150,11 @@ implements ClassVisitor
if (className != null &&
!containsWildCards(className) &&
programClassPool.getClass(className) == null &&
- libraryClassPool.getClass(className) == null)
+ libraryClassPool.getClass(className) == null &&
+ notePrinter.accepts(className))
{
- notePrinter.print("Note: the configuration refers to the unknown class '" +
+ notePrinter.print(className,
+ "Note: the configuration refers to the unknown class '" +
ClassUtil.externalClassName(className) + "'");
String fullyQualifiedClassName =
diff --git a/src/proguard/GPL.java b/src/proguard/GPL.java
index 64e37cb..272a837 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +166,7 @@ public class GPL
packageName.startsWith("org.eclipse") ||
packageName.startsWith("org.netbeans") ||
packageName.startsWith("com.sun.kvem") ||
+ packageName.startsWith("net.certiv.proguarddt") ||
packageName.startsWith("eclipseme") ||
packageName.startsWith("jg.j2me") ||
packageName.startsWith("jg.common") ||
diff --git a/src/proguard/Initializer.java b/src/proguard/Initializer.java
index 03048f2..41cf971 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ package proguard;
import proguard.classfile.ClassPool;
import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.constant.visitor.*;
import proguard.classfile.instruction.visitor.AllInstructionVisitor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
@@ -66,13 +67,8 @@ public class Initializer
ClassPool reducedLibraryClassPool = configuration.useUniqueClassMemberNames ?
null : new ClassPool();
- WarningPrinter classReferenceWarningPrinter = configuration.warn ?
- new WarningPrinter(System.err) :
- null;
-
- WarningPrinter dependencyWarningPrinter = configuration.warn ?
- new WarningPrinter(System.err) :
- null;
+ WarningPrinter classReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter dependencyWarningPrinter = new WarningPrinter(System.err, configuration.warn);
// Initialize the superclass hierarchies for program classes.
programClassPool.classesAccept(
@@ -81,39 +77,47 @@ public class Initializer
classReferenceWarningPrinter,
null));
+ // Initialize the superclass hierarchy of all library classes, without
+ // warnings.
+ libraryClassPool.classesAccept(
+ new ClassSuperHierarchyInitializer(programClassPool,
+ libraryClassPool,
+ null,
+ dependencyWarningPrinter));
+
+ // Initialize the class references of program class members and
+ // attributes. Note that all superclass hierarchies have to be
+ // initialized for this purpose.
+ WarningPrinter memberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+
+ programClassPool.classesAccept(
+ new ClassReferenceInitializer(programClassPool,
+ libraryClassPool,
+ classReferenceWarningPrinter,
+ memberReferenceWarningPrinter,
+ null));
+
if (reducedLibraryClassPool != null)
{
- // Collect the library classes that are referenced by program
- // classes.
+ // Collect the library classes that are directly referenced by
+ // program classes, without introspection.
programClassPool.classesAccept(
new ReferencedClassVisitor(
new LibraryClassFilter(
new ClassPoolFiller(reducedLibraryClassPool))));
- // Initialize the superclass hierarchy for referenced library
- // classes, with warnings.
+ // Reinitialize the superclass hierarchies of referenced library
+ // classes, this time with warnings.
reducedLibraryClassPool.classesAccept(
new ClassSuperHierarchyInitializer(programClassPool,
libraryClassPool,
classReferenceWarningPrinter,
- dependencyWarningPrinter));
+ null));
}
- // Initialize the superclass hierarchy for library classes, without
- // warnings.
- libraryClassPool.classesAccept(
- new ClassSuperHierarchyInitializer(programClassPool,
- libraryClassPool,
- null,
- dependencyWarningPrinter));
-
- WarningPrinter dynamicClassReferenceNotePrinter = configuration.warn ?
- new WarningPrinter(System.err) :
- null;
-
- WarningPrinter classForNameNotePrinter = configuration.note ?
- new WarningPrinter(System.out) :
- null;
+ // Initialize the Class.forName references.
+ WarningPrinter dynamicClassReferenceNotePrinter = new WarningPrinter(System.out, configuration.note);
+ WarningPrinter classForNameNotePrinter = new WarningPrinter(System.out, configuration.note);
programClassPool.classesAccept(
new AllMethodVisitor(
@@ -126,21 +130,8 @@ public class Initializer
classForNameNotePrinter,
createClassNoteExceptionMatcher(configuration.keep))))));
- // Initialize the class references of program class members and attributes.
- WarningPrinter memberReferenceWarningPrinter = configuration.warn ?
- new WarningPrinter(System.err) :
- null;
-
- programClassPool.classesAccept(
- new ClassReferenceInitializer(programClassPool,
- libraryClassPool,
- memberReferenceWarningPrinter,
- null));
-
// Initialize the Class.get[Declared]{Field,Method} references.
- WarningPrinter getMemberNotePrinter = configuration.note ?
- new WarningPrinter(System.out) :
- null;
+ WarningPrinter getMemberNotePrinter = new WarningPrinter(System.out, configuration.note);
programClassPool.classesAccept(
new AllMethodVisitor(
@@ -152,34 +143,33 @@ public class Initializer
createClassMemberNoteExceptionMatcher(configuration.keep, true),
createClassMemberNoteExceptionMatcher(configuration.keep, false))))));
- // Print various notes, if specified.
- WarningPrinter fullyQualifiedClassNameNotePrinter = configuration.note ?
- new WarningPrinter(System.out) :
- null;
-
- WarningPrinter descriptorKeepNotePrinter = configuration.note ?
- new WarningPrinter(System.out) :
- null;
-
- if (fullyQualifiedClassNameNotePrinter != null)
+ // Initialize other string constant references, if requested.
+ if (configuration.adaptClassStrings != null)
{
- new FullyQualifiedClassNameChecker(programClassPool,
- libraryClassPool,
- fullyQualifiedClassNameNotePrinter).checkClassSpecifications(configuration.keep);
+ programClassPool.classesAccept(
+ new ClassNameFilter(configuration.adaptClassStrings,
+ new AllConstantVisitor(
+ new StringReferenceInitializer(programClassPool,
+ libraryClassPool))));
}
- if (descriptorKeepNotePrinter != null)
- {
- new DescriptorKeepChecker(programClassPool,
- libraryClassPool,
- descriptorKeepNotePrinter).checkClassSpecifications(configuration.keep);
- }
+ // Print various notes, if specified.
+ WarningPrinter fullyQualifiedClassNameNotePrinter = new WarningPrinter(System.out, configuration.note);
+ WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ new FullyQualifiedClassNameChecker(programClassPool,
+ libraryClassPool,
+ fullyQualifiedClassNameNotePrinter).checkClassSpecifications(configuration.keep);
+
+ new DescriptorKeepChecker(programClassPool,
+ libraryClassPool,
+ descriptorKeepNotePrinter).checkClassSpecifications(configuration.keep);
// Initialize the class references of library class members.
if (reducedLibraryClassPool != null)
{
// Collect the library classes that are referenced by program
- // classes.
+ // classes, directly or indirectly, with or without introspection.
programClassPool.classesAccept(
new ReferencedClassVisitor(
new LibraryClassFilter(
@@ -187,11 +177,13 @@ public class Initializer
new LibraryClassFilter(
new ClassPoolFiller(reducedLibraryClassPool))))));
- // Initialize the class references of library class members.
+ // Initialize the class references of referenced library
+ // classes, without warnings.
reducedLibraryClassPool.classesAccept(
new ClassReferenceInitializer(programClassPool,
libraryClassPool,
null,
+ null,
dependencyWarningPrinter));
// Reset the library class pool.
@@ -221,6 +213,7 @@ public class Initializer
new ClassReferenceInitializer(programClassPool,
libraryClassPool,
null,
+ null,
dependencyWarningPrinter));
}
@@ -233,106 +226,95 @@ public class Initializer
libraryClassPool.classesAccept(new StringSharer());
// Print out a summary of the notes, if necessary.
- if (fullyQualifiedClassNameNotePrinter != null)
+ int fullyQualifiedNoteCount = fullyQualifiedClassNameNotePrinter.getWarningCount();
+ if (fullyQualifiedNoteCount > 0)
{
- int fullyQualifiedNoteCount = fullyQualifiedClassNameNotePrinter.getWarningCount();
- if (fullyQualifiedNoteCount > 0)
- {
- System.out.println("Note: there were " + fullyQualifiedNoteCount +
- " references to unknown classes.");
- System.out.println(" You should check your configuration for typos.");
- }
+ System.out.println("Note: there were " + fullyQualifiedNoteCount +
+ " references to unknown classes.");
+ System.out.println(" You should check your configuration for typos.");
}
- if (descriptorKeepNotePrinter != null)
+ int descriptorNoteCount = descriptorKeepNotePrinter.getWarningCount();
+ if (descriptorNoteCount > 0)
{
- int descriptorNoteCount = descriptorKeepNotePrinter.getWarningCount();
- if (descriptorNoteCount > 0)
- {
- System.out.println("Note: there were " + descriptorNoteCount +
- " unkept descriptor classes in kept class members.");
- System.out.println(" You should consider explicitly keeping the mentioned classes");
- System.out.println(" (using '-keep').");
- }
+ System.out.println("Note: there were " + descriptorNoteCount +
+ " unkept descriptor classes in kept class members.");
+ System.out.println(" You should consider explicitly keeping the mentioned classes");
+ System.out.println(" (using '-keep').");
}
- if (dynamicClassReferenceNotePrinter != null)
+ int dynamicClassReferenceNoteCount = dynamicClassReferenceNotePrinter.getWarningCount();
+ if (dynamicClassReferenceNoteCount > 0)
{
- int dynamicClassReferenceNoteCount = dynamicClassReferenceNotePrinter.getWarningCount();
- if (dynamicClassReferenceNoteCount > 0)
- {
- System.out.println("Note: there were " + dynamicClassReferenceNoteCount +
- " unresolved dynamic references to classes or interfaces.");
- System.err.println(" You should check if you need to specify additional program jars.");
- }
+ System.out.println("Note: there were " + dynamicClassReferenceNoteCount +
+ " unresolved dynamic references to classes or interfaces.");
+ System.err.println(" You should check if you need to specify additional program jars.");
}
- if (classForNameNotePrinter != null)
+ int classForNameNoteCount = classForNameNotePrinter.getWarningCount();
+ if (classForNameNoteCount > 0)
{
- int classForNameNoteCount = classForNameNotePrinter.getWarningCount();
- if (classForNameNoteCount > 0)
- {
- System.out.println("Note: there were " + classForNameNoteCount +
- " class casts of dynamically created class instances.");
- System.out.println(" You might consider explicitly keeping the mentioned classes and/or");
- System.out.println(" their implementations (using '-keep').");
- }
+ System.out.println("Note: there were " + classForNameNoteCount +
+ " class casts of dynamically created class instances.");
+ System.out.println(" You might consider explicitly keeping the mentioned classes and/or");
+ System.out.println(" their implementations (using '-keep').");
}
- if (getMemberNotePrinter != null)
+ int getmemberNoteCount = getMemberNotePrinter.getWarningCount();
+ if (getmemberNoteCount > 0)
{
- int getmemberNoteCount = getMemberNotePrinter.getWarningCount();
- if (getmemberNoteCount > 0)
- {
- System.out.println("Note: there were " + getmemberNoteCount +
- " accesses to class members by means of introspection.");
- System.out.println(" You should consider explicitly keeping the mentioned class members");
- System.out.println(" (using '-keep' or '-keepclassmembers').");
- }
+ System.out.println("Note: there were " + getmemberNoteCount +
+ " accesses to class members by means of introspection.");
+ System.out.println(" You should consider explicitly keeping the mentioned class members");
+ System.out.println(" (using '-keep' or '-keepclassmembers').");
}
// Print out a summary of the warnings, if necessary.
- if (classReferenceWarningPrinter != null &&
- dependencyWarningPrinter != null &&
- memberReferenceWarningPrinter != null )
+ int classReferenceWarningCount = classReferenceWarningPrinter.getWarningCount();
+ if (classReferenceWarningCount > 0)
{
- int classReferenceWarningCount = classReferenceWarningPrinter.getWarningCount();
- if (classReferenceWarningCount > 0)
- {
- 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("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.");
+ }
- int dependencyWarningCount = dependencyWarningPrinter.getWarningCount();
- if (dependencyWarningCount > 0)
- {
- System.err.println("Warning: there were " + dependencyWarningCount +
- " instances of library classes depending on program classes.");
- System.err.println(" You must avoid such dependencies, since the program classes will");
- System.err.println(" be processed, while the library classes will remain unchanged.");
- }
+ int dependencyWarningCount = dependencyWarningPrinter.getWarningCount();
+ if (dependencyWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + dependencyWarningCount +
+ " instances of library classes depending on program classes.");
+ System.err.println(" You must avoid such dependencies, since the program classes will");
+ System.err.println(" be processed, while the library classes will remain unchanged.");
+ }
- int memberReferenceWarningCount = memberReferenceWarningPrinter.getWarningCount();
- if (memberReferenceWarningCount > 0)
- {
- System.err.println("Warning: there were " + memberReferenceWarningCount +
- " unresolved references to program class members.");
- System.err.println(" Your input classes appear to be inconsistent.");
- System.err.println(" You may need to recompile them and try again.");
- System.err.println(" Alternatively, you may have to specify the options ");
- System.err.println(" '-dontskipnonpubliclibraryclasses' and/or");
- System.err.println(" '-dontskipnonpubliclibraryclassmembers'.");
- }
+ int memberReferenceWarningCount = memberReferenceWarningPrinter.getWarningCount();
+ if (memberReferenceWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + memberReferenceWarningCount +
+ " unresolved references to program class members.");
+ System.err.println(" Your input classes appear to be inconsistent.");
+ System.err.println(" You may need to recompile them and try again.");
+ System.err.println(" Alternatively, you may have to specify the options ");
+ System.err.println(" '-dontskipnonpubliclibraryclasses' and/or");
+ System.err.println(" '-dontskipnonpubliclibraryclassmembers'.");
+ }
- if ((classReferenceWarningCount > 0 ||
- dependencyWarningCount > 0 ||
- memberReferenceWarningCount > 0) &&
- !configuration.ignoreWarnings)
- {
- throw new IOException("Please correct the above warnings first.");
- }
+ if ((classReferenceWarningCount > 0 ||
+ dependencyWarningCount > 0 ||
+ memberReferenceWarningCount > 0) &&
+ !configuration.ignoreWarnings)
+ {
+ throw new IOException("Please correct the above warnings first.");
+ }
+
+ if ((configuration.note == null ||
+ !configuration.note.isEmpty()) &&
+ (configuration.warn != null &&
+ configuration.warn.isEmpty() ||
+ configuration.ignoreWarnings))
+ {
+ System.out.println("Note: You're ignoring all warnings!");
}
// Discard unused library classes.
@@ -356,18 +338,18 @@ public class Initializer
List noteExceptionNames = new ArrayList(noteExceptions.size());
for (int index = 0; index < noteExceptions.size(); index++)
{
- KeepSpecification keepSpecification = (KeepSpecification)noteExceptions.get(index);
- if (keepSpecification.markClasses)
+ KeepClassSpecification keepClassSpecification = (KeepClassSpecification)noteExceptions.get(index);
+ if (keepClassSpecification.markClasses)
{
// If the class itself is being kept, it's ok.
- String className = keepSpecification.className;
+ String className = keepClassSpecification.className;
if (className != null)
{
noteExceptionNames.add(className);
}
// If all of its extensions are being kept, it's ok too.
- String extendsClassName = keepSpecification.extendsClassName;
+ String extendsClassName = keepClassSpecification.extendsClassName;
if (extendsClassName != null)
{
noteExceptionNames.add(extendsClassName);
@@ -397,10 +379,10 @@ public class Initializer
List noteExceptionNames = new ArrayList();
for (int index = 0; index < noteExceptions.size(); index++)
{
- KeepSpecification keepSpecification = (KeepSpecification)noteExceptions.get(index);
+ KeepClassSpecification keepClassSpecification = (KeepClassSpecification)noteExceptions.get(index);
List memberSpecifications = isField ?
- keepSpecification.fieldSpecifications :
- keepSpecification.methodSpecifications;
+ keepClassSpecification.fieldSpecifications :
+ keepClassSpecification.methodSpecifications;
if (memberSpecifications != null)
{
diff --git a/src/proguard/InputReader.java b/src/proguard/InputReader.java
index ebdc831..c088324 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,24 +54,23 @@ public class InputReader
public void execute(ClassPool programClassPool,
ClassPool libraryClassPool) throws IOException
{
- WarningPrinter warningPrinter = configuration.warn ?
- new WarningPrinter(System.err) :
- null;
-
- WarningPrinter notePrinter = configuration.note ?
- new WarningPrinter(System.out) :
- null;
-
- DuplicateClassPrinter duplicateClassPrinter = configuration.note ?
- new DuplicateClassPrinter(notePrinter) :
- null;
-
// Check if we have at least some input classes.
if (configuration.programJars == null)
{
throw new IOException("The input is empty. You have to specify one or more '-injars' options");
}
+ // Perform some sanity checks on the class paths.
+ checkInputOutput(configuration.libraryJars,
+ configuration.programJars);
+ checkInputOutput(configuration.programJars,
+ configuration.programJars);
+
+ WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter notePrinter = new WarningPrinter(System.out, configuration.note);
+
+ DuplicateClassPrinter duplicateClassPrinter = new DuplicateClassPrinter(notePrinter);
+
// Read the program class files.
// Prepare a data entry reader to filter all classes,
// which are then decoded to classes by a class reader,
@@ -111,32 +110,58 @@ public class InputReader
}
// Print out a summary of the notes, if necessary.
- if (notePrinter != null)
+ int noteCount = notePrinter.getWarningCount();
+ if (noteCount > 0)
{
- int noteCount = notePrinter.getWarningCount();
- if (noteCount > 0)
- {
- System.err.println("Note: there were " + noteCount +
- " duplicate class definitions.");
- }
+ System.err.println("Note: there were " + noteCount +
+ " duplicate class definitions.");
}
// Print out a summary of the warnings, if necessary.
- if (warningPrinter != null)
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
{
- int warningCount = warningPrinter.getWarningCount();
- if (warningCount > 0)
+ System.err.println("Warning: there were " + warningCount +
+ " classes in incorrectly named files.");
+ System.err.println(" You should make sure all file names correspond to their class names.");
+ System.err.println(" The directory hierarchies must correspond to the package hierarchies.");
+
+ if (!configuration.ignoreWarnings)
{
- System.err.println("Warning: there were " + warningCount +
- " classes in incorrectly named files.");
- System.err.println(" You should make sure all file names correspond to their class names.");
- System.err.println(" The directory hierarchies must correspond to the package hierarchies.");
+ System.err.println(" If you don't mind the mentioned classes not being written out,");
+ System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ throw new IOException("Please correct the above warnings first.");
+ }
+ }
+ }
+
+
+ /**
+ * Performs some sanity checks on the class paths.
+ */
+ private void checkInputOutput(ClassPath inputClassPath,
+ ClassPath outputClassPath)
+ throws IOException
+ {
+ if (inputClassPath == null ||
+ outputClassPath == null)
+ {
+ return;
+ }
- if (!configuration.ignoreWarnings)
+ for (int index1 = 0; index1 < inputClassPath.size(); index1++)
+ {
+ ClassPathEntry entry1 = inputClassPath.get(index1);
+ if (!entry1.isOutput())
+ {
+ for (int index2 = 0; index2 < outputClassPath.size(); index2++)
{
- System.err.println(" If you don't mind the mentioned classes not being written out,");
- System.err.println(" you could try your luck using the '-ignorewarnings' option.");
- throw new IOException("Please correct the above warnings first.");
+ ClassPathEntry entry2 = outputClassPath.get(index2);
+ if (entry2.isOutput() &&
+ entry2.getName().equals(entry1.getName()))
+ {
+ throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"]");
+ }
}
}
}
diff --git a/src/proguard/KeepSpecification.java b/src/proguard/KeepClassSpecification.java
similarity index 79%
rename from src/proguard/KeepSpecification.java
rename to src/proguard/KeepClassSpecification.java
index 5fd4fae..29c0d3c 100644
--- a/src/proguard/KeepSpecification.java
+++ b/src/proguard/KeepClassSpecification.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,12 +21,11 @@
package proguard;
/**
- * This class stores a specification of keep option, with a purpose and a class
- * specification.
+ * This class represents a keep option with class specification.
*
* @author Eric Lafortune
*/
-public class KeepSpecification extends ClassSpecification
+public class KeepClassSpecification extends ClassSpecification
{
public final boolean markClasses;
public final boolean markConditionally;
@@ -36,7 +35,7 @@ public class KeepSpecification extends ClassSpecification
/**
- * Creates a new KeepSpecification for all possible classes.
+ * Creates a new KeepClassSpecification for all possible classes.
* @param markClasses specifies whether to mark the classes.
* If false, only class members are marked.
* If true, the classes are marked as well.
@@ -48,11 +47,11 @@ public class KeepSpecification extends ClassSpecification
* @param allowOptimization specifies whether optimization is allowed.
* @param allowObfuscation specifies whether obfuscation is allowed.
*/
- public KeepSpecification(boolean markClasses,
- boolean markConditionally,
- boolean allowShrinking,
- boolean allowOptimization,
- boolean allowObfuscation)
+ public KeepClassSpecification(boolean markClasses,
+ boolean markConditionally,
+ boolean allowShrinking,
+ boolean allowOptimization,
+ boolean allowObfuscation)
{
this.markClasses = markClasses;
this.markConditionally = markConditionally;
@@ -63,7 +62,7 @@ public class KeepSpecification extends ClassSpecification
/**
- * Creates a new KeepSpecification.
+ * Creates a new KeepClassSpecification.
* @param markClasses specifies whether to mark the classes.
* If false, only class members are marked.
* If true, the classes are marked as well.
@@ -76,12 +75,12 @@ public class KeepSpecification extends ClassSpecification
* @param allowObfuscation specifies whether obfuscation is allowed.
* @param classSpecification the specification of classes and class members.
*/
- public KeepSpecification(boolean markClasses,
- boolean markConditionally,
- boolean allowShrinking,
- boolean allowOptimization,
- boolean allowObfuscation,
- ClassSpecification classSpecification)
+ public KeepClassSpecification(boolean markClasses,
+ boolean markConditionally,
+ boolean allowShrinking,
+ boolean allowOptimization,
+ boolean allowObfuscation,
+ ClassSpecification classSpecification)
{
super(classSpecification);
@@ -103,7 +102,7 @@ public class KeepSpecification extends ClassSpecification
return false;
}
- KeepSpecification other = (KeepSpecification)object;
+ KeepClassSpecification other = (KeepClassSpecification)object;
return
this.markClasses == other.markClasses &&
this.markConditionally == other.markConditionally &&
diff --git a/src/proguard/MemberSpecification.java b/src/proguard/MemberSpecification.java
index 1f9c2ca..1cfa962 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 915e806..10c18fb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,11 @@
package proguard;
import proguard.classfile.ClassPool;
+import proguard.classfile.util.ClassUtil;
import proguard.io.*;
-import proguard.util.*;
import java.io.IOException;
+import java.util.*;
/**
* This class writes the output class files.
@@ -154,43 +155,58 @@ public class OutputWriter
new ClassRewriter(programClassPool, writer);
// The writer will also be used to write resource files.
- DataEntryReader resourceRewriter =
+ DataEntryReader resourceCopier =
new DataEntryCopier(writer);
+ DataEntryReader resourceRewriter = resourceCopier;
+
// Wrap the resource writer with a filter and a data entry rewriter,
// if required.
if (configuration.adaptResourceFileContents != null)
{
- DataEntryReader adaptedResourceRewriter =
- new DataEntryRewriter(programClassPool, writer);
-
- resourceRewriter = configuration.adaptResourceFileContents.size() > 0 ?
- new FilteredDataEntryReader(
- new DataEntryNameFilter(
- new ListParser(new FileNameParser()).parse(configuration.adaptResourceFileContents)),
- adaptedResourceRewriter, resourceRewriter) :
- adaptedResourceRewriter;
+ resourceRewriter =
+ new NameFilter(configuration.adaptResourceFileContents,
+ new NameFilter("META-INF/**",
+ new ManifestRewriter(programClassPool, writer),
+ new DataEntryRewriter(programClassPool, writer)),
+ resourceRewriter);
}
// Wrap the resource writer with a filter and a data entry renamer,
// if required.
if (configuration.adaptResourceFileNames != null)
{
- DataEntryReader adaptedResourceRewriter =
- new DataEntryRenamer(programClassPool, resourceRewriter);
-
- resourceRewriter = configuration.adaptResourceFileNames.size() > 0 ?
- new FilteredDataEntryReader(
- new DataEntryNameFilter(
- new ListParser(new FileNameParser()).parse(configuration.adaptResourceFileNames)),
- adaptedResourceRewriter, resourceRewriter) :
- adaptedResourceRewriter;
+ Map packagePrefixMap = createPackagePrefixMap(programClassPool);
+
+ resourceRewriter =
+ new NameFilter(configuration.adaptResourceFileNames,
+ new DataEntryObfuscator(programClassPool,
+ packagePrefixMap,
+ resourceRewriter),
+ resourceRewriter);
}
- // Create the reader that can write class files and copy resource
- // files to the above writer.
+ DataEntryReader directoryRewriter = null;
+
+ // Wrap the directory writer with a filter and a data entry renamer,
+ // if required.
+ if (configuration.keepDirectories != null)
+ {
+ Map packagePrefixMap = createPackagePrefixMap(programClassPool);
+
+ directoryRewriter =
+ new NameFilter(configuration.keepDirectories,
+ new DataEntryRenamer(packagePrefixMap,
+ resourceCopier,
+ resourceCopier));
+ }
+
+ // Create the reader that can write class files and copy directories
+ // and resource files to the main writer.
DataEntryReader reader =
- new ClassFilter(classRewriter, resourceRewriter);
+ new ClassFilter( classRewriter,
+ new DirectoryFilter(directoryRewriter,
+ resourceRewriter));
// Go over the specified input entries and write their processed
// versions.
@@ -208,4 +224,33 @@ public class OutputWriter
throw new IOException("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")");
}
}
+
+
+ /**
+ * Creates a map of old package prefixes to new package prefixes, based on
+ * the given class pool.
+ */
+ private static Map createPackagePrefixMap(ClassPool classPool)
+ {
+ Map PackagePrefixMap = new HashMap();
+
+ Iterator iterator = classPool.classNames();
+ while (iterator.hasNext())
+ {
+ String className = (String)iterator.next();
+ String PackagePrefix = ClassUtil.internalPackagePrefix(className);
+
+ String mappedNewPackagePrefix = (String)PackagePrefixMap.get(PackagePrefix);
+ if (mappedNewPackagePrefix == null ||
+ !mappedNewPackagePrefix.equals(PackagePrefix))
+ {
+ String newClassName = classPool.getClass(className).getName();
+ String newPackagePrefix = ClassUtil.internalPackagePrefix(newClassName);
+
+ PackagePrefixMap.put(PackagePrefix, newPackagePrefix);
+ }
+ }
+
+ return PackagePrefixMap;
+ }
}
diff --git a/src/proguard/ParseException.java b/src/proguard/ParseException.java
index 88378b3..9294200 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 a9f0e5c..8c30e10 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -37,7 +37,7 @@ import java.io.*;
*/
public class ProGuard
{
- public static final String VERSION = "ProGuard, version 4.3";
+ public static final String VERSION = "ProGuard, version 4.4";
private final Configuration configuration;
private ClassPool programClassPool = new ClassPool();
diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/SubclassedClassFilter.java
index 268a6fe..27cac11 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e2fcee8..5067205 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ public class Targeter
*/
public void execute(ClassPool programClassPool) throws IOException
{
- Set newerClassVersions = configuration.warn ? new HashSet() : null;
+ Set newerClassVersions = configuration.warn != null ? null : new HashSet();
programClassPool.classesAccept(new ClassVersionSetter(configuration.targetClassVersion,
newerClassVersions));
diff --git a/src/proguard/UpToDateChecker.java b/src/proguard/UpToDateChecker.java
index 0586d12..9fa5d16 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/WordReader.java b/src/proguard/WordReader.java
index 275f9b9..d73505a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ClassPathElement.java b/src/proguard/ant/ClassPathElement.java
index c644c88..b5c2df4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.ant;
import org.apache.tools.ant.*;
import org.apache.tools.ant.types.*;
import proguard.*;
+import proguard.util.ListUtil;
import java.io.File;
@@ -118,11 +119,11 @@ public class ClassPathElement extends Path
ClassPathEntry entry =
new ClassPathEntry(file.isAbsolute() ? file : new File(baseDir, fileName),
output);
- entry.setFilter(filter);
- entry.setJarFilter(jarFilter);
- entry.setWarFilter(warFilter);
- entry.setEarFilter(earFilter);
- entry.setZipFilter(zipFilter);
+ entry.setFilter(ListUtil.commaSeparatedList(filter));
+ entry.setJarFilter(ListUtil.commaSeparatedList(jarFilter));
+ entry.setWarFilter(ListUtil.commaSeparatedList(warFilter));
+ entry.setEarFilter(ListUtil.commaSeparatedList(earFilter));
+ entry.setZipFilter(ListUtil.commaSeparatedList(zipFilter));
// Add it to the class path.
classPath.add(entry);
diff --git a/src/proguard/ant/ClassSpecificationElement.java b/src/proguard/ant/ClassSpecificationElement.java
index 4356f15..f4ea2ff 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -92,7 +92,7 @@ public class ClassSpecificationElement extends DataType
new ClassSpecification(null,
requiredAccessFlags(true, access, type),
requiredAccessFlags(false, access, type),
- annotation != null ? ClassUtil.internalType(annotation) : null,
+ annotation != null ? ClassUtil.internalType(annotation) : null,
name != null ? ClassUtil.internalClassName(name) : null,
extendsAnnotation != null ? ClassUtil.internalType(extendsAnnotation) : null,
extends_ != null ? ClassUtil.internalClassName(extends_) : null);
diff --git a/src/proguard/ant/ConfigurationElement.java b/src/proguard/ant/ConfigurationElement.java
index b9d52af..76e9418 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 66b87b6..0d2f04f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,23 +43,47 @@ public class ConfigurationTask extends Task
public void appendTo(Configuration configuration)
{
// Append all of these configuration entries to the given configuration.
- configuration.programJars = extendClassPath(configuration.programJars,
- this.configuration.programJars);
+ configuration.programJars = extendClassPath(configuration.programJars,
+ this.configuration.programJars);
- configuration.libraryJars = extendClassPath(configuration.libraryJars,
- this.configuration.libraryJars);
+ configuration.libraryJars = extendClassPath(configuration.libraryJars,
+ this.configuration.libraryJars);
- configuration.keep = extendClassSpecifications(configuration.keep,
- this.configuration.keep);
+ configuration.keep = extendClassSpecifications(configuration.keep,
+ this.configuration.keep);
- configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping,
- this.configuration.whyAreYouKeeping);
+ configuration.keepDirectories = extendList(configuration.keepDirectories,
+ this.configuration.keepDirectories);
- configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects,
- this.configuration.assumeNoSideEffects);
+ configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping,
+ this.configuration.whyAreYouKeeping);
+
+ configuration.optimizations = extendClassSpecifications(configuration.optimizations,
+ this.configuration.optimizations);
+
+ configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects,
+ this.configuration.assumeNoSideEffects);
+
+ configuration.keepPackageNames = extendList(configuration.keepPackageNames,
+ this.configuration.keepPackageNames);
+
+ configuration.keepAttributes = extendList(configuration.keepAttributes,
+ this.configuration.keepAttributes);
- configuration.keepAttributes = extendList(configuration.keepAttributes,
- this.configuration.keepAttributes);
+ configuration.adaptClassStrings = extendList(configuration.adaptClassStrings,
+ this.configuration.adaptClassStrings);
+
+ configuration.adaptResourceFileNames = extendList(configuration.adaptResourceFileNames,
+ this.configuration.adaptResourceFileNames);
+
+ configuration.adaptResourceFileContents = extendList(configuration.adaptResourceFileContents,
+ this.configuration.adaptResourceFileContents);
+
+ configuration.note = extendList(configuration.note,
+ this.configuration.note);
+
+ configuration.warn = extendList(configuration.warn,
+ this.configuration.warn);
}
@@ -89,6 +113,20 @@ public class ConfigurationTask extends Task
}
+ public void addConfiguredKeepdirectory(FilterElement filterElement)
+ {
+ configuration.keepDirectories = extendFilter(configuration.keepDirectories,
+ filterElement);
+ }
+
+
+ public void addConfiguredKeepdirectories(FilterElement filterElement)
+ {
+ configuration.keepDirectories = extendFilter(configuration.keepDirectories,
+ filterElement);
+ }
+
+
public void addConfiguredKeep(KeepSpecificationElement keepSpecificationElement)
{
configuration.keep = extendKeepSpecifications(configuration.keep,
@@ -166,10 +204,52 @@ public class ConfigurationTask extends Task
}
- public void addConfiguredKeepattribute(KeepAttributeElement keepAttributeElement)
+ public void addConfiguredOptimizations(FilterElement filterElement)
+ {
+ addConfiguredOptimization(filterElement);
+ }
+
+
+ public void addConfiguredOptimization(FilterElement filterElement)
{
- configuration.keepAttributes = extendAttributes(configuration.keepAttributes,
- keepAttributeElement);
+ configuration.optimizations = extendFilter(configuration.optimizations,
+ filterElement);
+ }
+
+
+ public void addConfiguredKeeppackagename(FilterElement filterElement)
+ {
+ configuration.keepPackageNames = extendFilter(configuration.keepPackageNames,
+ filterElement,
+ true);
+ }
+
+
+ public void addConfiguredKeeppackagenames(FilterElement filterElement)
+ {
+ configuration.keepPackageNames = extendFilter(configuration.keepPackageNames,
+ filterElement,
+ true);
+ }
+
+
+ public void addConfiguredKeepattributes(FilterElement filterElement)
+ {
+ addConfiguredKeepattribute(filterElement);
+ }
+
+
+ public void addConfiguredKeepattribute(FilterElement filterElement)
+ {
+ configuration.keepAttributes = extendFilter(configuration.keepAttributes,
+ filterElement);
+ }
+
+
+ public void addConfiguredAdaptclassstrings(FilterElement filterElement)
+ {
+ configuration.adaptClassStrings = extendFilter(configuration.adaptClassStrings,
+ filterElement, true);
}
@@ -187,6 +267,18 @@ public class ConfigurationTask extends Task
}
+ public void addConfiguredDontnote(FilterElement filterElement)
+ {
+ configuration.note = extendFilter(configuration.note, filterElement, true);
+ }
+
+
+ public void addConfiguredDontwarn(FilterElement filterElement)
+ {
+ configuration.warn = extendFilter(configuration.warn, filterElement, true);
+ }
+
+
public void addConfiguredConfiguration(ConfigurationElement configurationElement)
{
configurationElement.appendTo(configuration);
@@ -308,29 +400,23 @@ public class ConfigurationTask extends Task
}
- private List extendAttributes(List attributes,
- KeepAttributeElement keepAttributeElement)
+ private List extendFilter(List filter,
+ FilterElement filterElement)
{
- if (attributes == null)
- {
- attributes = new ArrayList();
- }
-
- keepAttributeElement.appendTo(attributes);
-
- return attributes;
+ return extendFilter(filter, filterElement, false);
}
private List extendFilter(List filter,
- FilterElement filterElement)
+ FilterElement filterElement,
+ boolean internal)
{
if (filter == null)
{
filter = new ArrayList();
}
- filterElement.appendTo(filter);
+ filterElement.appendTo(filter, internal);
return filter;
}
diff --git a/src/proguard/ant/FilterElement.java b/src/proguard/ant/FilterElement.java
index 66d25ed..d792c5d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.ant;
import org.apache.tools.ant.types.DataType;
+import proguard.classfile.util.ClassUtil;
import proguard.util.ListUtil;
import java.util.List;
@@ -37,9 +38,11 @@ public class FilterElement extends DataType
/**
* Adds the contents of this element to the given name filter.
- * @param filter the list of attributes to be extended.
+ * @param filter the list of attributes to be extended.
+ * @param internal specifies whether the filter string should be converted
+ * to internal types.
*/
- public void appendTo(List filter)
+ public void appendTo(List filter, boolean internal)
{
// Get the referenced element, or else this one.
FilterElement filterElement = isReference() ?
@@ -56,6 +59,11 @@ public class FilterElement extends DataType
}
else
{
+ if (internal)
+ {
+ filterString = ClassUtil.internalClassName(filterString);
+ }
+
// Append the filter.
filter.addAll(ListUtil.commaSeparatedList(filterString));
}
@@ -64,6 +72,12 @@ public class FilterElement extends DataType
// Ant task attributes.
+ public void setName(String name)
+ {
+ this.filter = name;
+ }
+
+
public void setFilter(String filter)
{
this.filter = filter;
diff --git a/src/proguard/ant/KeepAttributeElement.java b/src/proguard/ant/KeepAttributeElement.java
deleted file mode 100644
index ac066a8..0000000
--- a/src/proguard/ant/KeepAttributeElement.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is 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.ant;
-
-import org.apache.tools.ant.types.DataType;
-
-import java.util.List;
-
-/**
- * This DataType represents a named attribute in Ant.
- *
- * @author Eric Lafortune
- */
-public class KeepAttributeElement extends DataType
-{
- private String name;
-
-
- /**
- * Adds the contents of this element to the given list of attributes.
- * @param keepAttributes the list of attributes to be extended.
- */
- public void appendTo(List keepAttributes)
- {
- // Get the referenced element, or else this one.
- KeepAttributeElement keepAttributeElement = isReference() ?
- (KeepAttributeElement)getCheckedRef(this.getClass(),
- this.getClass().getName()) :
- this;
-
- String name = keepAttributeElement.name;
-
- if (name == null)
- {
- // Clear the list to keep all attributes.
- keepAttributes.clear();
- }
- else
- {
- // Add the attibute name to the list.
- keepAttributes.add(name);
- }
- }
-
-
- // Ant task attributes.
-
- public void setName(String name)
- {
- this.name = name;
- }
-}
diff --git a/src/proguard/ant/KeepSpecificationElement.java b/src/proguard/ant/KeepSpecificationElement.java
index 9bc2856..e36b744 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,7 +20,7 @@
*/
package proguard.ant;
-import proguard.KeepSpecification;
+import proguard.KeepClassSpecification;
import java.util.List;
@@ -53,8 +53,8 @@ public class KeepSpecificationElement extends ClassSpecificationElement
this.getClass().getName()) :
this;
- KeepSpecification keepSpecification =
- new KeepSpecification(markClasses,
+ KeepClassSpecification keepClassSpecification =
+ new KeepClassSpecification(markClasses,
markConditionally,
allowShrinking,
allowOptimization,
@@ -62,7 +62,7 @@ public class KeepSpecificationElement extends ClassSpecificationElement
createClassSpecification(keepSpecificationElement));
// Add it to the list.
- keepSpecifications.add(keepSpecification);
+ keepSpecifications.add(keepClassSpecification);
}
diff --git a/src/proguard/ant/MemberSpecificationElement.java b/src/proguard/ant/MemberSpecificationElement.java
index a52541e..d4bb4a9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ProGuardTask.java b/src/proguard/ant/ProGuardTask.java
index 0dbd1e3..b7fc361 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ import proguard.*;
import proguard.classfile.util.ClassUtil;
import java.io.*;
+import java.util.ArrayList;
/**
* This Task allows to configure and run ProGuard from Ant.
@@ -240,13 +241,13 @@ public class ProGuardTask extends ConfigurationTask
public void setNote(boolean note)
{
- configuration.note = note;
+ configuration.note = note ? null : new ArrayList();
}
public void setWarn(boolean warn)
{
- configuration.warn = warn;
+ configuration.warn = warn ? null : new ArrayList();
}
diff --git a/src/proguard/classfile/ClassConstants.java b/src/proguard/classfile/ClassConstants.java
index e873e1f..3b243e0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/ClassPool.java b/src/proguard/classfile/ClassPool.java
index 3ccc787..57728a5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/Clazz.java b/src/proguard/classfile/Clazz.java
index e279598..da37d9a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/Field.java b/src/proguard/classfile/Field.java
index 03fe5cd..ba1315a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 77d5f33..0a27593 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/LibraryField.java b/src/proguard/classfile/LibraryField.java
index 91b9070..2908c37 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 4dc29c2..41ccb60 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 17e6208..a49a5f1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 170b296..1400b9c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2131ca8..ebcae2b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 5b1333a..9d0fc0c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/ProgramField.java b/src/proguard/classfile/ProgramField.java
index 05b3b10..5991b00 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a81bf99..ea6f46d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 70e6b8c..943c3d6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a312767..e38f888 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0f46fbc..2e16e22 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/CodeAttribute.java b/src/proguard/classfile/attribute/CodeAttribute.java
index 4206105..92ff9ea 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a3b5793..3ae991e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 cd5b39a..4180950 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 4314865..9275b3a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 765c250..082efab 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2e91add..d22c4a6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/InnerClassesAttribute.java b/src/proguard/classfile/attribute/InnerClassesAttribute.java
index 15a5460..2f7e310 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 e8b7fc4..1bdd6c3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/LineNumberInfo.java b/src/proguard/classfile/attribute/LineNumberInfo.java
index cbd42aa..f58083a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -37,4 +37,14 @@ public class LineNumberInfo
public LineNumberInfo()
{
}
+
+
+ /**
+ * Creates an initialized LineNumberInfo.
+ */
+ public LineNumberInfo(int u2startPC, int u2lineNumber)
+ {
+ this.u2startPC = u2startPC;
+ this.u2lineNumber = u2lineNumber;
+ }
}
diff --git a/src/proguard/classfile/attribute/LineNumberTableAttribute.java b/src/proguard/classfile/attribute/LineNumberTableAttribute.java
index 4e3784d..4d507d9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 03bf668..4e54c22 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,31 @@ public class LocalVariableInfo
/**
+ * Creates an uninitialized LocalVariableInfo.
+ */
+ public LocalVariableInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableInfo.
+ */
+ public LocalVariableInfo(int u2startPC,
+ int u2length,
+ int u2nameIndex,
+ int u2descriptorIndex,
+ int u2index)
+ {
+ this.u2startPC = u2startPC;
+ this.u2length = u2length;
+ this.u2nameIndex = u2nameIndex;
+ this.u2descriptorIndex = u2descriptorIndex;
+ this.u2index = u2index;
+ }
+
+
+ /**
* Lets the referenced class accept the given visitor.
*/
public void referencedClassAccept(ClassVisitor classVisitor)
diff --git a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
index 445b15f..9c3f115 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 3f9a960..1b71f35 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +47,31 @@ public class LocalVariableTypeInfo
/**
+ * Creates an uninitialized LocalVariableTypeInfo.
+ */
+ public LocalVariableTypeInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableTypeInfo.
+ */
+ public LocalVariableTypeInfo(int u2startPC,
+ int u2length,
+ int u2nameIndex,
+ int u2signatureIndex,
+ int u2index)
+ {
+ this.u2startPC = u2startPC;
+ this.u2length = u2length;
+ this.u2nameIndex = u2nameIndex;
+ this.u2signatureIndex = u2signatureIndex;
+ this.u2index = u2index;
+ }
+
+
+ /**
* Applies the given visitor to all referenced classes.
*/
public void referencedClassesAccept(ClassVisitor classVisitor)
diff --git a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
index f037d2a..fd856fe 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 71844f3..c7585fe 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 bdad238..a26e8b1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 876eb60..24269b7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 af9fc44..6ccb1b5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 1c9a665..2f138bd 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 aa48e4d..41bb8e3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0bb2302..b378cd2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 59f888d..29129d0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2bd564d..8117077 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 8bc9148..25b8b9f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 91838b5..ba51641 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 4b54ad7..3ebe5e5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 543f2d0..39f8953 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 70c180a..d46bb7f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 672478a..3c700c8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 5948cc1..9c8180c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 55deb6b..7e41656 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 9141f3a..380c52e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 d2c6b4d..626fbda 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 412ebd7..bce7170 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 388fd0d..7a1d7c6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 d521b34..c206c16 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 bf11340..d869fd2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 73101f9..16b2a56 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0d5540a..112084a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 7f151d4..d574dcb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2d79cab..2f24720 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a4cc663..adf5684 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 fc72343..55e3abe 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 b60c3ca..fcc8e0a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2142d68..9b14dd6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 40af23c..881f188 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a993a0f..f35cefd 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 f414971..fbdeec7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 7b9d215..db6747b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 f51df42..64b17f5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 1a99d0f..db53ff1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2214ed7..aa3e1f2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 7818804..0cddf70 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c5176e6..bde8dda 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 564ac1d..dc4654f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 aa61dd1..a495f1f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a1adc3c..f33d511 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 1c09367..f8ef7e0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 518d4a8..7db246c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 669a28f..e9931f8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 8c327d0..61b0f1a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/attribute/visitor/AllExceptionInfoVisitor.java
similarity index 71%
copy from src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
copy to src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
index 32c507e..839e104 100644
--- a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,29 +18,28 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package proguard.classfile.instruction.visitor;
+package proguard.classfile.attribute.visitor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
/**
- * This AttributeVisitor lets a given InstructionVisitor visit all Instruction
+ * This AttributeVisitor lets a given ExceptionInfoVisitor visit all exceptions
* objects of the CodeAttribute objects it visits.
*
* @author Eric Lafortune
*/
-public class AllInstructionVisitor
+public class AllExceptionInfoVisitor
extends SimplifiedVisitor
implements AttributeVisitor
{
- private final InstructionVisitor instructionVisitor;
+ private final ExceptionInfoVisitor exceptionInfoVisitor;
- public AllInstructionVisitor(InstructionVisitor instructionVisitor)
+ public AllExceptionInfoVisitor(ExceptionInfoVisitor exceptionInfoVisitor)
{
- this.instructionVisitor = instructionVisitor;
+ this.exceptionInfoVisitor = exceptionInfoVisitor;
}
@@ -51,6 +50,6 @@ implements AttributeVisitor
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
- codeAttribute.instructionsAccept(clazz, method, instructionVisitor);
+ codeAttribute.exceptionsAccept(clazz, method, exceptionInfoVisitor);
}
}
diff --git a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
index d7ad85a..aa81ce0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/AttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
index d55c4d9..e8f226b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
index 2717aa7..7c85e53 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0191bbb..91267b0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 397b8f2..e59ed7b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 57901c9..8647cb3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 33a4f25..9ad38e0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a457a85..870ba94 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/RequiredAttributeFilter.java b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
index df88bed..92099f9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/StackSizeComputer.java b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
index 28750ef..401f188 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -276,7 +276,7 @@ implements AttributeVisitor,
/**
* Evaluates a block of instructions that hasn't been handled before,
- * starting at the given offset and ending a branch instruction, a return
+ * starting at the given offset and ending at a branch instruction, a return
* instruction, or a throw instruction. Branch instructions are handled
* recursively.
*/
diff --git a/src/proguard/classfile/constant/ClassConstant.java b/src/proguard/classfile/constant/ClassConstant.java
index 374affb..d217bf6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 11e6177..30ce5df 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 48cff3b..61779b5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 fd7b0ba..d4afce5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 399f0f9..578f567 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 760c856..8a476c6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2bac149..ddee42f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/LongConstant.java b/src/proguard/classfile/constant/LongConstant.java
index 2a8eb29..ea66e07 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/MethodrefConstant.java b/src/proguard/classfile/constant/MethodrefConstant.java
index 82cce97..858eec9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c224f36..e83d2f1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c6179ef..4e4d019 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0a4b3a9..9a8d453 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 ad677c7..ae419c9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,24 +32,22 @@ import java.io.UnsupportedEncodingException;
*/
public class Utf8Constant extends Constant
{
- private static final String ENCODING = "UTF-8";
-
private static final char TWO_BYTE_LIMIT = 0x80;
- private static final byte TWO_BYTE_CONSTANT1 = (byte)0xc0;
- private static final byte TWO_BYTE_CONSTANT2 = (byte)0x80;
+ private static final int TWO_BYTE_CONSTANT1 = 0xc0;
+ private static final int TWO_BYTE_CONSTANT2 = 0x80;
private static final int TWO_BYTE_SHIFT1 = 6;
- private static final byte TWO_BYTE_MASK1 = (byte)0x1f;
- private static final byte TWO_BYTE_MASK2 = (byte)0x3f;
+ private static final int TWO_BYTE_MASK1 = 0x1f;
+ private static final int TWO_BYTE_MASK2 = 0x3f;
private static final char THREE_BYTE_LIMIT = 0x800;
- private static final byte THREE_BYTE_CONSTANT1 = (byte)0xe0;
- private static final byte THREE_BYTE_CONSTANT2 = (byte)0x80;
- private static final byte THREE_BYTE_CONSTANT3 = (byte)0x80;
+ private static final int THREE_BYTE_CONSTANT1 = 0xe0;
+ private static final int THREE_BYTE_CONSTANT2 = 0x80;
+ private static final int THREE_BYTE_CONSTANT3 = 0x80;
private static final int THREE_BYTE_SHIFT1 = 12;
private static final int THREE_BYTE_SHIFT2 = 6;
- private static final byte THREE_BYTE_MASK1 = (byte)0x0f;
- private static final byte THREE_BYTE_MASK2 = (byte)0x3f;
- private static final byte THREE_BYTE_MASK3 = (byte)0x3f;
+ private static final int THREE_BYTE_MASK1 = 0x0f;
+ private static final int THREE_BYTE_MASK2 = 0x3f;
+ private static final int THREE_BYTE_MASK3 = 0x3f;
// There are a lot of Utf8Constant objects, so we're optimising their storage.
@@ -60,7 +58,7 @@ public class Utf8Constant extends Constant
//private int u2length;
private byte[] bytes;
- private String utf8string;
+ private String string;
/**
@@ -75,10 +73,10 @@ public class Utf8Constant extends Constant
/**
* Creates a Utf8Constant containing the given string.
*/
- public Utf8Constant(String utf8string)
+ public Utf8Constant(String string)
{
- this.bytes = null;
- this.utf8string = utf8string;
+ this.bytes = null;
+ this.string = string;
}
@@ -87,8 +85,8 @@ public class Utf8Constant extends Constant
*/
public void setBytes(byte[] bytes)
{
- this.bytes = bytes;
- this.utf8string = null;
+ this.bytes = bytes;
+ this.string = null;
}
@@ -99,12 +97,14 @@ public class Utf8Constant extends Constant
{
try
{
- return getByteArrayRepresentation();
+ switchToByteArrayRepresentation();
}
catch (UnsupportedEncodingException ex)
{
throw new RuntimeException(ex.getMessage());
}
+
+ return bytes;
}
@@ -113,8 +113,8 @@ public class Utf8Constant extends Constant
*/
public void setString(String utf8String)
{
- this.bytes = null;
- this.utf8string = utf8String;
+ this.bytes = null;
+ this.string = utf8String;
}
@@ -132,9 +132,10 @@ public class Utf8Constant extends Constant
throw new RuntimeException(ex.getMessage());
}
- return utf8string;
+ return string;
}
+
// Implementations for Constant.
public int getTag()
@@ -148,42 +149,49 @@ public class Utf8Constant extends Constant
}
+ // Small utility methods.
+
/**
- * Switches to a String representation of the UTF-8 data.
+ * Switches to a byte array representation of the UTF-8 data.
*/
- private void switchToStringRepresentation() throws UnsupportedEncodingException
+ private void switchToByteArrayRepresentation() throws UnsupportedEncodingException
{
- if (utf8string == null)
+ if (bytes == null)
{
- utf8string = new String(bytes, ENCODING);
- bytes = null;
+ bytes = getByteArrayRepresentation(string);
+ string = null;
}
}
/**
- * Transforms UTF-8 bytes to the slightly modified UTF-8 representation that
- * is used by classes.
+ * Switches to a String representation of the UTF-8 data.
*/
- private byte[] getByteArrayRepresentation() throws UnsupportedEncodingException
+ private void switchToStringRepresentation() throws UnsupportedEncodingException
{
- // Do we still have the byte array representation?
- if (bytes != null)
+ if (string == null)
{
- // Then return that one.
- return bytes;
+ string = getStringRepresentation(bytes);
+ bytes = null;
}
+ }
+
+ /**
+ * Returns the modified UTF-8 byte array representation of the given string.
+ */
+ private byte[] getByteArrayRepresentation(String string) throws UnsupportedEncodingException
+ {
// We're computing the byte array ourselves, because the implementation
// of String.getBytes("UTF-8") has a bug, at least up to JRE 1.4.2.
// Also note the special treatment of the 0 character.
// Compute the byte array length.
int byteLength = 0;
- int stringLength = utf8string.length();
+ int stringLength = string.length();
for (int stringIndex = 0; stringIndex < stringLength; stringIndex++)
{
- char c = utf8string.charAt(stringIndex);
+ char c = string.charAt(stringIndex);
// The character is represented by one, two, or three bytes.
byteLength += c == 0 ? 2 :
@@ -199,12 +207,12 @@ public class Utf8Constant extends Constant
int byteIndex = 0;
for (int stringIndex = 0; stringIndex < stringLength; stringIndex++)
{
- char c = utf8string.charAt(stringIndex);
+ char c = string.charAt(stringIndex);
if (c == 0)
{
// The 0 character gets a two-byte representation in classes.
- bytes[byteIndex++] = TWO_BYTE_CONSTANT1;
- bytes[byteIndex++] = TWO_BYTE_CONSTANT2;
+ bytes[byteIndex++] = (byte)TWO_BYTE_CONSTANT1;
+ bytes[byteIndex++] = (byte)TWO_BYTE_CONSTANT2;
}
else if (c < TWO_BYTE_LIMIT)
{
@@ -228,4 +236,50 @@ public class Utf8Constant extends Constant
return bytes;
}
+
+
+ /**
+ * Returns the String representation of the given modified UTF-8 byte array.
+ */
+ private String getStringRepresentation(byte[] bytes) throws UnsupportedEncodingException
+ {
+ // We're computing the string ourselves, because the implementation
+ // of "new String(bytes)" doesn't honor the special treatment of
+ // the 0 character in JRE 1.6_u11.
+
+ // Allocate the byte array with the computed length.
+ char[] chars = new char[bytes.length];
+
+ // Fill out the array.
+ int charIndex = 0;
+ int byteIndex = 0;
+ while (byteIndex < bytes.length)
+ {
+
+ int b = bytes[byteIndex++] & 0xff;
+
+ // Depending on the flag bits in the first byte, the character
+ // is represented by a single byte, by two bytes, or by three
+ // bytes. We're not checking the redundant flag bits in the
+ // second byte and the third byte.
+ try
+ {
+ chars[charIndex++] =
+ (char)(b < TWO_BYTE_CONSTANT1 ? b :
+
+ b < THREE_BYTE_CONSTANT1 ? ((b & TWO_BYTE_MASK1) << TWO_BYTE_SHIFT1) |
+ ((bytes[byteIndex++] & TWO_BYTE_MASK2) ) :
+
+ ((b & THREE_BYTE_MASK1) << THREE_BYTE_SHIFT1) |
+ ((bytes[byteIndex++] & THREE_BYTE_MASK2) << THREE_BYTE_SHIFT2) |
+ ((bytes[byteIndex++] & THREE_BYTE_MASK3) ));
+ }
+ catch (ArrayIndexOutOfBoundsException e)
+ {
+ throw new UnsupportedEncodingException("Missing UTF-8 bytes after initial byte [0x"+Integer.toHexString(b)+"] in string ["+new String(chars, 0, charIndex)+"]");
+ }
+ }
+
+ return new String(chars, 0, charIndex);
+ }
}
diff --git a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java b/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
index 3530660..d2d3c2c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ConstantVisitor.java b/src/proguard/classfile/constant/visitor/ConstantVisitor.java
index 6c7a851..6cae352 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ExceptClassConstantFilter.java b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
index fc823c8..fbb3e52 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/AccessFixer.java b/src/proguard/classfile/editor/AccessFixer.java
index 786e241..7d6274e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/AnnotationAdder.java b/src/proguard/classfile/editor/AnnotationAdder.java
index 92ae382..359164a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,7 +27,8 @@ import proguard.classfile.util.SimplifiedVisitor;
/**
* This AnnotationVisitor adds all annotations that it visits to the given
- * target annotation element value or target annotation attribute.
+ * target annotation element value, target annotation attribute, or target
+ * parameter annotation attribute.
*
* @author Eric Lafortune
*/
@@ -38,11 +39,12 @@ implements AnnotationVisitor
private static final ElementValue[] EMPTY_ELEMENT_VALUES = new ElementValue[0];
- private final ProgramClass targetClass;
- private final AnnotationElementValue targetAnnotationElementValue;
+ private final ProgramClass targetClass;
+ private final AnnotationElementValue targetAnnotationElementValue;
+ private final AnnotationsAttributeEditor annotationsAttributeEditor;
+ private final ParameterAnnotationsAttributeEditor parameterAnnotationsAttributeEditor;
- private final ConstantAdder constantAdder;
- private final AnnotationsAttributeEditor annotationsAttributeEditor;
+ private final ConstantAdder constantAdder;
/**
@@ -52,26 +54,44 @@ implements AnnotationVisitor
public AnnotationAdder(ProgramClass targetClass,
AnnotationElementValue targetAnnotationElementValue)
{
- this.targetClass = targetClass;
- this.targetAnnotationElementValue = targetAnnotationElementValue;
+ this.targetClass = targetClass;
+ this.targetAnnotationElementValue = targetAnnotationElementValue;
+ this.annotationsAttributeEditor = null;
+ this.parameterAnnotationsAttributeEditor = null;
- constantAdder = new ConstantAdder(targetClass);
- annotationsAttributeEditor = null;
+ constantAdder = new ConstantAdder(targetClass);
}
/**
* Creates a new AnnotationAdder that will copy annotations into the given
- * target annotation.
+ * target annotations attribute.
*/
public AnnotationAdder(ProgramClass targetClass,
AnnotationsAttribute targetAnnotationsAttribute)
{
- this.targetClass = targetClass;
- this.targetAnnotationElementValue = null;
+ this.targetClass = targetClass;
+ this.targetAnnotationElementValue = null;
+ this.annotationsAttributeEditor = new AnnotationsAttributeEditor(targetAnnotationsAttribute);
+ this.parameterAnnotationsAttributeEditor = null;
- constantAdder = new ConstantAdder(targetClass);
- annotationsAttributeEditor = new AnnotationsAttributeEditor(targetAnnotationsAttribute);
+ constantAdder = new ConstantAdder(targetClass);
+ }
+
+
+ /**
+ * Creates a new AnnotationAdder that will copy annotations into the given
+ * target parameter annotations attribute.
+ */
+ public AnnotationAdder(ProgramClass targetClass,
+ ParameterAnnotationsAttribute targetParameterAnnotationsAttribute)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotationElementValue = null;
+ this.annotationsAttributeEditor = null;
+ this.parameterAnnotationsAttributeEditor = new ParameterAnnotationsAttributeEditor(targetParameterAnnotationsAttribute);
+
+ constantAdder = new ConstantAdder(targetClass);
}
@@ -111,6 +131,23 @@ implements AnnotationVisitor
public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
{
- // TODO: Handle parameter annotations.
+ Annotation newAnnotation =
+ new Annotation(constantAdder.addConstant(clazz, annotation.u2typeIndex),
+ 0,
+ annotation.u2elementValuesCount > 0 ?
+ new ElementValue[annotation.u2elementValuesCount] :
+ EMPTY_ELEMENT_VALUES);
+
+ // TODO: Clone array.
+ newAnnotation.referencedClasses = annotation.referencedClasses;
+
+ // Add the element values.
+ annotation.elementValuesAccept(clazz,
+ new ElementValueAdder(targetClass,
+ newAnnotation,
+ false));
+
+ // Add the completed annotation.
+ parameterAnnotationsAttributeEditor.addAnnotation(parameterIndex, newAnnotation);
}
}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
index a579ff7..bf8852c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 004019f..2b610b7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,13 +256,17 @@ implements AttributeVisitor
CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength + 32);
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
// Add the instructions.
codeAttribute.instructionsAccept(clazz,
method,
new InstructionAdder(targetClass,
codeAttributeComposer));
+
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+
// Add the exceptions.
codeAttribute.exceptionsAccept(clazz,
method,
@@ -303,19 +307,58 @@ implements AttributeVisitor
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
- // TODO: Implement method.
+ // Create a new line number table attribute.
+ LineNumberTableAttribute newLineNumberTableAttribute =
+ new LineNumberTableAttribute(constantAdder.addConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex),
+ 0,
+ new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]);
+
+ // Add the line numbers.
+ lineNumberTableAttribute.lineNumbersAccept(clazz,
+ method,
+ codeAttribute,
+ new LineNumberInfoAdder(newLineNumberTableAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newLineNumberTableAttribute);
}
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
{
- // TODO: Implement method.
+ // Create a new local variable table attribute.
+ LocalVariableTableAttribute newLocalVariableTableAttribute =
+ new LocalVariableTableAttribute(constantAdder.addConstant(clazz, localVariableTableAttribute.u2attributeNameIndex),
+ 0,
+ new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]);
+
+ // Add the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz,
+ method,
+ codeAttribute,
+ new LocalVariableInfoAdder(targetClass, newLocalVariableTableAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newLocalVariableTableAttribute);
}
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
{
- // TODO: Implement method.
+ // Create a new local variable type table attribute.
+ LocalVariableTypeTableAttribute newLocalVariableTypeTableAttribute =
+ new LocalVariableTypeTableAttribute(constantAdder.addConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex),
+ 0,
+ new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]);
+
+ // Add the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz,
+ method,
+ codeAttribute,
+ new LocalVariableTypeInfoAdder(targetClass, newLocalVariableTypeTableAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newLocalVariableTypeTableAttribute);
}
@@ -357,13 +400,41 @@ implements AttributeVisitor
public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
{
- // TODO: Implement method.
+ // Create a new annotations attribute.
+ RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute =
+ new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex),
+ 0,
+ new int[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount],
+ new Annotation[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount][]);
+
+ // Add the annotations.
+ runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz,
+ method,
+ new AnnotationAdder(targetClass,
+ newParameterAnnotationsAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newParameterAnnotationsAttribute);
}
public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
{
- // TODO: Implement method.
+ // Create a new annotations attribute.
+ RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute =
+ new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex),
+ 0,
+ new int[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount],
+ new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount][]);
+
+ // Add the annotations.
+ runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz,
+ method,
+ new AnnotationAdder(targetClass,
+ newParameterAnnotationsAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newParameterAnnotationsAttribute);
}
diff --git a/src/proguard/classfile/editor/AttributeSorter.java b/src/proguard/classfile/editor/AttributeSorter.java
index 4e24d5a..d8e3367 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 efd681e..10846cc 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ClassEditor.java b/src/proguard/classfile/editor/ClassEditor.java
index 9887600..e503ea3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 df250f7..3256c88 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 66de832..f31fcd0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 34624f6..9857903 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 d810403..e783203 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,9 +69,9 @@ implements AttributeVisitor,
private final int[] codeFragmentOffsets = new int[MAXIMUM_LEVELS];
private final int[] codeFragmentLengths = new int[MAXIMUM_LEVELS];
- private final int[][] instructionOffsetMap = new int[MAXIMUM_LEVELS][ClassConstants.TYPICAL_CODE_LENGTH];
+ private final int[][] instructionOffsetMap = new int[MAXIMUM_LEVELS][ClassConstants.TYPICAL_CODE_LENGTH + 1];
- private ExceptionInfo[] exceptionTable = new ExceptionInfo[ClassConstants.TYPICAL_EXCEPTION_TABLE_LENGTH];
+ private ExceptionInfo[] exceptionTable = new ExceptionInfo[ClassConstants.TYPICAL_EXCEPTION_TABLE_LENGTH];
private int expectedStackMapFrameOffset;
@@ -136,16 +136,8 @@ implements AttributeVisitor,
// Make sure there is sufficient space for adding the code fragment.
maximumCodeLength += maximumCodeFragmentLength;
- if (code.length < maximumCodeLength)
- {
- byte[] newCode = new byte[maximumCodeLength];
- System.arraycopy(code, 0, newCode, 0, codeLength);
- code = newCode;
- int[] newOldInstructionOffsets = new int[maximumCodeLength];
- System.arraycopy(oldInstructionOffsets, 0, newOldInstructionOffsets, 0, codeLength);
- oldInstructionOffsets = newOldInstructionOffsets;
- }
+ ensureCodeLength(maximumCodeLength);
// Try to reuse the previous array for this code fragment.
if (instructionOffsetMap[level].length <= maximumCodeFragmentLength)
@@ -180,6 +172,11 @@ implements AttributeVisitor,
println("["+codeLength+"] <- ", instruction.toString(oldInstructionOffset));
}
+ // Make sure the code array is large enough.
+ int newCodeLength = codeLength + instruction.length(codeLength);
+
+ ensureCodeLength(newCodeLength);
+
// Remember the old offset of the appended instruction.
oldInstructionOffsets[codeLength] = oldInstructionOffset;
@@ -195,7 +192,7 @@ implements AttributeVisitor,
instructionOffsetMap[level][oldInstructionOffset] = codeLength;
// Continue appending at the next instruction offset.
- codeLength += instruction.length(codeLength);
+ codeLength = newCodeLength;
}
@@ -316,7 +313,7 @@ implements AttributeVisitor,
int handlerPC = -exceptionInfo.u2handlerPC;
if (handlerPC > 0)
{
- if (instructionOffsetMap[level][handlerPC] < codeLength)
+ if (remappableInstructionOffset(handlerPC))
{
exceptionInfo.u2handlerPC = remapInstructionOffset(handlerPC);
}
@@ -492,10 +489,10 @@ implements AttributeVisitor,
// handlers are negated, in order to mark them as external.
int handlerPC = exceptionInfo.u2handlerPC;
exceptionInfo.u2handlerPC =
- allowExternalExceptionHandlers &&
- instructionOffsetMap[level][handlerPC] >= codeLength ?
- -handlerPC :
- remapInstructionOffset(handlerPC);
+ !allowExternalExceptionHandlers ||
+ remappableInstructionOffset(handlerPC) ?
+ remapInstructionOffset(handlerPC) :
+ -handlerPC;
}
@@ -603,6 +600,27 @@ implements AttributeVisitor,
// Small utility methods.
/**
+ * Make sure the code arrays have at least the given size.
+ */
+ private void ensureCodeLength(int newCodeLength)
+ {
+ if (code.length < newCodeLength)
+ {
+ // Add 20% to avoid extending the arrays too often.
+ newCodeLength = newCodeLength * 6 / 5;
+
+ byte[] newCode = new byte[newCodeLength];
+ System.arraycopy(code, 0, newCode, 0, codeLength);
+ code = newCode;
+
+ int[] newOldInstructionOffsets = new int[newCodeLength];
+ System.arraycopy(oldInstructionOffsets, 0, newOldInstructionOffsets, 0, codeLength);
+ oldInstructionOffsets = newOldInstructionOffsets;
+ }
+ }
+
+
+ /**
* Adjusts the given jump offsets for the instruction at the given offset.
*/
private void remapJumpOffsets(int offset, int[] jumpOffsets)
@@ -656,6 +674,17 @@ implements AttributeVisitor,
/**
+ * Returns whether the given old instruction offset can be remapped at the
+ */
+ private boolean remappableInstructionOffset(int oldInstructionOffset)
+ {
+ return
+ oldInstructionOffset <= codeFragmentLengths[level] &&
+ instructionOffsetMap[level][oldInstructionOffset] > INVALID;
+ }
+
+
+ /**
* Returns the given list of exceptions, without the ones that have empty
* code blocks.
*/
@@ -798,12 +827,12 @@ implements AttributeVisitor,
{
CodeAttributeComposer composer = new CodeAttributeComposer();
- composer.beginCodeFragment(10);
+ composer.beginCodeFragment(4);
composer.appendInstruction(0, new SimpleInstruction(InstructionConstants.OP_ICONST_0));
composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ISTORE, 0));
composer.appendInstruction(2, new BranchInstruction(InstructionConstants.OP_GOTO, 1));
- composer.beginCodeFragment(10);
+ composer.beginCodeFragment(4);
composer.appendInstruction(0, new VariableInstruction(InstructionConstants.OP_IINC, 0, 1));
composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ILOAD, 0));
composer.appendInstruction(2, new SimpleInstruction(InstructionConstants.OP_ICONST_5));
diff --git a/src/proguard/classfile/editor/CodeAttributeEditor.java b/src/proguard/classfile/editor/CodeAttributeEditor.java
index dc7915c..9658c98 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ 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;
/**
* This AttributeVisitor accumulates specified changes to code, and then applies
@@ -142,6 +143,28 @@ implements AttributeVisitor,
/**
+ * Remembers to place the given instructions right before the instruction
+ * at the given offset.
+ * @param instructionOffset the offset of the instruction.
+ * @param instructions the new instructions.
+ */
+ public void insertBeforeInstruction(int instructionOffset, Instruction[] instructions)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ preInsertions[instructionOffset] = new CompositeInstruction(instructions);
+
+ modified = true;
+ simple = false;
+
+ }
+
+
+ /**
* Remembers to replace the instruction at the given offset by the given
* instruction.
* @param instructionOffset the offset of the instruction to be replaced.
@@ -162,6 +185,26 @@ implements AttributeVisitor,
/**
+ * Remembers to replace the instruction at the given offset by the given
+ * instructions.
+ * @param instructionOffset the offset of the instruction to be replaced.
+ * @param instructions the new instructions.
+ */
+ public void replaceInstruction(int instructionOffset, Instruction[] instructions)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ replacements[instructionOffset] = new CompositeInstruction(instructions);
+
+ modified = true;
+ }
+
+
+ /**
* Remembers to place the given instruction right after the instruction
* at the given offset.
* @param instructionOffset the offset of the instruction.
@@ -183,6 +226,27 @@ implements AttributeVisitor,
/**
+ * Remembers to place the given instructions right after the instruction
+ * at the given offset.
+ * @param instructionOffset the offset of the instruction.
+ * @param instructions the new instructions.
+ */
+ public void insertAfterInstruction(int instructionOffset, Instruction[] instructions)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ postInsertions[instructionOffset] = new CompositeInstruction(instructions);
+
+ modified = true;
+ simple = false;
+ }
+
+
+ /**
* Remembers to delete the instruction at the given offset.
* @param instructionOffset the offset of the instruction to be deleted.
*/
@@ -610,15 +674,13 @@ implements AttributeVisitor,
Instruction preInstruction = preInsertions[oldOffset];
if (preInstruction != null)
{
- // Remap the instruction.
- preInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
-
if (DEBUG)
{
System.out.println(" Pre-inserted "+preInstruction.toString(newOffset));
}
- newOffset += preInstruction.length(newOffset);
+ // Remap the instruction.
+ preInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
// Remap and insert the replacement instruction, or the current
@@ -626,42 +688,35 @@ implements AttributeVisitor,
Instruction replacementInstruction = replacements[oldOffset];
if (replacementInstruction != null)
{
- // Remap the instruction.
- replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
-
if (DEBUG)
{
System.out.println(" Replaced "+replacementInstruction.toString(newOffset));
}
-
- newOffset += replacementInstruction.length(newOffset);
+ // Remap the instruction.
+ replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
else if (!deleted[oldOffset])
{
- // Remap the instruction.
- instruction.accept(clazz, method, codeAttribute, oldOffset, this);
-
if (DEBUG)
{
System.out.println(" Copied "+instruction.toString(newOffset));
}
- newOffset += instruction.length(newOffset);
+ // Remap the instruction.
+ instruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
// Remap and insert the post-inserted instruction, if any.
Instruction postInstruction = postInsertions[oldOffset];
if (postInstruction != null)
{
- // Remap the instruction.
- postInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
-
if (DEBUG)
{
System.out.println(" Post-inserted "+postInstruction.toString(newOffset));
}
- newOffset += postInstruction.length(newOffset);
+ // Remap the instruction.
+ postInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
}
@@ -676,6 +731,8 @@ implements AttributeVisitor,
codeAttribute,
newOffset,
simpleInstruction);
+
+ newOffset += simpleInstruction.length(newOffset);
}
@@ -687,6 +744,8 @@ implements AttributeVisitor,
codeAttribute,
newOffset,
constantInstruction);
+
+ newOffset += constantInstruction.length(newOffset);
}
@@ -698,6 +757,8 @@ implements AttributeVisitor,
codeAttribute,
newOffset,
variableInstruction);
+
+ newOffset += variableInstruction.length(newOffset);
}
@@ -713,6 +774,8 @@ implements AttributeVisitor,
codeAttribute,
newOffset,
branchInstruction);
+
+ newOffset += branchInstruction.length(newOffset);
}
@@ -732,6 +795,8 @@ implements AttributeVisitor,
codeAttribute,
newOffset,
tableSwitchInstruction);
+
+ newOffset += tableSwitchInstruction.length(newOffset);
}
@@ -751,6 +816,8 @@ implements AttributeVisitor,
codeAttribute,
newOffset,
lookUpSwitchInstruction);
+
+ newOffset += lookUpSwitchInstruction.length(newOffset);
}
@@ -996,4 +1063,101 @@ implements AttributeVisitor,
return newIndex;
}
+
+
+ private class CompositeInstruction
+ extends Instruction
+ {
+ private Instruction[] instructions;
+
+
+ private CompositeInstruction(Instruction[] instructions)
+ {
+ this.instructions = instructions;
+ }
+
+
+ // Implementations for Instruction.
+
+ public Instruction shrink()
+ {
+ for (int index = 0; index < instructions.length; index++)
+ {
+ instructions[index] = instructions[index].shrink();
+ }
+
+ return this;
+ }
+
+
+ public void write(byte[] code, int offset)
+ {
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+
+ instruction.write(code, offset);
+
+ offset += instruction.length(offset);
+ }
+ }
+
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ throw new UnsupportedOperationException("Can't read composite instruction");
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ throw new UnsupportedOperationException("Can't write composite instruction");
+ }
+
+
+ public int length(int offset)
+ {
+ int newOffset = offset;
+
+ for (int index = 0; index < instructions.length; index++)
+ {
+ newOffset += instructions[index].length(newOffset);
+ }
+
+ return newOffset - offset;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ if (instructionVisitor != CodeAttributeEditor.this)
+ {
+ throw new UnsupportedOperationException("Unexpected visitor ["+instructionVisitor+"]");
+ }
+
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+
+ instruction.accept(clazz, method, codeAttribute, offset, CodeAttributeEditor.this);
+
+ offset += instruction.length(offset);
+ }
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ StringBuffer stringBuffer = new StringBuffer();
+
+ for (int index = 0; index < instructions.length; index++)
+ {
+ stringBuffer.append(instructions[index].toString()).append("; ");
+ }
+
+ return stringBuffer.toString();
+ }
+ }
}
diff --git a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
index 53b0a73..9962ea5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 21a8f0b..bb81221 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ConstantAdder.java b/src/proguard/classfile/editor/ConstantAdder.java
index e2b620d..2b74f5f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ConstantPoolEditor.java b/src/proguard/classfile/editor/ConstantPoolEditor.java
index 509963e..8663dee 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ConstantPoolRemapper.java b/src/proguard/classfile/editor/ConstantPoolRemapper.java
index 33c4d9f..7430d3d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ConstantPoolSorter.java b/src/proguard/classfile/editor/ConstantPoolSorter.java
index 2828e7f..faae318 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ElementValueAdder.java b/src/proguard/classfile/editor/ElementValueAdder.java
index dbf5aa2..8cbd11d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 +85,6 @@ implements ElementValueVisitor
ArrayElementValue targetArrayElementValue,
boolean replaceElementValues)
{
-System.out.println("ElementValueAdder.ElementValueAdder "+targetClass.getName());
this.targetClass = targetClass;
this.targetAnnotationDefaultAttribute = null;
diff --git a/src/proguard/classfile/editor/ElementValuesEditor.java b/src/proguard/classfile/editor/ElementValuesEditor.java
index 5e06768..bfc4e9f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 48decfe..1ccb1a6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 b1c55ae..e0cc9c5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 08daa0b..4509a9a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/InstructionAdder.java b/src/proguard/classfile/editor/InstructionAdder.java
index ffd3d81..60fde6d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c7e3010..d842358 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 881b034..e095af6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 30a86da..6521369 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/InterfacesEditor.java b/src/proguard/classfile/editor/InterfacesEditor.java
index fb35ec9..d3170e1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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
new file mode 100644
index 0000000..aa8c0c4
--- /dev/null
+++ b/src/proguard/classfile/editor/LineNumberInfoAdder.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.attribute.visitor.LineNumberInfoVisitor;
+import proguard.classfile.attribute.*;
+import proguard.classfile.*;
+
+/**
+ * This LineNumberInfoVisitor adds all line numbers that it visits to the given
+ * target line number attribute.
+ */
+public class LineNumberInfoAdder
+implements LineNumberInfoVisitor
+{
+ private final LineNumberTableAttributeEditor lineNumberTableAttributeEditor;
+
+
+ /**
+ * Creates a new LineNumberInfoAdder that will copy line numbers into the
+ * given target line number table.
+ */
+ public LineNumberInfoAdder(LineNumberTableAttribute targetLineNumberTableAttribute)
+ {
+ this.lineNumberTableAttributeEditor = new LineNumberTableAttributeEditor(targetLineNumberTableAttribute);
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ // Create a new line number.
+ LineNumberInfo newLineNumberInfo =
+ new LineNumberInfo(lineNumberInfo.u2startPC,
+ lineNumberInfo.u2lineNumber);
+
+ // Add it to the target.
+ lineNumberTableAttributeEditor.addLineNumberInfo(newLineNumberInfo);
+ }
+}
diff --git a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
new file mode 100644
index 0000000..ab96b38
--- /dev/null
+++ b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.attribute.*;
+
+/**
+ * This class can add line numbers to a given line number table attribute.
+ * Line numbers to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class LineNumberTableAttributeEditor
+{
+ private LineNumberTableAttribute targetLineNumberTableAttribute;
+
+
+ /**
+ * Creates a new LineNumberTableAttributeEditor that will edit line numbers
+ * in the given line number table attribute.
+ */
+ public LineNumberTableAttributeEditor(LineNumberTableAttribute targetLineNumberTableAttribute)
+ {
+ this.targetLineNumberTableAttribute = targetLineNumberTableAttribute;
+ }
+
+
+ /**
+ * Adds a given line number to the line number table attribute.
+ */
+ public void addLineNumberInfo(LineNumberInfo lineNumberInfo)
+ {
+ int lineNumberTableLength = targetLineNumberTableAttribute.u2lineNumberTableLength;
+ LineNumberInfo[] lineNumberTable = targetLineNumberTableAttribute.lineNumberTable;
+
+ // Make sure there is enough space for the new lineNumberInfo.
+ if (lineNumberTable.length <= lineNumberTableLength)
+ {
+ targetLineNumberTableAttribute.lineNumberTable = new LineNumberInfo[lineNumberTableLength+1];
+ System.arraycopy(lineNumberTable, 0,
+ targetLineNumberTableAttribute.lineNumberTable, 0,
+ lineNumberTableLength);
+ lineNumberTable = targetLineNumberTableAttribute.lineNumberTable;
+ }
+
+ // Add the lineNumberInfo.
+ lineNumberTable[targetLineNumberTableAttribute.u2lineNumberTableLength++] = lineNumberInfo;
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/LocalVariableInfoAdder.java b/src/proguard/classfile/editor/LocalVariableInfoAdder.java
new file mode 100644
index 0000000..f285e4f
--- /dev/null
+++ b/src/proguard/classfile/editor/LocalVariableInfoAdder.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.attribute.visitor.LocalVariableInfoVisitor;
+import proguard.classfile.attribute.*;
+import proguard.classfile.*;
+
+/**
+ * This LocalVariableInfoVisitor adds all line numbers that it visits to the given
+ * target line number attribute.
+ */
+public class LocalVariableInfoAdder
+implements LocalVariableInfoVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final LocalVariableTableAttributeEditor localVariableTableAttributeEditor;
+
+
+ /**
+ * Creates a new LocalVariableInfoAdder that will copy line numbers into the
+ * given target line number table.
+ */
+ public LocalVariableInfoAdder(ProgramClass targetClass,
+ LocalVariableTableAttribute targetLocalVariableTableAttribute)
+ {
+ this.constantAdder = new ConstantAdder(targetClass);
+ this.localVariableTableAttributeEditor = new LocalVariableTableAttributeEditor(targetLocalVariableTableAttribute);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Create a new line number.
+ LocalVariableInfo newLocalVariableInfo =
+ new LocalVariableInfo(localVariableInfo.u2startPC,
+ localVariableInfo.u2length,
+ constantAdder.addConstant(clazz, localVariableInfo.u2nameIndex),
+ constantAdder.addConstant(clazz, localVariableInfo.u2descriptorIndex),
+ localVariableInfo.u2index);
+
+ newLocalVariableInfo.referencedClass = localVariableInfo.referencedClass;
+
+ // Add it to the target.
+ localVariableTableAttributeEditor.addLocalVariableInfo(newLocalVariableInfo);
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
new file mode 100644
index 0000000..053b628
--- /dev/null
+++ b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.attribute.*;
+
+/**
+ * This class can add local variables to a given local variable table attribute.
+ * Local variables to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTableAttributeEditor
+{
+ private LocalVariableTableAttribute targetLocalVariableTableAttribute;
+
+
+ /**
+ * Creates a new LocalVariableTableAttributeEditor that will edit line numbers
+ * in the given line number table attribute.
+ */
+ public LocalVariableTableAttributeEditor(LocalVariableTableAttribute targetLocalVariableTableAttribute)
+ {
+ this.targetLocalVariableTableAttribute = targetLocalVariableTableAttribute;
+ }
+
+
+ /**
+ * Adds a given line number to the line number table attribute.
+ */
+ public void addLocalVariableInfo(LocalVariableInfo localVariableInfo)
+ {
+ int localVariableTableLength = targetLocalVariableTableAttribute.u2localVariableTableLength;
+ LocalVariableInfo[] localVariableTable = targetLocalVariableTableAttribute.localVariableTable;
+
+ // Make sure there is enough space for the new localVariableInfo.
+ if (localVariableTable.length <= localVariableTableLength)
+ {
+ targetLocalVariableTableAttribute.localVariableTable = new LocalVariableInfo[localVariableTableLength+1];
+ System.arraycopy(localVariableTable, 0,
+ targetLocalVariableTableAttribute.localVariableTable, 0,
+ localVariableTableLength);
+ localVariableTable = targetLocalVariableTableAttribute.localVariableTable;
+ }
+
+ // Add the localVariableInfo.
+ localVariableTable[targetLocalVariableTableAttribute.u2localVariableTableLength++] = localVariableInfo;
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
new file mode 100644
index 0000000..ca50f3f
--- /dev/null
+++ b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.attribute.visitor.LocalVariableTypeInfoVisitor;
+import proguard.classfile.attribute.*;
+import proguard.classfile.*;
+
+/**
+ * This LocalVariableTypeInfoVisitor adds all line numbers that it visits to the given
+ * target line number attribute.
+ */
+public class LocalVariableTypeInfoAdder
+implements LocalVariableTypeInfoVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final LocalVariableTypeTableAttributeEditor localVariableTypeTableAttributeEditor;
+
+
+ /**
+ * Creates a new LocalVariableTypeInfoAdder that will copy line numbers into the
+ * given target line number table.
+ */
+ public LocalVariableTypeInfoAdder(ProgramClass targetClass,
+ LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute)
+ {
+ this.constantAdder = new ConstantAdder(targetClass);
+ this.localVariableTypeTableAttributeEditor = new LocalVariableTypeTableAttributeEditor(targetLocalVariableTypeTableAttribute);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Create a new line number.
+ LocalVariableTypeInfo newLocalVariableTypeInfo =
+ new LocalVariableTypeInfo(localVariableTypeInfo.u2startPC,
+ localVariableTypeInfo.u2length,
+ constantAdder.addConstant(clazz, localVariableTypeInfo.u2nameIndex),
+ constantAdder.addConstant(clazz, localVariableTypeInfo.u2signatureIndex),
+ localVariableTypeInfo.u2index);
+
+ // TODO: Clone array.
+ newLocalVariableTypeInfo.referencedClasses = localVariableTypeInfo.referencedClasses;
+
+ // Add it to the target.
+ localVariableTypeTableAttributeEditor.addLocalVariableTypeInfo(newLocalVariableTypeInfo);
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
new file mode 100644
index 0000000..fe5a64d
--- /dev/null
+++ b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.attribute.*;
+
+/**
+ * This class can add local variables to a given local variable type table
+ * attribute.
+ * Local variable types to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTypeTableAttributeEditor
+{
+ private LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute;
+
+
+ /**
+ * Creates a new LocalVariableTypeTableAttributeEditor that will edit line numbers
+ * in the given line number table attribute.
+ */
+ public LocalVariableTypeTableAttributeEditor(LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute)
+ {
+ this.targetLocalVariableTypeTableAttribute = targetLocalVariableTypeTableAttribute;
+ }
+
+
+ /**
+ * Adds a given line number to the line number table attribute.
+ */
+ public void addLocalVariableTypeInfo(LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ int localVariableTypeTableLength = targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength;
+ LocalVariableTypeInfo[] localVariableTypeTable = targetLocalVariableTypeTableAttribute.localVariableTypeTable;
+
+ // Make sure there is enough space for the new localVariableTypeInfo.
+ if (localVariableTypeTable.length <= localVariableTypeTableLength)
+ {
+ targetLocalVariableTypeTableAttribute.localVariableTypeTable = new LocalVariableTypeInfo[localVariableTypeTableLength+1];
+ System.arraycopy(localVariableTypeTable, 0,
+ targetLocalVariableTypeTableAttribute.localVariableTypeTable, 0,
+ localVariableTypeTableLength);
+ localVariableTypeTable = targetLocalVariableTypeTableAttribute.localVariableTypeTable;
+ }
+
+ // Add the localVariableTypeInfo.
+ localVariableTypeTable[targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength++] = localVariableTypeInfo;
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java
index c2083af..5f939bb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -139,6 +139,7 @@ implements MemberVisitor
EMPTY_ATTRIBUTES,
programField.referencedClass);
+ // Link to its visitor info.
newProgramField.setVisitorInfo(programField);
// Copy its attributes.
@@ -228,6 +229,7 @@ implements MemberVisitor
(Clazz[])programMethod.referencedClasses.clone() :
null);
+ // Link to its visitor info.
newProgramMethod.setVisitorInfo(programMethod);
// Copy its attributes.
diff --git a/src/proguard/classfile/editor/MemberReferenceFixer.java b/src/proguard/classfile/editor/MemberReferenceFixer.java
index d78a08c..4bd8af5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,8 +31,8 @@ import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
/**
- * This ClassVisitor fixes constant pool field and method references to
- * fields and methods whose names or descriptors have changed.
+ * This ClassVisitor fixes constant pool field and method references to fields
+ * and methods whose names or descriptors have changed.
*
* @author Eric Lafortune
*/
diff --git a/src/proguard/classfile/editor/MethodInvocationFixer.java b/src/proguard/classfile/editor/MethodInvocationFixer.java
index d60bb36..ef76012 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/NamedAttributeDeleter.java b/src/proguard/classfile/editor/NamedAttributeDeleter.java
index a8019f2..0c4d339 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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
new file mode 100644
index 0000000..4cad6b8
--- /dev/null
+++ b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.attribute.annotation.*;
+
+/**
+ * This class can add annotations to a given parameter annotations attribute.
+ * Annotations to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterAnnotationsAttributeEditor
+{
+ private ParameterAnnotationsAttribute targetParameterAnnotationsAttribute;
+
+
+ /**
+ * Creates a new ParameterAnnotationsAttributeEditor that will edit
+ * annotations in the given parameter annotations attribute.
+ */
+ public ParameterAnnotationsAttributeEditor(ParameterAnnotationsAttribute targetParameterAnnotationsAttribute)
+ {
+ this.targetParameterAnnotationsAttribute = targetParameterAnnotationsAttribute;
+ }
+
+
+ /**
+ * Adds a given annotation to the annotations attribute.
+ */
+ public void addAnnotation(int parameterIndex, Annotation annotation)
+ {
+ int annotationsCount = targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex];
+ Annotation[] annotations = targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex];
+
+ // Make sure there is enough space for the new annotation.
+ if (annotations == null ||
+ annotations.length <= annotationsCount)
+ {
+ targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex] = new Annotation[annotationsCount+1];
+ if (annotations != null)
+ {
+ System.arraycopy(annotations, 0,
+ targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex], 0,
+ annotationsCount);
+ }
+ annotations = targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex];
+ }
+
+ // Add the annotation.
+ annotations[targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]++] = annotation;
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/StackSizeUpdater.java b/src/proguard/classfile/editor/StackSizeUpdater.java
index 358e720..94e0519 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 9e204ff..6b9fd64 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 97d96b3..deb242f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/VariableCleaner.java b/src/proguard/classfile/editor/VariableCleaner.java
new file mode 100644
index 0000000..1e93c15
--- /dev/null
+++ b/src/proguard/classfile/editor/VariableCleaner.java
@@ -0,0 +1,135 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.optimize.info.VariableUsageMarker;
+
+/**
+ * This AttributeVisitor cleans up unused variables in all attributes that it
+ * visits.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableCleaner
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final VariableUsageMarker variableUsageMarker = new VariableUsageMarker();
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ 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);
+
+ // Clean up the variables of the attributes.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Clean up local variables that aren't used.
+ localVariableTableAttribute.u2localVariableTableLength =
+ removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Clean up local variables that aren't used.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength =
+ removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the given list of local variables, without the ones that aren't
+ * used
+ */
+ 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 < maxLocals; index++)
+ {
+ if (variableUsageMarker.isVariableUsed(index))
+ {
+ localVariableInfos[newIndex++] = localVariableInfos[index];
+ }
+ }
+
+ // Clean up any remaining array elements.
+ for (int index = newIndex; index < localVariableInfoCount; index++)
+ {
+ localVariableInfos[index] = null;
+ }
+
+ return newIndex;
+ }
+
+
+ /**
+ * Returns the given list of local variable types, without the ones that
+ * aren't used
+ */
+ 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 < maxLocals; index++)
+ {
+ if (variableUsageMarker.isVariableUsed(index))
+ {
+ localVariableTypeInfos[newIndex++] = localVariableTypeInfos[index];
+ }
+ }
+
+ // Clean up any remaining array elements.
+ for (int index = newIndex; index < localVariableTypeInfoCount; index++)
+ {
+ localVariableTypeInfos[index] = null;
+ }
+
+ return newIndex;
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/VariableEditor.java b/src/proguard/classfile/editor/VariableEditor.java
index 76556ed..a583b49 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/VariableRemapper.java b/src/proguard/classfile/editor/VariableRemapper.java
index 4728525..590cd4e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/VariableSizeUpdater.java b/src/proguard/classfile/editor/VariableSizeUpdater.java
index fe0c62a..18958c5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/BranchInstruction.java b/src/proguard/classfile/instruction/BranchInstruction.java
index afac36e..2baa917 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 1950b02..6c2d1a3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/Instruction.java b/src/proguard/classfile/instruction/Instruction.java
index bdd5c7f..8437495 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -690,7 +690,7 @@ public abstract class Instruction
/**
* Writes the Instruction at the given offset in the given code array.
*/
- public final void write(byte[] code, int offset)
+ public void write(byte[] code, int offset)
{
// Write the wide opcode, if necessary.
if (isWide())
diff --git a/src/proguard/classfile/instruction/InstructionConstants.java b/src/proguard/classfile/instruction/InstructionConstants.java
index 2f8e20d..78730b3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/InstructionFactory.java b/src/proguard/classfile/instruction/InstructionFactory.java
index bf6f8f9..f898471 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/InstructionUtil.java b/src/proguard/classfile/instruction/InstructionUtil.java
index f5e8d2b..a3a328a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a188e0b..178cce5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c351baa..84e6344 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 96fab5f..b98c2fb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 ec94dde..ee81af5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 220dc47..309f802 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,16 +137,29 @@ public class VariableInstruction extends Instruction
/**
+ * Returns whether this instruction stores the value of a variable.
+ * The value is false for the ret instruction, but true for the iinc
+ * instruction.
+ */
+ public boolean isStore()
+ {
+ // A store instruction can be recognized as follows. Note that this
+ // excludes the ret instruction, which has a negative opcode.
+ return opcode >= InstructionConstants.OP_ISTORE ||
+ opcode == InstructionConstants.OP_IINC;
+ }
+
+
+ /**
* Returns whether this instruction loads the value of a variable.
- * The value is true for the ret instruction, but false for the iinc
+ * The value is true for the ret instruction and for the iinc
* instruction.
*/
public boolean isLoad()
{
// A load instruction can be recognized as follows. Note that this
// includes the ret instruction, which has a negative opcode.
- return opcode < InstructionConstants.OP_ISTORE &&
- opcode != InstructionConstants.OP_IINC;
+ return opcode < InstructionConstants.OP_ISTORE;
}
diff --git a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
index 32c507e..71b2cde 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 5658953..1d10980 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 1a6b586..11af131 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2c373fb..aada455 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 8f17031..f14471c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ProgramClassReader.java b/src/proguard/classfile/io/ProgramClassReader.java
index b536e9a..476a346 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ProgramClassWriter.java b/src/proguard/classfile/io/ProgramClassWriter.java
index 041de2f..e56f08a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -278,9 +278,7 @@ implements ClassVisitor,
public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
{
// Write the unknown information.
- byte[] info = new byte[unknownAttribute.u4attributeLength];
- dataOutput.write(info);
- unknownAttribute.info = info;
+ dataOutput.write(unknownAttribute.info);
}
diff --git a/src/proguard/classfile/io/RuntimeDataInput.java b/src/proguard/classfile/io/RuntimeDataInput.java
index b123b9f..104b7c9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 89dc71d..ffde3af 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0f2ab64..3ad6961 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 ff88b76..b1f2c27 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,7 +63,8 @@ implements ClassVisitor,
{
private final ClassPool programClassPool;
private final ClassPool libraryClassPool;
- private final WarningPrinter missingWarningPrinter;
+ private final WarningPrinter missingClassWarningPrinter;
+ private final WarningPrinter missingMemberWarningPrinter;
private final WarningPrinter dependencyWarningPrinter;
private final MemberFinder memberFinder = new MemberFinder();
@@ -72,17 +73,19 @@ implements ClassVisitor,
/**
* Creates a new ClassReferenceInitializer that initializes the references
* of all visited class files, optionally printing warnings if some classes
- * can't be found or if they are in the program class pool.
+ * or class members can't be found or if they are in the program class pool.
*/
public ClassReferenceInitializer(ClassPool programClassPool,
ClassPool libraryClassPool,
- WarningPrinter missingWarningPrinter,
+ WarningPrinter missingClassWarningPrinter,
+ WarningPrinter missingMemberWarningPrinter,
WarningPrinter dependencyWarningPrinter)
{
- this.programClassPool = programClassPool;
- this.libraryClassPool = libraryClassPool;
- this.missingWarningPrinter = missingWarningPrinter;
- this.dependencyWarningPrinter = dependencyWarningPrinter;
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.missingClassWarningPrinter = missingClassWarningPrinter;
+ this.missingMemberWarningPrinter = missingMemberWarningPrinter;
+ this.dependencyWarningPrinter = dependencyWarningPrinter;
}
@@ -189,18 +192,19 @@ implements ClassVisitor,
isFieldRef);
refConstant.referencedClass = memberFinder.correspondingClass();
- if (refConstant.referencedMember == null &&
- missingWarningPrinter != null)
+ if (refConstant.referencedMember == null)
{
// We've haven't found the class member anywhere in the hierarchy.
- missingWarningPrinter.print("Warning: " +
- ClassUtil.externalClassName(clazz.getName()) +
- ": can't find referenced " +
- (isFieldRef ?
- "field '" + ClassUtil.externalFullFieldDescription(0, name, type) :
- "method '" + ClassUtil.externalFullMethodDescription(className, 0, name, type)) +
- "' in class " +
- ClassUtil.externalClassName(className));
+ missingMemberWarningPrinter.print(clazz.getName(),
+ className,
+ "Warning: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ ": can't find referenced " +
+ (isFieldRef ?
+ "field '" + ClassUtil.externalFullFieldDescription(0, name, type) :
+ "method '" + ClassUtil.externalFullMethodDescription(className, 0, name, type)) +
+ "' in class " +
+ ClassUtil.externalClassName(className));
}
}
}
@@ -236,14 +240,12 @@ implements ClassVisitor,
if (referencedClass == null)
{
// We couldn't find the enclosing class.
- if (missingWarningPrinter != null)
- {
- missingWarningPrinter.print("Warning: " +
- ClassUtil.externalClassName(className) +
- ": can't find enclosing class " +
- ClassUtil.externalClassName(enclosingClassName));
- }
-
+ missingClassWarningPrinter.print(className,
+ enclosingClassName,
+ "Warning: " +
+ ClassUtil.externalClassName(className) +
+ ": can't find enclosing class " +
+ ClassUtil.externalClassName(enclosingClassName));
return;
}
@@ -262,16 +264,14 @@ implements ClassVisitor,
if (referencedMethod == null)
{
// We couldn't find the enclosing method.
- if (missingWarningPrinter != null)
- {
- missingWarningPrinter.print("Warning: " +
- ClassUtil.externalClassName(className) +
- ": can't find enclosing method '" +
- ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) +
- "' in class " +
- ClassUtil.externalClassName(enclosingClassName));
- }
-
+ 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;
}
@@ -517,20 +517,24 @@ implements ClassVisitor,
clazz = libraryClassPool.getClass(name);
if (clazz == null &&
- missingWarningPrinter != null)
+ missingClassWarningPrinter != null)
{
// We didn't find the superclass or interface. Print a warning.
- missingWarningPrinter.print("Warning: " +
- ClassUtil.externalClassName(referencingClassName) +
- ": can't find referenced class " +
- ClassUtil.externalClassName(name));
+ missingClassWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: " +
+ ClassUtil.externalClassName(referencingClassName) +
+ ": can't find referenced class " +
+ ClassUtil.externalClassName(name));
}
}
else if (dependencyWarningPrinter != null)
{
// The superclass or interface was found in the program class pool.
// Print a warning.
- dependencyWarningPrinter.print("Warning: library class " +
+ dependencyWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: library class " +
ClassUtil.externalClassName(referencingClassName) +
" depends on program class " +
ClassUtil.externalClassName(name));
diff --git a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
index c65b512..30fd526 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2896a63..af2a209 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -143,7 +143,9 @@ implements ClassVisitor,
missingWarningPrinter != null)
{
// We didn't find the superclass or interface. Print a warning.
- missingWarningPrinter.print("Warning: " +
+ missingWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: " +
ClassUtil.externalClassName(referencingClassName) +
": can't find superclass or interface " +
ClassUtil.externalClassName(name));
@@ -153,7 +155,9 @@ implements ClassVisitor,
{
// The superclass or interface was found in the program class pool.
// Print a warning.
- dependencyWarningPrinter.print("Warning: library class " +
+ dependencyWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: library class " +
ClassUtil.externalClassName(referencingClassName) +
" extends or implements program class " +
ClassUtil.externalClassName(name));
diff --git a/src/proguard/classfile/util/ClassUtil.java b/src/proguard/classfile/util/ClassUtil.java
index dc46ef3..5f25f01 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/DescriptorClassEnumeration.java b/src/proguard/classfile/util/DescriptorClassEnumeration.java
index 4523722..0bee2d5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.classfile.util;
import proguard.classfile.ClassConstants;
+import java.util.Stack;
+
/**
* A <code>DescriptorClassEnumeration</code> provides an enumeration of all
* classes mentioned in a given descriptor or signature.
@@ -36,6 +38,7 @@ public class DescriptorClassEnumeration
private int nestingLevel;
private boolean isInnerClassName;
private String accumulatedClassName;
+ private Stack accumulatedClassNames;
/**
@@ -95,11 +98,26 @@ public class DescriptorClassEnumeration
case ClassConstants.INTERNAL_TYPE_GENERIC_START:
{
nestingLevel++;
+
+ // Make sure we have a stack.
+ if (accumulatedClassNames == null)
+ {
+ accumulatedClassNames = new Stack();
+ }
+
+ // Remember the accumulated class name.
+ accumulatedClassNames.push(accumulatedClassName);
+
break;
}
case ClassConstants.INTERNAL_TYPE_GENERIC_END:
{
nestingLevel--;
+
+ // Return to the accumulated class name outside the
+ // generic block.
+ accumulatedClassName = (String)accumulatedClassNames.pop();
+
continue loop;
}
case ClassConstants.INTERNAL_TYPE_GENERIC_BOUND:
diff --git a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
index d849121..09ffdd0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -313,11 +313,12 @@ implements InstructionVisitor,
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
// Print out a note about the class cast.
- if (notePrinter != null &&
- (noteExceptionMatcher == null ||
- !noteExceptionMatcher.matches(classConstant.getName(clazz))))
+ if (noteExceptionMatcher == null ||
+ !noteExceptionMatcher.matches(classConstant.getName(clazz)))
{
- notePrinter.print("Note: " +
+ notePrinter.print(clazz.getName(),
+ classConstant.getName(clazz),
+ "Note: " +
ClassUtil.externalClassName(clazz.getName()) +
" calls '(" +
ClassUtil.externalClassName(classConstant.getName(clazz)) +
@@ -452,7 +453,9 @@ implements InstructionVisitor,
missingNotePrinter != null)
{
// We didn't find the superclass or interface. Print a note.
- missingNotePrinter.print("Note: " +
+ missingNotePrinter.print(referencingClassName,
+ name,
+ "Note: " +
ClassUtil.externalClassName(referencingClassName) +
": can't find dynamically referenced class " +
ClassUtil.externalClassName(name));
@@ -462,7 +465,9 @@ implements InstructionVisitor,
{
// The superclass or interface was found in the program class pool.
// Print a warning.
- dependencyWarningPrinter.print("Warning: library class " +
+ dependencyWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: library class " +
ClassUtil.externalClassName(referencingClassName) +
" depends dynamically on program class " +
ClassUtil.externalClassName(name));
diff --git a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
index b6cc51d..1f57708 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -457,7 +457,8 @@ implements InstructionVisitor,
boolean isDeclared)
{
// Print out a note about the dynamic invocation.
- if (notePrinter != null)
+ if (notePrinter != null &&
+ notePrinter.accepts(clazz.getName()))
{
// Is the class member name in the list of exceptions?
StringMatcher noteExceptionMatcher = isField ?
@@ -495,7 +496,8 @@ implements InstructionVisitor,
}
// Print out the actual note.
- notePrinter.print("Note: " +
+ notePrinter.print(clazz.getName(),
+ "Note: " +
ClassUtil.externalClassName(clazz.getName()) +
" accesses a " +
(isDeclared ? "declared " : "") +
@@ -551,40 +553,52 @@ implements InstructionVisitor,
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- System.out.println(" Maybe this is program field '" +
- ClassUtil.externalFullClassDescription(0, programClass.getName()) +
- " { " +
- ClassUtil.externalFullFieldDescription(0, programField.getName(programClass), programField.getDescriptor(programClass)) +
- "; }'");
+ if (notePrinter.accepts(programClass.getName()))
+ {
+ System.out.println(" Maybe this is program field '" +
+ ClassUtil.externalFullClassDescription(0, programClass.getName()) +
+ " { " +
+ ClassUtil.externalFullFieldDescription(0, programField.getName(programClass), programField.getDescriptor(programClass)) +
+ "; }'");
+ }
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- System.out.println(" Maybe this is program method '" +
- ClassUtil.externalFullClassDescription(0, programClass.getName()) +
- " { " +
- ClassUtil.externalFullMethodDescription(null, 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) +
- "; }'");
+ if (notePrinter.accepts(programClass.getName()))
+ {
+ System.out.println(" Maybe this is program method '" +
+ ClassUtil.externalFullClassDescription(0, programClass.getName()) +
+ " { " +
+ ClassUtil.externalFullMethodDescription(null, 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) +
+ "; }'");
+ }
}
public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
{
- System.out.println(" Maybe this is library field '" +
- ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
- " { " +
- ClassUtil.externalFullFieldDescription(0, libraryField.getName(libraryClass), libraryField.getDescriptor(libraryClass)) +
- "; }'");
+ if (notePrinter.accepts(libraryClass.getName()))
+ {
+ System.out.println(" Maybe this is library field '" +
+ ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
+ " { " +
+ ClassUtil.externalFullFieldDescription(0, libraryField.getName(libraryClass), libraryField.getDescriptor(libraryClass)) +
+ "; }'");
+ }
}
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
{
- System.out.println(" Maybe this is library method '" +
- ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
- " { " +
- ClassUtil.externalFullMethodDescription(null, 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) +
- "; }'");
+ if (notePrinter.accepts(libraryClass.getName()))
+ {
+ System.out.println(" Maybe this is library method '" +
+ ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
+ " { " +
+ ClassUtil.externalFullMethodDescription(null, 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) +
+ "; }'");
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/util/ExternalTypeEnumeration.java b/src/proguard/classfile/util/ExternalTypeEnumeration.java
index bf43501..6371888 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 22b88c0..8a689d5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,12 +60,13 @@ implements InstructionVisitor,
private final Constant[] patternConstants;
private final Instruction[] patternInstructions;
- private boolean matching;
- private int patternInstructionIndex;
+ private boolean matching;
+ private boolean matchingAnyWildCards;
+ private int patternInstructionIndex;
private final int[] matchedInstructionOffsets;
- private int matchedArgumentFlags;
+ private int matchedArgumentFlags;
private final int[] matchedArguments = new int[7];
- private int matchedConstantFlags;
+ private long matchedConstantFlags;
private final int[] matchedConstantIndices;
// Fields acting as a parameter and a return value for visitor methods.
@@ -97,7 +98,7 @@ implements InstructionVisitor,
{
patternInstructionIndex = 0;
matchedArgumentFlags = 0;
- matchedConstantFlags = 0;
+ matchedConstantFlags = 0L;
}
@@ -107,6 +108,12 @@ implements InstructionVisitor,
}
+ public boolean isMatchingAnyWildcards()
+ {
+ return matchingAnyWildCards;
+ }
+
+
public int instructionCount()
{
return patternInstructions.length;
@@ -487,7 +494,7 @@ implements InstructionVisitor,
// Check the constant index.
return matchingArguments(constantIndex1, constantIndex2);
}
- else if ((matchedConstantFlags & (1 << constantIndex2)) == 0)
+ else if ((matchedConstantFlags & (1L << constantIndex2)) == 0)
{
// Check the actual constant.
matchingConstant = false;
@@ -501,7 +508,7 @@ implements InstructionVisitor,
{
// Store the constant index.
matchedConstantIndices[constantIndex2] = constantIndex1;
- matchedConstantFlags |= 1 << constantIndex2;
+ matchedConstantFlags |= 1L << constantIndex2;
}
}
@@ -588,6 +595,9 @@ 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 80bb608..76f7e84 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c066e10..0fdeec0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 7857cc3..5f2ea6f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/SimplifiedVisitor.java b/src/proguard/classfile/util/SimplifiedVisitor.java
index 126562f..87b7fe4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/StringReferenceInitializer.java b/src/proguard/classfile/util/StringReferenceInitializer.java
new file mode 100644
index 0000000..3884a04
--- /dev/null
+++ b/src/proguard/classfile/util/StringReferenceInitializer.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This ConstantVisitor initializes any class references of all string constants
+ * it visits. More specifically, it fills out the references of string constant
+ * pool entries that happen to refer to a class in the program class pool or in
+ * the library class pool.
+ *
+ * @author Eric Lafortune
+ */
+public class StringReferenceInitializer
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+
+
+ /**
+ * Creates a new StringReferenceInitializer.
+ */
+ public StringReferenceInitializer(ClassPool programClassPool,
+ ClassPool libraryClassPool)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ if (stringConstant.referencedClass == null)
+ {
+ // See if we can find the referenced class.
+ stringConstant.referencedClass =
+ findClass(ClassUtil.internalClassName(stringConstant.getString(clazz)));
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the class with the given name, either for the program class pool
+ * or from the library class pool, or <code>null</code> if it can't be found.
+ */
+ private Clazz findClass(String name)
+ {
+ // First look for the class in the program class pool.
+ Clazz clazz = programClassPool.getClass(name);
+
+ // Otherwise look for the class in the library class pool.
+ if (clazz == null)
+ {
+ clazz = libraryClassPool.getClass(name);
+ }
+
+ return clazz;
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/util/StringSharer.java b/src/proguard/classfile/util/StringSharer.java
index 3d9005b..56de7c5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/WarningPrinter.java b/src/proguard/classfile/util/WarningPrinter.java
index 88de32f..87d8978 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,7 +20,10 @@
*/
package proguard.classfile.util;
+import proguard.util.*;
+
import java.io.PrintStream;
+import java.util.List;
/**
* This class prints out and counts warnings.
@@ -29,8 +32,9 @@ import java.io.PrintStream;
*/
public class WarningPrinter
{
- private final PrintStream printStream;
- private int warningCount;
+ private final PrintStream printStream;
+ private final StringMatcher classFilter;
+ private int warningCount;
/**
@@ -48,13 +52,73 @@ public class WarningPrinter
public WarningPrinter(PrintStream printStream)
{
this.printStream = printStream;
+ this.classFilter = null;
+ }
+
+
+ /**
+ * Creates a new WarningPrinter that prints to the given print stream,
+ * except if the names of any involved classes matches the given filter.
+ */
+ public WarningPrinter(PrintStream printStream, List classFilter)
+ {
+ this.printStream = printStream;
+ this.classFilter = classFilter == null ? null :
+ new ListParser(new ClassNameParser()).parse(classFilter);
+ }
+
+
+ /**
+ * Prints out the given warning and increments the warning count, if
+ * the given class name passes the class name filter.
+ */
+ public void print(String className, String warning)
+ {
+ if (accepts(className))
+ {
+ print(warning);
+ }
+ }
+
+
+ /**
+ * Returns whether the given class name passes the class name filter.
+ */
+ public boolean accepts(String className)
+ {
+ return classFilter == null ||
+ !classFilter.matches(className);
+ }
+
+
+ /**
+ * Prints out the given warning and increments the warning count, if
+ * the given class names pass the class name filter.
+ */
+ public void print(String className1, String className2, String warning)
+ {
+ if (accepts(className1, className2))
+ {
+ print(warning);
+ }
+ }
+
+
+ /**
+ * Returns whether the given class names pass the class name filter.
+ */
+ public boolean accepts(String className1, String className2)
+ {
+ return classFilter == null ||
+ !(classFilter.matches(className1) ||
+ classFilter.matches(className2));
}
/**
* Prints out the given warning and increments the warning count.
*/
- public void print(String warning)
+ private void print(String warning)
{
printStream.println(warning);
diff --git a/src/proguard/classfile/visitor/AllClassVisitor.java b/src/proguard/classfile/visitor/AllClassVisitor.java
index e8c67db..06aca2c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 eb0047c..8bff7d4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 d22dfd2..448470e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 70cbf51..75b919d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 7aaaabc..8f5bdd1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 90aee34..a8815b6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 5bab937..36165ef 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 24b6ed9..a69fe76 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 9aadce6..c58c090 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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
index 7c93e78..ee028f8 100644
--- a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java
+++ b/src/proguard/classfile/visitor/ClassForNameClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
index b0d9da2..2e1755e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 f924efb..c016a34 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,8 @@ package proguard.classfile.visitor;
import proguard.classfile.*;
import proguard.util.*;
+import java.util.List;
+
/**
* This <code>ClassVisitor</code> delegates its visits to another given
* <code>ClassVisitor</code>, but only when the visited class has a name that
@@ -53,6 +55,21 @@ public class ClassNameFilter implements ClassVisitor
/**
* Creates a new ClassNameFilter.
+ * @param regularExpression the regular expression against which class names
+ * will be matched.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ClassNameFilter(List regularExpression,
+ ClassVisitor classVisitor)
+ {
+ this(new ListParser(new ClassNameParser()).parse(regularExpression),
+ classVisitor);
+ }
+
+
+ /**
+ * Creates a new ClassNameFilter.
* @param regularExpressionMatcher the regular expression against which
* class names will be matched.
* @param classVisitor the <code>ClassVisitor</code> to which
diff --git a/src/proguard/classfile/visitor/ClassPoolFiller.java b/src/proguard/classfile/visitor/ClassPoolFiller.java
index 3fd7a72..e1773de 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 9b15722..0b659dc 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 3b6294f..429c340 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 4d09c13..1da7d16 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -397,11 +397,16 @@ implements ClassVisitor,
public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
{
println(visitorInfo(enclosingMethodAttribute) +
- " Enclosing method attribute [" +
- clazz.getClassName(enclosingMethodAttribute.u2classIndex) +
- (enclosingMethodAttribute.u2nameAndTypeIndex == 0 ? "" : "." +
- clazz.getName(enclosingMethodAttribute.u2nameAndTypeIndex) + " " +
- clazz.getType(enclosingMethodAttribute.u2nameAndTypeIndex)) + "]");
+ " Enclosing method attribute:");
+
+ indent();
+ clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2classIndex, this);
+
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2nameAndTypeIndex, this);
+ }
+ outdent();
}
diff --git a/src/proguard/classfile/visitor/ClassVersionFilter.java b/src/proguard/classfile/visitor/ClassVersionFilter.java
index 1465ded..578cabf 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ClassVersionSetter.java b/src/proguard/classfile/visitor/ClassVersionSetter.java
index 2f99af9..34dfbc1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 3219e7e..fdba2df 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 de8f2b1..ec3fe68 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 aa4b672..263dbd5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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/ExceptClassFilter.java b/src/proguard/classfile/visitor/ExceptClassFilter.java
index c13cc94..924485e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 11a1348..7380c40 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 6c37579..c324129 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0989002..3911e39 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 ExceptionInfoVisitor
public ExceptionExcludedOffsetFilter(int instructionOffset,
ExceptionInfoVisitor exceptionInfoVisitor)
{
- this.instructionOffset = instructionOffset;
+ this.instructionOffset = instructionOffset;
this.exceptionInfoVisitor = exceptionInfoVisitor;
}
diff --git a/src/proguard/classfile/visitor/ExceptionCounter.java b/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
similarity index 58%
copy from src/proguard/classfile/visitor/ExceptionCounter.java
copy to src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
index 6c37579..e0fdec3 100644
--- a/src/proguard/classfile/visitor/ExceptionCounter.java
+++ b/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,25 +21,31 @@
package proguard.classfile.visitor;
import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
/**
- * This ExceptionInfoVisitor counts the number of exceptions that has been visited.
+ * This <code>ExceptionInfoVisitor</code> lets a given
+ * <code>ConstantVisitor</code> visit all catch class constants of exceptions
+ * that it visits.
*
* @author Eric Lafortune
*/
-public class ExceptionCounter implements ExceptionInfoVisitor
+public class ExceptionHandlerConstantVisitor
+implements ExceptionInfoVisitor
{
- private int count;
+ private final ConstantVisitor constantVisitor;
/**
- * Returns the number of exceptions that has been visited so far.
+ * Creates a new ExceptionHandlerConstantVisitor.
+ * @param constantVisitor the ConstantVisitor that will visit the catch
+ * class constants.
*/
- public int getCount()
+ public ExceptionHandlerConstantVisitor(ConstantVisitor constantVisitor)
{
- return count;
+ this.constantVisitor = constantVisitor;
}
@@ -47,6 +53,10 @@ public class ExceptionCounter implements ExceptionInfoVisitor
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- count++;
+ int catchType = exceptionInfo.u2catchType;
+ if (catchType != 0)
+ {
+ clazz.constantPoolEntryAccept(catchType, constantVisitor);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/ExceptionRangeFilter.java b/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
similarity index 74%
copy from src/proguard/classfile/visitor/ExceptionRangeFilter.java
copy to src/proguard/classfile/visitor/ExceptionHandlerFilter.java
index a2e0f93..a90fb56 100644
--- a/src/proguard/classfile/visitor/ExceptionRangeFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,11 +27,11 @@ import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
/**
* This <code>ExceptionInfoVisitor</code> delegates its visits to another given
* <code>ExceptionInfoVisitor</code>, but only when the visited exception
- * overlaps with the given instruction range.
+ * targets an instruction in the given range of offsets.
*
* @author Eric Lafortune
*/
-public class ExceptionRangeFilter
+public class ExceptionHandlerFilter
implements ExceptionInfoVisitor
{
private final int startOffset;
@@ -40,15 +40,15 @@ implements ExceptionInfoVisitor
/**
- * Creates a new ExceptionRangeFilter.
- * @param startOffset the start offset of the instruction range.
- * @param endOffset the end offset of the instruction range.
+ * Creates a new ExceptionHandlerFilter.
+ * @param startOffset the start of the instruction offset range.
+ * @param endOffset the end of the instruction offset range.
* @param exceptionInfoVisitor the ExceptionInfoVisitor to which visits
* will be delegated.
*/
- public ExceptionRangeFilter(int startOffset,
- int endOffset,
- ExceptionInfoVisitor exceptionInfoVisitor)
+ public ExceptionHandlerFilter(int startOffset,
+ int endOffset,
+ ExceptionInfoVisitor exceptionInfoVisitor)
{
this.startOffset = startOffset;
this.endOffset = endOffset;
@@ -60,9 +60,11 @@ implements ExceptionInfoVisitor
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- if (exceptionInfo.isApplicable(startOffset, endOffset))
+ int handlerPC = exceptionInfo.u2handlerPC;
+ if (handlerPC >= startOffset &&
+ handlerPC < endOffset)
{
exceptionInfoVisitor.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/ExceptionOffsetFilter.java b/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
index 3114dbb..e2a4fc9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 ExceptionInfoVisitor
public ExceptionOffsetFilter(int instructionOffset,
ExceptionInfoVisitor exceptionInfoVisitor)
{
- this.instructionOffset = instructionOffset;
+ this.instructionOffset = instructionOffset;
this.exceptionInfoVisitor = exceptionInfoVisitor;
}
diff --git a/src/proguard/classfile/visitor/ExceptionRangeFilter.java b/src/proguard/classfile/visitor/ExceptionRangeFilter.java
index a2e0f93..c541b1f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 9c59944..6fe2e7d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 7e78cd9..955a74e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a247c64..9e9cea3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2e23a51..0e40f2f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 aea455d..0ee80e5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 485f5df..6fd32e3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 39296cd..85272ff 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 41e3403..ec68b2d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 933c957..c2da72e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 4721c77..bd69304 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 935f1ad..0fe450e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 2f75efe..a405cfc 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 96caaee..01fdf71 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 4b97050..57d923a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c9bd99e..dc0ea36 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 13d4b3e..044d55a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 0259b73..d34d91e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 9edfeb7..cc4629c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a7aabc2..a14d04a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 bb47b27..76b66c6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 5b30fe3..d4611c1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 e4ddd56..fba3b21 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 5463791..048a1e6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 aba4b7b..986c3f9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 proguard.classfile.util.SimplifiedVisitor;
/**
* This ClassVisitor, MemberVisitor, ConstantVisitor, AttributeVisitor, etc.
* lets a given ClassVisitor visit all the referenced classes of the elements
- * that it visits.
+ * that it visits. Only downstream elements are considered (in order to avoid
+ * loops and repeated visits).
*
* @author Eric Lafortune
*/
diff --git a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
index 93aba43..c4d34b8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 c62865c..6dc06af 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 a6e438f..a661110 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 ad3aa1f..69ea1a1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 97c263c..4170341 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 673b328..2f575c4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it 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 b6b69ee..c58cff3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 1a5fad4..3a2db76 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 c05bd53..bccd866 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -232,7 +232,7 @@ implements InvocationUnit,
/**
- * Sets the class thru which the specified field is accessed.
+ * Sets the class through which the specified field is accessed.
*/
protected void setFieldClassValue(Clazz clazz,
RefConstant refConstant,
@@ -243,7 +243,7 @@ implements InvocationUnit,
/**
- * Returns the class thru which the specified field is accessed.
+ * Returns the class though which the specified field is accessed.
*/
protected Value getFieldClassValue(Clazz clazz,
RefConstant refConstant,
diff --git a/src/proguard/evaluation/BranchUnit.java b/src/proguard/evaluation/BranchUnit.java
index 9d8b1cc..b709807 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/InvocationUnit.java b/src/proguard/evaluation/InvocationUnit.java
index f18581f..cb4d3c5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 9f30010..74afd0b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/Stack.java b/src/proguard/evaluation/Stack.java
index b2cb0ee..2808e62 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/TracedStack.java b/src/proguard/evaluation/TracedStack.java
index cf32883..c24f783 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 375150f..1ae6ba6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/Variables.java b/src/proguard/evaluation/Variables.java
index 53d5db0..4496aaa 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/Category1Value.java b/src/proguard/evaluation/value/Category1Value.java
index 7db7eca..b8c5db2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 95e22db..65916c7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 6fcc22b..e4e2e02 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.evaluation.value;
/**
- * This IntegerValue represents the result of a comparions of two scalar
+ * This IntegerValue represents the result of a comparisons of two scalar
* values.
*
* @author Eric Lafortune
diff --git a/src/proguard/evaluation/value/CompositeDoubleValue.java b/src/proguard/evaluation/value/CompositeDoubleValue.java
index c3b4c2b..a6d48ef 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 73698fb..4df890a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/CompositeIntegerValue.java b/src/proguard/evaluation/value/CompositeIntegerValue.java
index 72ffbc9..6d4f59c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 7f2b5f8..7f63211 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 b32665a..7ab5d0a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 a0ce754..76568d1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 b39dce2..a6afe34 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 cabf6ef..33683b7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 3bc6b2a..aecb533 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 427a539..ec97008 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 183c513..ab79b49 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f83a639..e39ee5c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/FloatValue.java b/src/proguard/evaluation/value/FloatValue.java
index b981155..b30e395 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 44d3769..4009c6e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 1bf7b51..87bed64 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 9c9e490..66e88ee 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 33bb78e..eea1816 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 323b93f..cb5efc1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/IdentifiedValueFactory.java b/src/proguard/evaluation/value/IdentifiedValueFactory.java
index 0b37ee7..2b14e72 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 a60008e..10b5a6f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 3de3aae..508c5f5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 be51d5d..f7ba162 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 44a1978..2bc9423 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 31b338c..0ddf4ab 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 22f9c5f..a89a2d9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 52ee767..c3b22bb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e436b9c..05bc559 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ParticularFloatValue.java b/src/proguard/evaluation/value/ParticularFloatValue.java
index 0bf5306..59e4357 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ParticularIntegerValue.java b/src/proguard/evaluation/value/ParticularIntegerValue.java
index b1a2b35..8a4ac1d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 762c5ba..61d2e04 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 bdc522b..418c6f8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -496,7 +496,7 @@ public class ReferenceValue extends Category1Value
{
return true;
}
-
+
if (object == null ||
this.getClass() != object.getClass())
{
diff --git a/src/proguard/evaluation/value/SpecificDoubleValue.java b/src/proguard/evaluation/value/SpecificDoubleValue.java
index 973b678..572d891 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/SpecificFloatValue.java b/src/proguard/evaluation/value/SpecificFloatValue.java
index e507e76..3bc3679 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/SpecificIntegerValue.java b/src/proguard/evaluation/value/SpecificIntegerValue.java
index 5e1e594..57c48b1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 0b07daf..5e12bde 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 5bc5b7e..72dd1d3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/TopValue.java b/src/proguard/evaluation/value/TopValue.java
index 0a53e7e..048a1ff 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 dd2d519..79cc4de 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 bd1d745..3f9622a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f25b398..be5e79d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f169208..83a75dc 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f3f6393..e24ece1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 1a84d58..8415381 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 29532f3..95f3d1b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,13 +20,14 @@
*/
package proguard.gui;
+import proguard.*;
+import proguard.util.ListUtil;
+
+import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
-
-import javax.swing.*;
-
-import proguard.*;
+import java.util.List;
/**
* This <code>ListPanel</code> allows the user to add, edit, filter, move, and
@@ -417,7 +418,7 @@ class ClassPathPanel extends ListPanel
}
- private StringBuffer appendFilter(StringBuffer filter, String additionalFilter)
+ private StringBuffer appendFilter(StringBuffer filter, List additionalFilter)
{
if (filter != null)
{
@@ -431,7 +432,7 @@ class ClassPathPanel extends ListPanel
filter = new StringBuffer().append('(');
}
- filter.append(additionalFilter);
+ filter.append(ListUtil.commaSeparatedString(additionalFilter));
}
return filter;
diff --git a/src/proguard/gui/ClassSpecificationDialog.java b/src/proguard/gui/ClassSpecificationDialog.java
index d2478b2..36d80d4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 +79,7 @@ final class ClassSpecificationDialog extends JDialog
public ClassSpecificationDialog(JFrame owner, boolean fullKeepOptions)
{
- super(owner, true);
+ super(owner, msg("specifyClasses"), true);
setResizable(true);
// Create some constraints that can be reused.
@@ -346,15 +346,15 @@ final class ClassSpecificationDialog extends JDialog
/**
- * Sets the KeepSpecification to be represented in this dialog.
+ * Sets the KeepClassSpecification to be represented in this dialog.
*/
- public void setKeepSpecification(KeepSpecification keepSpecification)
+ public void setKeepSpecification(KeepClassSpecification keepClassSpecification)
{
- boolean markClasses = keepSpecification.markClasses;
- boolean markConditionally = keepSpecification.markConditionally;
- boolean allowShrinking = keepSpecification.allowShrinking;
- boolean allowOptimization = keepSpecification.allowOptimization;
- boolean allowObfuscation = keepSpecification.allowObfuscation;
+ boolean markClasses = keepClassSpecification.markClasses;
+ boolean markConditionally = keepClassSpecification.markConditionally;
+ boolean allowShrinking = keepClassSpecification.allowShrinking;
+ boolean allowOptimization = keepClassSpecification.allowOptimization;
+ boolean allowObfuscation = keepClassSpecification.allowObfuscation;
// Figure out the proper keep radio button and set it.
JRadioButton keepOptionRadioButton =
@@ -369,7 +369,7 @@ final class ClassSpecificationDialog extends JDialog
allowOptimizationCheckBox.setSelected(allowOptimization);
allowObfuscationCheckBox .setSelected(allowObfuscation);
- setClassSpecification(keepSpecification);
+ setClassSpecification(keepClassSpecification);
}
@@ -409,9 +409,9 @@ final class ClassSpecificationDialog extends JDialog
/**
- * Returns the KeepSpecification currently represented in this dialog.
+ * Returns the KeepClassSpecification currently represented in this dialog.
*/
- public KeepSpecification getKeepSpecification()
+ public KeepClassSpecification getKeepSpecification()
{
boolean markClasses = !keepClassMembersRadioButton .isSelected();
boolean markConditionally = keepClassesWithMembersRadioButton.isSelected();
@@ -419,7 +419,7 @@ final class ClassSpecificationDialog extends JDialog
boolean allowOptimization = allowOptimizationCheckBox .isSelected();
boolean allowObfuscation = allowObfuscationCheckBox .isSelected();
- return new KeepSpecification(markClasses,
+ return new KeepClassSpecification(markClasses,
markConditionally,
allowShrinking,
allowOptimization,
@@ -490,8 +490,8 @@ final class ClassSpecificationDialog extends JDialog
* flags of the given keep option.
*/
private void setClassSpecificationRadioButtons(ClassSpecification classSpecification,
- int flag,
- JRadioButton[] radioButtons)
+ int flag,
+ JRadioButton[] radioButtons)
{
int index = (classSpecification.requiredSetAccessFlags & flag) != 0 ? 0 :
(classSpecification.requiredUnsetAccessFlags & flag) != 0 ? 1 :
@@ -505,8 +505,8 @@ final class ClassSpecificationDialog extends JDialog
* button triplet.
*/
private void getClassSpecificationRadioButtons(ClassSpecification classSpecification,
- int flag,
- JRadioButton[] radioButtons)
+ int flag,
+ JRadioButton[] radioButtons)
{
if (radioButtons[0].isSelected())
{
diff --git a/src/proguard/gui/ClassSpecificationsPanel.java b/src/proguard/gui/ClassSpecificationsPanel.java
index 03ee429..2cf0b1d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 ef66a7a..d67be40 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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
new file mode 100644
index 0000000..e46193f
--- /dev/null
+++ b/src/proguard/gui/FilterBuilder.java
@@ -0,0 +1,208 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.gui;
+
+import javax.swing.*;
+
+/**
+ * This class builds filters corresponding to the selections and names of a
+ * given list of check boxes.
+ */
+public class FilterBuilder
+{
+ private JCheckBox[] checkBoxes;
+ private char separator;
+
+
+ /**
+ * Creates a new FilterBuilder.
+ * @param checkBoxes the check boxes with names and selections that should
+ * be reflected in the output filter.
+ * @param separator the separator for the names in the check boxes.
+ */
+ public FilterBuilder(JCheckBox[] checkBoxes, char separator)
+ {
+ this.checkBoxes = checkBoxes;
+ this.separator = separator;
+ }
+
+
+ /**
+ * Builds a filter for the current names and selections of the check boxes.
+ */
+ public String buildFilter()
+ {
+ StringBuffer positive = new StringBuffer();
+ StringBuffer negative = new StringBuffer();
+
+ buildFilter("", positive, negative);
+
+ return positive.length() <= negative.length() ?
+ positive.toString() :
+ negative.toString();
+ }
+
+
+ /**
+ * Builds two versions of the filter for the given prefix.
+ * @param prefix the prefix.
+ * @param positive the filter to be extended, assuming the matching
+ * strings are accepted.
+ * @param negative the filter to be extended, assuming the matching
+ * strings are rejected.
+ */
+ private void buildFilter(String prefix,
+ StringBuffer positive,
+ StringBuffer negative)
+ {
+ int positiveCount = 0;
+ int negativeCount = 0;
+
+ // Count all selected and unselected check boxes with the prefix.
+ for (int index = 0; index < checkBoxes.length; index++)
+ {
+ JCheckBox checkBox = checkBoxes[index];
+ String name = checkBox.getText();
+
+ if (name.startsWith(prefix))
+ {
+ if (checkBox.isSelected())
+ {
+ positiveCount++;
+ }
+ else
+ {
+ negativeCount++;
+ }
+ }
+ }
+
+ // Are there only unselected check boxes?
+ if (positiveCount == 0)
+ {
+ // Extend the positive filter with exceptions and return.
+ if (positive.length() > 0)
+ {
+ positive.append(',');
+ }
+ positive.append('!').append(prefix);
+ if (prefix.length() == 0 ||
+ prefix.charAt(prefix.length()-1) == separator)
+ {
+ positive.append('*');
+ }
+
+ return;
+ }
+
+ // Are there only selected check boxes?
+ if (negativeCount == 0)
+ {
+ // Extend the negative filter with exceptions and return.
+ if (negative.length() > 0)
+ {
+ negative.append(',');
+ }
+ negative.append(prefix);
+ if (prefix.length() == 0 ||
+ prefix.charAt(prefix.length()-1) == separator)
+ {
+ negative.append('*');
+ }
+
+ return;
+ }
+
+ // Create new positive and negative filters for names starting with the
+ // prefix only.
+ StringBuffer positiveFilter = new StringBuffer();
+ StringBuffer negativeFilter = new StringBuffer();
+
+ String newPrefix = null;
+
+ for (int index = 0; index < checkBoxes.length; index++)
+ {
+ String name = checkBoxes[index].getText();
+
+ if (name.startsWith(prefix))
+ {
+ if (newPrefix == null ||
+ !name.startsWith(newPrefix))
+ {
+ int prefixIndex =
+ name.indexOf(separator, prefix.length()+1);
+
+ newPrefix = prefixIndex >= 0 ?
+ name.substring(0, prefixIndex+1) :
+ name;
+
+ buildFilter(newPrefix,
+ positiveFilter,
+ negativeFilter);
+ }
+ }
+ }
+
+ // Extend the positive filter.
+ if (positiveFilter.length() <= negativeFilter.length() + prefix.length() + 3)
+ {
+ if (positive.length() > 0 &&
+ positiveFilter.length() > 0)
+ {
+ positive.append(',');
+ }
+
+ positive.append(positiveFilter);
+ }
+ else
+ {
+ if (positive.length() > 0 &&
+ negativeFilter.length() > 0)
+ {
+ positive.append(',');
+ }
+
+ positive.append(negativeFilter).append(",!").append(prefix).append('*');
+ }
+
+ // Extend the negative filter.
+ if (negativeFilter.length() <= positiveFilter.length() + prefix.length() + 4)
+ {
+ if (negative.length() > 0 &&
+ negativeFilter.length() > 0)
+ {
+ negative.append(',');
+ }
+
+ negative.append(negativeFilter);
+ }
+ else
+ {
+ if (negative.length() > 0 &&
+ positiveFilter.length() > 0)
+ {
+ negative.append(',');
+ }
+
+ negative.append(positiveFilter).append(',').append(prefix).append('*');
+ }
+ }
+}
diff --git a/src/proguard/gui/FilterDialog.java b/src/proguard/gui/FilterDialog.java
index 1d82ad9..1567a31 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,10 +20,13 @@
*/
package proguard.gui;
+import proguard.util.ListUtil;
+
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
+import java.util.List;
/**
* This <code>JDialog</code> allows the user to enter a String.
@@ -177,100 +180,100 @@ public class FilterDialog extends JDialog
/**
* Sets the filter to be represented in this dialog.
*/
- public void setFilter(String filter)
+ public void setFilter(List filter)
{
- filterTextField.setText(filter != null ? filter : DEFAULT_FILTER);
+ filterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_FILTER);
}
/**
* Returns the filter currently represented in this dialog.
*/
- public String getFilter()
+ public List getFilter()
{
String filter = filterTextField.getText();
- return filter.equals(DEFAULT_FILTER) ? null : filter;
+ return filter.equals(DEFAULT_FILTER) ? null : ListUtil.commaSeparatedList(filter);
}
/**
* Sets the jar filter to be represented in this dialog.
*/
- public void setJarFilter(String filter)
+ public void setJarFilter(List filter)
{
- jarFilterTextField.setText(filter != null ? filter : DEFAULT_JAR_FILTER);
+ jarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_JAR_FILTER);
}
/**
* Returns the jar filter currently represented in this dialog.
*/
- public String getJarFilter()
+ public List getJarFilter()
{
String filter = jarFilterTextField.getText();
- return filter.equals(DEFAULT_JAR_FILTER) ? null : filter;
+ return filter.equals(DEFAULT_JAR_FILTER) ? null : ListUtil.commaSeparatedList(filter);
}
/**
* Sets the war filter to be represented in this dialog.
*/
- public void setWarFilter(String filter)
+ public void setWarFilter(List filter)
{
- warFilterTextField.setText(filter != null ? filter : DEFAULT_WAR_FILTER);
+ warFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_WAR_FILTER);
}
/**
* Returns the war filter currently represented in this dialog.
*/
- public String getWarFilter()
+ public List getWarFilter()
{
String filter = warFilterTextField.getText();
- return filter.equals(DEFAULT_WAR_FILTER) ? null : filter;
+ return filter.equals(DEFAULT_WAR_FILTER) ? null : ListUtil.commaSeparatedList(filter);
}
/**
* Sets the ear filter to be represented in this dialog.
*/
- public void setEarFilter(String filter)
+ public void setEarFilter(List filter)
{
- earFilterTextField.setText(filter != null ? filter : DEFAULT_EAR_FILTER);
+ earFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_EAR_FILTER);
}
/**
* Returns the ear filter currently represented in this dialog.
*/
- public String getEarFilter()
+ public List getEarFilter()
{
String filter = earFilterTextField.getText();
- return filter.equals(DEFAULT_EAR_FILTER) ? null : filter;
+ return filter.equals(DEFAULT_EAR_FILTER) ? null : ListUtil.commaSeparatedList(filter);
}
/**
* Sets the zip filter to be represented in this dialog.
*/
- public void setZipFilter(String filter)
+ public void setZipFilter(List filter)
{
- zipFilterTextField.setText(filter != null ? filter : DEFAULT_ZIP_FILTER);
+ zipFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_ZIP_FILTER);
}
/**
* Returns the zip filter currently represented in this dialog.
*/
- public String getZipFilter()
+ public List getZipFilter()
{
String filter = zipFilterTextField.getText();
- return filter.equals(DEFAULT_ZIP_FILTER) ? null : filter;
+ return filter.equals(DEFAULT_ZIP_FILTER) ? null : ListUtil.commaSeparatedList(filter);
}
diff --git a/src/proguard/gui/GUIResources.java b/src/proguard/gui/GUIResources.java
index 868de88..85d582c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 28568eb..86ab7a1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+# Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
#
# Tab names.
@@ -25,7 +25,7 @@ preverification = Preverification
#
# Panel titles.
#
-welcome = Welcome to ProGuard, version 4.3
+welcome = Welcome to ProGuard, version 4.4
options = Options
keepAdditional = Keep additional classes and class members
keepNamesAdditional = Keep additional class names and class member names
@@ -64,7 +64,7 @@ proGuardInfo = \
\n\n\
Distributed under the GNU General Public License.\
\n\
- Copyright (c) 2002-2008.
+ Copyright (c) 2002-2009.
processingInfo = \
You can now start processing your code, \
@@ -89,6 +89,7 @@ printUsage = Print usage
optimize = Optimize
allowAccessModification = Allow access modification
mergeInterfacesAggressively = Merge interfaces aggressively
+optimizations = Optimizations
optimizationPasses = Optimization passes
obfuscate = Obfuscate
@@ -99,11 +100,13 @@ classObfuscationDictionary = Class obfuscation dictionary
packageObfuscationDictionary = Package obfuscation dictionary
overloadAggressively = Overload aggressively
useUniqueClassMemberNames = Use unique class member names
+keepPackageNames = Keep package names
flattenPackageHierarchy = Flatten package hierarchy
repackageClasses = Repackage classes
useMixedCaseClassNames = Use mixed-case class names
keepAttributes = Keep attributes
renameSourceFileAttribute = Rename SourceFile attribute
+adaptClassStrings = Adapt class strings
adaptResourceFileNames = Adapt resource file names
adaptResourceFileContents = Adapt resource file contents
@@ -116,6 +119,7 @@ warn = Warn about possibly erronous input
ignoreWarnings = Ignore warnings about possibly erronous input
skipNonPublicLibraryClasses = Skip non-public library classes
skipNonPublicLibraryClassMembers = Skip non-public library class members
+keepDirectories = Keep directories
forceProcessing = Force processing
target = Target
targets = 1.0,1.1,1.2,1.3,1.4,1.5,1.6
@@ -145,8 +149,14 @@ allowAccessModificationTip = \
mergeInterfacesAggressivelyTip = \
<html>Allow interfaces to be merged, even if their implementations don't implement all<br>\
interface methods. This is not allowed in the Java language, but it is allowed in bytecode.</html>
+optimizationsTip = \
+ Specify the types of optimizations to be performed.
+optimizationsFilterTip = \
+ A filter for the names of the optimizations to be performed.
+optimizationsSelectTip = \
+ Select from the currently available optimizations...
optimizationPassesTip = \
- The number of optimization passes to be performed.
+ Specify the number of optimization passes to be performed.
obfuscateTip = \
Obfuscate the names of the processed classes, fields, and methods.
@@ -166,19 +176,31 @@ overloadAggressivelyTip = \
useUniqueClassMemberNamesTip = \
<html>Make sure fields and methods get the same obfuscation mapping across classes, even<br>\
if they are unrelated. This is advisable if the output is to be obfuscated incrementally.</html>
+keepPackageNamesTip = \
+ Keep the specified package names from being obfuscated.
+packageNamesTip = \
+ <html>An optional comma-separated list of package names,<br>\
+ e.g. <code>myapplication,mylibrary.**</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
flattenPackageHierarchyTip = \
Move all packages that are renamed into the given parent package.
repackageClassesTip = \
Move all classes that are renamed into the given package.
packageTip = \
- The package name (optionally nothing, for the root package).
+ The optional package name.
useMixedCaseClassNamesTip = \
<html>Generate mixed-case obfucated class names. This will complicate unpacking<br>\
the resulting jars on case-insensitive file systems, should that be necessary.</html>
keepAttributesTip = \
Keep the specified optional class file attributes.
attributesTip = \
- <html>A comma-separated list of class file attributes.\
+ <html>An optional comma-separated list of class file attributes.\
<ul>\
<li>"Exceptions,Innerclasses, Signature" are necessary if the output is to be used as a library.\
<li>"Deprecated" is optional if the output is to be used as a library.\
@@ -192,11 +214,14 @@ renameSourceFileAttributeTip = \
It will appear as the file name of the classes in stack traces.</html>
sourceFileAttributeTip = \
The replacement "SourceFile" string.
+adaptClassStringsTip = \
+ <html>Adapt string constants in the specified classes, based<br>\
+ on the obfuscated names of corresponding classes.</html>
adaptResourceFileNamesTip = \
<html>Rename the specified resource files, based on the<br>\
obfuscated names of the corresponding class files.</html>
adaptResourceFileContentsTip = \
- <html>Adapt the contents of the given resource files, based<br>\
+ <html>Adapt the contents of the specified resource files, based<br>\
on the obfuscated names of the processed classes.</html>
fileNameFilterTip = \
<html>A filter on file names,<br>\
@@ -206,7 +231,8 @@ fileNameFilterTip = \
<li><code>?</code> for any single character, except the directory separator.\
<li><code>*</code> for any number of any characters, except the directory separator.\
<li><code>**</code> for any number of any characters.\
- </ul></html>
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
preverifyTip = \
Preverify the processed classes, for Java Micro Edition or for Java 6.
@@ -217,9 +243,13 @@ verboseTip = \
Print out verbose messages while processing.
noteTip = \
Print out notes about special or unusual input.
+noteFilterTip = \
+ A filter matching classes for which no notes should be printed.
warnTip = \
<html>Print out warnings about possibly erronous input.<br>\
<i>Only unset this option if you know what you're doing!</i></html>
+warnFilterTip = \
+ A filter matching classes for which no warnings should be printed.
ignoreWarningsTip = \
<html>Ignore any warnings about possibly erronous input.<br>\
<i>Only set this option if you know what you're doing!</i></html>
@@ -229,6 +259,18 @@ skipNonPublicLibraryClassesTip = \
skipNonPublicLibraryClassMembersTip = \
<html>Skip reading non-public library fields and methods, for efficiency.<br>\
You may have to unset this option if ProGuard complains about missing class members.</html>
+keepDirectoriesTip = \
+ Keep the specified directories in the output jars, wars, ears, zips, or directories.
+directoriesTip = \
+ <html>A filter on directory names,<br>\
+ e.g. <code>mydirectory1,mydirectory2/**</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character, except the directory separator.\
+ <li><code>*</code> for any number of any characters, except the directory separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
forceProcessingTip = \
Always process the input, even if the output seems up to date.
targetTip = \
@@ -287,6 +329,10 @@ allowObfuscationTip = \
#
# Further keep titles and labels.
#
+specifyClasses = Specify classes and class members...
+specifyFields = Specify fields...
+specifyMethods = Specify methods...
+
comments = Comments
access = Access
required = Required
@@ -345,57 +391,125 @@ classNameTip = \
<html>The class name, e.g. <code>myPackage.MyClass</code><br>\
Possible wildcards:\
<ul>\
- <li><code>?<code> for any single character, except the package separator.\
- <li><code>*<code> for any number of any characters, except the package separator.\
- <li><code>**<code> for any number of any characters.\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
</ul></html>
classNamesTip = \
<html>A regular expression to further constrain the class names,<br>\
e.g. <code>myPackage1.MyClass,myPackage2.**</code><br>\
Possible wildcards:\
<ul>\
- <li><code>?<code> for any single character, except the package separator.\
- <li><code>*<code> for any number of any characters, except the package separator.\
- <li><code>**<code> for any number of any characters.\
- </ul></html>
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
typeTip = \
<html>The type, e.g. <code>int</code>, or <code>java.lang.String[]</code><br>\
Possible wildcards:\
<ul>\
- <li><code>%<code> for any primitive type.\
- <li><code>?<code> for any single character, except the package separator.\
- <li><code>*<code> for any number of any characters, except the package separator.\
- <li><code>**<code> for any number of any characters.\
- <li><code>***<code> (or empty) for any type.\
+ <li><code>%</code> for any primitive type.\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ <li><code>***</code> (or empty) for any type.\
</ul></html>
fieldNameTip = \
<html>The field name, e.g. <code>myField</code><br>\
Possible wildcards:\
<ul>\
- <li><code>?<code> for any single character.\
- <li><code>*<code> for any number of any characters.\
+ <li><code>?</code> for any single character.\
+ <li><code>*</code> for any number of any characters.\
</ul></html>
methodNameTip = \
<html>The method name, e.g. <code>myMethod</code><br>\
Possible wildcards:\
<ul>\
- <li><code>?<code> for any single character.\
- <li><code>*<code> for any number of any characters.\
+ <li><code>?</code> for any single character.\
+ <li><code>*</code> for any number of any characters.\
</ul></html>
argumentTypes2Tip = \
<html>The comma-separated list of argument types,<br>\
e.g. <code>java.lang.String[],int,boolean</code><br>\
Possible wildcards:\
<ul>\
- <li><code>%<code> for any primitive type.\
- <li><code>?<code> for any single character, except the package separator.\
- <li><code>*<code> for any number of any characters, except the package separator.\
- <li><code>**<code> for any number of any characters.\
- <li><code>***<code> for any type.\
- <li><code>...<code> for any number of any arguments.\
+ <li><code>%</code> for any primitive type.\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ <li><code>***</code> for any type.\
+ <li><code>...</code> for any number of any arguments.\
</ul></html>
#
+# Titles and labels corresponding to optimization options.
+#
+selectOptimizations = Select optimizations...
+
+field = Field
+method = Method
+code = Code
+
+class_marking_finalTip = \
+ Mark classes as final, whenever possible.
+class_merging_verticalTip = \
+ Merge classes vertically in the class hierarchy, whenever possible.
+class_merging_horizontalTip = \
+ Merge classes horizontally in the class hierarchy, whenever possible.
+field_removal_writeonlyTip = \
+ Remove write-only fields.
+field_marking_privateTip = \
+ Mark fields as private, whenever possible.
+field_propagation_valueTip = \
+ Propagate the values of fields across methods.
+method_marking_privateTip = \
+ Mark methods as private, whenever possible (devirtualization).
+method_marking_staticTip = \
+ Mark methods as static, whenever possible (devirtualization).
+method_marking_finalTip = \
+ Mark methods as final, whenever possible.
+method_removal_parameterTip = \
+ Remove unused method parameters.
+method_propagation_parameterTip = \
+ Propagate the values of method parameters from method invocations to \
+ the invoked methods.
+method_propagation_returnvalueTip = \
+ Propagate the values of method return values from methods to their \
+ invocations.
+method_inlining_shortTip = \
+ Inline short methods.
+method_inlining_uniqueTip = \
+ Inline methods that are only called once.
+method_inlining_tailrecursionTip = \
+ Simplify tail recursion calls, whenever possible.
+code_mergingTip = \
+ Merge identical blocks of code by modifying branch targets.
+code_simplification_variableTip = \
+ Perform peephole optimizations for variable loading and storing.
+code_simplification_arithmeticTip = \
+ Perform peephole optimizations for arithmetic instructions.
+code_simplification_castTip = \
+ Perform peephole optimizations for casting operations.
+code_simplification_fieldTip = \
+ Perform peephole optimizations for field loading and storing.
+code_simplification_branchTip = \
+ Perform peephole optimizations for branch instructions.
+code_simplification_advancedTip = \
+ Simplify code based on control flow analysis and data flow analysis.
+code_removal_advancedTip = \
+ Remove dead code based on control flow analysis and data flow analysis.
+code_removal_simpleTip = \
+ Remove dead code based on a simple control flow analysis.
+code_removal_variableTip = \
+ Remove unused variables from the local variable frame.
+code_removal_exceptionTip = \
+ Remove exceptions with empty catch blocks.
+code_allocation_variableTip = \
+ Optimize variable allocation on the local variable frame.
+
+
+#
# File selection titles.
#
selectConfigurationFile = Select a configuration file...
@@ -439,22 +553,24 @@ zipNameFilterTip = A filter on zip file names.
#
# Simple button texts.
#
-previous = Previous
-next = Next
-browse = Browse...
-advanced = Advanced options
-basic = Basic options
-ok = Ok
-cancel = Cancel
-
-add = Add...
-addInput = Add input...
-addOutput = Add output...
-edit = Edit...
-filter = Filter...
-remove = Remove
-moveUp = Move up
-moveDown = Move down
+previous = Previous
+next = Next
+browse = Browse...
+advanced = Advanced options
+basic = Basic options
+selectAll = Select all
+selectNone = Select none
+ok = Ok
+cancel = Cancel
+
+add = Add...
+addInput = Add input...
+addOutput = Add output...
+edit = Edit...
+filter = Filter...
+remove = Remove
+moveUp = Move up
+moveDown = Move down
moveToLibraries = Move to libraries
moveToProgram = Move to program
@@ -462,6 +578,8 @@ moveToProgram = Move to program
addField = Add field...
addMethod = Add method...
+select = Select...
+
loadConfiguration = Load configuration...
viewConfiguration = View configuration
saveConfiguration = Save configuration...
diff --git a/src/proguard/gui/KeepSpecificationsPanel.java b/src/proguard/gui/KeepSpecificationsPanel.java
index 3a3d4b8..4c3c953 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 javax.swing.*;
/**
* This <code>ListPanel</code> allows the user to add, edit, move, and remove
- * KeepSpecification entries in a list.
+ * KeepClassSpecification entries in a list.
*
* @author Eric Lafortune
*/
@@ -60,7 +60,7 @@ final class KeepSpecificationsPanel extends ClassSpecificationsPanel
protected ClassSpecification createClassSpecification()
{
- return new KeepSpecification(markClasses,
+ return new KeepClassSpecification(markClasses,
markConditionally,
allowShrinking,
allowOptimization,
@@ -70,7 +70,7 @@ final class KeepSpecificationsPanel extends ClassSpecificationsPanel
protected void setClassSpecification(ClassSpecification classSpecification)
{
- classSpecificationDialog.setKeepSpecification((KeepSpecification)classSpecification);
+ classSpecificationDialog.setKeepSpecification((KeepClassSpecification)classSpecification);
}
diff --git a/src/proguard/gui/ListPanel.java b/src/proguard/gui/ListPanel.java
index e0ab998..0132340 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 22f5b88..46a3f6f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 @@ final class MemberSpecificationDialog extends JDialog
public MemberSpecificationDialog(JDialog owner, boolean isField)
{
- super(owner, true);
+ super(owner, msg(isField ? "specifyFields" : "specifyMethods"), true);
setResizable(true);
// Create some constraints that can be reused.
@@ -439,8 +439,8 @@ final class MemberSpecificationDialog extends JDialog
* flags of the given keep option.
*/
private void setMemberSpecificationRadioButtons(MemberSpecification memberSpecification,
- int flag,
- JRadioButton[] radioButtons)
+ int flag,
+ JRadioButton[] radioButtons)
{
if (radioButtons != null)
{
diff --git a/src/proguard/gui/MemberSpecificationsPanel.java b/src/proguard/gui/MemberSpecificationsPanel.java
index 9fe5b9f..20b2f17 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 00a02b3..e58f1c6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ package proguard.gui;
import javax.swing.*;
import java.awt.*;
+import java.lang.reflect.InvocationTargetException;
/**
@@ -46,10 +47,17 @@ final class MessageDialogRunnable implements Runnable
String title,
int messageType)
{
- SwingUtil.invokeAndWait(new MessageDialogRunnable(parentComponent,
- message,
- title,
- messageType));
+ try
+ {
+ SwingUtil.invokeAndWait(new MessageDialogRunnable(parentComponent,
+ message,
+ title,
+ messageType));
+ }
+ catch (Exception e)
+ {
+ // Nothing.
+ }
}
diff --git a/src/proguard/gui/OptimizationsDialog.java b/src/proguard/gui/OptimizationsDialog.java
new file mode 100644
index 0000000..044c338
--- /dev/null
+++ b/src/proguard/gui/OptimizationsDialog.java
@@ -0,0 +1,251 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.gui;
+
+import proguard.optimize.Optimizer;
+import proguard.util.*;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * This <code>JDialog</code> allows the user to enter a String.
+ *
+ * @author Eric Lafortune
+ */
+final class OptimizationsDialog extends JDialog
+{
+ /**
+ * Return value if the dialog is canceled (with the Cancel button or by
+ * closing the dialog window).
+ */
+ public static final int CANCEL_OPTION = 1;
+
+ /**
+ * Return value if the dialog is approved (with the Ok button).
+ */
+ public static final int APPROVE_OPTION = 0;
+
+
+ private final JCheckBox[] optimizationCheckBoxes = new JCheckBox[Optimizer.OPTIMIZATION_NAMES.length];
+
+ private int returnValue;
+
+
+ public OptimizationsDialog(JFrame owner)
+ {
+ super(owner, msg("selectOptimizations"), true);
+ setResizable(true);
+
+ // Create some constraints that can be reused.
+ GridBagConstraints constraintsLast = new GridBagConstraints();
+ constraintsLast.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLast.anchor = GridBagConstraints.WEST;
+ constraintsLast.insets = new Insets(1, 2, 1, 2);
+
+ GridBagConstraints constraintsLastStretch = new GridBagConstraints();
+ constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLastStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsLastStretch.weightx = 1.0;
+ constraintsLastStretch.anchor = GridBagConstraints.WEST;
+ constraintsLastStretch.insets = constraintsLast.insets;
+
+ GridBagConstraints panelConstraints = new GridBagConstraints();
+ panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ panelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ panelConstraints.weightx = 1.0;
+ panelConstraints.weighty = 0.0;
+ panelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ panelConstraints.insets = constraintsLast.insets;
+
+ GridBagConstraints selectButtonConstraints = new GridBagConstraints();
+ selectButtonConstraints.weighty = 1.0;
+ selectButtonConstraints.anchor = GridBagConstraints.SOUTHWEST;
+ selectButtonConstraints.insets = new Insets(4, 4, 8, 4);
+
+ GridBagConstraints okButtonConstraints = new GridBagConstraints();
+ okButtonConstraints.weightx = 1.0;
+ okButtonConstraints.weighty = 1.0;
+ okButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ okButtonConstraints.insets = selectButtonConstraints.insets;
+
+ GridBagConstraints cancelButtonConstraints = new GridBagConstraints();
+ cancelButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ cancelButtonConstraints.weighty = 1.0;
+ cancelButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ cancelButtonConstraints.insets = selectButtonConstraints.insets;
+
+ GridBagLayout layout = new GridBagLayout();
+
+ Border etchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
+
+ // Create the optimizations panel.
+ JPanel optimizationsPanel = new JPanel(layout);
+ JPanel optimizationSubpanel = null;
+ String lastOptimizationPrefix = null;
+
+ for (int index = 0; index < Optimizer.OPTIMIZATION_NAMES.length; index++)
+ {
+ String optimizationName = Optimizer.OPTIMIZATION_NAMES[index];
+
+ String optimizationPrefix = optimizationName.substring(0, optimizationName.indexOf('/'));
+
+ if (optimizationSubpanel == null || !optimizationPrefix.equals(lastOptimizationPrefix))
+ {
+ // Create a new keep subpanel and add it.
+ optimizationSubpanel = new JPanel(layout);
+ optimizationSubpanel.setBorder(BorderFactory.createTitledBorder(etchedBorder, msg(optimizationPrefix)));
+ optimizationsPanel.add(optimizationSubpanel, panelConstraints);
+
+ lastOptimizationPrefix = optimizationPrefix;
+ }
+
+ JCheckBox optimizationCheckBox = new JCheckBox(optimizationName);
+ optimizationCheckBoxes[index] = optimizationCheckBox;
+
+ optimizationSubpanel.add(tip(optimizationCheckBox, optimizationName.replace('/', '_')+"Tip"), constraintsLastStretch);
+ }
+
+ // Create the Select All button.
+ JButton selectAllButton = new JButton(msg("selectAll"));
+ selectAllButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ for (int index = 0; index < optimizationCheckBoxes.length; index++)
+ {
+ optimizationCheckBoxes[index].setSelected(true);
+ }
+ }
+ });
+
+ // Create the Select All button.
+ JButton selectNoneButton = new JButton(msg("selectNone"));
+ selectNoneButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ for (int index = 0; index < optimizationCheckBoxes.length; index++)
+ {
+ optimizationCheckBoxes[index].setSelected(false);
+ }
+ }
+ });
+
+ // Create the Ok button.
+ JButton okButton = new JButton(msg("ok"));
+ okButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ returnValue = APPROVE_OPTION;
+ hide();
+ }
+ });
+
+ // Create the Cancel button.
+ JButton cancelButton = new JButton(msg("cancel"));
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ hide();
+ }
+ });
+
+ // Add all panels to the main panel.
+ optimizationsPanel.add(selectAllButton, selectButtonConstraints);
+ optimizationsPanel.add(selectNoneButton, selectButtonConstraints);
+ optimizationsPanel.add(okButton, okButtonConstraints);
+ optimizationsPanel.add(cancelButton, cancelButtonConstraints);
+
+ getContentPane().add(new JScrollPane(optimizationsPanel));
+ }
+
+
+ /**
+ * Sets the initial optimization filter to be used by the dialog.
+ */
+ public void setFilter(String optimizations)
+ {
+ StringMatcher filter = optimizations != null && optimizations.length() > 0 ?
+ new ListParser(new NameParser()).parse(optimizations) :
+ new FixedStringMatcher("");
+
+ for (int index = 0; index < Optimizer.OPTIMIZATION_NAMES.length; index++)
+ {
+ optimizationCheckBoxes[index].setSelected(filter.matches(Optimizer.OPTIMIZATION_NAMES[index]));
+ }
+ }
+
+
+ /**
+ * Returns the optimization filter composed from the settings in the dialog.
+ */
+ public String getFilter()
+ {
+ return new FilterBuilder(optimizationCheckBoxes, '/').buildFilter();
+ }
+
+
+ /**
+ * Shows this dialog. This method only returns when the dialog is closed.
+ *
+ * @return <code>CANCEL_OPTION</code> or <code>APPROVE_OPTION</code>,
+ * depending on the choice of the user.
+ */
+ public int showDialog()
+ {
+ returnValue = CANCEL_OPTION;
+
+ // Open the dialog in the right place, then wait for it to be closed,
+ // one way or another.
+ pack();
+ setLocationRelativeTo(getOwner());
+ show();
+
+ return returnValue;
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/gui/ProGuardGUI.java b/src/proguard/gui/ProGuardGUI.java
index da9e74f..f27d698 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +33,7 @@ import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.List;
+import java.lang.reflect.InvocationTargetException;
/**
@@ -44,10 +45,11 @@ public class ProGuardGUI extends JFrame
{
private static final String NO_SPLASH_OPTION = "-nosplash";
- private static final String TITLE_IMAGE_FILE = "vtitle.gif";
+ private static final String TITLE_IMAGE_FILE = "vtitle.png";
private static final String BOILERPLATE_CONFIGURATION = "boilerplate.pro";
private static final String DEFAULT_CONFIGURATION = "default.pro";
+ private static final String OPTIMIZATIONS_DEFAULT = "*";
private static final String KEEP_ATTRIBUTE_DEFAULT = "Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod";
private static final String SOURCE_FILE_ATTRIBUTE_DEFAULT = "SourceFile";
private static final String ADAPT_RESOURCE_FILE_NAMES_DEFAULT = "**.properties";
@@ -65,15 +67,15 @@ public class ProGuardGUI extends JFrame
private final ClassPathPanel programPanel = new ClassPathPanel(this, true);
private final ClassPathPanel libraryPanel = new ClassPathPanel(this, false);
- private KeepSpecification[] boilerplateKeep;
- private final JCheckBox[] boilerplateKeepCheckBoxes;
- private final JTextField[] boilerplateKeepTextFields;
+ private KeepClassSpecification[] boilerplateKeep;
+ private final JCheckBox[] boilerplateKeepCheckBoxes;
+ private final JTextField[] boilerplateKeepTextFields;
private final KeepSpecificationsPanel additionalKeepPanel = new KeepSpecificationsPanel(this, true, false, false, false, false);
- private KeepSpecification[] boilerplateKeepNames;
- private final JCheckBox[] boilerplateKeepNamesCheckBoxes;
- private final JTextField[] boilerplateKeepNamesTextFields;
+ private KeepClassSpecification[] boilerplateKeepNames;
+ private final JCheckBox[] boilerplateKeepNamesCheckBoxes;
+ private final JTextField[] boilerplateKeepNamesTextFields;
private final KeepSpecificationsPanel additionalKeepNamesPanel = new KeepSpecificationsPanel(this, true, false, true, false, false);
@@ -90,8 +92,10 @@ public class ProGuardGUI extends JFrame
private final JCheckBox optimizeCheckBox = new JCheckBox(msg("optimize"));
private final JCheckBox allowAccessModificationCheckBox = new JCheckBox(msg("allowAccessModification"));
private final JCheckBox mergeInterfacesAggressivelyCheckBox = new JCheckBox(msg("mergeInterfacesAggressively"));
+ private final JLabel optimizationsLabel = new JLabel(msg("optimizations"));
private final JLabel optimizationPassesLabel = new JLabel(msg("optimizationPasses"));
- private final JSpinner optimizationPassesSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 9, 1));
+
+ private final JSpinner optimizationPassesSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 9, 1));
private final JCheckBox obfuscateCheckBox = new JCheckBox(msg("obfuscate"));
private final JCheckBox printMappingCheckBox = new JCheckBox(msg("printMapping"));
@@ -102,10 +106,12 @@ public class ProGuardGUI extends JFrame
private final JCheckBox overloadAggressivelyCheckBox = new JCheckBox(msg("overloadAggressively"));
private final JCheckBox useUniqueClassMemberNamesCheckBox = new JCheckBox(msg("useUniqueClassMemberNames"));
private final JCheckBox useMixedCaseClassNamesCheckBox = new JCheckBox(msg("useMixedCaseClassNames"));
+ private final JCheckBox keepPackageNamesCheckBox = new JCheckBox(msg("keepPackageNames"));
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 newSourceFileAttributeCheckBox = new JCheckBox(msg("renameSourceFileAttribute"));
+ private final JCheckBox adaptClassStringsCheckBox = new JCheckBox(msg("adaptClassStrings"));
private final JCheckBox adaptResourceFileNamesCheckBox = new JCheckBox(msg("adaptResourceFileNames"));
private final JCheckBox adaptResourceFileContentsCheckBox = new JCheckBox(msg("adaptResourceFileContents"));
@@ -113,31 +119,38 @@ public class ProGuardGUI extends JFrame
private final JCheckBox microEditionCheckBox = new JCheckBox(msg("microEdition"));
private final JCheckBox targetCheckBox = new JCheckBox(msg("target"));
- private final JComboBox targetComboBox = new JComboBox(ListUtil.commaSeparatedList(msg("targets")).toArray());
+ private final JComboBox targetComboBox = new JComboBox(ListUtil.commaSeparatedList(msg("targets")).toArray());
private final JCheckBox verboseCheckBox = new JCheckBox(msg("verbose"));
- private final JCheckBox ignoreWarningsCheckBox = new JCheckBox(msg("ignoreWarnings"));
- private final JCheckBox warnCheckBox = new JCheckBox(msg("warn"));
private final JCheckBox noteCheckBox = new JCheckBox(msg("note"));
+ private final JCheckBox warnCheckBox = new JCheckBox(msg("warn"));
+ private final JCheckBox ignoreWarningsCheckBox = new JCheckBox(msg("ignoreWarnings"));
private final JCheckBox skipNonPublicLibraryClassesCheckBox = new JCheckBox(msg("skipNonPublicLibraryClasses"));
private final JCheckBox skipNonPublicLibraryClassMembersCheckBox = new JCheckBox(msg("skipNonPublicLibraryClassMembers"));
+ private final JCheckBox keepDirectoriesCheckBox = new JCheckBox(msg("keepDirectories"));
private final JCheckBox forceProcessingCheckBox = new JCheckBox(msg("forceProcessing"));
private final JCheckBox printSeedsCheckBox = new JCheckBox(msg("printSeeds"));
private final JCheckBox printConfigurationCheckBox = new JCheckBox(msg("printConfiguration"));
private final JCheckBox dumpCheckBox = new JCheckBox(msg("dump"));
private final JTextField printUsageTextField = new JTextField(40);
+ private final JTextField optimizationsTextField = new JTextField(40);
private final JTextField printMappingTextField = new JTextField(40);
private final JTextField applyMappingTextField = new JTextField(40);
private final JTextField obfuscationDictionaryTextField = new JTextField(40);
private final JTextField classObfuscationDictionaryTextField = new JTextField(40);
private final JTextField packageObfuscationDictionaryTextField = new JTextField(40);
+ private final JTextField keepPackageNamesTextField = new JTextField(40);
private final JTextField flattenPackageHierarchyTextField = new JTextField(40);
private final JTextField repackageClassesTextField = new JTextField(40);
private final JTextField keepAttributesTextField = new JTextField(40);
private final JTextField newSourceFileAttributeTextField = new JTextField(40);
+ private final JTextField adaptClassStringsTextField = new JTextField(40);
private final JTextField adaptResourceFileNamesTextField = new JTextField(40);
private final JTextField adaptResourceFileContentsTextField = new JTextField(40);
+ private final JTextField noteTextField = new JTextField(40);
+ private final JTextField warnTextField = new JTextField(40);
+ private final JTextField keepDirectoriesTextField = new JTextField(40);
private final JTextField printSeedsTextField = new JTextField(40);
private final JTextField printConfigurationTextField = new JTextField(40);
private final JTextField dumpTextField = new JTextField(40);
@@ -382,6 +395,8 @@ public class ProGuardGUI extends JFrame
obfuscationOptionsPanel.add(tip(overloadAggressivelyCheckBox, "overloadAggressivelyTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(useUniqueClassMemberNamesCheckBox, "useUniqueClassMemberNamesTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(useMixedCaseClassNamesCheckBox, "useMixedCaseClassNamesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(keepPackageNamesCheckBox, "keepPackageNamesTip"), constraints);
+ obfuscationOptionsPanel.add(tip(keepPackageNamesTextField, "packageNamesTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(flattenPackageHierarchyCheckBox, "flattenPackageHierarchyTip"), constraints);
obfuscationOptionsPanel.add(tip(flattenPackageHierarchyTextField, "packageTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(repackageClassesCheckBox, "repackageClassesTip"), constraints);
@@ -390,6 +405,8 @@ public class ProGuardGUI extends JFrame
obfuscationOptionsPanel.add(tip(keepAttributesTextField, "attributesTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(newSourceFileAttributeCheckBox, "renameSourceFileAttributeTip"), constraints);
obfuscationOptionsPanel.add(tip(newSourceFileAttributeTextField, "sourceFileAttributeTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(adaptClassStringsCheckBox, "adaptClassStringsTip"), constraints);
+ obfuscationOptionsPanel.add(tip(adaptClassStringsTextField, "classNamesTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(adaptResourceFileNamesCheckBox, "adaptResourceFileNamesTip"), constraints);
obfuscationOptionsPanel.add(tip(adaptResourceFileNamesTextField, "fileNameFilterTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(adaptResourceFileContentsCheckBox, "adaptResourceFileContentsTip"), constraints);
@@ -412,9 +429,15 @@ public class ProGuardGUI extends JFrame
JPanel optimizationOptionsPanel = new JPanel(layout);
addBorder(optimizationOptionsPanel, "options");
+ JButton optimizationsButton =
+ createOptimizationsButton(optimizationsTextField);
+
optimizationOptionsPanel.add(tip(optimizeCheckBox, "optimizeTip"), constraintsLastStretch);
optimizationOptionsPanel.add(tip(allowAccessModificationCheckBox, "allowAccessModificationTip"), constraintsLastStretch);
optimizationOptionsPanel.add(tip(mergeInterfacesAggressivelyCheckBox, "mergeInterfacesAggressivelyTip"), constraintsLastStretch);
+ optimizationOptionsPanel.add(tip(optimizationsLabel, "optimizationsTip"), constraints);
+ optimizationOptionsPanel.add(tip(optimizationsTextField, "optimizationsFilterTip"), constraintsStretch);
+ optimizationOptionsPanel.add(tip(optimizationsButton, "optimizationsSelectTip"), constraintsLast);
optimizationOptionsPanel.add(tip(optimizationPassesLabel, "optimizationPassesTip"), constraints);
optimizationOptionsPanel.add(tip(optimizationPassesSpinner, "optimizationPassesTip"), constraintsLast);
@@ -454,11 +477,15 @@ public class ProGuardGUI extends JFrame
addBorder(consistencyPanel, "consistencyAndCorrectness");
consistencyPanel.add(tip(verboseCheckBox, "verboseTip"), constraintsLastStretch);
- consistencyPanel.add(tip(noteCheckBox, "noteTip"), constraintsLastStretch);
- consistencyPanel.add(tip(warnCheckBox, "warnTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(noteCheckBox, "noteTip"), constraints);
+ consistencyPanel.add(tip(noteTextField, "noteFilterTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(warnCheckBox, "warnTip"), constraints);
+ consistencyPanel.add(tip(warnTextField, "warnFilterTip"), constraintsLastStretch);
consistencyPanel.add(tip(ignoreWarningsCheckBox, "ignoreWarningsTip"), constraintsLastStretch);
consistencyPanel.add(tip(skipNonPublicLibraryClassesCheckBox, "skipNonPublicLibraryClassesTip"), constraintsLastStretch);
consistencyPanel.add(tip(skipNonPublicLibraryClassMembersCheckBox, "skipNonPublicLibraryClassMembersTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(keepDirectoriesCheckBox, "keepDirectoriesTip"), constraints);
+ consistencyPanel.add(tip(keepDirectoriesTextField, "directoriesTip"), constraintsLastStretch);
consistencyPanel.add(tip(forceProcessingCheckBox, "forceProcessingTip"), constraintsLastStretch);
consistencyPanel.add(tip(printSeedsCheckBox, "printSeedsTip"), constraints);
consistencyPanel.add(tip(printSeedsTextField, "outputFileTip"), constraintsStretch);
@@ -669,40 +696,40 @@ public class ProGuardGUI extends JFrame
* Returns an array containing the ClassSpecifications instances with
* matching flags.
*/
- private KeepSpecification[] extractKeepSpecifications(List keepSpecifications,
- boolean allowShrinking,
- boolean allowObfuscation)
+ private KeepClassSpecification[] extractKeepSpecifications(List keepSpecifications,
+ boolean allowShrinking,
+ boolean allowObfuscation)
{
List matches = new ArrayList();
for (int index = 0; index < keepSpecifications.size(); index++)
{
- KeepSpecification keepSpecification = (KeepSpecification)keepSpecifications.get(index);
- if (keepSpecification.allowShrinking == allowShrinking &&
- keepSpecification.allowObfuscation == allowObfuscation)
+ KeepClassSpecification keepClassSpecification = (KeepClassSpecification)keepSpecifications.get(index);
+ if (keepClassSpecification.allowShrinking == allowShrinking &&
+ keepClassSpecification.allowObfuscation == allowObfuscation)
{
- matches.add(keepSpecification);
+ matches.add(keepClassSpecification);
}
}
- KeepSpecification[] matchingKeepSpecifications = new KeepSpecification[matches.size()];
- matches.toArray(matchingKeepSpecifications);
+ KeepClassSpecification[] matchingKeepClassSpecifications = new KeepClassSpecification[matches.size()];
+ matches.toArray(matchingKeepClassSpecifications);
- return matchingKeepSpecifications;
+ return matchingKeepClassSpecifications;
}
/**
* Returns an array containing the ClassSpecification instances of the
- * given array of KeepSpecification instances.
+ * given array of KeepClassSpecification instances.
*/
- private ClassSpecification[] extractClassSpecifications(KeepSpecification[] keepSpecifications)
+ private ClassSpecification[] extractClassSpecifications(KeepClassSpecification[] keepClassSpecifications)
{
- ClassSpecification[] classSpecifications = new ClassSpecification[keepSpecifications.length];
+ ClassSpecification[] classSpecifications = new ClassSpecification[keepClassSpecifications.length];
for (int index = 0; index < classSpecifications.length; index++)
{
- classSpecifications[index] = keepSpecifications[index];
+ classSpecifications[index] = keepClassSpecifications[index];
}
return classSpecifications;
@@ -840,12 +867,14 @@ public class ProGuardGUI extends JFrame
{
public void actionPerformed(ActionEvent e)
{
+ // Update the file chooser.
fileChooser.setDialogTitle(title);
fileChooser.setSelectedFile(new File(textField.getText()));
int returnVal = fileChooser.showDialog(ProGuardGUI.this, msg("ok"));
if (returnVal == JFileChooser.APPROVE_OPTION)
{
+ // Update the text field.
textField.setText(fileChooser.getSelectedFile().getPath());
}
}
@@ -855,6 +884,31 @@ public class ProGuardGUI extends JFrame
}
+ protected JButton createOptimizationsButton(final JTextField textField)
+ {
+ final OptimizationsDialog optimizationsDialog = new OptimizationsDialog(ProGuardGUI.this);
+
+ JButton optimizationsButton = new JButton(msg("select"));
+ optimizationsButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ // Update the dialog.
+ optimizationsDialog.setFilter(textField.getText());
+
+ int returnValue = optimizationsDialog.showDialog();
+ if (returnValue == OptimizationsDialog.APPROVE_OPTION)
+ {
+ // Update the text field.
+ textField.setText(optimizationsDialog.getFilter());
+ }
+ }
+ });
+
+ return optimizationsButton;
+ }
+
+
/**
* Sets the preferred sizes of the given components to the maximum of their
* current preferred sizes.
@@ -945,12 +999,12 @@ public class ProGuardGUI extends JFrame
// Set up the other options.
shrinkCheckBox .setSelected(configuration.shrink);
- printUsageCheckBox .setSelected(configuration.printUsage != null);
+ printUsageCheckBox .setSelected(configuration.printUsage != null);
optimizeCheckBox .setSelected(configuration.optimize);
- optimizationPassesSpinner.getModel() .setValue(new Integer(configuration.optimizationPasses));
allowAccessModificationCheckBox .setSelected(configuration.allowAccessModification);
mergeInterfacesAggressivelyCheckBox .setSelected(configuration.mergeInterfacesAggressively);
+ optimizationPassesSpinner.getModel() .setValue(new Integer(configuration.optimizationPasses));
obfuscateCheckBox .setSelected(configuration.obfuscate);
printMappingCheckBox .setSelected(configuration.printMapping != null);
@@ -961,10 +1015,12 @@ public class ProGuardGUI extends JFrame
overloadAggressivelyCheckBox .setSelected(configuration.overloadAggressively);
useUniqueClassMemberNamesCheckBox .setSelected(configuration.useUniqueClassMemberNames);
useMixedCaseClassNamesCheckBox .setSelected(configuration.useMixedCaseClassNames);
+ keepPackageNamesCheckBox .setSelected(configuration.keepPackageNames != null);
flattenPackageHierarchyCheckBox .setSelected(configuration.flattenPackageHierarchy != null);
repackageClassesCheckBox .setSelected(configuration.repackageClasses != null);
keepAttributesCheckBox .setSelected(configuration.keepAttributes != null);
newSourceFileAttributeCheckBox .setSelected(configuration.newSourceFileAttribute != null);
+ adaptClassStringsCheckBox .setSelected(configuration.adaptClassStrings != null);
adaptResourceFileNamesCheckBox .setSelected(configuration.adaptResourceFileNames != null);
adaptResourceFileContentsCheckBox .setSelected(configuration.adaptResourceFileContents != null);
@@ -973,26 +1029,33 @@ public class ProGuardGUI extends JFrame
targetCheckBox .setSelected(configuration.targetClassVersion != 0);
verboseCheckBox .setSelected(configuration.verbose);
- noteCheckBox .setSelected(configuration.note);
- warnCheckBox .setSelected(configuration.warn);
+ noteCheckBox .setSelected(configuration.note == null || !configuration.note.isEmpty());
+ warnCheckBox .setSelected(configuration.warn == null || !configuration.warn.isEmpty());
ignoreWarningsCheckBox .setSelected(configuration.ignoreWarnings);
skipNonPublicLibraryClassesCheckBox .setSelected(configuration.skipNonPublicLibraryClasses);
skipNonPublicLibraryClassMembersCheckBox.setSelected(configuration.skipNonPublicLibraryClassMembers);
+ keepDirectoriesCheckBox .setSelected(configuration.keepDirectories != null);
forceProcessingCheckBox .setSelected(configuration.lastModified == Long.MAX_VALUE);
- printSeedsCheckBox .setSelected(configuration.printSeeds != null);
- printConfigurationCheckBox .setSelected(configuration.printConfiguration != null);
- dumpCheckBox .setSelected(configuration.dump != null);
+ printSeedsCheckBox .setSelected(configuration.printSeeds != null);
+ printConfigurationCheckBox .setSelected(configuration.printConfiguration != null);
+ dumpCheckBox .setSelected(configuration.dump != null);
printUsageTextField .setText(fileName(configuration.printUsage));
+ optimizationsTextField .setText(configuration.optimizations == null ? OPTIMIZATIONS_DEFAULT : ListUtil.commaSeparatedString(configuration.optimizations));
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)));
flattenPackageHierarchyTextField .setText(configuration.flattenPackageHierarchy);
repackageClassesTextField .setText(configuration.repackageClasses);
keepAttributesTextField .setText(configuration.keepAttributes == null ? KEEP_ATTRIBUTE_DEFAULT : ListUtil.commaSeparatedString(configuration.keepAttributes));
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));
printSeedsTextField .setText(fileName(configuration.printSeeds));
printConfigurationTextField .setText(fileName(configuration.printConfiguration));
dumpTextField .setText(fileName(configuration.dump));
@@ -1098,43 +1161,47 @@ public class ProGuardGUI extends JFrame
// Get the other options.
configuration.shrink = shrinkCheckBox .isSelected();
- configuration.printUsage = printUsageCheckBox .isSelected() ? new File(printUsageTextField .getText()) : null;
+ configuration.printUsage = printUsageCheckBox .isSelected() ? new File(printUsageTextField .getText()) : null;
configuration.optimize = optimizeCheckBox .isSelected();
- configuration.optimizationPasses = ((SpinnerNumberModel)optimizationPassesSpinner.getModel()).getNumber().intValue();
configuration.allowAccessModification = allowAccessModificationCheckBox .isSelected();
configuration.mergeInterfacesAggressively = mergeInterfacesAggressivelyCheckBox .isSelected();
+ configuration.optimizations = optimizationsTextField.getText().length() > 1 ? ListUtil.commaSeparatedList(optimizationsTextField .getText()) : null;
+ configuration.optimizationPasses = ((SpinnerNumberModel)optimizationPassesSpinner.getModel()).getNumber().intValue();
configuration.obfuscate = obfuscateCheckBox .isSelected();
- configuration.printMapping = printMappingCheckBox .isSelected() ? new File(printMappingTextField .getText()) : null;
- configuration.applyMapping = applyMappingCheckBox .isSelected() ? new File(applyMappingTextField .getText()) : null;
- configuration.obfuscationDictionary = obfuscationDictionaryCheckBox .isSelected() ? new File(obfuscationDictionaryTextField .getText()) : null;
- configuration.classObfuscationDictionary = classObfuscationDictionaryCheckBox .isSelected() ? new File(classObfuscationDictionaryTextField .getText()) : null;
- configuration.packageObfuscationDictionary = packageObfuscationDictionaryCheckBox .isSelected() ? new File(packageObfuscationDictionaryTextField .getText()) : null;
+ configuration.printMapping = printMappingCheckBox .isSelected() ? new File(printMappingTextField .getText()) : null;
+ configuration.applyMapping = applyMappingCheckBox .isSelected() ? new File(applyMappingTextField .getText()) : null;
+ configuration.obfuscationDictionary = obfuscationDictionaryCheckBox .isSelected() ? new File(obfuscationDictionaryTextField .getText()) : null;
+ configuration.classObfuscationDictionary = classObfuscationDictionaryCheckBox .isSelected() ? new File(classObfuscationDictionaryTextField .getText()) : null;
+ configuration.packageObfuscationDictionary = packageObfuscationDictionaryCheckBox .isSelected() ? new File(packageObfuscationDictionaryTextField .getText()) : null;
configuration.overloadAggressively = overloadAggressivelyCheckBox .isSelected();
configuration.useUniqueClassMemberNames = useUniqueClassMemberNamesCheckBox .isSelected();
configuration.useMixedCaseClassNames = useMixedCaseClassNamesCheckBox .isSelected();
- 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.newSourceFileAttribute = newSourceFileAttributeCheckBox .isSelected() ? newSourceFileAttributeTextField .getText() : null;
- configuration.adaptResourceFileNames = adaptResourceFileNamesCheckBox .isSelected() ? ListUtil.commaSeparatedList(adaptResourceFileNamesTextField .getText()) : null;
- configuration.adaptResourceFileContents = adaptResourceFileContentsCheckBox .isSelected() ? ListUtil.commaSeparatedList(adaptResourceFileContentsTextField.getText()) : null;
+ configuration.keepPackageNames = keepPackageNamesCheckBox .isSelected() ? keepPackageNamesTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(keepPackageNamesTextField.getText())) : new ArrayList() : null;
+ 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.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;
+ configuration.adaptResourceFileContents = adaptResourceFileContentsCheckBox .isSelected() ? ListUtil.commaSeparatedList(adaptResourceFileContentsTextField .getText()) : null;
configuration.preverify = preverifyCheckBox .isSelected();
configuration.microEdition = microEditionCheckBox .isSelected();
configuration.targetClassVersion = targetCheckBox .isSelected() ? ClassUtil.internalClassVersion(targetComboBox.getSelectedItem().toString()) : 0;
configuration.verbose = verboseCheckBox .isSelected();
- configuration.note = noteCheckBox .isSelected();
- configuration.warn = warnCheckBox .isSelected();
+ configuration.note = noteCheckBox .isSelected() ? noteTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(noteTextField.getText())) : null : new ArrayList();
+ configuration.warn = warnCheckBox .isSelected() ? warnTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(warnTextField.getText())) : null : new ArrayList();
configuration.ignoreWarnings = ignoreWarningsCheckBox .isSelected();
configuration.skipNonPublicLibraryClasses = skipNonPublicLibraryClassesCheckBox .isSelected();
configuration.skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembersCheckBox.isSelected();
+ configuration.keepDirectories = keepDirectoriesCheckBox .isSelected() ? keepDirectoriesTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(keepDirectoriesTextField.getText())) : new ArrayList() : null;
configuration.lastModified = forceProcessingCheckBox .isSelected() ? Long.MAX_VALUE : System.currentTimeMillis();
- configuration.printSeeds = printSeedsCheckBox .isSelected() ? new File(printSeedsTextField .getText()) : null;
- configuration.printConfiguration = printConfigurationCheckBox .isSelected() ? new File(printConfigurationTextField .getText()) : null;
- configuration.dump = dumpCheckBox .isSelected() ? new File(dumpTextField .getText()) : null;
+ configuration.printSeeds = printSeedsCheckBox .isSelected() ? new File(printSeedsTextField .getText()) : null;
+ configuration.printConfiguration = printConfigurationCheckBox .isSelected() ? new File(printConfigurationTextField .getText()) : null;
+ configuration.dump = dumpCheckBox .isSelected() ? new File(dumpTextField .getText()) : null;
return configuration;
}
@@ -1179,12 +1246,12 @@ public class ProGuardGUI extends JFrame
for (int index = 0; index < keepSpecifications.size(); index++)
{
- KeepSpecification keepSpecification =
- (KeepSpecification)keepSpecifications.get(index);
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepSpecifications.get(index);
- if (keepSpecification.allowShrinking == allowShrinking)
+ if (keepClassSpecification.allowShrinking == allowShrinking)
{
- filteredKeepSpecifications.add(keepSpecification);
+ filteredKeepSpecifications.add(keepClassSpecification);
}
}
@@ -1198,7 +1265,7 @@ public class ProGuardGUI extends JFrame
* matching keep specifications, and removes the matching keep
* specifications as a side effect.
*/
- private String findMatchingKeepSpecifications(KeepSpecification keepSpecificationTemplate,
+ private String findMatchingKeepSpecifications(KeepClassSpecification keepClassSpecificationTemplate,
List keepSpecifications)
{
if (keepSpecifications == null)
@@ -1210,11 +1277,11 @@ public class ProGuardGUI extends JFrame
for (int index = 0; index < keepSpecifications.size(); index++)
{
- KeepSpecification listedKeepSpecification =
- (KeepSpecification)keepSpecifications.get(index);
- String className = listedKeepSpecification.className;
- keepSpecificationTemplate.className = className;
- if (keepSpecificationTemplate.equals(listedKeepSpecification))
+ KeepClassSpecification listedKeepClassSpecification =
+ (KeepClassSpecification)keepSpecifications.get(index);
+ String className = listedKeepClassSpecification.className;
+ keepClassSpecificationTemplate.className = className;
+ if (keepClassSpecificationTemplate.equals(listedKeepClassSpecification))
{
if (buffer == null)
{
@@ -1620,45 +1687,52 @@ public class ProGuardGUI extends JFrame
*/
public static void main(final String[] args)
{
-// SwingUtil.invokeAndWait(new Runnable()
-// {
-// public void run()
+ try
+ {
+ SwingUtil.invokeAndWait(new Runnable()
{
- 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
+ public void run()
{
- gui.startSplash();
- }
+ 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++;
- }
+ // 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)
+ {
+ System.out.println(gui.getClass().getName() + ": ignoring extra arguments [" + args[argIndex] + "...]");
+ }
- }
-// });
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ // Nothing.
+ }
}
}
diff --git a/src/proguard/gui/ProGuardRunnable.java b/src/proguard/gui/ProGuardRunnable.java
index 56ccb36..c5c5937 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e9355a6..1ca19ca 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,8 @@ final class ReTraceRunnable implements Runnable
try
{
// Create a new ProGuard object with the GUI's configuration.
- ReTrace reTrace = new ReTrace(verbose,
+ ReTrace reTrace = new ReTrace(ReTrace.STACK_TRACE_EXPRESSION,
+ verbose,
mappingFile);
// Run it.
diff --git a/src/proguard/gui/SwingUtil.java b/src/proguard/gui/SwingUtil.java
index bceccfe..75d2f02 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.gui;
import javax.swing.*;
+import java.lang.reflect.InvocationTargetException;
/**
@@ -30,7 +31,7 @@ import javax.swing.*;
* @see SwingUtilities
* @author Eric Lafortune
*/
-class SwingUtil
+public class SwingUtil
{
/**
* Invokes the given Runnable in the AWT event dispatching thread,
@@ -40,6 +41,7 @@ class SwingUtil
* @param runnable the Runnable to be executed.
*/
public static void invokeAndWait(Runnable runnable)
+ throws InterruptedException, InvocationTargetException
{
try
{
diff --git a/src/proguard/gui/TabbedPane.java b/src/proguard/gui/TabbedPane.java
index 35dad8f..a6460f5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -155,14 +155,15 @@ public class TabbedPane
imageConstraints.fill = GridBagConstraints.BOTH;
imageConstraints.anchor = GridBagConstraints.SOUTHWEST;
- JPanel component = new JPanel()
- {
- public void paintComponent(Graphics graphics)
- {
- graphics.drawImage(image, 0, getHeight() - image.getHeight(null), this);
- }
- };
- component.setBorder(BorderFactory.createEtchedBorder());
+ JButton component = new JButton(new ImageIcon(image));
+ component.setFocusPainted(false);
+ component.setFocusable(false);
+ component.setRequestFocusEnabled(false);
+ component.setRolloverEnabled(false);
+ component.setMargin(new Insets(0, 0, 0, 0));
+ component.setHorizontalAlignment(JButton.LEFT);
+ component.setVerticalAlignment(JButton.BOTTOM);
+ component.setPreferredSize(new Dimension(0, 0));
add(component, imageConstraints);
diff --git a/src/proguard/gui/TextAreaOutputStream.java b/src/proguard/gui/TextAreaOutputStream.java
index d46b3b1..57f983d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ package proguard.gui;
import javax.swing.*;
import java.io.*;
+import java.lang.reflect.InvocationTargetException;
/**
@@ -48,8 +49,15 @@ final class TextAreaOutputStream extends FilterOutputStream implements Runnable
{
super.flush();
- // Append the accumulated buffer contents to the text area.
- SwingUtil.invokeAndWait(this);
+ try
+ {
+ // Append the accumulated buffer contents to the text area.
+ SwingUtil.invokeAndWait(this);
+ }
+ catch (Exception e)
+ {
+ // Nothing.
+ }
}
diff --git a/src/proguard/gui/splash/BufferedSprite.java b/src/proguard/gui/splash/BufferedSprite.java
index dfa52ec..8427832 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 26f6782..5dc65eb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 70cd627..55f9eac 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 c3b2372..3f9bc3b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 b8b524a..2480ead 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e520fac..94c78df 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 1ae8386..0874d6d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 4a01c6e..3f1ac03 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 da39e66..537196d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 6ab1548..7617c3f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 19ba182..dfde644 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 11c77cb..9a554ba 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 afdea51..6e7c189 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 83c22fd..3a7674d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 cb3b7f9..046ae84 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 80d5b2b..8d299bc 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 dfd9171..9b26644 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 45277b6..4333459 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 5f81330..d204831 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e470d50..076d5e2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 a273e46..c3504f3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 90ea8b8..eb0a7cc 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 69f9aba..a985712 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 2d49646..23a9ce4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.gui.splash;
+import proguard.gui.SwingUtil;
+
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@@ -114,7 +116,7 @@ public class SplashPanel extends JPanel
// Repaint the SplashPanel one last time.
try
{
- SwingUtilities.invokeAndWait(repainter);
+ SwingUtil.invokeAndWait(repainter);
}
catch (InterruptedException ex)
{
@@ -157,7 +159,7 @@ public class SplashPanel extends JPanel
}
// Do a repaint and time it.
- SwingUtilities.invokeAndWait(repainter);
+ SwingUtil.invokeAndWait(repainter);
// Sleep for a proportional while.
long repaintTime = System.currentTimeMillis() - time;
diff --git a/src/proguard/gui/splash/Sprite.java b/src/proguard/gui/splash/Sprite.java
index 990c53a..ada7a81 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 d287914..bbf37d4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 49c3b27..921bef2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 84b09e9..887d737 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 d576e28..9f1441e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 908e057..6a30062 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 b72362b..39302dd 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 1676b63..a7de8d7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 a58d138..68a33af 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 949eeb0..e36d28c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e98b93e..1dec23b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/vtitle.gif b/src/proguard/gui/vtitle.gif
deleted file mode 100644
index 646c69b..0000000
Binary files a/src/proguard/gui/vtitle.gif and /dev/null differ
diff --git a/src/proguard/gui/vtitle.png b/src/proguard/gui/vtitle.png
new file mode 100644
index 0000000..218f716
Binary files /dev/null and b/src/proguard/gui/vtitle.png differ
diff --git a/src/proguard/io/CascadingDataEntryWriter.java b/src/proguard/io/CascadingDataEntryWriter.java
index 6347bf0..15719e6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +52,16 @@ public class CascadingDataEntryWriter implements DataEntryWriter
// Implementations for DataEntryWriter.
+
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ // Try to create a directory with the first data entry writer, or
+ // otherwise with the second data entry writer.
+ return dataEntryWriter1.createDirectory(dataEntry) ||
+ dataEntryWriter2.createDirectory(dataEntry);
+ }
+
+
public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
{
return getOutputStream(dataEntry, null);
diff --git a/src/proguard/io/ClassFilter.java b/src/proguard/io/ClassFilter.java
index 01fbaf3..bf591ab 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,11 +32,8 @@ import java.io.IOException;
*
* @author Eric Lafortune
*/
-public class ClassFilter implements DataEntryReader
+public class ClassFilter extends FilteredDataEntryReader
{
- private final FilteredDataEntryReader filteredDataEntryReader;
-
-
/**
* Creates a new ClassFilter that delegates reading classes to the
* given reader.
@@ -54,19 +51,9 @@ public class ClassFilter implements DataEntryReader
public ClassFilter(DataEntryReader classReader,
DataEntryReader dataEntryReader)
{
- filteredDataEntryReader =
- new FilteredDataEntryReader(
- new DataEntryNameFilter(
- new ExtensionMatcher(ClassConstants.CLASS_FILE_EXTENSION)),
- classReader,
- dataEntryReader);
- }
-
-
- // Implementations for DataEntryReader.
-
- public void read(DataEntry dataEntry) throws IOException
- {
- filteredDataEntryReader.read(dataEntry);
+ super(new DataEntryNameFilter(
+ new ExtensionMatcher(ClassConstants.CLASS_FILE_EXTENSION)),
+ classReader,
+ dataEntryReader);
}
}
diff --git a/src/proguard/io/ClassReader.java b/src/proguard/io/ClassReader.java
index d6c28d3..e21968c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -98,7 +98,8 @@ public class ClassReader implements DataEntryReader
if (!dataEntry.getName().replace(File.pathSeparatorChar, ClassConstants.INTERNAL_PACKAGE_SEPARATOR).equals(className+ClassConstants.CLASS_FILE_EXTENSION) &&
warningPrinter != null)
{
- warningPrinter.print("Warning: class [" + dataEntry.getName() + "] unexpectedly contains class [" + ClassUtil.externalClassName(className) + "]");
+ warningPrinter.print(className,
+ "Warning: class [" + dataEntry.getName() + "] unexpectedly contains class [" + ClassUtil.externalClassName(className) + "]");
}
clazz.accept(classVisitor);
diff --git a/src/proguard/io/ClassRewriter.java b/src/proguard/io/ClassRewriter.java
index 98cafdd..bd19e1d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 d5d9018..af0e373 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.io;
import java.io.*;
/**
- * This interface describes a data entry, e.g. a ZIP entry or a file.
+ * This interface describes a data entry, e.g. a ZIP entry, a file, or a
+ * directory.
*
* @author Eric Lafortune
*/
@@ -34,9 +35,15 @@ public interface DataEntry
*/
public String getName();
+ /**
+ * Returns whether the data entry represents a directory.
+ */
+ public boolean isDirectory();
+
/**
* Returns an input stream for reading the content of this data entry.
+ * The data entry may not represent a directory.
*/
public InputStream getInputStream() throws IOException;
diff --git a/src/proguard/io/DataEntryCopier.java b/src/proguard/io/DataEntryCopier.java
index 2f6e37e..faaa555 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -52,17 +52,24 @@ public class DataEntryCopier implements DataEntryReader
{
try
{
- // Get the output entry corresponding to this input entry.
- OutputStream outputStream = dataEntryWriter.getOutputStream(dataEntry);
- if (outputStream != null)
+ if (dataEntry.isDirectory())
{
- InputStream inputStream = dataEntry.getInputStream();
+ dataEntryWriter.createDirectory(dataEntry);
+ }
+ else
+ {
+ // Get the output entry corresponding to this input entry.
+ OutputStream outputStream = dataEntryWriter.getOutputStream(dataEntry);
+ if (outputStream != null)
+ {
+ InputStream inputStream = dataEntry.getInputStream();
- // Copy the data from the input entry to the output entry.
- copyData(inputStream, outputStream);
+ // Copy the data from the input entry to the output entry.
+ copyData(inputStream, outputStream);
- // Close the data entries.
- dataEntry.closeInputStream();
+ // Close the data entries.
+ dataEntry.closeInputStream();
+ }
}
}
catch (IOException ex)
@@ -72,14 +79,12 @@ public class DataEntryCopier implements DataEntryReader
}
- // Small utility methods.
-
/**
* Copies all data that it can read from the given input stream to the
* given output stream.
*/
- private void copyData(InputStream inputStream,
- OutputStream outputStream)
+ protected void copyData(InputStream inputStream,
+ OutputStream outputStream)
throws IOException
{
while (true)
diff --git a/src/proguard/io/DataEntryReader.java b/src/proguard/io/DataEntryDirectoryFilter.java
similarity index 67%
copy from src/proguard/io/DataEntryReader.java
copy to src/proguard/io/DataEntryDirectoryFilter.java
index 4759310..bb36f3e 100644
--- a/src/proguard/io/DataEntryReader.java
+++ b/src/proguard/io/DataEntryDirectoryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,19 +20,21 @@
*/
package proguard.io;
-import java.io.IOException;
-
+import proguard.util.StringMatcher;
/**
- * This interface provides methods for reading data entries. The implementation
- * determines what to do with the read data, if anything.
+ * This DataEntryFilter filters data entries based on whether they represent
+ * directories.
*
* @author Eric Lafortune
*/
-public interface DataEntryReader
+public class DataEntryDirectoryFilter
+implements DataEntryFilter
{
- /**
- * Reads the given data entry.
- */
- public void read(DataEntry dataEntry) throws IOException;
-}
+ // Implementations for DataEntryFilter.
+
+ public boolean accepts(DataEntry dataEntry)
+ {
+ return dataEntry != null && dataEntry.isDirectory();
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/io/DataEntryFilter.java b/src/proguard/io/DataEntryFilter.java
index e84c4c6..ddcd0be 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 21947e1..d6afd2e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/DataEntryObfuscator.java
similarity index 64%
copy from src/proguard/io/DataEntryRenamer.java
copy to src/proguard/io/DataEntryObfuscator.java
index 34f5a21..aa63af1 100644
--- a/src/proguard/io/DataEntryRenamer.java
+++ b/src/proguard/io/DataEntryObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,10 @@
package proguard.io;
import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
import java.io.IOException;
+import java.util.Map;
/**
* This DataEntryReader delegates to another DataEntryReader, renaming the
@@ -30,17 +32,29 @@ import java.io.IOException;
*
* @author Eric Lafortune
*/
-public class DataEntryRenamer implements DataEntryReader
+public class DataEntryObfuscator implements DataEntryReader
{
private final ClassPool classPool;
+ private final Map packagePrefixMap;
private final DataEntryReader dataEntryReader;
- public DataEntryRenamer(ClassPool classPool,
- DataEntryReader dataEntryReader)
+ /**
+ * Creates a new DataEntryObfuscator.
+ * @param classPool the class pool that maps from old names to new
+ * names.
+ * @param packagePrefixMap the map from old package prefixes to new package
+ * prefixes.
+ * @param dataEntryReader the DataEntryReader to which calls will be
+ * delegated.
+ */
+ public DataEntryObfuscator(ClassPool classPool,
+ Map packagePrefixMap,
+ DataEntryReader dataEntryReader)
{
- this.classPool = classPool;
- this.dataEntryReader = dataEntryReader;
+ this.classPool = classPool;
+ this.packagePrefixMap = packagePrefixMap;
+ this.dataEntryReader = dataEntryReader;
}
@@ -69,15 +83,15 @@ public class DataEntryRenamer implements DataEntryReader
char c = dataEntryName.charAt(suffixIndex);
if (!Character.isLetterOrDigit(c))
{
- // Stop looking at the first package separator.
+ // Chop off the suffix.
+ String className = dataEntryName.substring(0, suffixIndex);
+
+ // Did we get to the package separator?
if (c == ClassConstants.INTERNAL_PACKAGE_SEPARATOR)
{
break;
}
- // Chop off the suffix.
- String className = dataEntryName.substring(0, suffixIndex);
-
// Is there a class corresponding to the data entry?
Clazz clazz = classPool.getClass(className);
if (clazz != null)
@@ -87,9 +101,8 @@ public class DataEntryRenamer implements DataEntryReader
if (!className.equals(newClassName))
{
// Return a renamed data entry.
- String newDataEntryName = suffixIndex > 0 ?
- newClassName + dataEntryName.substring(suffixIndex) :
- newClassName;
+ String newDataEntryName =
+ newClassName + dataEntryName.substring(suffixIndex);
return new RenamedDataEntry(dataEntry, newDataEntryName);
}
@@ -100,6 +113,19 @@ public class DataEntryRenamer implements DataEntryReader
}
}
+ // Did the package get a new name?
+ String packagePrefix = ClassUtil.internalPackagePrefix(dataEntryName);
+ String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
+ if (newPackagePrefix != null &&
+ !packagePrefix.equals(newPackagePrefix))
+ {
+ // Return a renamed data entry.
+ String newDataEntryName =
+ newPackagePrefix + dataEntryName.substring(packagePrefix.length());
+
+ return new RenamedDataEntry(dataEntry, newDataEntryName);
+ }
+
return dataEntry;
}
}
diff --git a/src/proguard/io/DataEntryParentFilter.java b/src/proguard/io/DataEntryParentFilter.java
index 838ea54..fbeac4f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 d897685..bfe22a3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 4759310..e77f7bf 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 34f5a21..45c61ee 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,86 +20,85 @@
*/
package proguard.io;
-import proguard.classfile.*;
+import proguard.classfile.ClassConstants;
import java.io.IOException;
+import java.util.Map;
/**
* This DataEntryReader delegates to another DataEntryReader, renaming the
- * data entries based on the renamed classes in the given ClassPool.
+ * data entries based on the given map. Entries whose name does not appear
+ * in the map may be passed to an alternative DataEntryReader.
*
* @author Eric Lafortune
*/
public class DataEntryRenamer implements DataEntryReader
{
- private final ClassPool classPool;
- private final DataEntryReader dataEntryReader;
+ private final Map nameMap;
+ private final DataEntryReader renamedDataEntryReader;
+ private final DataEntryReader missingDataEntryReader;
- public DataEntryRenamer(ClassPool classPool,
- DataEntryReader dataEntryReader)
- {
- this.classPool = classPool;
- this.dataEntryReader = dataEntryReader;
- }
-
-
- // Implementations for DataEntryReader.
-
- public void read(DataEntry dataEntry) throws IOException
+ /**
+ * Creates a new DataEntryRenamer.
+ * @param nameMap the map from old names to new names.
+ * @param renamedDataEntryReader the DataEntryReader to which renamed data
+ * entries will be passed.
+ */
+ public DataEntryRenamer(Map nameMap,
+ DataEntryReader renamedDataEntryReader)
{
- // Delegate to the actual data entry reader.
- dataEntryReader.read(renamedDataEntry(dataEntry));
+ this(nameMap, renamedDataEntryReader, null);
}
/**
- * Create a renamed data entry, if possible.
+ * Creates a new DataEntryRenamer.
+ * @param nameMap the map from old names to new names.
+ * @param renamedDataEntryReader the DataEntryReader to which renamed data
+ * entries will be passed.
+ * @param missingDataEntryReader the optional DataEntryReader to which data
+ * entries that can't be renamed will be
+ * passed.
*/
- private DataEntry renamedDataEntry(DataEntry dataEntry)
+ public DataEntryRenamer(Map nameMap,
+ DataEntryReader renamedDataEntryReader,
+ DataEntryReader missingDataEntryReader)
{
- String dataEntryName = dataEntry.getName();
+ this.nameMap = nameMap;
+ this.renamedDataEntryReader = renamedDataEntryReader;
+ this.missingDataEntryReader = missingDataEntryReader;
+ }
- // Try to find a corresponding class name by removing increasingly
- // long suffixes,
- for (int suffixIndex = dataEntryName.length() - 1;
- suffixIndex > 0;
- suffixIndex--)
- {
- char c = dataEntryName.charAt(suffixIndex);
- if (!Character.isLetterOrDigit(c))
- {
- // Stop looking at the first package separator.
- if (c == ClassConstants.INTERNAL_PACKAGE_SEPARATOR)
- {
- break;
- }
- // Chop off the suffix.
- String className = dataEntryName.substring(0, suffixIndex);
+ // Implementations for DataEntryReader.
- // Is there a class corresponding to the data entry?
- Clazz clazz = classPool.getClass(className);
- if (clazz != null)
- {
- // Did the class get a new name?
- String newClassName = clazz.getName();
- if (!className.equals(newClassName))
- {
- // Return a renamed data entry.
- String newDataEntryName = suffixIndex > 0 ?
- newClassName + dataEntryName.substring(suffixIndex) :
- newClassName;
+ public void read(DataEntry dataEntry) throws IOException
+ {
+ String name = dataEntry.getName();
- return new RenamedDataEntry(dataEntry, newDataEntryName);
- }
+ // Add a directory separator if necessary.
+ if (dataEntry.isDirectory() &&
+ name.length() > 0)
+ {
+ name += ClassConstants.INTERNAL_PACKAGE_SEPARATOR;
+ }
- // Otherwise stop looking.
- break;
- }
+ String newName = (String)nameMap.get(name);
+ if (newName != null)
+ {
+ // Add remove the directory separator if necessary.
+ if (dataEntry.isDirectory() &&
+ newName.length() > 0)
+ {
+ newName = newName.substring(0, newName.length() - 1);
}
- }
- return dataEntry;
+ renamedDataEntryReader.read(new RenamedDataEntry(dataEntry, newName));
+ }
+ else if (missingDataEntryReader != null)
+ {
+ missingDataEntryReader.read(dataEntry);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/io/DataEntryRewriter.java b/src/proguard/io/DataEntryRewriter.java
index 7c28381..eefced4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,10 +31,9 @@ import java.io.*;
*
* @author Eric Lafortune
*/
-public class DataEntryRewriter implements DataEntryReader
+public class DataEntryRewriter extends DataEntryCopier
{
- private final ClassPool classPool;
- private final DataEntryWriter dataEntryWriter;
+ private final ClassPool classPool;
/**
@@ -43,50 +42,36 @@ public class DataEntryRewriter implements DataEntryReader
public DataEntryRewriter(ClassPool classPool,
DataEntryWriter dataEntryWriter)
{
- this.classPool = classPool;
- this.dataEntryWriter = dataEntryWriter;
+ super(dataEntryWriter);
+
+ this.classPool = classPool;
}
- // Implementations for DataEntryReader.
+ // Implementations for DataEntryCopier.
- public void read(DataEntry dataEntry) throws IOException
+ protected void copyData(InputStream inputStream,
+ OutputStream outputStream)
+ throws IOException
{
- try
- {
- // Get the output entry corresponding to this input entry.
- OutputStream outputStream = dataEntryWriter.getOutputStream(dataEntry);
- if (outputStream != null)
- {
- InputStream inputStream = dataEntry.getInputStream();
+ Reader reader = new BufferedReader(new InputStreamReader(inputStream));
+ Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream));
- // Copy the data from the input entry to the output entry.
- copyData(inputStream, outputStream);
+ copyData(reader, writer);
- // Close the data entries.
- dataEntry.closeInputStream();
- }
- }
- catch (IOException ex)
- {
- System.err.println("Warning: can't write resource [" + dataEntry.getName() + "] (" + ex.getMessage() + ")");
- }
+ writer.flush();
+ outputStream.flush();
}
- // Small utility methods.
-
/**
- * Copies all data that it can read from the given input stream to the
- * given output stream.
+ * Copies all data that it can read from the given reader to the given
+ * writer.
*/
- private void copyData(InputStream inputStream,
- OutputStream outputStream)
+ protected void copyData(Reader reader,
+ Writer writer)
throws IOException
{
- Reader reader = new BufferedReader(new InputStreamReader(inputStream));
- Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream));
-
StringBuffer word = new StringBuffer();
while (true)
@@ -119,12 +104,11 @@ public class DataEntryRewriter implements DataEntryReader
// Write out the final word.
writeUpdatedWord(writer, word.toString());
-
- writer.flush();
- outputStream.flush();
}
+ // Small utility methods.
+
/**
* Writes the given word to the given writer, after having adapted it,
* based on the renamed class names.
diff --git a/src/proguard/io/DataEntryWriter.java b/src/proguard/io/DataEntryWriter.java
index b30bb62..9ecf79b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +33,14 @@ import java.io.*;
public interface DataEntryWriter
{
/**
+ * Creates a directory.
+ * @param dataEntry the data entry for which the directory is to be created.
+ * @return whether the directory has been created.
+ */
+ public boolean createDirectory(DataEntry dataEntry) throws IOException;
+
+
+ /**
* Returns an output stream for writing data. The caller must not close
* the output stream; closing the output stream is the responsibility of
* the implementation of this interface.
diff --git a/src/proguard/io/ClassFilter.java b/src/proguard/io/DirectoryFilter.java
similarity index 58%
copy from src/proguard/io/ClassFilter.java
copy to src/proguard/io/DirectoryFilter.java
index 01fbaf3..a45d1aa 100644
--- a/src/proguard/io/ClassFilter.java
+++ b/src/proguard/io/DirectoryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,22 +28,19 @@ import java.io.IOException;
/**
* This DataEntryReader delegates to one of two other DataEntryReader instances,
- * depending on the extension of the data entry.
+ * depending on whether the data entry represents a directory or not.
*
* @author Eric Lafortune
*/
-public class ClassFilter implements DataEntryReader
+public class DirectoryFilter extends FilteredDataEntryReader
{
- private final FilteredDataEntryReader filteredDataEntryReader;
-
-
/**
- * Creates a new ClassFilter that delegates reading classes to the
+ * Creates a new ClassFilter that delegates reading directories to the
* given reader.
*/
- public ClassFilter(DataEntryReader classReader)
+ public DirectoryFilter(DataEntryReader directoryReader)
{
- this(classReader, null);
+ this (directoryReader, null);
}
@@ -51,22 +48,11 @@ public class ClassFilter implements DataEntryReader
* Creates a new ClassFilter that delegates to either of the two given
* readers.
*/
- public ClassFilter(DataEntryReader classReader,
- DataEntryReader dataEntryReader)
- {
- filteredDataEntryReader =
- new FilteredDataEntryReader(
- new DataEntryNameFilter(
- new ExtensionMatcher(ClassConstants.CLASS_FILE_EXTENSION)),
- classReader,
- dataEntryReader);
- }
-
-
- // Implementations for DataEntryReader.
-
- public void read(DataEntry dataEntry) throws IOException
+ public DirectoryFilter(DataEntryReader directoryReader,
+ DataEntryReader otherReader)
{
- filteredDataEntryReader.read(dataEntry);
+ super(new DataEntryDirectoryFilter(),
+ directoryReader,
+ otherReader);
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/io/DirectoryPump.java b/src/proguard/io/DirectoryPump.java
index 04eee76..cab2ff3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -61,6 +61,9 @@ public class DirectoryPump implements DataEntryPump
private void readFiles(File file, DataEntryReader dataEntryReader)
throws IOException
{
+ // Pass the file data entry to the reader.
+ dataEntryReader.read(new FileDataEntry(directory, file));
+
if (file.isDirectory())
{
// Recurse into the subdirectory.
@@ -71,9 +74,5 @@ public class DirectoryPump implements DataEntryPump
readFiles(files[index], dataEntryReader);
}
}
- else
- {
- dataEntryReader.read(new FileDataEntry(directory, file));
- }
}
}
diff --git a/src/proguard/io/DirectoryWriter.java b/src/proguard/io/DirectoryWriter.java
index 172966d..c6605df 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +55,26 @@ public class DirectoryWriter implements DataEntryWriter
// Implementations for DataEntryWriter.
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ // Should we close the current file?
+ if (!isFile &&
+ currentFile != null)
+ {
+ closeEntry();
+ }
+
+ File directory = getFile(dataEntry);
+ if (!directory.exists() &&
+ !directory.mkdirs())
+ {
+ throw new IOException("Can't create directory [" + directory.getPath() + "]");
+ }
+
+ return true;
+ }
+
+
public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
{
return getOutputStream(dataEntry, null);
@@ -64,10 +84,12 @@ public class DirectoryWriter implements DataEntryWriter
public OutputStream getOutputStream(DataEntry dataEntry,
Finisher finisher) throws IOException
{
+ File file = getFile(dataEntry);
+
// Should we close the current file?
if (!isFile &&
currentFile != null &&
- !currentFile.equals(getFile(dataEntry)))
+ !currentFile.equals(file))
{
closeEntry();
}
@@ -75,8 +97,6 @@ public class DirectoryWriter implements DataEntryWriter
// Do we need a new stream?
if (currentOutputStream == null)
{
- File file = getFile(dataEntry);
-
// Make sure the parent directories exist.
File parentDirectory = file.getParentFile();
if (parentDirectory != null &&
diff --git a/src/proguard/io/FileDataEntry.java b/src/proguard/io/FileDataEntry.java
index 0c484ca..d0449ee 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,11 @@ public class FileDataEntry implements DataEntry
}
- // Implementations for InputEntry.
+ public boolean isDirectory()
+ {
+ return file.isDirectory();
+ }
+
public InputStream getInputStream() throws IOException
{
diff --git a/src/proguard/io/FilteredDataEntryReader.java b/src/proguard/io/FilteredDataEntryReader.java
index 40e733d..11da0d4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 6c50bea..40a8c64 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +74,19 @@ public class FilteredDataEntryWriter implements DataEntryWriter
// Implementations for DataEntryWriter.
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ // Get the right data entry writer.
+ DataEntryWriter dataEntryWriter = dataEntryFilter.accepts(dataEntry) ?
+ acceptedDataEntryWriter :
+ rejectedDataEntryWriter;
+
+ // Delegate to it, if it's not null.
+ return dataEntryWriter != null &&
+ dataEntryWriter.createDirectory(dataEntry);
+ }
+
+
public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
{
return getOutputStream(dataEntry, null);
diff --git a/src/proguard/io/Finisher.java b/src/proguard/io/Finisher.java
index 792e032..8c4cc1e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 7e366f9..f96b4aa 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -61,13 +61,10 @@ public class JarReader implements DataEntryReader
break;
}
- if (!zipEntry.isDirectory())
- {
- // Delegate the actual reading to the data entry reader.
- dataEntryReader.read(new ZipDataEntry(dataEntry,
- zipEntry,
- zipInputStream));
- }
+ // Delegate the actual reading to the data entry reader.
+ dataEntryReader.read(new ZipDataEntry(dataEntry,
+ zipEntry,
+ zipInputStream));
}
}
finally
diff --git a/src/proguard/io/JarWriter.java b/src/proguard/io/JarWriter.java
index cb0f0a8..3e40cdf 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.io;
+import proguard.classfile.ClassConstants;
+
import java.io.*;
import java.util.*;
import java.util.jar.*;
@@ -71,6 +73,39 @@ public class JarWriter implements DataEntryWriter, Finisher
// Implementations for DataEntryWriter.
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ //Make sure we can start with a new entry.
+ if (!prepareEntry(dataEntry))
+ {
+ return false;
+ }
+
+ // Close the previous ZIP entry, if any.
+ closeEntry();
+
+ // Get the directory entry name.
+ String name = dataEntry.getName() + ClassConstants.INTERNAL_PACKAGE_SEPARATOR;
+
+ // We have to check if the name is already used, because
+ // ZipOutputStream doesn't handle this case properly (it throws
+ // an exception which can be caught, but the ZipDataEntry is
+ // remembered anyway).
+ if (jarEntryNames.add(name))
+ {
+ // Create a new directory entry.
+ currentJarOutputStream.putNextEntry(new ZipEntry(name));
+ currentJarOutputStream.closeEntry();
+ }
+
+ // Clear the finisher.
+ currentFinisher = null;
+ currentDataEntry = null;
+
+ return true;
+ }
+
+
public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
{
return getOutputStream(dataEntry, null);
@@ -80,34 +115,12 @@ public class JarWriter implements DataEntryWriter, Finisher
public OutputStream getOutputStream(DataEntry dataEntry,
Finisher finisher) throws IOException
{
- // Get the parent stream, new or exisiting.
- // This may finish our own jar output stream.
- OutputStream parentOutputStream =
- dataEntryWriter.getOutputStream(dataEntry.getParent(), this);
-
- // Did we get a stream?
- if (parentOutputStream == null)
+ //Make sure we can start with a new entry.
+ if (!prepareEntry(dataEntry))
{
return null;
}
- // Do we need a new stream?
- if (currentParentOutputStream == null)
- {
- currentParentOutputStream = parentOutputStream;
-
- // Create a new jar stream, with a manifest, if set.
- currentJarOutputStream = manifest != null ?
- new JarOutputStream(parentOutputStream, manifest) :
- new ZipOutputStream(parentOutputStream);
-
- // Add a comment, if set.
- if (comment != null)
- {
- currentJarOutputStream.setComment(comment);
- }
- }
-
// Do we need a new entry?
if (!dataEntry.equals(currentDataEntry))
{
@@ -117,9 +130,10 @@ public class JarWriter implements DataEntryWriter, Finisher
// Get the entry name.
String name = dataEntry.getName();
- // We have to check if the name is already used, because ZipOutputStream
- // doesn't handle this case properly (it throws an exception which can
- // be caught, but the ZipDataEntry is remembered anyway).
+ // We have to check if the name is already used, because
+ // ZipOutputStream doesn't handle this case properly (it throws
+ // an exception which can be caught, but the ZipDataEntry is
+ // remembered anyway).
if (!jarEntryNames.add(name))
{
throw new IOException("Duplicate zip entry ["+dataEntry+"]");
@@ -128,6 +142,7 @@ public class JarWriter implements DataEntryWriter, Finisher
// Create a new entry.
currentJarOutputStream.putNextEntry(new ZipEntry(name));
+ // Set up the finisher for the entry.
currentFinisher = finisher;
currentDataEntry = dataEntry;
}
@@ -163,6 +178,43 @@ public class JarWriter implements DataEntryWriter, Finisher
// Small utility methods.
/**
+ * Makes sure the current output stream is set up for the given entry.
+ */
+ private boolean prepareEntry(DataEntry dataEntry) throws IOException
+ {
+ // Get the parent stream, new or exisiting.
+ // This may finish our own jar output stream.
+ OutputStream parentOutputStream =
+ dataEntryWriter.getOutputStream(dataEntry.getParent(), this);
+
+ // Did we get a stream?
+ if (parentOutputStream == null)
+ {
+ return false;
+ }
+
+ // Do we need a new stream?
+ if (currentParentOutputStream == null)
+ {
+ currentParentOutputStream = parentOutputStream;
+
+ // Create a new jar stream, with a manifest, if set.
+ currentJarOutputStream = manifest != null ?
+ new JarOutputStream(parentOutputStream, manifest) :
+ new ZipOutputStream(parentOutputStream);
+
+ // Add a comment, if set.
+ if (comment != null)
+ {
+ currentJarOutputStream.setComment(comment);
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
* Closes the previous ZIP entry, if any.
*/
private void closeEntry() throws IOException
diff --git a/src/proguard/io/ManifestRewriter.java b/src/proguard/io/ManifestRewriter.java
new file mode 100644
index 0000000..f10307e
--- /dev/null
+++ b/src/proguard/io/ManifestRewriter.java
@@ -0,0 +1,216 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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 java.io.*;
+
+/**
+ * This DataEntryReader writes the manifest data entries that it reads to a
+ * given DataEntryWriter, updating their contents based on the renamed classes
+ * in the given ClassPool.
+ *
+ * @author Eric Lafortune
+ */
+public class ManifestRewriter extends DataEntryRewriter
+{
+ /**
+ * Creates a new ManifestRewriter.
+ */
+ public ManifestRewriter(ClassPool classPool,
+ DataEntryWriter dataEntryWriter)
+ {
+ super(classPool, dataEntryWriter);
+ }
+
+
+ // Implementations for DataEntryRewriter.
+
+ protected void copyData(Reader reader,
+ Writer writer)
+ throws IOException
+ {
+ super.copyData(new SplitLineReader(reader),
+ new SplitLineWriter(writer));
+ }
+
+
+ /**
+ * This Reader reads manifest files, joining any split lines.
+ */
+ private static class SplitLineReader extends FilterReader
+ {
+ private char[] buffer = new char[2];
+ private int bufferIndex = 0;
+ private int bufferSize = 0;
+
+
+ public SplitLineReader(Reader reader)
+ {
+ super(reader);
+ }
+
+
+ // Implementations for Reader.
+
+ public int read() throws IOException
+ {
+ while (true)
+ {
+ if (bufferIndex < bufferSize)
+ {
+ return buffer[bufferIndex++];
+ }
+
+ // Read the first character.
+ int c1 = super.read();
+ if (c1 != '\n' && c1 != '\r')
+ {
+ return c1;
+ }
+
+ bufferIndex = 0;
+ bufferSize = 0;
+ buffer[bufferSize++] = '\n';
+
+ // Read the second character.
+ int c2 = super.read();
+ if (c2 == ' ')
+ {
+ bufferSize = 0;
+ continue;
+ }
+
+ if (c1 != '\r' || c2 != '\n')
+ {
+ buffer[bufferSize++] = (char)c2;
+ continue;
+ }
+
+ // Read the third character.
+ int c3 = super.read();
+ if (c3 == ' ')
+ {
+ bufferSize = 0;
+ continue;
+ }
+
+ buffer[bufferSize++] = (char)c3;
+ }
+ }
+
+
+ public int read(char[] cbuf, int off, int len) throws IOException
+ {
+ // Delegate to reading a single character at a time.
+ int count = 0;
+ while (count < len)
+ {
+ int c = read();
+ if (c == -1)
+ {
+ break;
+ }
+
+ cbuf[off + count++] = (char)c;
+ }
+
+ return count;
+ }
+
+
+ public long skip(long n) throws IOException
+ {
+ // Delegate to reading a single character at a time.
+ int count = 0;
+ while (count < n)
+ {
+ int c = read();
+ if (c == -1)
+ {
+ break;
+ }
+
+ count++;
+ }
+
+ return count;
+ }
+ }
+
+
+ /**
+ * This Writer writes manifest files, splitting any long lines.
+ */
+ private static class SplitLineWriter extends FilterWriter
+ {
+ private int counter = 0;
+
+
+ public SplitLineWriter(Writer writer)
+ {
+ super(writer);
+ }
+
+
+ // Implementations for Reader.
+
+ public void write(int c) throws IOException
+ {
+ // TODO: We should actually count the Utf-8 bytes, not the characters.
+ if (c == '\n')
+ {
+ // Reset the character count.
+ counter = 0;
+ }
+ else if (counter == 70)
+ {
+ // Insert are newline and space.
+ super.write('\n');
+ super.write(' ');
+
+ counter = 2;
+ }
+ else
+ {
+ counter++;
+ }
+
+ super.write(c);
+ }
+
+
+ public void write(char[] cbuf, int off, int len) throws IOException
+ {
+ for (int count = 0; count < len; count++)
+ {
+ write(cbuf[off + count]);
+ }
+ }
+
+
+ public void write(String str, int off, int len) throws IOException
+ {
+ write(str.toCharArray(), off, len);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/io/NameFilter.java b/src/proguard/io/NameFilter.java
new file mode 100644
index 0000000..2a9fbc3
--- /dev/null
+++ b/src/proguard/io/NameFilter.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.util.*;
+
+import java.util.List;
+
+/**
+ * This DataEntryReader delegates to one of two other DataEntryReader instances,
+ * depending on the name of the data entry.
+ *
+ * @author Eric Lafortune
+ */
+public class NameFilter extends FilteredDataEntryReader
+{
+ /**
+ * Creates a new NameFilter that delegates to the given reader, depending
+ * on the given list of filters.
+ */
+ public NameFilter(String regularExpression,
+ DataEntryReader acceptedDataEntryReader)
+ {
+ this(regularExpression, acceptedDataEntryReader, null);
+ }
+
+
+ /**
+ * Creates a new NameFilter that delegates to either of the two given
+ * readers, depending on the given list of filters.
+ */
+ public NameFilter(String regularExpression,
+ DataEntryReader acceptedDataEntryReader,
+ DataEntryReader rejectedDataEntryReader)
+ {
+ super(new DataEntryNameFilter(new ListParser(new FileNameParser()).parse(regularExpression)),
+ acceptedDataEntryReader,
+ rejectedDataEntryReader);
+ }
+
+
+ /**
+ * Creates a new NameFilter that delegates to the given reader, depending
+ * on the given list of filters.
+ */
+ public NameFilter(List regularExpressions,
+ DataEntryReader acceptedDataEntryReader)
+ {
+ this(regularExpressions, acceptedDataEntryReader, null);
+ }
+
+
+ /**
+ * Creates a new NameFilter that delegates to either of the two given
+ * readers, depending on the given list of filters.
+ */
+ public NameFilter(List regularExpressions,
+ DataEntryReader acceptedDataEntryReader,
+ DataEntryReader rejectedDataEntryReader)
+ {
+ super(new DataEntryNameFilter(new ListParser(new FileNameParser()).parse(regularExpressions)),
+ acceptedDataEntryReader,
+ rejectedDataEntryReader);
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/io/ParentDataEntryWriter.java b/src/proguard/io/ParentDataEntryWriter.java
index 5def90c..4f16d12 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,13 @@ public class ParentDataEntryWriter implements DataEntryWriter
// Implementations for DataEntryWriter.
+
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ return getOutputStream(dataEntry) != null;
+ }
+
+
public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
{
return getOutputStream(dataEntry, null);
diff --git a/src/proguard/io/RenamedDataEntry.java b/src/proguard/io/RenamedDataEntry.java
index 410523d..ae2d267 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +50,12 @@ public class RenamedDataEntry implements DataEntry
}
+ public boolean isDirectory()
+ {
+ return dataEntry.isDirectory();
+ }
+
+
public InputStream getInputStream() throws IOException
{
return dataEntry.getInputStream();
diff --git a/src/proguard/io/ZipDataEntry.java b/src/proguard/io/ZipDataEntry.java
index a760709..5779fd8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 ZipDataEntry implements DataEntry
{
private final DataEntry parent;
private final ZipEntry zipEntry;
- private ZipInputStream zipInputStream;
+ private ZipInputStream zipInputStream;
public ZipDataEntry(DataEntry parent,
@@ -51,9 +51,22 @@ public class ZipDataEntry implements DataEntry
public String getName()
{
- // Chop the directory name from the file name and get the right separators.
- return zipEntry.getName()
+ // Get the right separators.
+ String name = zipEntry.getName()
.replace(File.separatorChar, ClassConstants.INTERNAL_PACKAGE_SEPARATOR);
+
+ // Chop the trailing directory slash, if any.
+ int length = name.length();
+ return length > 0 &&
+ name.charAt(length-1) == ClassConstants.INTERNAL_PACKAGE_SEPARATOR ?
+ name.substring(0, length -1) :
+ name;
+ }
+
+
+ public boolean isDirectory()
+ {
+ return zipEntry.isDirectory();
}
diff --git a/src/proguard/obfuscate/AttributeShrinker.java b/src/proguard/obfuscate/AttributeShrinker.java
index e5a99e6..a8bc36b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/AttributeUsageMarker.java b/src/proguard/obfuscate/AttributeUsageMarker.java
index d195386..e772324 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ClassObfuscator.java b/src/proguard/obfuscate/ClassObfuscator.java
index 9e6ec83..9af0c82 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ import proguard.classfile.constant.ClassConstant;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.ClassVisitor;
+import proguard.util.*;
import java.util.*;
@@ -49,24 +50,29 @@ implements ClassVisitor,
private final DictionaryNameFactory classNameFactory;
private final DictionaryNameFactory packageNameFactory;
private final boolean useMixedCaseClassNames;
+ private final StringMatcher keepPackageNamesMatcher;
private final String flattenPackageHierarchy;
private final String repackageClasses;
private final boolean allowAccessModification;
- private final Set classNamesToAvoid = new HashSet();
+ private final Set classNamesToAvoid = new HashSet();
// Map: [package prefix - new package prefix]
- private final Map packagePrefixMap = new HashMap();
+ private final Map packagePrefixMap = new HashMap();
// Map: [package prefix - package name factory]
- private final Map packagePrefixPackageNameFactoryMap = new HashMap();
+ private final Map packagePrefixPackageNameFactoryMap = new HashMap();
- // Map: [package prefix - class name factory]
- private final Map packagePrefixClassNameFactoryMap = new HashMap();
+ // Map: [package prefix - numeric class name factory]
+ private final Map packagePrefixClassNameFactoryMap = new HashMap();
- // A field acting as a temporary variable and as a return value for names
- // of outer classes.
- private String newClassName;
+ // Map: [package prefix - numeric class name factory]
+ private final Map packagePrefixNumericClassNameFactoryMap = new HashMap();
+
+ // Field acting as temporary variables and as return values for names
+ // of outer classes and types of inner classes.
+ private String newClassName;
+ private boolean numericClassName;
/**
@@ -78,6 +84,8 @@ implements ClassVisitor,
* dictionary.
* @param useMixedCaseClassNames specifies whether obfuscated packages and
* classes can get mixed-case names.
+ * @param keepPackageNames the optional filter for which matching
+ * package names are kept.
* @param flattenPackageHierarchy the base package if the obfuscated package
* hierarchy is to be flattened.
* @param repackageClasses the base package if the obfuscated classes
@@ -89,6 +97,7 @@ implements ClassVisitor,
DictionaryNameFactory classNameFactory,
DictionaryNameFactory packageNameFactory,
boolean useMixedCaseClassNames,
+ List keepPackageNames,
String flattenPackageHierarchy,
String repackageClasses,
boolean allowAccessModification)
@@ -111,6 +120,8 @@ implements ClassVisitor,
}
this.useMixedCaseClassNames = useMixedCaseClassNames;
+ this.keepPackageNamesMatcher = keepPackageNames == null ? null :
+ new ListParser(new FileNameParser()).parse(keepPackageNames);
this.flattenPackageHierarchy = flattenPackageHierarchy;
this.repackageClasses = repackageClasses;
this.allowAccessModification = allowAccessModification;
@@ -137,14 +148,16 @@ implements ClassVisitor,
programClass.attributesAccept(this);
// Figure out a package prefix. The package prefix may actually be
- // the outer class prefix, if any, or it may be the fixed base
+ // the an outer class prefix, if any, or it may be the fixed base
// package, if classes are to be repackaged.
String newPackagePrefix = newClassName != null ?
newClassName + ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR :
newPackagePrefix(ClassUtil.internalPackagePrefix(programClass.getName()));
- // Come up with a new class name.
- newClassName = generateUniqueClassName(newPackagePrefix);
+ // Come up with a new class name, numeric or ordinary.
+ newClassName = newClassName != null && numericClassName ?
+ generateUniqueNumericClassName(newPackagePrefix) :
+ generateUniqueClassName(newPackagePrefix);
setNewClassName(programClass, newClassName);
}
@@ -167,6 +180,12 @@ implements ClassVisitor,
{
// Make sure the enclosing class has a name.
enclosingMethodAttribute.referencedClassAccept(this);
+
+ String innerClassName = clazz.getName();
+ String outerClassName = clazz.getClassName(enclosingMethodAttribute.u2classIndex);
+
+ numericClassName = isNumericClassName(innerClassName,
+ outerClassName);
}
@@ -178,11 +197,45 @@ implements ClassVisitor,
int innerClassIndex = innerClassesInfo.u2innerClassIndex;
int outerClassIndex = innerClassesInfo.u2outerClassIndex;
if (innerClassIndex != 0 &&
- outerClassIndex != 0 &&
- clazz.getClassName(innerClassIndex).equals(clazz.getName()))
+ outerClassIndex != 0)
+ {
+ String innerClassName = clazz.getClassName(innerClassIndex);
+ if (innerClassName.equals(clazz.getName()))
+ {
+ clazz.constantPoolEntryAccept(outerClassIndex, this);
+
+ String outerClassName = clazz.getClassName(outerClassIndex);
+
+ numericClassName = isNumericClassName(innerClassName,
+ outerClassName);
+ }
+ }
+ }
+
+
+ /**
+ * Returns whether the given inner class name is a numeric name.
+ */
+ private boolean isNumericClassName(String innerClassName,
+ String outerClassName)
+ {
+ int innerClassNameStart = outerClassName.length() + 1;
+ int innerClassNameLength = innerClassName.length();
+
+ if (innerClassNameStart >= innerClassNameLength)
{
- clazz.constantPoolEntryAccept(outerClassIndex, this);
+ return false;
}
+
+ for (int index = innerClassNameStart; index < innerClassNameLength; index++)
+ {
+ if (!Character.isDigit(innerClassName.charAt(index)))
+ {
+ return false;
+ }
+ }
+
+ return true;
}
@@ -217,7 +270,7 @@ implements ClassVisitor,
String className = programClass.getName();
// Keep the package name for all other classes in the same
- // package. Do this resursively if we're not doing any
+ // package. Do this recursively if we're not doing any
// repackaging.
mapPackageName(className,
newClassName,
@@ -275,6 +328,15 @@ implements ClassVisitor,
String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
if (newPackagePrefix == null)
{
+ // Are we keeping the package name?
+ if (keepPackageNamesMatcher != null &&
+ keepPackageNamesMatcher.matches(packagePrefix.length() > 0 ?
+ packagePrefix.substring(0, packagePrefix.length()-1) :
+ packagePrefix))
+ {
+ return packagePrefix;
+ }
+
// Are we forcing a new package prefix?
if (repackageClasses != null)
{
@@ -282,7 +344,7 @@ implements ClassVisitor,
}
// Are we forcing a new superpackage prefix?
- // Othewrise figure out the new superpackage prefix, recursively.
+ // Otherwise figure out the new superpackage prefix, recursively.
String newSuperPackagePrefix = flattenPackageHierarchy != null ?
flattenPackageHierarchy :
newPackagePrefix(ClassUtil.internalPackagePrefix(packagePrefix));
@@ -322,6 +384,17 @@ implements ClassVisitor,
packageNameFactory);
}
+ return generateUniquePackagePrefix(newSuperPackagePrefix, packageNameFactory);
+ }
+
+
+ /**
+ * Creates a new package prefix in the given new superpackage, with the
+ * given package name factory.
+ */
+ private String generateUniquePackagePrefix(String newSuperPackagePrefix,
+ NameFactory packageNameFactory)
+ {
// Come up with package names until we get an original one.
String newPackagePrefix;
do
@@ -347,8 +420,8 @@ implements ClassVisitor,
(NameFactory)packagePrefixClassNameFactoryMap.get(newPackagePrefix);
if (classNameFactory == null)
{
- // We haven't seen classes in this package before. Create a new name
- // factory for them.
+ // We haven't seen classes in this package before.
+ // Create a new name factory for them.
classNameFactory = new SimpleNameFactory(useMixedCaseClassNames);
if (this.classNameFactory != null)
{
@@ -361,6 +434,39 @@ implements ClassVisitor,
classNameFactory);
}
+ return generateUniqueClassName(newPackagePrefix, classNameFactory);
+ }
+
+
+ /**
+ * Creates a new class name in the given new package.
+ */
+ private String generateUniqueNumericClassName(String newPackagePrefix)
+ {
+ // Find the right name factory for this package.
+ NameFactory classNameFactory =
+ (NameFactory)packagePrefixNumericClassNameFactoryMap.get(newPackagePrefix);
+ if (classNameFactory == null)
+ {
+ // We haven't seen classes in this package before.
+ // Create a new name factory for them.
+ classNameFactory = new NumericNameFactory();
+
+ packagePrefixNumericClassNameFactoryMap.put(newPackagePrefix,
+ classNameFactory);
+ }
+
+ return generateUniqueClassName(newPackagePrefix, classNameFactory);
+ }
+
+
+ /**
+ * Creates a new class name in the given new package, with the given
+ * class name factory.
+ */
+ private String generateUniqueClassName(String newPackagePrefix,
+ NameFactory classNameFactory)
+ {
// Come up with class names until we get an original one.
String newClassName;
do
@@ -374,6 +480,7 @@ implements ClassVisitor,
return newClassName;
}
+
/**
* Returns the given class name, unchanged if mixed-case class names are
* allowed, or the lower-case version otherwise.
diff --git a/src/proguard/obfuscate/ClassRenamer.java b/src/proguard/obfuscate/ClassRenamer.java
index bde6982..143e3fb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 b0ca387..f262664 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f1fd597..fdefec5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 2213b91..c9d6aa6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ package proguard.obfuscate;
import proguard.classfile.*;
import proguard.classfile.util.*;
+import proguard.util.ListUtil;
/**
@@ -75,7 +76,9 @@ public class MappingKeeper implements MappingProcessor
if (currentNewName != null &&
!currentNewName.equals(newName))
{
- warningPrinter.print("Warning: " +
+ warningPrinter.print(name,
+ currentNewName,
+ "Warning: " +
className +
" is not being kept as '" +
ClassUtil.externalClassName(currentNewName) +
@@ -116,7 +119,8 @@ public class MappingKeeper implements MappingProcessor
if (currentNewName != null &&
!currentNewName.equals(newFieldName))
{
- warningPrinter.print("Warning: " +
+ warningPrinter.print(ClassUtil.internalClassName(className),
+ "Warning: " +
className +
": field '" + fieldType + " " + fieldName +
"' is not being kept as '" + currentNewName +
@@ -135,17 +139,17 @@ public class MappingKeeper implements MappingProcessor
int firstLineNumber,
int lastLineNumber,
String methodReturnType,
- String methodNameAndArguments,
+ String methodName,
+ String methodArguments,
String newMethodName)
{
if (clazz != null)
{
// Find the method.
- String name = ClassUtil.externalMethodName(methodNameAndArguments);
String descriptor = ClassUtil.internalMethodDescriptor(methodReturnType,
- methodNameAndArguments);
+ ListUtil.commaSeparatedList(methodArguments));
- Method method = clazz.findMethod(name, descriptor);
+ Method method = clazz.findMethod(methodName, descriptor);
if (method != null)
{
// Print out a warning if the mapping conflicts with a name that
@@ -156,9 +160,10 @@ public class MappingKeeper implements MappingProcessor
if (currentNewName != null &&
!currentNewName.equals(newMethodName))
{
- warningPrinter.print("Warning: " +
+ warningPrinter.print(ClassUtil.internalClassName(className),
+ "Warning: " +
className +
- ": method '" + methodReturnType + " " + methodNameAndArguments +
+ ": method '" + methodReturnType + " " + methodName + ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN + methodArguments + ClassConstants.EXTERNAL_METHOD_ARGUMENTS_CLOSE +
"' is not being kept as '" + currentNewName +
"', but remapped to '" + newMethodName + "'");
}
diff --git a/src/proguard/obfuscate/MappingPrinter.java b/src/proguard/obfuscate/MappingPrinter.java
index 0327687..aa8b13e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 972d190..01c1809 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,20 +59,21 @@ public interface MappingProcessor
/**
* Processes the given method name mapping.
*
- * @param className the original class name.
- * @param firstLineNumber the first line number of the method, or
- * 0 if it is not known.
- * @param lastLineNumber the last line number of the method, or
- * 0 if it is not known.
- * @param methodReturnType the original external method return type.
- * @param methodNameAndArguments the original external method name and
- * arguments.
- * @param newMethodName the new method name.
+ * @param className the original class name.
+ * @param firstLineNumber the first line number of the method, or 0 if it
+ * is not known.
+ * @param lastLineNumber the last line number of the method, or 0 if it
+ * is not known.
+ * @param methodReturnType the original external method return type.
+ * @param methodName the original external method name.
+ * @param methodArguments the original external method arguments.
+ * @param newMethodName the new method name.
*/
public void processMethodMapping(String className,
int firstLineNumber,
int lastLineNumber,
String methodReturnType,
- String methodNameAndArguments,
+ String methodName,
+ String methodArguments,
String newMethodName);
}
diff --git a/src/proguard/obfuscate/MappingReader.java b/src/proguard/obfuscate/MappingReader.java
index 1bbace3..24fd26c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,11 @@ public class MappingReader
break;
}
+ line = line.trim();
+
// The distinction between a class mapping and a class
// member mapping is the initial whitespace.
- if (!line.startsWith(" "))
+ if (line.endsWith(":"))
{
// Process the class mapping and remember the class's
// old name.
@@ -108,8 +110,6 @@ public class MappingReader
// See if we can parse "___ -> ___:", containing the original
// class name and the new class name.
- line = line.trim();
-
int arrowIndex = line.indexOf("->");
if (arrowIndex < 0)
{
@@ -141,49 +141,58 @@ public class MappingReader
String line,
MappingProcessor mappingProcessor)
{
- // See if we can parse " ___:___:___ ___ -> ___",
+ // See if we can parse "___:___:___ ___(___) -> ___",
// containing the optional line numbers, the return type, the original
- // field/method name (including arguments), and the new method name.
-
- line = line.trim();
-
- int colonIndex1 = line.indexOf(':');
- int colonIndex2 = line.indexOf(':', colonIndex1 + 1);
+ // field/method name, optional arguments, and the new field/method name.
- int spaceIndex = line.indexOf(' ', colonIndex2 + 1);
- if (spaceIndex < 0)
- {
- return;
- }
+ int colonIndex1 = line.indexOf(':');
+ int colonIndex2 = colonIndex1 < 0 ? -1 : line.indexOf(':', colonIndex1 + 1);
+ int spaceIndex = line.indexOf(' ', colonIndex2 + 2);
+ int argumentIndex1 = line.indexOf('(', spaceIndex + 1);
+ int argumentIndex2 = argumentIndex1 < 0 ? -1 : line.indexOf(')', argumentIndex1 + 1);
+ int arrowIndex = line.indexOf("->", Math.max(spaceIndex, argumentIndex2) + 1);
- int arrowIndex = line.indexOf("->", spaceIndex + 1);
- if (arrowIndex < 1)
+ if (spaceIndex < 0 ||
+ arrowIndex < 0)
{
return;
}
- int firstLineNumber = colonIndex1 < 0 ? 0 :
- Integer.parseInt(line.substring(0, colonIndex1).trim());
-
- int lastLineNumber = colonIndex1 < 0 ||
- colonIndex2 < 0 ? 0 :
- Integer.parseInt(line.substring(colonIndex1 + 1, colonIndex2).trim());
-
// Extract the elements.
String type = line.substring(colonIndex2 + 1, spaceIndex).trim();
- String name = line.substring(spaceIndex + 1, arrowIndex).trim();
+ String name = line.substring(spaceIndex + 1, argumentIndex1 >= 0 ? argumentIndex1 : arrowIndex).trim();
String newName = line.substring(arrowIndex + 2).trim();
// Process this class member mapping.
- if (type.length() > 0 && name.length() > 0)
+ if (type.length() > 0 &&
+ name.length() > 0 &&
+ newName.length() > 0)
{
- if (name.charAt(name.length() - 1) != ')')
+ // Is it a field or a method?
+ if (argumentIndex2 < 0)
{
mappingProcessor.processFieldMapping(className, type, name, newName);
}
else
{
- mappingProcessor.processMethodMapping(className, firstLineNumber, lastLineNumber, type, name, newName);
+ int firstLineNumber = 0;
+ int lastLineNumber = 0;
+
+ if (colonIndex2 > 0)
+ {
+ firstLineNumber = Integer.parseInt(line.substring(0, colonIndex1).trim());
+ lastLineNumber = Integer.parseInt(line.substring(colonIndex1 + 1, colonIndex2).trim());
+ }
+
+ String arguments = line.substring(argumentIndex1 + 1, argumentIndex2).trim();
+
+ mappingProcessor.processMethodMapping(className,
+ firstLineNumber,
+ lastLineNumber,
+ type,
+ name,
+ arguments,
+ newName);
}
}
}
diff --git a/src/proguard/obfuscate/MemberNameCleaner.java b/src/proguard/obfuscate/MemberNameCleaner.java
index 646d1e5..c41c59d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 a168647..c248820 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 d3bb02c..b9093a6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -136,7 +136,8 @@ public class MemberNameConflictFixer implements MemberVisitor
warningPrinter != null)
{
descriptor = member.getDescriptor(clazz);
- warningPrinter.print("Warning: " + ClassUtil.externalClassName(clazz.getName()) +
+ warningPrinter.print(clazz.getName(),
+ "Warning: " + ClassUtil.externalClassName(clazz.getName()) +
(isField ?
": field '" + ClassUtil.externalFullFieldDescription(0, name, descriptor) :
": method '" + ClassUtil.externalFullMethodDescription(clazz.getName(), 0, name, descriptor)) +
diff --git a/src/proguard/obfuscate/MemberObfuscator.java b/src/proguard/obfuscate/MemberObfuscator.java
index bdd11f7..332b849 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 4f252d4..f83374b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/MultiMappingProcessor.java b/src/proguard/obfuscate/MultiMappingProcessor.java
index 777e3f8..4074ff8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 +78,8 @@ public class MultiMappingProcessor implements MappingProcessor
int firstLineNumber,
int lastLineNumber,
String methodReturnType,
- String methodNameAndArguments,
+ String methodName,
+ String methodArguments,
String newMethodName)
{
for (int index = 0; index < mappingProcessors.length; index++)
@@ -87,7 +88,8 @@ public class MultiMappingProcessor implements MappingProcessor
firstLineNumber,
lastLineNumber,
methodReturnType,
- methodNameAndArguments,
+ methodName,
+ methodArguments,
newMethodName);
}
}
diff --git a/src/proguard/obfuscate/NameAndTypeShrinker.java b/src/proguard/obfuscate/NameAndTypeShrinker.java
index 812768b..1284c82 100644
--- a/src/proguard/obfuscate/NameAndTypeShrinker.java
+++ b/src/proguard/obfuscate/NameAndTypeShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/NameAndTypeUsageMarker.java b/src/proguard/obfuscate/NameAndTypeUsageMarker.java
index a179781..cc779f0 100644
--- a/src/proguard/obfuscate/NameAndTypeUsageMarker.java
+++ b/src/proguard/obfuscate/NameAndTypeUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/NameFactory.java b/src/proguard/obfuscate/NameFactory.java
index 095b64d..c64d1ad 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 ae51e7f..b6ba6ad 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 302893e..2ce0ee9 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/NameFactory.java b/src/proguard/obfuscate/NumericNameFactory.java
similarity index 67%
copy from src/proguard/obfuscate/NameFactory.java
copy to src/proguard/obfuscate/NumericNameFactory.java
index 095b64d..cc21c4b 100644
--- a/src/proguard/obfuscate/NameFactory.java
+++ b/src/proguard/obfuscate/NumericNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,15 +20,30 @@
*/
package proguard.obfuscate;
+import java.util.*;
+
+
/**
- * This interfaces provides methods to generate unique sequences of names.
- * The names must be valid Java identifiers.
+ * This <code>NameFactory</code> generates unique numeric names, starting at
+ * "1".
*
* @author Eric Lafortune
*/
-public interface NameFactory
+public class NumericNameFactory implements NameFactory
{
- public void reset();
+ private int index;
+
+
+ // Implementations for NameFactory.
+
+ public void reset()
+ {
+ index = 0;
+ }
+
- public String nextName();
-}
+ public String nextName()
+ {
+ return Integer.toString(++index);
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/obfuscate/Obfuscator.java b/src/proguard/obfuscate/Obfuscator.java
index 04a80b5..dce563a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -70,25 +70,6 @@ public class Obfuscator
programClassPool.classesAccept(new ClassCleaner());
libraryClassPool.classesAccept(new ClassCleaner());
- // Mark attributes that have to be kept.
- AttributeUsageMarker requiredAttributeUsageMarker =
- new AttributeUsageMarker();
-
- AttributeVisitor optionalAttributeUsageMarker =
- configuration.keepAttributes == null ? null :
- configuration.keepAttributes.size() == 0 ?
- (AttributeVisitor)requiredAttributeUsageMarker :
- (AttributeVisitor)new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes),
- requiredAttributeUsageMarker);
-
- programClassPool.classesAccept(
- new AllAttributeVisitor(true,
- new RequiredAttributeFilter(requiredAttributeUsageMarker,
- optionalAttributeUsageMarker)));
-
- // Remove the attributes that can be discarded.
- programClassPool.classesAccept(new AttributeShrinker());
-
// If the class member names have to correspond globally,
// link all class members in all classes, otherwise
// link all non-private methods in all class hierarchies.
@@ -117,13 +98,30 @@ public class Obfuscator
libraryClassPool.classesAccept(nameMarker);
libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker));
+ // Mark attributes that have to be kept.
+ AttributeUsageMarker requiredAttributeUsageMarker =
+ new AttributeUsageMarker();
+
+ AttributeVisitor optionalAttributeUsageMarker =
+ configuration.keepAttributes == null ? null :
+ new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes),
+ requiredAttributeUsageMarker);
+
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(true,
+ new RequiredAttributeFilter(requiredAttributeUsageMarker,
+ optionalAttributeUsageMarker)));
+
+ // 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.
+ programClassPool.classesAccept(new AttributeShrinker());
+
// Apply the mapping, if one has been specified. The mapping can
// override the names of library classes and of library class members.
if (configuration.applyMapping != null)
{
- WarningPrinter warningPrinter = configuration.warn ?
- new WarningPrinter(System.err) :
- null;
+ WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
MappingReader reader = new MappingReader(configuration.applyMapping);
@@ -136,22 +134,19 @@ public class Obfuscator
reader.pump(keeper);
- if (warningPrinter != null)
+ // Print out a summary of the warnings if necessary.
+ int mappingWarningCount = warningPrinter.getWarningCount();
+ if (mappingWarningCount > 0)
{
- // Print out a summary of the warnings if necessary.
- int mappingWarningCount = warningPrinter.getWarningCount();
- if (mappingWarningCount > 0)
+ System.err.println("Warning: there were " + mappingWarningCount +
+ " kept classes and class members that were remapped anyway.");
+ System.err.println(" You should adapt your configuration or edit the mapping file.");
+
+ if (!configuration.ignoreWarnings)
{
- System.err.println("Warning: there were " + mappingWarningCount +
- " kept classes and class members that were remapped anyway.");
- System.err.println(" You should adapt your configuration or edit the mapping file.");
-
- if (!configuration.ignoreWarnings)
- {
- System.err.println(" If you are sure this remapping won't hurt,");
- System.err.println(" you could try your luck using the '-ignorewarnings' option.");
- throw new IOException("Please correct the above warnings first.");
- }
+ System.err.println(" If you are sure this remapping won't hurt,");
+ System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ throw new IOException("Please correct the above warnings first.");
}
}
}
@@ -170,6 +165,7 @@ public class Obfuscator
classNameFactory,
packageNameFactory,
configuration.useMixedCaseClassNames,
+ configuration.keepPackageNames,
configuration.flattenPackageHierarchy,
configuration.repackageClasses,
configuration.allowAccessModification));
@@ -183,9 +179,7 @@ public class Obfuscator
nameFactory);
}
- WarningPrinter warningPrinter = configuration.warn ?
- new WarningPrinter(System.err) :
- null;
+ WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
// Maintain a map of names to avoid [descriptor - new name - old name].
Map descriptorMap = new HashMap();
@@ -356,21 +350,18 @@ public class Obfuscator
}));
// Print out any warnings about member name conflicts.
- if (warningPrinter != null)
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
{
- int warningCount = warningPrinter.getWarningCount();
- if (warningCount > 0)
- {
- System.err.println("Warning: there were " + warningCount +
- " conflicting class member name mappings.");
- System.err.println(" Your configuration may be inconsistent.");
+ System.err.println("Warning: there were " + warningCount +
+ " conflicting class member name mappings.");
+ System.err.println(" Your configuration may be inconsistent.");
- if (!configuration.ignoreWarnings)
- {
- System.err.println(" If you are sure the conflicts are harmless,");
- System.err.println(" you could try your luck using the '-ignorewarnings' option.");
- throw new IOException("Please correct the above warnings first.");
- }
+ if (!configuration.ignoreWarnings)
+ {
+ System.err.println(" If you are sure the conflicts are harmless,");
+ System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ throw new IOException("Please correct the above warnings first.");
}
}
diff --git a/src/proguard/obfuscate/SimpleNameFactory.java b/src/proguard/obfuscate/SimpleNameFactory.java
index 211dbc3..bce22de 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 daf4df6..cbf1b63 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,12 +62,6 @@ implements ClassVisitor,
}
- public void visitLibraryClass(LibraryClass libraryClass)
- {
- // Library classes don't have attributes.
- }
-
-
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
diff --git a/src/proguard/obfuscate/SpecialNameFactory.java b/src/proguard/obfuscate/SpecialNameFactory.java
index 64607aa..a5431ca 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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
index 9ceb02c..87ada80 100644
--- a/src/proguard/obfuscate/Utf8Shrinker.java
+++ b/src/proguard/obfuscate/Utf8Shrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Utf8UsageMarker.java b/src/proguard/obfuscate/Utf8UsageMarker.java
index b521193..c59ebb8 100644
--- a/src/proguard/obfuscate/Utf8UsageMarker.java
+++ b/src/proguard/obfuscate/Utf8UsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ChangedCodePrinter.java b/src/proguard/optimize/ChangedCodePrinter.java
index 29d21ee..67a79ab 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ConstantMemberFilter.java b/src/proguard/optimize/ConstantMemberFilter.java
index 4058eb1..56437c3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 @@ import proguard.optimize.evaluation.StoringInvocationUnit;
/**
* This <code>MemberVisitor</code> delegates its visits to program class members
* to another given <code>MemberVisitor</code>, but only when the visited
- * field has been marked as a constant.
+ * class member has been marked as a constant.
*
* @see StoringInvocationUnit
* @author Eric Lafortune
diff --git a/src/proguard/optimize/ConstantParameterFilter.java b/src/proguard/optimize/ConstantParameterFilter.java
new file mode 100644
index 0000000..24a7040
--- /dev/null
+++ b/src/proguard/optimize/ConstantParameterFilter.java
@@ -0,0 +1,79 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is 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.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
+import proguard.optimize.evaluation.StoringInvocationUnit;
+import proguard.optimize.info.ParameterUsageMarker;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to program methods
+ * to another given <code>MemberVisitor</code>, for each method parameter
+ * that has been marked as constant.
+ *
+ * @see StoringInvocationUnit
+ * @author Eric Lafortune
+ */
+public class ConstantParameterFilter
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final MemberVisitor constantParameterVisitor;
+
+
+ /**
+ * Creates a new ConstantParameterFilter.
+ * @param constantParameterVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public ConstantParameterFilter(MemberVisitor constantParameterVisitor)
+ {
+ this.constantParameterVisitor = constantParameterVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // All parameters of non-static methods are shifted by one in the local
+ // variable frame.
+ int firstParameterIndex =
+ (programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ?
+ 0 : 1;
+
+ int parameterCount =
+ ClassUtil.internalMethodParameterCount(programMethod.getDescriptor(programClass));
+
+ for (int index = firstParameterIndex; index < parameterCount; index++)
+ {
+ Value value = StoringInvocationUnit.getMethodParameterValue(programMethod, index);
+ if (value != null &&
+ value.isParticular())
+ {
+ constantParameterVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/proguard/optimize/DuplicateInitializerFixer.java b/src/proguard/optimize/DuplicateInitializerFixer.java
index 27c655b..746d182 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/DuplicateInitializerInvocationFixer.java b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
index 23973c9..ca24481 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/KeepMarker.java b/src/proguard/optimize/KeepMarker.java
index 704bde5..4297996 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/MemberDescriptorSpecializer.java b/src/proguard/optimize/MemberDescriptorSpecializer.java
index 1e1ba75..0d0b841 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/MethodDescriptorShrinker.java b/src/proguard/optimize/MethodDescriptorShrinker.java
index 52c1134..48374e7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 MemberVisitor,
private static final boolean DEBUG = false;
- private final MemberVisitor extraParameterMemberVisitor;
+ private final MemberVisitor extraMemberVisitor;
/**
@@ -61,13 +61,12 @@ implements MemberVisitor,
/**
* Creates a new MethodDescriptorShrinker with an extra visitor.
- * @param extraParameterMemberVisitor an optional extra visitor for all
- * methods whose parameters have been
- * simplified.
+ * @param extraMemberVisitor an optional extra visitor for all methods whose
+ * parameters have been simplified.
*/
- public MethodDescriptorShrinker(MemberVisitor extraParameterMemberVisitor)
+ public MethodDescriptorShrinker(MemberVisitor extraMemberVisitor)
{
- this.extraParameterMemberVisitor = extraParameterMemberVisitor;
+ this.extraMemberVisitor = extraMemberVisitor;
}
@@ -124,9 +123,9 @@ implements MemberVisitor,
constantPoolEditor.addUtf8Constant(newDescriptor);
// Visit the method, if required.
- if (extraParameterMemberVisitor != null)
+ if (extraMemberVisitor != null)
{
- extraParameterMemberVisitor.visitProgramMethod(programClass, programMethod);
+ extraMemberVisitor.visitProgramMethod(programClass, programMethod);
}
}
}
diff --git a/src/proguard/optimize/MethodStaticizer.java b/src/proguard/optimize/MethodStaticizer.java
index 15518a3..8dd11e1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f91f6bf..8760aee 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 8d61e10..a3e8a6e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,12 +28,15 @@ import proguard.classfile.editor.*;
import proguard.classfile.instruction.visitor.*;
import proguard.classfile.util.MethodLinker;
import proguard.classfile.visitor.*;
+import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.evaluation.*;
import proguard.optimize.info.*;
import proguard.optimize.peephole.*;
+import proguard.util.*;
import java.io.IOException;
+import java.util.*;
/**
* This class optimizes class pools according to a given configuration.
@@ -42,6 +45,66 @@ import java.io.IOException;
*/
public class Optimizer
{
+ private static final String CLASS_MARKING_FINAL = "class/marking/final";
+ private static final String CLASS_MERGING_VERTICAL = "class/merging/vertical";
+ private static final String CLASS_MERGING_HORIZONTAL = "class/merging/horizontal";
+ private static final String FIELD_REMOVAL_WRITEONLY = "field/removal/writeonly";
+ private static final String FIELD_MARKING_PRIVATE = "field/marking/private";
+ private static final String FIELD_PROPAGATION_VALUE = "field/propagation/value";
+ private static final String METHOD_MARKING_PRIVATE = "method/marking/private";
+ private static final String METHOD_MARKING_STATIC = "method/marking/static";
+ private static final String METHOD_MARKING_FINAL = "method/marking/final";
+ private static final String METHOD_REMOVAL_PARAMETER = "method/removal/parameter";
+ private static final String METHOD_PROPAGATION_PARAMETER = "method/propagation/parameter";
+ private static final String METHOD_PROPAGATION_RETURNVALUE = "method/propagation/returnvalue";
+ private static final String METHOD_INLINING_SHORT = "method/inlining/short";
+ private static final String METHOD_INLINING_UNIQUE = "method/inlining/unique";
+ private static final String METHOD_INLINING_TAILRECURSION = "method/inlining/tailrecursion";
+ private static final String CODE_MERGING = "code/merging";
+ private static final String CODE_SIMPLIFICATION_VARIABLE = "code/simplification/variable";
+ private static final String CODE_SIMPLIFICATION_ARITHMETIC = "code/simplification/arithmetic";
+ 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_ADVANCED = "code/simplification/advanced";
+ private static final String CODE_REMOVAL_ADVANCED = "code/removal/advanced";
+ private static final String CODE_REMOVAL_SIMPLE = "code/removal/simple";
+ private static final String CODE_REMOVAL_VARIABLE = "code/removal/variable";
+ private static final String CODE_REMOVAL_EXCEPTION = "code/removal/exception";
+ private static final String CODE_ALLOCATION_VARIABLE = "code/allocation/variable";
+
+
+ public static final String[] OPTIMIZATION_NAMES = new String[]
+ {
+ CLASS_MARKING_FINAL,
+ CLASS_MERGING_VERTICAL,
+ CLASS_MERGING_HORIZONTAL,
+ FIELD_REMOVAL_WRITEONLY,
+ FIELD_PROPAGATION_VALUE,
+ METHOD_MARKING_PRIVATE,
+ METHOD_MARKING_STATIC,
+ METHOD_MARKING_FINAL,
+ METHOD_REMOVAL_PARAMETER,
+ METHOD_PROPAGATION_PARAMETER,
+ METHOD_PROPAGATION_RETURNVALUE,
+ METHOD_INLINING_SHORT,
+ METHOD_INLINING_UNIQUE,
+ METHOD_INLINING_TAILRECURSION,
+ CODE_MERGING,
+ CODE_SIMPLIFICATION_VARIABLE,
+ CODE_SIMPLIFICATION_ARITHMETIC,
+ CODE_SIMPLIFICATION_CAST,
+ CODE_SIMPLIFICATION_FIELD,
+ CODE_SIMPLIFICATION_BRANCH,
+ CODE_SIMPLIFICATION_ADVANCED,
+ CODE_REMOVAL_ADVANCED,
+ CODE_REMOVAL_SIMPLE,
+ CODE_REMOVAL_VARIABLE,
+ CODE_REMOVAL_EXCEPTION,
+ CODE_ALLOCATION_VARIABLE,
+ };
+
+
private final Configuration configuration;
@@ -68,29 +131,90 @@ public class Optimizer
throw new IOException("You have to specify '-keep' options for the optimization step.");
}
+ // Create a matcher for filtering optimizations.
+ StringMatcher filter = configuration.optimizations != null ?
+ new ListParser(new NameParser()).parse(configuration.optimizations) :
+ new ConstantMatcher(true);
+
+ boolean classMarkingFinal = filter.matches(CLASS_MARKING_FINAL);
+ boolean classMergingVertical = filter.matches(CLASS_MERGING_VERTICAL);
+ boolean classMergingHorizontal = filter.matches(CLASS_MERGING_HORIZONTAL);
+ boolean fieldRemovalWriteonly = filter.matches(FIELD_REMOVAL_WRITEONLY);
+ boolean fieldMarkingPrivate = filter.matches(FIELD_MARKING_PRIVATE);
+ boolean fieldPropagationValue = filter.matches(FIELD_PROPAGATION_VALUE);
+ boolean methodMarkingPrivate = filter.matches(METHOD_MARKING_PRIVATE);
+ boolean methodMarkingStatic = filter.matches(METHOD_MARKING_STATIC);
+ boolean methodMarkingFinal = filter.matches(METHOD_MARKING_FINAL);
+ boolean methodRemovalParameter = filter.matches(METHOD_REMOVAL_PARAMETER);
+ boolean methodPropagationParameter = filter.matches(METHOD_PROPAGATION_PARAMETER);
+ boolean methodPropagationReturnvalue = filter.matches(METHOD_PROPAGATION_RETURNVALUE);
+ boolean methodInliningShort = filter.matches(METHOD_INLINING_SHORT);
+ boolean methodInliningUnique = filter.matches(METHOD_INLINING_UNIQUE);
+ boolean methodInliningTailrecursion = filter.matches(METHOD_INLINING_TAILRECURSION);
+ boolean codeMerging = filter.matches(CODE_MERGING);
+ boolean codeSimplificationVariable = filter.matches(CODE_SIMPLIFICATION_VARIABLE);
+ boolean codeSimplificationArithmetic = filter.matches(CODE_SIMPLIFICATION_ARITHMETIC);
+ boolean codeSimplificationCast = filter.matches(CODE_SIMPLIFICATION_CAST);
+ boolean codeSimplificationField = filter.matches(CODE_SIMPLIFICATION_FIELD);
+ boolean codeSimplificationBranch = filter.matches(CODE_SIMPLIFICATION_BRANCH);
+ boolean codeSimplificationAdvanced = filter.matches(CODE_SIMPLIFICATION_ADVANCED);
+ boolean codeRemovalAdvanced = filter.matches(CODE_REMOVAL_ADVANCED);
+ boolean codeRemovalSimple = filter.matches(CODE_REMOVAL_SIMPLE);
+ boolean codeRemovalVariable = filter.matches(CODE_REMOVAL_VARIABLE);
+ boolean codeRemovalException = filter.matches(CODE_REMOVAL_EXCEPTION);
+ boolean codeAllocationVariable = filter.matches(CODE_ALLOCATION_VARIABLE);
+
// Create counters to count the numbers of optimizations.
- ClassCounter classMergeCounter = new ClassCounter();
- ClassCounter finalClassCounter = new ClassCounter();
- MemberCounter finalMethodCounter = new MemberCounter();
- MemberCounter privateFieldCounter = new MemberCounter();
- MemberCounter privateMethodCounter = new MemberCounter();
- MemberCounter staticMethodCounter = new MemberCounter();
- MemberCounter writeOnlyFieldCounter = new MemberCounter();
- MemberCounter constantFieldCounter = new MemberCounter();
- MemberCounter constantMethodCounter = new MemberCounter();
- MemberCounter descriptorShrinkCounter = new MemberCounter();
- MemberCounter initializerFixCounter = new MemberCounter();
- MemberCounter parameterShrinkCounter = new MemberCounter();
- MemberCounter variableShrinkCounter = new MemberCounter();
- ExceptionCounter exceptionCounter = new ExceptionCounter();
- InstructionCounter inliningCounter = new InstructionCounter();
- InstructionCounter tailRecursionCounter = new InstructionCounter();
- InstructionCounter commonCodeCounter = new InstructionCounter();
- InstructionCounter pushCounter = new InstructionCounter();
- InstructionCounter branchCounter = new InstructionCounter();
- InstructionCounter deletedCounter = new InstructionCounter();
- InstructionCounter addedCounter = new InstructionCounter();
- InstructionCounter peepholeCounter = new InstructionCounter();
+ ClassCounter classMarkingFinalCounter = new ClassCounter();
+ ClassCounter classMergingVerticalCounter = new ClassCounter();
+ ClassCounter classMergingHorizontalCounter = new ClassCounter();
+ MemberCounter fieldRemovalWriteonlyCounter = new MemberCounter();
+ MemberCounter fieldMarkingPrivateCounter = new MemberCounter();
+ MemberCounter fieldPropagationValueCounter = new MemberCounter();
+ MemberCounter methodMarkingPrivateCounter = new MemberCounter();
+ MemberCounter methodMarkingStaticCounter = new MemberCounter();
+ MemberCounter methodMarkingFinalCounter = new MemberCounter();
+ MemberCounter methodRemovalParameterCounter = new MemberCounter();
+ MemberCounter methodPropagationParameterCounter = new MemberCounter();
+ MemberCounter methodPropagationReturnvalueCounter = new MemberCounter();
+ InstructionCounter methodInliningShortCounter = new InstructionCounter();
+ InstructionCounter methodInliningUniqueCounter = new InstructionCounter();
+ InstructionCounter methodInliningTailrecursionCounter = new InstructionCounter();
+ InstructionCounter codeMergingCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationVariableCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationArithmeticCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationCastCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationFieldCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationBranchCounter = 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();
+
+ // Some optimizations are required by other optimizations.
+ codeSimplificationAdvanced =
+ codeSimplificationAdvanced ||
+ fieldPropagationValue ||
+ methodPropagationParameter ||
+ methodPropagationReturnvalue;
+
+ codeRemovalAdvanced =
+ codeRemovalAdvanced ||
+ fieldRemovalWriteonly ||
+ methodMarkingStatic ||
+ methodRemovalParameter;
+
+ codeRemovalSimple =
+ codeRemovalSimple ||
+ codeSimplificationBranch;
+
+ codeRemovalException =
+ codeRemovalException ||
+ codeRemovalAdvanced ||
+ codeRemovalSimple;
// Clean up any old visitor info.
programClassPool.classesAccept(new ClassCleaner());
@@ -120,14 +244,16 @@ public class Optimizer
libraryClassPool.classesAccept(new AllMemberVisitor(keepMarker));
// We also keep all classes that are involved in .class constructs.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new AllInstructionVisitor(
- new DotClassClassVisitor(keepMarker)))));
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new AllInstructionVisitor(
+ new DotClassClassVisitor(keepMarker)))));
// We also keep all classes that are involved in Class.forName constructs.
- programClassPool.classesAccept(new AllConstantVisitor(
- new ClassForNameClassVisitor(keepMarker)));
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new ClassForNameClassVisitor(keepMarker)));
// Attach some optimization info to all classes and class members, so
// it can be filled out later.
@@ -150,19 +276,49 @@ public class Optimizer
libraryClassPool.accept(noClassPoolvisitor);
}
- // Make classes and methods final, as far as possible.
- programClassPool.classesAccept(new ClassFinalizer(finalClassCounter, finalMethodCounter));
+ if (classMarkingFinal)
+ {
+ // Make classes final, whereever possible.
+ programClassPool.classesAccept(
+ new ClassFinalizer(classMarkingFinalCounter));
+ }
+
+ if (methodMarkingFinal)
+ {
+ // Make methods final, whereever possible.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new MethodFinalizer(methodMarkingFinalCounter)));
+ }
- // Mark all fields that are write-only.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new AllInstructionVisitor(
- new ReadWriteFieldMarker()))));
+ if (fieldRemovalWriteonly)
+ {
+ // Mark all fields that are write-only.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new AllInstructionVisitor(
+ new ReadWriteFieldMarker()))));
+
+ // Count the write-only fields.
+ programClassPool.classesAccept(
+ new AllFieldVisitor(
+ new WriteOnlyFieldFilter(fieldRemovalWriteonlyCounter)));
+ }
+ else
+ {
+ // Mark all fields as read/write.
+ programClassPool.classesAccept(
+ new AllFieldVisitor(
+ new ReadWriteFieldMarker()));
+ }
// Mark all used parameters, including the 'this' parameters.
- programClassPool.classesAccept(new AllMethodVisitor(
- new OptimizationInfoMemberFilter(
- new ParameterUsageMarker())));
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new OptimizationInfoMemberFilter(
+ new ParameterUsageMarker(!methodMarkingStatic,
+ !methodRemovalParameter))));
// Mark all methods that have side effects.
programClassPool.accept(new SideEffectMethodMarker());
@@ -174,53 +330,116 @@ public class Optimizer
// and method return values.
ValueFactory valueFactory = new IdentifiedValueFactory();
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new PartialEvaluator(valueFactory, new StoringInvocationUnit(valueFactory), false))));
-
- // Simplify based on partial evaluation.
- // Also remove unused parameters from the stack before method invocations,
- // and make method invocations static when possible, for
- // MethodDescriptorShrinker, MethodStaticizer.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new EvaluationSimplifier(
- new PartialEvaluator(valueFactory, new LoadingInvocationUnit(valueFactory), false),
- pushCounter, branchCounter, deletedCounter, addedCounter))));
-
- // Shrink the parameters in the method descriptors.
- programClassPool.classesAccept(new AllMethodVisitor(
- new OptimizationInfoMemberFilter(
- new MethodDescriptorShrinker(descriptorShrinkCounter))));
-
- // Make all non-static methods that don't require the 'this' parameter static.
- programClassPool.classesAccept(new AllMethodVisitor(
- new OptimizationInfoMemberFilter(
- new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_STATIC,
- new MethodStaticizer(staticMethodCounter)))));
-
- // Fix all references to class members, for MethodDescriptorShrinker.
- // This operation also updates the stack sizes.
- programClassPool.classesAccept(new MemberReferenceFixer());
-
- // Remove all unused parameters from the byte code, shifting all
- // remaining variables, for MethodDescriptorShrinker, MethodStaticizer.
- // This operation also updates the local variable frame sizes.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new ParameterShrinker(parameterShrinkCounter))));
-
- // Count the write-only fields, and the constant fields and methods.
- programClassPool.classesAccept(new MultiClassVisitor(
- new ClassVisitor[]
- {
- new AllFieldVisitor(
- new WriteOnlyFieldFilter(writeOnlyFieldCounter)),
- new AllFieldVisitor(
- new ConstantMemberFilter(constantFieldCounter)),
- new AllMethodVisitor(
- new ConstantMemberFilter(constantMethodCounter)),
- }));
+ if (fieldPropagationValue ||
+ methodPropagationParameter ||
+ methodPropagationReturnvalue)
+ {
+ // Fill out fields, method parameters, and return values, so they
+ // can be propagated.
+ InvocationUnit storingInvocationUnit =
+ new StoringInvocationUnit(valueFactory,
+ fieldPropagationValue,
+ methodPropagationParameter,
+ methodPropagationReturnvalue);
+
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new PartialEvaluator(valueFactory, storingInvocationUnit, false))));
+
+ // Count the constant fields and methods.
+ programClassPool.classesAccept(
+ new MultiClassVisitor(
+ new ClassVisitor[]
+ {
+ new AllFieldVisitor(
+ new ConstantMemberFilter(fieldPropagationValueCounter)),
+ new AllMethodVisitor(
+ new ConstantParameterFilter(methodPropagationParameterCounter)),
+ new AllMethodVisitor(
+ new ConstantMemberFilter(methodPropagationReturnvalueCounter)),
+ }));
+ }
+
+ InvocationUnit loadingInvocationUnit =
+ new LoadingInvocationUnit(valueFactory,
+ fieldPropagationValue,
+ methodPropagationParameter,
+ methodPropagationReturnvalue);
+
+ if (codeSimplificationAdvanced)
+ {
+ // Simplify based on partial evaluation, propagating constant
+ // field values, method parameter values, and return values.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new EvaluationSimplifier(
+ new PartialEvaluator(valueFactory, loadingInvocationUnit, false),
+ codeSimplificationAdvancedCounter))));
+ }
+
+ if (codeRemovalAdvanced)
+ {
+ // Remove code based on partial evaluation, also removing unused
+ // parameters from method invocations, and making methods static
+ // if possible.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new EvaluationShrinker(
+ new PartialEvaluator(valueFactory, loadingInvocationUnit, !codeSimplificationAdvanced),
+ deletedCounter, addedCounter))));
+ }
+
+ if (methodRemovalParameter)
+ {
+ // Shrink the parameters in the method descriptors.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new OptimizationInfoMemberFilter(
+ new MethodDescriptorShrinker())));
+ }
+
+ if (methodMarkingStatic)
+ {
+ // Make all non-static methods that don't require the 'this'
+ // parameter static.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new OptimizationInfoMemberFilter(
+ new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_STATIC,
+ new MethodStaticizer(methodMarkingStaticCounter)))));
+ }
+
+ if (methodRemovalParameter)
+ {
+ // Fix all references to class members.
+ // This operation also updates the stack sizes.
+ programClassPool.classesAccept(
+ new MemberReferenceFixer());
+ }
+
+ if (methodRemovalParameter ||
+ methodMarkingPrivate ||
+ methodMarkingStatic)
+ {
+ // Remove all unused parameters from the byte code, shifting all
+ // remaining variables.
+ // This operation also updates the local variable frame sizes.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new ParameterShrinker(methodRemovalParameterCounter))));
+ }
+ else if (codeRemovalAdvanced)
+ {
+ // Just update the local variable frame sizes.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new StackSizeUpdater())));
+ }
// // Specializing the class member descriptors seems to increase the
// // class file size, on average.
@@ -234,237 +453,424 @@ public class Optimizer
// new OptimizationInfoMemberFilter(
// new ClassReferenceFixer(true))));
- if (configuration.allowAccessModification)
- {
- // Fix the access flags of referenced classes and class members,
- // for SingleImplementationInliner.
- programClassPool.classesAccept(new AllConstantVisitor(
- new AccessFixer()));
- }
-
// Mark all classes with package visible members.
// Mark all exception catches of methods.
// Count all method invocations.
// Mark super invocations and other access of methods.
- programClassPool.classesAccept(new MultiClassVisitor(
- new ClassVisitor[]
- {
- new AllConstantVisitor(
- new PackageVisibleMemberInvokingClassMarker()),
- new AllMethodVisitor(
- new MultiMemberVisitor(
- new MemberVisitor[]
- {
- new PackageVisibleMemberContainingClassMarker(),
- new AllAttributeVisitor(
- new MultiAttributeVisitor(
- new AttributeVisitor[]
- {
- new CatchExceptionMarker(),
- new AllInstructionVisitor(
- new MultiInstructionVisitor(
- new InstructionVisitor[]
- {
- new InstantiationClassMarker(),
- new InstanceofClassMarker(),
- new DotClassMarker(),
- new MethodInvocationMarker(),
- new SuperInvocationMarker(),
- new BackwardBranchMarker(),
- new AccessMethodMarker(),
- })),
- })),
- })),
- }));
-
- // Tweak the descriptors of duplicate initializers.
- programClassPool.classesAccept(new AllMethodVisitor(
- new DuplicateInitializerFixer(initializerFixCounter)));
-
- if (initializerFixCounter.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());
+ programClassPool.classesAccept(
+ new MultiClassVisitor(
+ new ClassVisitor[]
+ {
+ new AllConstantVisitor(
+ new PackageVisibleMemberInvokingClassMarker()),
+ new AllMethodVisitor(
+ new MultiMemberVisitor(
+ new MemberVisitor[]
+ {
+ new PackageVisibleMemberContainingClassMarker(),
+ new AllAttributeVisitor(
+ new MultiAttributeVisitor(
+ new AttributeVisitor[]
+ {
+ new CatchExceptionMarker(),
+ new AllInstructionVisitor(
+ new MultiInstructionVisitor(
+ new InstructionVisitor[]
+ {
+ new InstantiationClassMarker(),
+ new InstanceofClassMarker(),
+ new DotClassMarker(),
+ new MethodInvocationMarker(),
+ new SuperInvocationMarker(),
+ new BackwardBranchMarker(),
+ new AccessMethodMarker(),
+ })),
+ new AllExceptionInfoVisitor(
+ new ExceptionHandlerConstantVisitor(
+ new ReferencedClassVisitor(
+ new CaughtClassMarker()))),
+ })),
+ })),
+ }));
+
+ if (classMergingVertical)
+ {
+ // Merge classes into their superclasses or interfaces.
+ programClassPool.classesAccept(
+ new VerticalClassMerger(configuration.allowAccessModification,
+ configuration.mergeInterfacesAggressively,
+ classMergingVerticalCounter));
}
- // Merge classes into their superclasses or interfaces.
- programClassPool.classesAccept(new VerticalClassMerger(configuration.allowAccessModification,
- configuration.mergeInterfacesAggressively,
- classMergeCounter));
+ if (classMergingHorizontal)
+ {
+ // Merge classes into their sibling classes.
+ programClassPool.classesAccept(
+ new HorizontalClassMerger(configuration.allowAccessModification,
+ configuration.mergeInterfacesAggressively,
+ classMergingHorizontalCounter));
+ }
- // Merge classes into their sibling classes.
- programClassPool.classesAccept(new HorizontalClassMerger(configuration.allowAccessModification,
- configuration.mergeInterfacesAggressively,
- classMergeCounter));
+ if (classMergingVertical ||
+ classMergingHorizontal)
+ {
+ // Clean up inner class attributes to avoid loops.
+ programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover());
- // Clean up inner class attributes to avoid loops.
- programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover());
+ // Update references to merged classes.
+ programClassPool.classesAccept(new TargetClassChanger());
+ programClassPool.classesAccept(new ClassReferenceFixer(true));
+ programClassPool.classesAccept(new MemberReferenceFixer());
- // Update references to merged classes.
- programClassPool.classesAccept(new TargetClassChanger());
- programClassPool.classesAccept(new ClassReferenceFixer(true));
- programClassPool.classesAccept(new MemberReferenceFixer());
+ if (configuration.allowAccessModification)
+ {
+ // Fix the access flags of referenced merged classes and their
+ // class members.
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new AccessFixer()));
+ }
+ }
+
+ if (methodRemovalParameter ||
+ classMergingVertical ||
+ classMergingHorizontal)
+ {
+ // Tweak the descriptors of duplicate initializers.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new DuplicateInitializerFixer(initializerFixCounter)));
+
+ if (initializerFixCounter.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());
+ }
+ }
- if (configuration.allowAccessModification)
+ if (methodInliningUnique)
{
- // Fix the access flags of referenced merged classes and their class
- // members.
- programClassPool.classesAccept(new AllConstantVisitor(
- new AccessFixer()));
+ // Inline methods that are only invoked once.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new MethodInliner(configuration.microEdition,
+ configuration.allowAccessModification,
+ true,
+ methodInliningUniqueCounter))));
}
- // Inline methods that are only invoked once.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new MethodInliner(configuration.microEdition, configuration.allowAccessModification, true, inliningCounter))));
+ if (methodInliningShort)
+ {
+ // Inline short methods.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new MethodInliner(configuration.microEdition,
+ configuration.allowAccessModification,
+ false,
+ methodInliningShortCounter))));
+ }
- // Inline short methods.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new MethodInliner(configuration.microEdition, configuration.allowAccessModification, false, inliningCounter))));
+ if (methodInliningTailrecursion)
+ {
+ // Simplify tail recursion calls.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new TailRecursionSimplifier(methodInliningTailrecursionCounter))));
+ }
- // Simplify tail recursion calls.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new TailRecursionSimplifier(tailRecursionCounter))));
+ if (fieldMarkingPrivate ||
+ methodMarkingPrivate)
+ {
+ // Mark all class members that can not be made private.
+ programClassPool.classesAccept(
+ new NonPrivateMemberMarker());
+ }
- // Mark all class members that can not be made private.
- programClassPool.classesAccept(new NonPrivateMemberMarker());
+ if (fieldMarkingPrivate ||
+ methodMarkingPrivate)
+ {
+ // Make all non-private fields private, whereever possible.
+ programClassPool.classesAccept(
+ new AllFieldVisitor(
+ new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
+ new MemberPrivatizer(fieldMarkingPrivateCounter))));
+ }
- // Make all non-private and unmarked class members in non-interface
- // classes private.
- programClassPool.classesAccept(new ClassAccessFilter(0, ClassConstants.INTERNAL_ACC_INTERFACE,
- new AllMemberVisitor(
- new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
- new MemberPrivatizer(privateFieldCounter, privateMethodCounter)))));
+ if (methodMarkingPrivate)
+ {
+ // Make all non-private methods private, whereever possible.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.INTERNAL_ACC_INTERFACE,
+ new AllMethodVisitor(
+ new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
+ new MemberPrivatizer(methodMarkingPrivateCounter)))));
+ }
- if (configuration.allowAccessModification)
+ if ((methodInliningUnique ||
+ methodInliningShort ||
+ methodInliningTailrecursion) &&
+ configuration.allowAccessModification)
{
// Fix the access flags of referenced classes and class members,
// for MethodInliner.
- programClassPool.classesAccept(new AllConstantVisitor(
- new AccessFixer()));
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new AccessFixer()));
}
- // Fix invocations of methods that have become non-abstract or private,
- // for ClassMerger, MemberPrivatizer, AccessFixer.
- programClassPool.classesAccept(new AllMemberVisitor(
- new AllAttributeVisitor(
- new MethodInvocationFixer())));
+ if (methodRemovalParameter ||
+ classMergingVertical ||
+ classMergingHorizontal ||
+ methodMarkingPrivate)
+ {
+ // Fix invocations of interface methods, of methods that have become
+ // non-abstract or private, and of methods that have moved to a
+ // different package.
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new AllAttributeVisitor(
+ new MethodInvocationFixer())));
+ }
+
+ if (codeMerging)
+ {
+ // Share common blocks of code at branches.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new GotoCommonCodeReplacer(codeMergingCounter))));
+ }
// Create a branch target marker and a code attribute editor that can
// be reused for all code attributes.
BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
- // Share common blocks of code at branches.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new GotoCommonCodeReplacer(commonCodeCounter))));
-
- // Perform various peephole optimisations.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new PeepholeOptimizer(branchTargetFinder, codeAttributeEditor,
- new MultiInstructionVisitor(
- new InstructionVisitor[]
- {
- new InstructionSequencesReplacer(InstructionSequenceConstants.PATTERN_CONSTANTS,
- InstructionSequenceConstants.INSTRUCTION_SEQUENCES,
- branchTargetFinder, codeAttributeEditor, peepholeCounter),
- new GotoGotoReplacer( codeAttributeEditor, peepholeCounter),
- new GotoReturnReplacer( codeAttributeEditor, peepholeCounter),
- })))));
-
- // Remove unnecessary exception handlers.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new UnreachableExceptionRemover(exceptionCounter))));
-
- // Remove unreachable code.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new UnreachableCodeRemover(deletedCounter))));
-
- // Remove all unused local variables.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new VariableShrinker(variableShrinkCounter))));
-
- // Optimize the variables.
- programClassPool.classesAccept(new AllMethodVisitor(
- new AllAttributeVisitor(
- new VariableOptimizer(!configuration.microEdition))));
-
- int classMergeCound = classMergeCounter .getCount();
- int finalClassCount = finalClassCounter .getCount();
- int privateFieldCount = privateFieldCounter .getCount();
- int privateMethodCount = privateMethodCounter .getCount();
- int staticMethodCount = staticMethodCounter .getCount();
- int finalMethodCount = finalMethodCounter .getCount();
- int writeOnlyFieldCount = writeOnlyFieldCounter .getCount();
- int constantFieldCount = constantFieldCounter .getCount();
- int constantMethodCount = constantMethodCounter .getCount();
- int descriptorShrinkCount = descriptorShrinkCounter.getCount() - initializerFixCounter.getCount();
- int parameterShrinkCount = parameterShrinkCounter .getCount() - initializerFixCounter.getCount();
- int variableShrinkCount = variableShrinkCounter .getCount();
- int exceptionCount = exceptionCounter .getCount();
- int tailRecursionCount = tailRecursionCounter .getCount();
- int inliningCount = inliningCounter .getCount();
- int commonCodeCount = commonCodeCounter .getCount();
- int pushCount = pushCounter .getCount();
- int branchCount = branchCounter .getCount();
- int removedCount = deletedCounter .getCount() - addedCounter.getCount();
- int peepholeCount = peepholeCounter .getCount();
+ List peepholeOptimizations = new ArrayList();
+ if (codeSimplificationVariable)
+ {
+ // Peephole optimizations involving local variables.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS,
+ InstructionSequenceConstants.VARIABLE,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationVariableCounter));
+ }
+
+ if (codeSimplificationArithmetic)
+ {
+ // Peephole optimizations involving arithmetic operations.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS,
+ InstructionSequenceConstants.ARITHMETIC,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationArithmeticCounter));
+ }
+
+ if (codeSimplificationCast)
+ {
+ // Peephole optimizations involving cast operations.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS,
+ InstructionSequenceConstants.CAST,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationCastCounter));
+ }
+
+ if (codeSimplificationField)
+ {
+ // Peephole optimizations involving fields.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS,
+ InstructionSequenceConstants.FIELD,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationFieldCounter));
+ }
+
+ if (codeSimplificationBranch)
+ {
+ // Peephole optimizations involving branches.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS,
+ InstructionSequenceConstants.BRANCH,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationBranchCounter));
+
+ // Include optimization of branches to branches and returns.
+ peepholeOptimizations.add(
+ new GotoGotoReplacer(codeAttributeEditor, codeSimplificationBranchCounter));
+ peepholeOptimizations.add(
+ new GotoReturnReplacer(codeAttributeEditor, codeSimplificationBranchCounter));
+ }
+
+ if (!peepholeOptimizations.isEmpty())
+ {
+ // Convert the list into an array.
+ InstructionVisitor[] peepholeOptimizationsArray =
+ new InstructionVisitor[peepholeOptimizations.size()];
+ peepholeOptimizations.toArray(peepholeOptimizationsArray);
+
+ // Perform the peephole optimisations.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new PeepholeOptimizer(branchTargetFinder, codeAttributeEditor,
+ new MultiInstructionVisitor(
+ peepholeOptimizationsArray)))));
+ }
+
+ if (codeRemovalException)
+ {
+ // Remove unnecessary exception handlers.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new UnreachableExceptionRemover(codeRemovalExceptionCounter))));
+ }
+
+ if (codeRemovalSimple)
+ {
+ // Remove unreachable code.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new UnreachableCodeRemover(deletedCounter))));
+ }
+
+ if (codeRemovalVariable)
+ {
+ // Remove all unused local variables.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new VariableShrinker(codeRemovalVariableCounter))));
+ }
+ else
+ {
+ // Clean up all unused local variables.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new VariableCleaner())));
+ }
+
+ if (codeAllocationVariable)
+ {
+ // Optimize the variables.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new VariableOptimizer(false, codeAllocationVariableCounter))));
+ }
+
+ int classMarkingFinalCount = classMarkingFinalCounter .getCount();
+ int classMergingVerticalCount = classMergingVerticalCounter .getCount();
+ int classMergingHorizontalCount = classMergingHorizontalCounter .getCount();
+ int fieldRemovalWriteonlyCount = fieldRemovalWriteonlyCounter .getCount();
+ int fieldMarkingPrivateCount = fieldMarkingPrivateCounter .getCount();
+ int fieldPropagationValueCount = fieldPropagationValueCounter .getCount();
+ int methodMarkingPrivateCount = methodMarkingPrivateCounter .getCount();
+ int methodMarkingStaticCount = methodMarkingStaticCounter .getCount();
+ int methodMarkingFinalCount = methodMarkingFinalCounter .getCount();
+ int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter.getCount();
+ int methodPropagationParameterCount = methodPropagationParameterCounter .getCount();
+ int methodPropagationReturnvalueCount = methodPropagationReturnvalueCounter.getCount();
+ int methodInliningShortCount = methodInliningShortCounter .getCount();
+ int methodInliningUniqueCount = methodInliningUniqueCounter .getCount();
+ int methodInliningTailrecursionCount = methodInliningTailrecursionCounter .getCount();
+ int codeMergingCount = codeMergingCounter .getCount();
+ int codeSimplificationVariableCount = codeSimplificationVariableCounter .getCount();
+ int codeSimplificationArithmeticCount = codeSimplificationArithmeticCounter.getCount();
+ int codeSimplificationCastCount = codeSimplificationCastCounter .getCount();
+ int codeSimplificationFieldCount = codeSimplificationFieldCounter .getCount();
+ int codeSimplificationBranchCount = codeSimplificationBranchCounter .getCount();
+ int codeSimplificationAdvancedCount = codeSimplificationAdvancedCounter .getCount();
+ int codeRemovalCount = deletedCounter .getCount() - addedCounter.getCount();
+ int codeRemovalVariableCount = codeRemovalVariableCounter .getCount();
+ int codeRemovalExceptionCount = codeRemovalExceptionCounter .getCount();
+ int codeAllocationVariableCount = codeAllocationVariableCounter .getCount();
if (configuration.verbose)
{
- System.out.println(" Number of merged classes: "+classMergeCound);
- System.out.println(" Number of finalized classes: "+finalClassCount);
- System.out.println(" Number of privatized fields: "+privateFieldCount);
- System.out.println(" Number of privatized methods: "+privateMethodCount);
- System.out.println(" Number of staticized methods: "+staticMethodCount);
- System.out.println(" Number of finalized methods: "+finalMethodCount);
- System.out.println(" Number of removed write-only fields: "+writeOnlyFieldCount);
- System.out.println(" Number of inlined constant fields: "+constantFieldCount);
- System.out.println(" Number of inlined constant methods: "+constantMethodCount);
- System.out.println(" Number of simplified method declarations: "+descriptorShrinkCount);
- System.out.println(" Number of removed parameters: "+parameterShrinkCount);
- System.out.println(" Number of removed local variables: "+variableShrinkCount);
- System.out.println(" Number of inlined method calls: "+inliningCount);
- System.out.println(" Number of simplified tail recursion calls: "+tailRecursionCount);
- System.out.println(" Number of removed exception blocks: "+exceptionCount);
- System.out.println(" Number of merged code blocks: "+commonCodeCount);
- System.out.println(" Number of simplified push instructions: "+pushCount);
- System.out.println(" Number of simplified branches: "+branchCount);
- System.out.println(" Number of removed instructions: "+removedCount);
- System.out.println(" Number of peephole optimizations: "+peepholeCount);
- }
-
- return classMergeCound > 0 ||
- finalClassCount > 0 ||
- privateFieldCount > 0 ||
- privateMethodCount > 0 ||
- staticMethodCount > 0 ||
- finalMethodCount > 0 ||
- writeOnlyFieldCount > 0 ||
- constantFieldCount > 0 ||
- constantMethodCount > 0 ||
- descriptorShrinkCount > 0 ||
- parameterShrinkCount > 0 ||
- variableShrinkCount > 0 ||
- inliningCount > 0 ||
- tailRecursionCount > 0 ||
- exceptionCount > 0 ||
- commonCodeCount > 0 ||
- pushCount > 0 ||
- branchCount > 0 ||
- removedCount > 0 ||
- peepholeCount > 0;
+ System.out.println(" Number of finalized classes: " + classMarkingFinalCount + disabled(classMarkingFinal));
+ System.out.println(" Number of vertically merged classes: " + classMergingVerticalCount + disabled(classMergingVertical));
+ System.out.println(" Number of horizontally merged classes: " + classMergingHorizontalCount + disabled(classMergingHorizontal));
+ System.out.println(" Number of removed write-only fields: " + fieldRemovalWriteonlyCount + disabled(fieldRemovalWriteonly));
+ System.out.println(" Number of privatized fields: " + fieldMarkingPrivateCount + disabled(fieldMarkingPrivate));
+ System.out.println(" Number of inlined constant fields: " + fieldPropagationValueCount + disabled(fieldPropagationValue));
+ System.out.println(" Number of privatized methods: " + methodMarkingPrivateCount + disabled(methodMarkingPrivate));
+ System.out.println(" Number of staticized methods: " + methodMarkingStaticCount + disabled(methodMarkingStatic));
+ System.out.println(" Number of finalized methods: " + methodMarkingFinalCount + disabled(methodMarkingFinal));
+ System.out.println(" Number of removed method parameters: " + methodRemovalParameterCount + disabled(methodRemovalParameter));
+ System.out.println(" Number of inlined constant parameters: " + methodPropagationParameterCount + disabled(methodPropagationParameter));
+ System.out.println(" Number of inlined constant return values: " + methodPropagationReturnvalueCount + disabled(methodPropagationReturnvalue));
+ System.out.println(" Number of inlined short method calls: " + methodInliningShortCount + disabled(methodInliningShort));
+ System.out.println(" Number of inlined unique method calls: " + methodInliningUniqueCount + disabled(methodInliningUnique));
+ System.out.println(" Number of inlined tail recursion calls: " + methodInliningTailrecursionCount + disabled(methodInliningTailrecursion));
+ System.out.println(" Number of merged code blocks: " + codeMergingCount + disabled(codeMerging));
+ System.out.println(" Number of variable peephole optimizations: " + codeSimplificationVariableCount + disabled(codeSimplificationVariable));
+ System.out.println(" Number of arithmetic peephole optimizations: " + codeSimplificationArithmeticCount + disabled(codeSimplificationArithmetic));
+ 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 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));
+ System.out.println(" Number of removed exception blocks: " + codeRemovalExceptionCount + disabled(codeRemovalException));
+ System.out.println(" Number of optimized local variable frames: " + codeAllocationVariableCount + disabled(codeAllocationVariable));
+ }
+
+ return classMarkingFinalCount > 0 ||
+ classMergingVerticalCount > 0 ||
+ classMergingHorizontalCount > 0 ||
+ fieldRemovalWriteonlyCount > 0 ||
+ fieldMarkingPrivateCount > 0 ||
+ methodMarkingPrivateCount > 0 ||
+ methodMarkingStaticCount > 0 ||
+ methodMarkingFinalCount > 0 ||
+ fieldPropagationValueCount > 0 ||
+ methodRemovalParameterCount > 0 ||
+ methodPropagationParameterCount > 0 ||
+ methodPropagationReturnvalueCount > 0 ||
+ methodInliningShortCount > 0 ||
+ methodInliningUniqueCount > 0 ||
+ methodInliningTailrecursionCount > 0 ||
+ codeMergingCount > 0 ||
+ codeSimplificationVariableCount > 0 ||
+ codeSimplificationArithmeticCount > 0 ||
+ codeSimplificationCastCount > 0 ||
+ codeSimplificationFieldCount > 0 ||
+ codeSimplificationBranchCount > 0 ||
+ codeSimplificationAdvancedCount > 0 ||
+ codeRemovalCount > 0 ||
+ codeRemovalVariableCount > 0 ||
+ codeRemovalExceptionCount > 0 ||
+ codeAllocationVariableCount > 0;
+ }
+
+
+ /**
+ * Returns a String indicating whether the given flag is enabled or
+ * disabled.
+ */
+ private String disabled(boolean flag)
+ {
+ return flag ? "" : " (disabled)";
+ }
+
+
+ /**
+ * Returns a String indicating whether the given flags are enabled or
+ * disabled.
+ */
+ private String disabled(boolean flag1, boolean flag2)
+ {
+ return flag1 && flag2 ? "" :
+ flag1 || flag2 ? " (partially disabled)" :
+ " (disabled)";
}
}
diff --git a/src/proguard/optimize/ParameterShrinker.java b/src/proguard/optimize/ParameterShrinker.java
index 9e94985..a2bc6d3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.VariableEditor;
+import proguard.classfile.editor.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
import proguard.optimize.info.ParameterUsageMarker;
@@ -46,7 +46,7 @@ implements AttributeVisitor
private final MemberVisitor extraVariableMemberVisitor;
- private final VariableEditor variableEditor = new VariableEditor();
+ private final VariableRemapper variableRemapper = new VariableRemapper();
/**
@@ -97,21 +97,30 @@ implements AttributeVisitor
System.out.println(" Max locals = " + maxLocals);
}
- // Delete unused variables from the local variable frame.
- variableEditor.reset(maxLocals);
+ // Create a variable map.
+ int[] variableMap = new int[maxLocals];
+ // Move unused parameters right after the parameter block.
+ int usedParameterIndex = 0;
+ int unusedParameterIndex = newParameterSize;
for (int parameterIndex = 0; parameterIndex < oldParameterSize; parameterIndex++)
{
- // Is the variable not required as a parameter?
- if (!ParameterUsageMarker.isParameterUsed(method, parameterIndex))
+ // Is the variable required as a parameter?
+ if (ParameterUsageMarker.isParameterUsed(method, parameterIndex))
+ {
+ // Keep the variable as a parameter.
+ variableMap[parameterIndex] = usedParameterIndex++;
+ }
+ else
{
if (DEBUG)
{
System.out.println(" Deleting parameter #"+parameterIndex);
}
- // Delete the unused variable.
- variableEditor.deleteVariable(parameterIndex);
+ // Shift the variable to the unused parameter block,
+ // in case it is still used as a variable.
+ variableMap[parameterIndex] = unusedParameterIndex++;
// Visit the method, if required.
if (extraVariableMemberVisitor != null)
@@ -121,8 +130,17 @@ implements AttributeVisitor
}
}
- // Shift all remaining parameters and variables in the byte code.
- variableEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ // Fill out the remainder of the map.
+ for (int variableIndex = oldParameterSize; variableIndex < maxLocals; variableIndex++)
+ {
+ variableMap[variableIndex] = variableIndex;
+ }
+
+ // Set the map.
+ variableRemapper.setVariableMap(variableMap);
+
+ // Remap the variables.
+ variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
}
}
}
diff --git a/src/proguard/optimize/TailRecursionSimplifier.java b/src/proguard/optimize/TailRecursionSimplifier.java
index c571cf7..0946b6a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,9 +43,6 @@ implements AttributeVisitor,
ConstantVisitor,
ExceptionInfoVisitor
{
- private static final int MAXIMUM_CODE_EXPANSION = 2;
- private static final int MAXIMUM_EXTRA_CODE_LENGTH = 128;
-
//*
private static final boolean DEBUG = false;
/*/
@@ -131,8 +128,7 @@ implements AttributeVisitor,
{
// The code may expand, due to expanding constant and variable
// instructions.
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength * MAXIMUM_CODE_EXPANSION +
- MAXIMUM_EXTRA_CODE_LENGTH);
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
// Copy the instructions.
codeAttribute.instructionsAccept(clazz, method, this);
@@ -281,7 +277,7 @@ implements AttributeVisitor,
}
}
- codeAttributeComposer.beginCodeFragment((parameterOffset + parameterCount) * 4);
+ codeAttributeComposer.beginCodeFragment(parameterSize + 1);
// Go over the parameter types backward, storing the stack entries
// in their corresponding variables.
diff --git a/src/proguard/optimize/WriteOnlyFieldFilter.java b/src/proguard/optimize/WriteOnlyFieldFilter.java
index 8a1985d..578beb2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationShrinker.java
similarity index 61%
copy from src/proguard/optimize/evaluation/EvaluationSimplifier.java
copy to src/proguard/optimize/evaluation/EvaluationShrinker.java
index 95abf42..1463feb 100644
--- a/src/proguard/optimize/evaluation/EvaluationSimplifier.java
+++ b/src/proguard/optimize/evaluation/EvaluationShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,8 @@ package proguard.optimize.evaluation;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.RefConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.editor.CodeAttributeEditor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
@@ -38,29 +40,25 @@ import proguard.optimize.info.*;
*
* @author Eric Lafortune
*/
-public class EvaluationSimplifier
+public class EvaluationShrinker
extends SimplifiedVisitor
implements AttributeVisitor
{
//*
private static final boolean DEBUG_RESULTS = false;
- private static final boolean DEBUG_ANALYSIS = false;
private static final boolean DEBUG = false;
/*/
private static boolean DEBUG_RESULTS = true;
- private static boolean DEBUG_ANALYSIS = true;
private static boolean DEBUG = true;
//*/
- private final InstructionVisitor extraPushInstructionVisitor;
- private final InstructionVisitor extraBranchInstructionVisitor;
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 MyInstructionSimplifier instructionSimplifier = new MyInstructionSimplifier();
+ 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);
@@ -69,46 +67,36 @@ implements AttributeVisitor
private boolean[][] stacksNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
private boolean[][] stacksSimplifiedBefore = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
private boolean[] instructionsNecessary = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
- private boolean[] instructionsSimplified = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
- private int[] aliasingVariables = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int maxMarkedOffset;
/**
- * Creates a new EvaluationSimplifier.
+ * Creates a new EvaluationShrinker.
*/
- public EvaluationSimplifier()
+ public EvaluationShrinker()
{
- this(new PartialEvaluator(), null, null, null, null);
+ this(new PartialEvaluator(), null, null);
}
/**
- * Creates a new EvaluationSimplifier.
+ * Creates a new EvaluationShrinker.
* @param partialEvaluator the partial evaluator that will
* execute the code and provide
* information about the results.
- * @param extraPushInstructionVisitor an optional extra visitor for all
- * simplified push instructions.
- * @param extraBranchInstructionVisitor an optional extra visitor for all
- * simplified branch instructions.
* @param extraDeletedInstructionVisitor an optional extra visitor for all
* deleted instructions.
* @param extraAddedInstructionVisitor an optional extra visitor for all
* added instructions.
*/
- public EvaluationSimplifier(PartialEvaluator partialEvaluator,
- InstructionVisitor extraPushInstructionVisitor,
- InstructionVisitor extraBranchInstructionVisitor,
- InstructionVisitor extraDeletedInstructionVisitor,
- InstructionVisitor extraAddedInstructionVisitor)
+ public EvaluationShrinker(PartialEvaluator partialEvaluator,
+ InstructionVisitor extraDeletedInstructionVisitor,
+ InstructionVisitor extraAddedInstructionVisitor)
{
- this.partialEvaluator = partialEvaluator;
- this.extraPushInstructionVisitor = extraPushInstructionVisitor;
- this.extraBranchInstructionVisitor = extraBranchInstructionVisitor;
- this.extraDeletedInstructionVisitor = extraDeletedInstructionVisitor;
- this.extraAddedInstructionVisitor = extraAddedInstructionVisitor;
+ this.partialEvaluator = partialEvaluator;
+ this.extraDeletedInstructionVisitor = extraDeletedInstructionVisitor;
+ this.extraAddedInstructionVisitor = extraAddedInstructionVisitor;
}
@@ -119,11 +107,11 @@ implements AttributeVisitor
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
-// DEBUG = DEBUG_ANALYSIS = DEBUG_RESULTS =
+// DEBUG = DEBUG_RESULTS =
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
- // TODO: Remove this when the evaluation simplifier has stabilized.
+ // TODO: Remove this when the evaluation shrinker has stabilized.
// Catch any unexpected exceptions from the actual visiting method.
try
{
@@ -132,7 +120,7 @@ implements AttributeVisitor
}
catch (RuntimeException ex)
{
- System.err.println("Unexpected error while optimizing after partial evaluation:");
+ System.err.println("Unexpected error while shrinking instructions after partial evaluation:");
System.err.println(" Class = ["+clazz.getName()+"]");
System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
@@ -171,8 +159,8 @@ implements AttributeVisitor
// Reset the code changes.
codeAttributeEditor.reset(codeLength);
- // Replace any instructions that can be simplified.
- if (DEBUG_ANALYSIS) System.out.println("Instruction simplification:");
+ // Mark any unused method parameters on the stack.
+ if (DEBUG) System.out.println("Invocation simplification:");
for (int offset = 0; offset < codeLength; offset++)
{
@@ -181,12 +169,12 @@ implements AttributeVisitor
Instruction instruction = InstructionFactory.create(codeAttribute.code,
offset);
- instruction.accept(clazz, method, codeAttribute, offset, instructionSimplifier);
+ instruction.accept(clazz, method, codeAttribute, offset, unusedParameterSimplifier);
}
}
// Mark all essential instructions that have been encountered as used.
- if (DEBUG_ANALYSIS) System.out.println("Usage initialization: ");
+ if (DEBUG) System.out.println("Usage initialization: ");
maxMarkedOffset = -1;
@@ -195,7 +183,7 @@ implements AttributeVisitor
int superInitializationOffset = partialEvaluator.superInitializationOffset();
if (superInitializationOffset != PartialEvaluator.NONE)
{
- if (DEBUG_ANALYSIS) System.out.print("(super.<init>)");
+ if (DEBUG) System.out.print("(super.<init>)");
markInstruction(superInitializationOffset);
}
@@ -212,7 +200,7 @@ implements AttributeVisitor
if (instruction.opcode == InstructionConstants.OP_GOTO &&
((BranchInstruction)instruction).branchOffset == 0)
{
- if (DEBUG_ANALYSIS) System.out.print("(infinite loop)");
+ if (DEBUG) System.out.print("(infinite loop)");
markInstruction(offset);
}
@@ -227,7 +215,7 @@ implements AttributeVisitor
}
}
}
- if (DEBUG_ANALYSIS) System.out.println();
+ if (DEBUG) System.out.println();
// Globally mark instructions and their produced variables and stack
@@ -235,7 +223,7 @@ implements AttributeVisitor
// Instead of doing this recursively, we loop across all instructions,
// starting at the highest previously unmarked instruction that has
// been been marked.
- if (DEBUG_ANALYSIS) System.out.println("Usage marking:");
+ if (DEBUG) System.out.println("Usage marking:");
while (maxMarkedOffset >= 0)
{
@@ -247,22 +235,10 @@ implements AttributeVisitor
{
if (isInstructionNecessary(offset))
{
- if (isInstructionSimplified(offset))
- {
- int variableIndex = getAliasingVariable(offset);
-
- if (variableIndex >= 0)
- {
- markVariableProducers(offset, variableIndex);
- }
- }
- else
- {
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
- instruction.accept(clazz, method, codeAttribute, offset, producerMarker);
- }
+ instruction.accept(clazz, method, codeAttribute, offset, producerMarker);
}
// Check if this instruction is a branch origin from a branch
@@ -278,7 +254,7 @@ implements AttributeVisitor
false);
}
- if (DEBUG_ANALYSIS)
+ if (DEBUG)
{
if (maxMarkedOffset > offset)
{
@@ -286,13 +262,13 @@ implements AttributeVisitor
}
}
}
- if (DEBUG_ANALYSIS) System.out.println();
+ if (DEBUG) System.out.println();
// Mark variable initializations, even if they aren't strictly necessary.
// The virtual machine's verification step is not smart enough to see
// this, and may complain otherwise.
- if (DEBUG_ANALYSIS) System.out.println("Initialization marking: ");
+ if (DEBUG) System.out.println("Initialization marking: ");
for (int offset = 0; offset < codeLength; offset++)
{
@@ -314,11 +290,11 @@ implements AttributeVisitor
}
}
}
- if (DEBUG_ANALYSIS) System.out.println();
+ if (DEBUG) System.out.println();
// Locally fix instructions, in order to keep the stack consistent.
- if (DEBUG_ANALYSIS) System.out.println("Stack consistency fixing:");
+ if (DEBUG) System.out.println("Stack consistency fixing:");
maxMarkedOffset = codeLength - 1;
@@ -348,18 +324,18 @@ implements AttributeVisitor
false);
}
}
- if (DEBUG_ANALYSIS) System.out.println();
+ if (DEBUG) System.out.println();
// Replace traced but unmarked backward branches by infinite loops.
// The virtual machine's verification step is not smart enough to see
// the code isn't reachable, and may complain otherwise.
// Any clearly unreachable code will still be removed elsewhere.
- if (DEBUG_ANALYSIS) System.out.println("Infinite loop fixing:");
+ if (DEBUG) System.out.println("Infinite loop fixing:");
for (int offset = 0; offset < codeLength; offset++)
{
- // Is a traced but unmarked backward branch, without an unmarked
+ // Is it a traced but unmarked backward branch, without an unmarked
// straddling forward branch? Note that this is still a heuristic.
if (partialEvaluator.isTraced(offset) &&
!isInstructionNecessary(offset) &&
@@ -368,13 +344,35 @@ implements AttributeVisitor
!isAnyUnnecessaryInstructionBranchingOver(lastNecessaryInstructionOffset(offset),
offset))
{
+ replaceByInfiniteLoop(clazz, offset);
+ }
+ }
+ if (DEBUG) System.out.println();
+
+
+ // Insert infinite loops after jumps to subroutines that don't return.
+ // The virtual machine's verification step is not smart enough to see
+ // the code isn't reachable, and may complain otherwise.
+ if (DEBUG) System.out.println("Non-returning subroutine fixing:");
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Is it a traced but unmarked backward branch, without an unmarked
+ // straddling forward branch? Note that this is still a heuristic.
+ if (isInstructionNecessary(offset) &&
+ partialEvaluator.isSubroutineInvocation(offset))
+ {
Instruction instruction = InstructionFactory.create(codeAttribute.code,
offset);
- replaceByInfiniteLoop(clazz, offset, instruction);
+ int nextOffset = offset + instruction.length(offset);
+ if (!isInstructionNecessary(nextOffset))
+ {
+ replaceByInfiniteLoop(clazz, nextOffset);
+ }
}
}
- if (DEBUG_ANALYSIS) System.out.println();
+ if (DEBUG) System.out.println();
// Delete all instructions that are not used.
@@ -387,9 +385,9 @@ implements AttributeVisitor
{
codeAttributeEditor.deleteInstruction(offset);
- codeAttributeEditor.insertBeforeInstruction(offset, null);
- codeAttributeEditor.replaceInstruction(offset, null);
- codeAttributeEditor.insertAfterInstruction(offset, null);
+ codeAttributeEditor.insertBeforeInstruction(offset, (Instruction)null);
+ codeAttributeEditor.replaceInstruction(offset, (Instruction)null);
+ codeAttributeEditor.insertAfterInstruction(offset, (Instruction)null);
// Visit the instruction, if required.
if (extraDeletedInstructionVisitor != null)
@@ -464,239 +462,43 @@ implements AttributeVisitor
/**
- * This InstructionVisitor simplifies the instructions that it visits,
- * whenever possible, and marks them as such.
+ * This MemberVisitor marks stack entries that aren't necessary because
+ * parameters aren't used in the methods that are visited.
*/
- private class MyInstructionSimplifier
+ private class MyUnusedParameterSimplifier
extends SimplifiedVisitor
- implements InstructionVisitor
+ implements InstructionVisitor, ConstantVisitor, MemberVisitor
{
- // Implementations for InstructionVisitor.
-
- public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
- {
- switch (simpleInstruction.opcode)
- {
- case InstructionConstants.OP_IALOAD:
- case InstructionConstants.OP_BALOAD:
- case InstructionConstants.OP_CALOAD:
- case InstructionConstants.OP_SALOAD:
- case InstructionConstants.OP_IADD:
- case InstructionConstants.OP_ISUB:
- case InstructionConstants.OP_IMUL:
- case InstructionConstants.OP_IDIV:
- case InstructionConstants.OP_IREM:
- case InstructionConstants.OP_INEG:
- case InstructionConstants.OP_ISHL:
- case InstructionConstants.OP_ISHR:
- case InstructionConstants.OP_IUSHR:
- case InstructionConstants.OP_IAND:
- case InstructionConstants.OP_IOR:
- case InstructionConstants.OP_IXOR:
- case InstructionConstants.OP_L2I:
- case InstructionConstants.OP_F2I:
- case InstructionConstants.OP_D2I:
- case InstructionConstants.OP_I2B:
- case InstructionConstants.OP_I2C:
- case InstructionConstants.OP_I2S:
- replaceIntegerPushInstruction(clazz, offset, simpleInstruction);
- break;
-
- case InstructionConstants.OP_LALOAD:
- case InstructionConstants.OP_LADD:
- case InstructionConstants.OP_LSUB:
- case InstructionConstants.OP_LMUL:
- case InstructionConstants.OP_LDIV:
- case InstructionConstants.OP_LREM:
- case InstructionConstants.OP_LNEG:
- case InstructionConstants.OP_LSHL:
- case InstructionConstants.OP_LSHR:
- case InstructionConstants.OP_LUSHR:
- case InstructionConstants.OP_LAND:
- case InstructionConstants.OP_LOR:
- case InstructionConstants.OP_LXOR:
- case InstructionConstants.OP_I2L:
- case InstructionConstants.OP_F2L:
- case InstructionConstants.OP_D2L:
- replaceLongPushInstruction(clazz, offset, simpleInstruction);
- break;
-
- case InstructionConstants.OP_FALOAD:
- case InstructionConstants.OP_FADD:
- case InstructionConstants.OP_FSUB:
- case InstructionConstants.OP_FMUL:
- case InstructionConstants.OP_FDIV:
- case InstructionConstants.OP_FREM:
- case InstructionConstants.OP_FNEG:
- case InstructionConstants.OP_I2F:
- case InstructionConstants.OP_L2F:
- case InstructionConstants.OP_D2F:
- replaceFloatPushInstruction(clazz, offset, simpleInstruction);
- break;
-
- case InstructionConstants.OP_DALOAD:
- case InstructionConstants.OP_DADD:
- case InstructionConstants.OP_DSUB:
- case InstructionConstants.OP_DMUL:
- case InstructionConstants.OP_DDIV:
- case InstructionConstants.OP_DREM:
- case InstructionConstants.OP_DNEG:
- case InstructionConstants.OP_I2D:
- case InstructionConstants.OP_L2D:
- case InstructionConstants.OP_F2D:
- replaceDoublePushInstruction(clazz, offset, simpleInstruction);
- break;
-
- case InstructionConstants.OP_AALOAD:
- replaceReferencePushInstruction(clazz, offset, simpleInstruction);
- break;
- }
- }
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- int variableIndex = variableInstruction.variableIndex;
-
- switch (variableInstruction.opcode)
- {
- case InstructionConstants.OP_ILOAD:
- case InstructionConstants.OP_ILOAD_0:
- case InstructionConstants.OP_ILOAD_1:
- case InstructionConstants.OP_ILOAD_2:
- case InstructionConstants.OP_ILOAD_3:
- replaceIntegerPushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
-
- case InstructionConstants.OP_LLOAD:
- case InstructionConstants.OP_LLOAD_0:
- case InstructionConstants.OP_LLOAD_1:
- case InstructionConstants.OP_LLOAD_2:
- case InstructionConstants.OP_LLOAD_3:
- replaceLongPushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
-
- case InstructionConstants.OP_FLOAD:
- case InstructionConstants.OP_FLOAD_0:
- case InstructionConstants.OP_FLOAD_1:
- case InstructionConstants.OP_FLOAD_2:
- case InstructionConstants.OP_FLOAD_3:
- replaceFloatPushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
+ private int invocationOffset;
+ private ConstantInstruction invocationInstruction;
- case InstructionConstants.OP_DLOAD:
- case InstructionConstants.OP_DLOAD_0:
- case InstructionConstants.OP_DLOAD_1:
- case InstructionConstants.OP_DLOAD_2:
- case InstructionConstants.OP_DLOAD_3:
- replaceDoublePushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
- case InstructionConstants.OP_ALOAD:
- case InstructionConstants.OP_ALOAD_0:
- case InstructionConstants.OP_ALOAD_1:
- case InstructionConstants.OP_ALOAD_2:
- case InstructionConstants.OP_ALOAD_3:
- replaceReferencePushInstruction(clazz, offset, variableInstruction);
- break;
+ // 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_GETSTATIC:
- case InstructionConstants.OP_GETFIELD:
- replaceAnyPushInstruction(clazz, offset, constantInstruction);
- break;
-
case InstructionConstants.OP_INVOKEVIRTUAL:
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
- new ReferencedMemberVisitor(
- new MyUnusedParameterSimplifier(offset,
- constantInstruction)));
-
- if (constantInstruction.stackPushCount(clazz) > 0 &&
- !sideEffectInstructionChecker.hasSideEffects(clazz,
- method,
- codeAttribute,
- offset,
- constantInstruction))
- {
- replaceAnyPushInstruction(clazz, offset, constantInstruction);
- }
-
- break;
-
- case InstructionConstants.OP_CHECKCAST:
- replaceReferencePushInstruction(clazz, offset, constantInstruction);
+ this.invocationOffset = offset;
+ this.invocationInstruction = constantInstruction;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
break;
}
}
- public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
- {
- switch (branchInstruction.opcode)
- {
- case InstructionConstants.OP_GOTO:
- case InstructionConstants.OP_GOTO_W:
- // Don't replace unconditional branches.
- break;
-
- case InstructionConstants.OP_JSR:
- case InstructionConstants.OP_JSR_W:
- replaceJsrInstruction(clazz, offset, branchInstruction);
- break;
-
- default:
- replaceBranchInstruction(clazz, offset, branchInstruction);
- break;
- }
- }
-
-
- public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
- {
- // First try to simplify it to a simple branch.
- replaceBranchInstruction(clazz, offset, switchInstruction);
-
- // Otherwise make sure all branch targets are valid.
- if (!isInstructionSimplified(offset))
- {
- replaceSwitchInstruction(clazz, offset, switchInstruction);
- }
- }
- }
-
-
- /**
- * This MemberVisitor marks stack entries that aren't necessary because
- * parameters aren't used in the methods that are visited.
- */
- private class MyUnusedParameterSimplifier
- extends SimplifiedVisitor
- implements MemberVisitor
- {
- private int invocationOffset;
- private ConstantInstruction invocationInstruction;
-
+ // Implementations for ConstantVisitor.
- /**
- * Creates a new MyUnusedParameterSimplifier for the given invocation
- * at the given offset.
- */
- private MyUnusedParameterSimplifier(int invocationOffset,
- ConstantInstruction invocationInstruction)
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
- this.invocationOffset = invocationOffset;
- this.invocationInstruction = invocationInstruction;
+ refConstant.referencedMemberAccept(this);
}
@@ -714,9 +516,9 @@ implements AttributeVisitor
if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0 &&
!ParameterUsageMarker.isParameterUsed(programMethod, 0))
{
- replaceInvocationInstruction(programClass,
- invocationOffset,
- invocationInstruction);
+ replaceByStaticInvocation(programClass,
+ invocationOffset,
+ invocationInstruction);
}
// Remove unused parameters.
@@ -897,14 +699,14 @@ implements AttributeVisitor
// Push some necessary stack entries.
if (requiredPushCount > 0)
{
- if (DEBUG_ANALYSIS) System.out.print(" Inserting before marked consumer "+instruction.toString(offset));
+ if (DEBUG) System.out.println(" Inserting before marked consumer "+instruction.toString(offset));
if (requiredPushCount > (instruction.isCategory2() ? 2 : 1))
{
throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"]");
}
- increaseStackSize(offset, tracedStack.getTop(0).computationalType(), false);
+ insertPushInstructions(offset, false, tracedStack.getTop(0).computationalType());
}
}
@@ -933,9 +735,9 @@ implements AttributeVisitor
// Pop the unnecessary stack entries.
if (requiredPopCount > 0)
{
- if (DEBUG_ANALYSIS) System.out.print(" Inserting after marked producer "+instruction.toString(offset));
+ if (DEBUG) System.out.println(" Inserting after marked producer "+instruction.toString(offset));
- decreaseStackSize(offset, requiredPopCount, false, false);
+ insertPopInstructions(offset, false, requiredPopCount);
}
}
}
@@ -966,9 +768,9 @@ implements AttributeVisitor
// Pop the unnecessary stack entries.
if (expectedPopCount > 0)
{
- if (DEBUG_ANALYSIS) System.out.print(" Replacing unmarked consumer "+instruction.toString(offset));
+ if (DEBUG) System.out.println(" Replacing unmarked consumer "+instruction.toString(offset));
- decreaseStackSize(offset, expectedPopCount, true, true);
+ insertPopInstructions(offset, true, expectedPopCount);
}
}
@@ -996,9 +798,9 @@ implements AttributeVisitor
// Push some necessary stack entries.
if (expectedPushCount > 0)
{
- if (DEBUG_ANALYSIS) System.out.print(" Replacing unmarked producer "+instruction.toString(offset));
+ if (DEBUG) System.out.println(" Replacing unmarked producer "+instruction.toString(offset));
- increaseStackSize(offset, tracedStack.getTop(0).computationalType(), true);
+ insertPushInstructions(offset, true, tracedStack.getTop(0).computationalType());
}
}
}
@@ -1225,7 +1027,7 @@ implements AttributeVisitor
if (!isInstructionNecessary(branchOrigin) &&
isAnyInstructionNecessary(instructionOffsetStart, instructionOffsetEnd))
{
- if (DEBUG_ANALYSIS) System.out.print("["+branchOrigin+"->"+branchTarget+"]");
+ if (DEBUG) System.out.print("["+branchOrigin+"->"+branchTarget+"]");
// Mark the branch instruction.
markInstruction(branchOrigin);
@@ -1450,14 +1252,14 @@ implements AttributeVisitor
extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, dupOffset, null);
}
- if (DEBUG_ANALYSIS) System.out.println(" Marking but deleting instruction "+instruction.toString(dupOffset));
+ if (DEBUG) System.out.println(" Marking but deleting instruction "+instruction.toString(dupOffset));
}
else if (newOpcode == oldOpcode)
{
// Leave the instruction unchanged.
codeAttributeEditor.undeleteInstruction(dupOffset);
- if (DEBUG_ANALYSIS) System.out.println(" Marking unchanged instruction "+instruction.toString(dupOffset));
+ if (DEBUG) System.out.println(" Marking unchanged instruction "+instruction.toString(dupOffset));
}
else
{
@@ -1466,23 +1268,18 @@ implements AttributeVisitor
codeAttributeEditor.replaceInstruction(dupOffset,
replacementInstruction);
- if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString());
+ if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString());
}
}
/**
- * Puts the required push instruction before the given index. The
- * instruction is marked as necessary.
- * @param offset the offset of the instruction.
- * @param computationalType the computational type on the stack, for
- * push instructions.
- * @param delete specifies whether the instruction should be
- * deleted.
+ * Pushes a specified type of stack entry before or at the given offset.
+ * The instruction is marked as necessary.
*/
- private void increaseStackSize(int offset,
- int computationalType,
- boolean delete)
+ private void insertPushInstructions(int offset,
+ boolean replace,
+ int computationalType)
{
// Mark this instruction.
markInstruction(offset);
@@ -1491,22 +1288,18 @@ implements AttributeVisitor
Instruction replacementInstruction =
new SimpleInstruction(pushOpcode(computationalType));
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
+ if (DEBUG) System.out.println(": "+replacementInstruction.toString(offset));
- // Delete the original instruction if necessary.
- if (delete)
+ // Replace or insert the push instruction.
+ if (replace)
{
- if (DEBUG_ANALYSIS) System.out.println(" Deleting original instruction at "+offset);
-
// Replace the push instruction.
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
}
else
{
// Insert the push instruction.
- codeAttributeEditor.insertBeforeInstruction(offset,
- replacementInstruction);
+ codeAttributeEditor.insertBeforeInstruction(offset, replacementInstruction);
if (extraAddedInstructionVisitor != null)
{
@@ -1538,629 +1331,144 @@ implements AttributeVisitor
/**
- * Puts the required pop instruction at the given index. The
- * instruction is marked as necessary.
- * @param offset the offset of the instruction.
- * @param popCount the required reduction of the stack size.
- * @param before specifies whether the pop instruction should be inserted
- * before or after the present instruction.
- * @param delete specifies whether the instruction should be deleted.
+ * Pops the given number of stack entries at or after the given offset.
+ * The instructions are marked as necessary.
*/
- private void decreaseStackSize(int offset,
- int popCount,
- boolean before,
- boolean delete)
+ private void insertPopInstructions(int offset, boolean replace, int popCount)
{
// Mark this instruction.
markInstruction(offset);
- boolean after = !before;
-
- int remainingPopCount = popCount;
-
- if (delete)
+ switch (popCount)
{
- // Replace the original instruction.
- int count = remainingPopCount == 1 ? 1 : 2;
-
- // Create a simple pop instrucion.
- byte replacementOpcode = count == 1 ?
- InstructionConstants.OP_POP :
- InstructionConstants.OP_POP2;
-
- Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
-
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
- // Insert the pop instruction.
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- remainingPopCount -= count;
-
- // We may insert other pop instructions before and after this one.
- before = true;
- after = true;
- }
-
- if (before && remainingPopCount > 0)
- {
- // Insert before the original instruction.
- int count = remainingPopCount == 1 ? 1 : 2;
-
- // Create a simple pop instrucion.
- byte replacementOpcode = count == 1 ?
- InstructionConstants.OP_POP :
- InstructionConstants.OP_POP2;
-
- Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
-
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
- // Insert the pop instruction.
- codeAttributeEditor.insertBeforeInstruction(offset,
- replacementInstruction);
-
- remainingPopCount -= count;
-
- if (extraAddedInstructionVisitor != null)
+ case 1:
{
- replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
- }
- }
-
- if (after && remainingPopCount > 0)
- {
- // Insert after the original instruction.
- int count = remainingPopCount == 1 ? 1 : 2;
-
- // Create a simple pop instrucion.
- byte replacementOpcode = count == 1 ?
- InstructionConstants.OP_POP :
- InstructionConstants.OP_POP2;
-
- Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
+ // Replace or insert a single pop instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
- // Insert the pop instruction.
- codeAttributeEditor.insertAfterInstruction(offset,
- replacementInstruction);
-
- remainingPopCount -= count;
+ if (replace)
+ {
+ codeAttributeEditor.replaceInstruction(offset, popInstruction);
+ }
+ else
+ {
+ codeAttributeEditor.insertAfterInstruction(offset, popInstruction);
- if (extraAddedInstructionVisitor != null)
- {
- replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
+ if (extraAddedInstructionVisitor != null)
+ {
+ popInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
+ }
+ }
+ break;
}
- }
-
- if (remainingPopCount > 0)
- {
- throw new UnsupportedOperationException("Unsupported stack size reduction ["+popCount+"]");
- }
- }
-
-
- // Small utility methods.
-
- /**
- * Replaces the push instruction at the given offset by a simpler push
- * instruction, if possible.
- */
- private void replaceAnyPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- switch (pushedValue.computationalType())
+ case 2:
{
- case Value.TYPE_INTEGER:
- replaceIntegerPushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_LONG:
- replaceLongPushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_FLOAT:
- replaceFloatPushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_DOUBLE:
- replaceDoublePushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_REFERENCE:
- replaceReferencePushInstruction(clazz, offset, instruction);
- break;
- }
- }
- }
-
+ // Replace or insert a single pop2 instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
- /**
- * Replaces the integer pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceIntegerPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- replaceIntegerPushInstruction(clazz,
- offset,
- instruction,
- partialEvaluator.getVariablesBefore(offset).size());
- }
-
-
- /**
- * Replaces the integer pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceIntegerPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- int maxVariableIndex)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- int value = pushedValue.integerValue().value();
- if (value << 16 >> 16 == value)
- {
- replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_SIPUSH,
- value);
- }
- }
- else if (pushedValue.isSpecific())
- {
- TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
- for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
- {
- if (pushedValue.equals(variables.load(variableIndex)))
+ if (replace)
{
- replaceVariablePushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_ILOAD,
- variableIndex);
+ codeAttributeEditor.replaceInstruction(offset, popInstruction);
}
- }
- }
- }
-
-
- /**
- * Replaces the long pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceLongPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- replaceLongPushInstruction(clazz,
- offset,
- instruction,
- partialEvaluator.getVariablesBefore(offset).size());
- }
-
-
- /**
- * Replaces the long pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceLongPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- int maxVariableIndex)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- long value = pushedValue.longValue().value();
- if (value == 0L ||
- value == 1L)
- {
- replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_LCONST_0,
- (int)value);
- }
- }
- else if (pushedValue.isSpecific())
- {
- TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
- for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
- {
- if (pushedValue.equals(variables.load(variableIndex)))
+ else
{
- replaceVariablePushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_LLOAD,
- variableIndex);
+ codeAttributeEditor.insertAfterInstruction(offset, popInstruction);
+
+ if (extraAddedInstructionVisitor != null)
+ {
+ popInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
+ }
}
+ break;
}
- }
- }
-
-
- /**
- * Replaces the float pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceFloatPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- replaceFloatPushInstruction(clazz,
- offset,
- instruction,
- partialEvaluator.getVariablesBefore(offset).size());
- }
+ default:
+ {
+ // Replace or insert the specified number of pop instructions.
+ Instruction[] popInstructions =
+ new Instruction[popCount / 2 + popCount % 2];
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
- /**
- * Replaces the float pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceFloatPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- int maxVariableIndex)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- float value = pushedValue.floatValue().value();
- if (value == 0f ||
- value == 1f ||
- value == 2f)
- {
- replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_FCONST_0,
- (int)value);
- }
- }
- else if (pushedValue.isSpecific())
- {
- TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
- for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
- {
- if (pushedValue.equals(variables.load(variableIndex)))
+ for (int index = 0; index < popCount / 2; index++)
{
- replaceVariablePushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_FLOAD,
- variableIndex);
+ popInstructions[index] = popInstruction;
}
- }
- }
- }
+ if (popCount % 2 == 1)
+ {
+ popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
- /**
- * Replaces the double pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceDoublePushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- replaceDoublePushInstruction(clazz,
- offset,
- instruction,
- partialEvaluator.getVariablesBefore(offset).size());
- }
+ popInstructions[popCount / 2] = popInstruction;
+ }
+ if (replace)
+ {
+ codeAttributeEditor.replaceInstruction(offset, popInstructions);
- /**
- * Replaces the double pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceDoublePushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- int maxVariableIndex)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- double value = pushedValue.doubleValue().value();
- if (value == 0.0 ||
- value == 1.0)
- {
- replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_DCONST_0,
- (int)value);
- }
- }
- else if (pushedValue.isSpecific())
- {
- TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
- for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
- {
- if (pushedValue.equals(variables.load(variableIndex)))
+ for (int index = 1; index < popInstructions.length; index++)
+ {
+ if (extraAddedInstructionVisitor != null)
+ {
+ popInstructions[index].accept(null, null, null, offset, extraAddedInstructionVisitor);
+ }
+ }
+ }
+ else
{
- replaceVariablePushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_DLOAD,
- variableIndex);
+ codeAttributeEditor.insertAfterInstruction(offset, popInstructions);
+
+ for (int index = 0; index < popInstructions.length; index++)
+ {
+ if (extraAddedInstructionVisitor != null)
+ {
+ popInstructions[index].accept(null, null, null, offset, extraAddedInstructionVisitor);
+ }
+ }
}
+ break;
}
}
}
/**
- * Replaces the reference pushing instruction at the given offset by a
- * simpler push instruction, if possible.
- */
- private void replaceReferencePushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- // A reference value can only be specific if it is null.
- replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_ACONST_NULL,
- 0);
- }
- }
-
-
- /**
- * Replaces the instruction at a given offset by a given push instruction
- * of a constant.
- */
- private void replaceConstantPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- byte replacementOpcode,
- int value)
- {
- replacePushInstruction(clazz,
- offset,
- instruction,
- new SimpleInstruction(replacementOpcode, value).shrink());
- }
-
-
- /**
- * Replaces the instruction at a given offset by a given push instruction
- * of a variable.
- */
- private void replaceVariablePushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- byte replacementOpcode,
- int variableIndex)
- {
- replacePushInstruction(clazz,
- offset,
- instruction,
- new VariableInstruction(replacementOpcode, variableIndex).shrink());
-
- // Mark that the instruction has been simplified by loading an aliasing
- // variable.
- setAliasingVariable(offset, variableIndex);
- }
-
-
- /**
- * Replaces the instruction at a given offset by a given push instruction.
- */
- private void replacePushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- Instruction replacementInstruction)
- {
- if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction at ["+offset+"] by "+replacementInstruction.toString());
-
- codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
-
- // Mark that the instruction has been simplified.
- markSimplification(clazz, offset, instruction);
-
- // Visit the instruction, if required.
- if (extraPushInstructionVisitor != null)
- {
- // Note: we're not passing the right arguments for now, knowing that
- // they aren't used anyway.
- extraPushInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
- }
- }
-
-
- /**
* Replaces the instruction at a given offset by a static invocation.
*/
- private void replaceInvocationInstruction(Clazz clazz,
- int offset,
- ConstantInstruction constantInstruction)
+ private void replaceByStaticInvocation(Clazz clazz,
+ int offset,
+ ConstantInstruction constantInstruction)
{
// Remember the replacement instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
constantInstruction.constantIndex).shrink();
- if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction at ["+offset+"] by "+replacementInstruction.toString());
+ if (DEBUG) System.out.println(" Replacing by static invocation "+constantInstruction.toString(offset)+" -> "+replacementInstruction.toString());
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
-
- // Mark that the instruction has been simplified.
- //markSimplification(clazz, offset, constantInstruction);
-
- // Visit the instruction, if required.
- //if (extraPushInstructionVisitor != null)
- //{
- // // Note: we're not passing the right arguments for now, knowing that
- // // they aren't used anyway.
- // extraPushInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
- //}
- }
-
-
- /**
- * Replaces the given 'jsr' instruction by a simpler branch instruction,
- * if possible.
- */
- private void replaceJsrInstruction(Clazz clazz,
- int offset,
- BranchInstruction branchInstruction)
- {
- // Is the subroutine ever returning?
- if (!partialEvaluator.isSubroutineReturning(offset + branchInstruction.branchOffset))
- {
- // All 'jsr' instructions to this subroutine can be replaced
- // by unconditional branch instructions.
- replaceBranchInstruction(clazz, offset, branchInstruction);
- }
- else if (!partialEvaluator.isTraced(offset + branchInstruction.length(offset)))
- {
- // We have to make sure the instruction after this 'jsr'
- // instruction is valid, even if it is never reached.
- replaceByInfiniteLoop(clazz, offset + branchInstruction.length(offset), branchInstruction);
- }
- }
-
-
- /**
- * Deletes the given branch instruction, or replaces it by a simpler branch
- * instruction, if possible.
- */
- private void replaceBranchInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
-
- // Is there exactly one branch target (not from a goto or jsr)?
- if (branchTargets != null &&
- branchTargets.instructionOffsetCount() == 1)
- {
- // Is it branching to the next instruction?
- int branchOffset = branchTargets.instructionOffset(0) - offset;
- if (branchOffset == instruction.length(offset))
- {
- if (DEBUG_ANALYSIS) System.out.println(" Ignoring zero branch instruction at ["+offset+"]");
- }
- else
- {
- // Replace the branch instruction by a simple branch instruction.
- Instruction replacementInstruction =
- new BranchInstruction(InstructionConstants.OP_GOTO_W,
- branchOffset).shrink();
-
- if (DEBUG_ANALYSIS) System.out.println(" Replacing branch instruction at ["+offset+"] by "+replacementInstruction.toString());
-
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- // Mark that the instruction has been simplified.
- markSimplification(clazz, offset, instruction);
-
- // Visit the instruction, if required.
- if (extraBranchInstructionVisitor != null)
- {
- extraBranchInstructionVisitor.visitBranchInstruction(null, null, null, offset, null);
- }
- }
- }
- }
-
-
- /**
- * Makes sure all branch targets of the given switch instruction are valid.
- */
- private void replaceSwitchInstruction(Clazz clazz,
- int offset,
- SwitchInstruction switchInstruction)
- {
- // Get the actual branch targets.
- InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
-
- // Get an offset that can serve as a valid default offset.
- int defaultOffset =
- branchTargets.instructionOffset(branchTargets.instructionOffsetCount()-1) -
- offset;
-
- Instruction replacementInstruction = null;
-
- // Check the jump offsets.
- int[] jumpOffsets = switchInstruction.jumpOffsets;
- for (int index = 0; index < jumpOffsets.length; index++)
- {
- if (!branchTargets.contains(offset + jumpOffsets[index]))
- {
- // Replace the unused offset.
- jumpOffsets[index] = defaultOffset;
-
- // Remember to replace the instruction.
- replacementInstruction = switchInstruction;
- }
- }
-
- // Check the default offset.
- if (!branchTargets.contains(offset + switchInstruction.defaultOffset))
- {
- // Replace the unused offset.
- switchInstruction.defaultOffset = defaultOffset;
-
- // Remember to replace the instruction.
- replacementInstruction = switchInstruction;
- }
-
- if (replacementInstruction != null)
- {
- if (DEBUG_ANALYSIS) System.out.println(" Replacing switch instruction at ["+offset+"] by "+replacementInstruction.toString());
-
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- // Visit the instruction, if required.
- if (extraBranchInstructionVisitor != null)
- {
- // Note: we're not passing the right arguments for now,
- // knowing that they aren't used anyway.
- extraBranchInstructionVisitor.visitBranchInstruction(null, null, null, offset, null);
- }
- }
}
/**
* Replaces the given instruction by an infinite loop.
*/
- private void replaceByInfiniteLoop(Clazz clazz,
- int offset,
- Instruction instruction)
+ private void replaceByInfiniteLoop(Clazz clazz,
+ int offset)
{
- if (DEBUG_ANALYSIS) System.out.println(" Inserting infinite loop at ["+offset+"]");
+ if (DEBUG) System.out.println(" Inserting infinite loop at ["+offset+"]");
+
+ // Mark the instruction.
+ markInstruction(offset);
// Replace the instruction by an infinite loop.
Instruction replacementInstruction =
new BranchInstruction(InstructionConstants.OP_GOTO, 0);
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- // Mark the instruction.
- markInstruction(offset);
- markSimplification(clazz, offset, instruction);
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
}
@@ -2329,23 +1637,15 @@ implements AttributeVisitor
if (instructionsNecessary.length < codeLength)
{
- instructionsNecessary = new boolean[codeLength];
- instructionsSimplified = new boolean[codeLength];
- aliasingVariables = new int[codeLength];
+ instructionsNecessary = new boolean[codeLength];
}
else
{
for (int index = 0; index < codeLength; index++)
{
- instructionsNecessary[index] = false;
- instructionsSimplified[index] = false;
+ instructionsNecessary[index] = false;
}
}
-
- for (int index = 0; index < codeLength; index++)
- {
- aliasingVariables[index] = -1;
- }
}
@@ -2384,13 +1684,13 @@ implements AttributeVisitor
// Is the variable necessary anywhere at all?
if (isVariableNecessaryAfterAny(0, codeLength, variableIndex))
{
- if (DEBUG_ANALYSIS) System.out.println("Simple partial evalutation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
+ if (DEBUG) System.out.println("Simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
// Lazily compute perform simple partial evaluation, the way the
// JVM preverifier would do it.
simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
- if (DEBUG_ANALYSIS) System.out.println("End of simple partial evalutation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
+ if (DEBUG) System.out.println("End of simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
// Check if the variable is necessary elsewhere.
for (int offset = 0; offset < codeLength; offset++)
@@ -2435,7 +1735,7 @@ implements AttributeVisitor
{
if (!isVariableNecessaryAfter(instructionOffset, variableIndex))
{
- if (DEBUG_ANALYSIS) System.out.print("["+instructionOffset+".v"+variableIndex+"],");
+ if (DEBUG) System.out.print("["+instructionOffset+".v"+variableIndex+"],");
variablesNecessaryAfter[instructionOffset][variableIndex] = true;
@@ -2502,7 +1802,7 @@ implements AttributeVisitor
{
if (!isStackEntryNecessaryAfter(instructionOffset, stackIndex))
{
- if (DEBUG_ANALYSIS) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
+ if (DEBUG) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
stacksNecessaryAfter[instructionOffset][stackIndex] = true;
@@ -2553,51 +1853,11 @@ implements AttributeVisitor
}
- private void markSimplification(Clazz clazz,
- int instructionOffset,
- Instruction instruction)
- {
- // Mark the instruction itself.
- instructionsSimplified[instructionOffset] = true;
-
- // Also mark all stack entries that would be popped.
- TracedStack tracedStack =
- partialEvaluator.getStackBefore(instructionOffset);
-
- int top = tracedStack.size() - 1;
- int popCount = instruction.stackPopCount(clazz);
-
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
- {
- markStackSimplificationBefore(instructionOffset, top - stackIndex);
- }
- }
-
-
- private boolean isInstructionSimplified(int instructionOffset)
- {
- return instructionsSimplified[instructionOffset];
- }
-
-
- private void setAliasingVariable(int instructionOffset,
- int variableIndex)
- {
- aliasingVariables[instructionOffset] = variableIndex;
- }
-
-
- private int getAliasingVariable(int instructionOffset)
- {
- return aliasingVariables[instructionOffset];
- }
-
-
private void markInstruction(int instructionOffset)
{
if (!isInstructionNecessary(instructionOffset))
{
- if (DEBUG_ANALYSIS) System.out.print(instructionOffset+",");
+ if (DEBUG) System.out.print(instructionOffset+",");
instructionsNecessary[instructionOffset] = true;
@@ -2649,4 +1909,4 @@ implements AttributeVisitor
return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
instructionsNecessary[instructionOffset];
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
index 95abf42..0c3a9c7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.evaluation;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.editor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
@@ -40,75 +40,44 @@ import proguard.optimize.info.*;
*/
public class EvaluationSimplifier
extends SimplifiedVisitor
-implements AttributeVisitor
+implements AttributeVisitor,
+ InstructionVisitor
{
//*
- private static final boolean DEBUG_RESULTS = false;
- private static final boolean DEBUG_ANALYSIS = false;
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG_RESULTS = true;
- private static boolean DEBUG_ANALYSIS = true;
- private static boolean DEBUG = true;
+ private static boolean DEBUG = true;
//*/
- private final InstructionVisitor extraPushInstructionVisitor;
- private final InstructionVisitor extraBranchInstructionVisitor;
- private final InstructionVisitor extraDeletedInstructionVisitor;
- private final InstructionVisitor extraAddedInstructionVisitor;
+ private final InstructionVisitor extraInstructionVisitor;
private final PartialEvaluator partialEvaluator;
- private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
- private final MyInstructionSimplifier instructionSimplifier = new MyInstructionSimplifier();
- private final MyProducerMarker producerMarker = new MyProducerMarker();
- 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];
- private boolean[][] stacksSimplifiedBefore = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
- private boolean[] instructionsNecessary = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
- private boolean[] instructionsSimplified = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
- private int[] aliasingVariables = new int[ClassConstants.TYPICAL_CODE_LENGTH];
-
- private int maxMarkedOffset;
-
/**
* Creates a new EvaluationSimplifier.
*/
public EvaluationSimplifier()
{
- this(new PartialEvaluator(), null, null, null, null);
+ this(new PartialEvaluator(), null);
}
/**
* Creates a new EvaluationSimplifier.
- * @param partialEvaluator the partial evaluator that will
- * execute the code and provide
- * information about the results.
- * @param extraPushInstructionVisitor an optional extra visitor for all
- * simplified push instructions.
- * @param extraBranchInstructionVisitor an optional extra visitor for all
- * simplified branch instructions.
- * @param extraDeletedInstructionVisitor an optional extra visitor for all
- * deleted instructions.
- * @param extraAddedInstructionVisitor an optional extra visitor for all
- * added instructions.
+ * @param partialEvaluator the partial evaluator that will
+ * execute the code and provide
+ * information about the results.
+ * @param extraInstructionVisitor an optional extra visitor for all
+ * simplified instructions.
*/
public EvaluationSimplifier(PartialEvaluator partialEvaluator,
- InstructionVisitor extraPushInstructionVisitor,
- InstructionVisitor extraBranchInstructionVisitor,
- InstructionVisitor extraDeletedInstructionVisitor,
- InstructionVisitor extraAddedInstructionVisitor)
+ InstructionVisitor extraInstructionVisitor)
{
- this.partialEvaluator = partialEvaluator;
- this.extraPushInstructionVisitor = extraPushInstructionVisitor;
- this.extraBranchInstructionVisitor = extraBranchInstructionVisitor;
- this.extraDeletedInstructionVisitor = extraDeletedInstructionVisitor;
- this.extraAddedInstructionVisitor = extraAddedInstructionVisitor;
+ this.partialEvaluator = partialEvaluator;
+ this.extraInstructionVisitor = extraInstructionVisitor;
}
@@ -119,7 +88,7 @@ implements AttributeVisitor
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
-// DEBUG = DEBUG_ANALYSIS = DEBUG_RESULTS =
+// DEBUG =
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
@@ -132,7 +101,7 @@ implements AttributeVisitor
}
catch (RuntimeException ex)
{
- System.err.println("Unexpected error while optimizing after partial evaluation:");
+ System.err.println("Unexpected error while simplifying instructions after partial evaluation:");
System.err.println(" Class = ["+clazz.getName()+"]");
System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
@@ -150,7 +119,7 @@ implements AttributeVisitor
public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
- if (DEBUG_RESULTS)
+ if (DEBUG)
{
System.out.println();
System.out.println("Class "+ClassUtil.externalClassName(clazz.getName()));
@@ -160,9 +129,6 @@ implements AttributeVisitor
method.getDescriptor(clazz)));
}
- // Initialize the necessary array.
- initializeNecessary(codeAttribute);
-
// Evaluate the method.
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
@@ -172,8 +138,6 @@ implements AttributeVisitor
codeAttributeEditor.reset(codeLength);
// Replace any instructions that can be simplified.
- if (DEBUG_ANALYSIS) System.out.println("Instruction simplification:");
-
for (int offset = 0; offset < codeLength; offset++)
{
if (partialEvaluator.isTraced(offset))
@@ -181,1596 +145,376 @@ implements AttributeVisitor
Instruction instruction = InstructionFactory.create(codeAttribute.code,
offset);
- instruction.accept(clazz, method, codeAttribute, offset, instructionSimplifier);
+ instruction.accept(clazz, method, codeAttribute, offset, this);
}
}
- // Mark all essential instructions that have been encountered as used.
- if (DEBUG_ANALYSIS) System.out.println("Usage initialization: ");
+ // Apply all accumulated changes to the code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
- maxMarkedOffset = -1;
- // The invocation of the "super" or "this" <init> method inside a
- // constructor is always necessary.
- int superInitializationOffset = partialEvaluator.superInitializationOffset();
- if (superInitializationOffset != PartialEvaluator.NONE)
- {
- if (DEBUG_ANALYSIS) System.out.print("(super.<init>)");
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ case InstructionConstants.OP_IADD:
+ case InstructionConstants.OP_ISUB:
+ case InstructionConstants.OP_IMUL:
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_INEG:
+ case InstructionConstants.OP_ISHL:
+ case InstructionConstants.OP_ISHR:
+ case InstructionConstants.OP_IUSHR:
+ case InstructionConstants.OP_IAND:
+ case InstructionConstants.OP_IOR:
+ case InstructionConstants.OP_IXOR:
+ case InstructionConstants.OP_L2I:
+ case InstructionConstants.OP_F2I:
+ case InstructionConstants.OP_D2I:
+ case InstructionConstants.OP_I2B:
+ case InstructionConstants.OP_I2C:
+ case InstructionConstants.OP_I2S:
+ replaceIntegerPushInstruction(clazz, offset, simpleInstruction);
+ break;
- markInstruction(superInitializationOffset);
- }
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_LADD:
+ case InstructionConstants.OP_LSUB:
+ case InstructionConstants.OP_LMUL:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_LNEG:
+ case InstructionConstants.OP_LSHL:
+ case InstructionConstants.OP_LSHR:
+ case InstructionConstants.OP_LUSHR:
+ case InstructionConstants.OP_LAND:
+ case InstructionConstants.OP_LOR:
+ case InstructionConstants.OP_LXOR:
+ case InstructionConstants.OP_I2L:
+ case InstructionConstants.OP_F2L:
+ case InstructionConstants.OP_D2L:
+ replaceLongPushInstruction(clazz, offset, simpleInstruction);
+ break;
- // Also mark infinite loops and instructions that cause side effects.
- for (int offset = 0; offset < codeLength; offset++)
- {
- if (partialEvaluator.isTraced(offset))
- {
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_FADD:
+ case InstructionConstants.OP_FSUB:
+ case InstructionConstants.OP_FMUL:
+ case InstructionConstants.OP_FDIV:
+ case InstructionConstants.OP_FREM:
+ case InstructionConstants.OP_FNEG:
+ case InstructionConstants.OP_I2F:
+ case InstructionConstants.OP_L2F:
+ case InstructionConstants.OP_D2F:
+ replaceFloatPushInstruction(clazz, offset, simpleInstruction);
+ break;
- // Mark that the instruction is necessary if it is an infinite loop.
- if (instruction.opcode == InstructionConstants.OP_GOTO &&
- ((BranchInstruction)instruction).branchOffset == 0)
- {
- if (DEBUG_ANALYSIS) System.out.print("(infinite loop)");
- markInstruction(offset);
- }
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_DADD:
+ case InstructionConstants.OP_DSUB:
+ case InstructionConstants.OP_DMUL:
+ case InstructionConstants.OP_DDIV:
+ case InstructionConstants.OP_DREM:
+ case InstructionConstants.OP_DNEG:
+ case InstructionConstants.OP_I2D:
+ case InstructionConstants.OP_L2D:
+ case InstructionConstants.OP_F2D:
+ replaceDoublePushInstruction(clazz, offset, simpleInstruction);
+ break;
- // Mark that the instruction is necessary if it has side effects.
- else if (sideEffectInstructionChecker.hasSideEffects(clazz,
- method,
- codeAttribute,
- offset,
- instruction))
- {
- markInstruction(offset);
- }
- }
+ case InstructionConstants.OP_AALOAD:
+ replaceReferencePushInstruction(clazz, offset, simpleInstruction);
+ break;
}
- if (DEBUG_ANALYSIS) System.out.println();
+ }
- // Globally mark instructions and their produced variables and stack
- // entries on which necessary instructions depend.
- // Instead of doing this recursively, we loop across all instructions,
- // starting at the highest previously unmarked instruction that has
- // been been marked.
- if (DEBUG_ANALYSIS) System.out.println("Usage marking:");
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ int variableIndex = variableInstruction.variableIndex;
- while (maxMarkedOffset >= 0)
+ switch (variableInstruction.opcode)
{
- int offset = maxMarkedOffset;
-
- maxMarkedOffset = offset - 1;
+ case InstructionConstants.OP_ILOAD:
+ case InstructionConstants.OP_ILOAD_0:
+ case InstructionConstants.OP_ILOAD_1:
+ case InstructionConstants.OP_ILOAD_2:
+ case InstructionConstants.OP_ILOAD_3:
+ replaceIntegerPushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
- if (partialEvaluator.isTraced(offset))
- {
- if (isInstructionNecessary(offset))
- {
- if (isInstructionSimplified(offset))
- {
- int variableIndex = getAliasingVariable(offset);
-
- if (variableIndex >= 0)
- {
- markVariableProducers(offset, variableIndex);
- }
- }
- else
- {
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
-
- instruction.accept(clazz, method, codeAttribute, offset, producerMarker);
- }
- }
+ case InstructionConstants.OP_LLOAD:
+ case InstructionConstants.OP_LLOAD_0:
+ case InstructionConstants.OP_LLOAD_1:
+ case InstructionConstants.OP_LLOAD_2:
+ case InstructionConstants.OP_LLOAD_3:
+ replaceLongPushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
- // Check if this instruction is a branch origin from a branch
- // that straddles some marked code.
- markStraddlingBranches(offset,
- partialEvaluator.branchTargets(offset),
- true);
-
- // Check if this instruction is a branch target from a branch
- // that straddles some marked code.
- markStraddlingBranches(offset,
- partialEvaluator.branchOrigins(offset),
- false);
- }
+ case InstructionConstants.OP_FLOAD:
+ case InstructionConstants.OP_FLOAD_0:
+ case InstructionConstants.OP_FLOAD_1:
+ case InstructionConstants.OP_FLOAD_2:
+ case InstructionConstants.OP_FLOAD_3:
+ replaceFloatPushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
- if (DEBUG_ANALYSIS)
- {
- if (maxMarkedOffset > offset)
- {
- System.out.println(" -> "+maxMarkedOffset);
- }
- }
- }
- if (DEBUG_ANALYSIS) System.out.println();
+ case InstructionConstants.OP_DLOAD:
+ case InstructionConstants.OP_DLOAD_0:
+ case InstructionConstants.OP_DLOAD_1:
+ case InstructionConstants.OP_DLOAD_2:
+ case InstructionConstants.OP_DLOAD_3:
+ replaceDoublePushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
+ case InstructionConstants.OP_ALOAD:
+ case InstructionConstants.OP_ALOAD_0:
+ case InstructionConstants.OP_ALOAD_1:
+ case InstructionConstants.OP_ALOAD_2:
+ case InstructionConstants.OP_ALOAD_3:
+ replaceReferencePushInstruction(clazz, offset, variableInstruction);
+ break;
- // Mark variable initializations, even if they aren't strictly necessary.
- // The virtual machine's verification step is not smart enough to see
- // this, and may complain otherwise.
- if (DEBUG_ANALYSIS) System.out.println("Initialization marking: ");
+ case InstructionConstants.OP_ASTORE:
+ case InstructionConstants.OP_ASTORE_0:
+ case InstructionConstants.OP_ASTORE_1:
+ case InstructionConstants.OP_ASTORE_2:
+ case InstructionConstants.OP_ASTORE_3:
+ deleteReferencePopInstruction(clazz, offset, variableInstruction);
+ break;
- for (int offset = 0; offset < codeLength; offset++)
- {
- // Is it a variable initialization that hasn't been marked yet?
- 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);
- }
- }
+ case InstructionConstants.OP_RET:
+ replaceBranchInstruction(clazz, offset, variableInstruction);
+ break;
}
- if (DEBUG_ANALYSIS) System.out.println();
-
-
- // Locally fix instructions, in order to keep the stack consistent.
- if (DEBUG_ANALYSIS) System.out.println("Stack consistency fixing:");
+ }
- maxMarkedOffset = codeLength - 1;
- while (maxMarkedOffset >= 0)
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
{
- int offset = maxMarkedOffset;
-
- maxMarkedOffset = offset - 1;
-
- if (partialEvaluator.isTraced(offset))
- {
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
-
- instruction.accept(clazz, method, codeAttribute, offset, stackConsistencyFixer);
-
- // Check if this instruction is a branch origin from a branch
- // that straddles some marked code.
- markStraddlingBranches(offset,
- partialEvaluator.branchTargets(offset),
- true);
-
- // Check if this instruction is a branch target from a branch
- // that straddles some marked code.
- markStraddlingBranches(offset,
- partialEvaluator.branchOrigins(offset),
- false);
- }
- }
- if (DEBUG_ANALYSIS) System.out.println();
-
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ replaceAnyPushInstruction(clazz, offset, constantInstruction);
+ break;
- // Replace traced but unmarked backward branches by infinite loops.
- // The virtual machine's verification step is not smart enough to see
- // the code isn't reachable, and may complain otherwise.
- // Any clearly unreachable code will still be removed elsewhere.
- if (DEBUG_ANALYSIS) System.out.println("Infinite loop fixing:");
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ if (constantInstruction.stackPushCount(clazz) > 0 &&
+ !sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ constantInstruction))
+ {
+ replaceAnyPushInstruction(clazz, offset, constantInstruction);
+ }
- for (int offset = 0; offset < codeLength; offset++)
- {
- // Is a traced but unmarked backward branch, without an unmarked
- // straddling forward branch? Note that this is still a heuristic.
- if (partialEvaluator.isTraced(offset) &&
- !isInstructionNecessary(offset) &&
- isAllSmallerThanOrEqual(partialEvaluator.branchTargets(offset),
- offset) &&
- !isAnyUnnecessaryInstructionBranchingOver(lastNecessaryInstructionOffset(offset),
- offset))
- {
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
+ break;
- replaceByInfiniteLoop(clazz, offset, instruction);
- }
+ case InstructionConstants.OP_CHECKCAST:
+ replaceReferencePushInstruction(clazz, offset, constantInstruction);
+ break;
}
- if (DEBUG_ANALYSIS) System.out.println();
+ }
- // Delete all instructions that are not used.
- int offset = 0;
- do
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ switch (branchInstruction.opcode)
{
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
- if (!isInstructionNecessary(offset))
- {
- codeAttributeEditor.deleteInstruction(offset);
-
- codeAttributeEditor.insertBeforeInstruction(offset, null);
- codeAttributeEditor.replaceInstruction(offset, null);
- codeAttributeEditor.insertAfterInstruction(offset, null);
+ case InstructionConstants.OP_GOTO:
+ case InstructionConstants.OP_GOTO_W:
+ // Don't replace unconditional branches.
+ break;
- // Visit the instruction, if required.
- if (extraDeletedInstructionVisitor != null)
- {
- instruction.accept(clazz, method, codeAttribute, offset, extraDeletedInstructionVisitor);
- }
- }
+ case InstructionConstants.OP_JSR:
+ case InstructionConstants.OP_JSR_W:
+ replaceJsrInstruction(clazz, offset, branchInstruction);
+ break;
- offset += instruction.length(offset);
+ default:
+ replaceBranchInstruction(clazz, offset, branchInstruction);
+ break;
}
- while (offset < codeLength);
-
-
- if (DEBUG_RESULTS)
- {
- System.out.println("Simplification results:");
+ }
- offset = 0;
- do
- {
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
- System.out.println((isInstructionNecessary(offset) ? " + " : " - ")+instruction.toString(offset));
- if (partialEvaluator.isTraced(offset))
- {
- int initializationOffset = partialEvaluator.initializationOffset(offset);
- if (initializationOffset != PartialEvaluator.NONE)
- {
- System.out.println(" is to be initialized at ["+initializationOffset+"]");
- }
-
- InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
- if (branchTargets != null)
- {
- System.out.println(" has overall been branching to "+branchTargets);
- }
-
- boolean deleted = codeAttributeEditor.deleted[offset];
- if (isInstructionNecessary(offset) && deleted)
- {
- System.out.println(" is deleted");
- }
-
- Instruction preInsertion = codeAttributeEditor.preInsertions[offset];
- if (preInsertion != null)
- {
- System.out.println(" is preceded by: "+preInsertion);
- }
-
- Instruction replacement = codeAttributeEditor.replacements[offset];
- if (replacement != null)
- {
- System.out.println(" is replaced by: "+replacement);
- }
-
- Instruction postInsertion = codeAttributeEditor.postInsertions[offset];
- if (postInsertion != null)
- {
- System.out.println(" is followed by: "+postInsertion);
- }
- }
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ // First try to simplify it to a simple branch.
+ replaceBranchInstruction(clazz, offset, switchInstruction);
- offset += instruction.length(offset);
- }
- while (offset < codeLength);
+ // Otherwise make sure all branch targets are valid.
+ if (!codeAttributeEditor.isModified(offset))
+ {
+ replaceSwitchInstruction(clazz, offset, switchInstruction);
}
-
- // Apply all accumulated changes to the code.
- codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
}
+ // Small utility methods.
+
/**
- * This InstructionVisitor simplifies the instructions that it visits,
- * whenever possible, and marks them as such.
+ * Replaces the push instruction at the given offset by a simpler push
+ * instruction, if possible.
*/
- private class MyInstructionSimplifier
- extends SimplifiedVisitor
- implements InstructionVisitor
+ private void replaceAnyPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
{
- // Implementations for InstructionVisitor.
-
- public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
{
- switch (simpleInstruction.opcode)
+ switch (pushedValue.computationalType())
{
- case InstructionConstants.OP_IALOAD:
- case InstructionConstants.OP_BALOAD:
- case InstructionConstants.OP_CALOAD:
- case InstructionConstants.OP_SALOAD:
- case InstructionConstants.OP_IADD:
- case InstructionConstants.OP_ISUB:
- case InstructionConstants.OP_IMUL:
- case InstructionConstants.OP_IDIV:
- case InstructionConstants.OP_IREM:
- case InstructionConstants.OP_INEG:
- case InstructionConstants.OP_ISHL:
- case InstructionConstants.OP_ISHR:
- case InstructionConstants.OP_IUSHR:
- case InstructionConstants.OP_IAND:
- case InstructionConstants.OP_IOR:
- case InstructionConstants.OP_IXOR:
- case InstructionConstants.OP_L2I:
- case InstructionConstants.OP_F2I:
- case InstructionConstants.OP_D2I:
- case InstructionConstants.OP_I2B:
- case InstructionConstants.OP_I2C:
- case InstructionConstants.OP_I2S:
- replaceIntegerPushInstruction(clazz, offset, simpleInstruction);
+ case Value.TYPE_INTEGER:
+ replaceIntegerPushInstruction(clazz, offset, instruction);
break;
-
- case InstructionConstants.OP_LALOAD:
- case InstructionConstants.OP_LADD:
- case InstructionConstants.OP_LSUB:
- case InstructionConstants.OP_LMUL:
- case InstructionConstants.OP_LDIV:
- case InstructionConstants.OP_LREM:
- case InstructionConstants.OP_LNEG:
- case InstructionConstants.OP_LSHL:
- case InstructionConstants.OP_LSHR:
- case InstructionConstants.OP_LUSHR:
- case InstructionConstants.OP_LAND:
- case InstructionConstants.OP_LOR:
- case InstructionConstants.OP_LXOR:
- case InstructionConstants.OP_I2L:
- case InstructionConstants.OP_F2L:
- case InstructionConstants.OP_D2L:
- replaceLongPushInstruction(clazz, offset, simpleInstruction);
+ case Value.TYPE_LONG:
+ replaceLongPushInstruction(clazz, offset, instruction);
break;
-
- case InstructionConstants.OP_FALOAD:
- case InstructionConstants.OP_FADD:
- case InstructionConstants.OP_FSUB:
- case InstructionConstants.OP_FMUL:
- case InstructionConstants.OP_FDIV:
- case InstructionConstants.OP_FREM:
- case InstructionConstants.OP_FNEG:
- case InstructionConstants.OP_I2F:
- case InstructionConstants.OP_L2F:
- case InstructionConstants.OP_D2F:
- replaceFloatPushInstruction(clazz, offset, simpleInstruction);
+ case Value.TYPE_FLOAT:
+ replaceFloatPushInstruction(clazz, offset, instruction);
break;
-
- case InstructionConstants.OP_DALOAD:
- case InstructionConstants.OP_DADD:
- case InstructionConstants.OP_DSUB:
- case InstructionConstants.OP_DMUL:
- case InstructionConstants.OP_DDIV:
- case InstructionConstants.OP_DREM:
- case InstructionConstants.OP_DNEG:
- case InstructionConstants.OP_I2D:
- case InstructionConstants.OP_L2D:
- case InstructionConstants.OP_F2D:
- replaceDoublePushInstruction(clazz, offset, simpleInstruction);
+ case Value.TYPE_DOUBLE:
+ replaceDoublePushInstruction(clazz, offset, instruction);
break;
-
- case InstructionConstants.OP_AALOAD:
- replaceReferencePushInstruction(clazz, offset, simpleInstruction);
+ case Value.TYPE_REFERENCE:
+ replaceReferencePushInstruction(clazz, offset, instruction);
break;
}
}
+ }
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- int variableIndex = variableInstruction.variableIndex;
-
- switch (variableInstruction.opcode)
- {
- case InstructionConstants.OP_ILOAD:
- case InstructionConstants.OP_ILOAD_0:
- case InstructionConstants.OP_ILOAD_1:
- case InstructionConstants.OP_ILOAD_2:
- case InstructionConstants.OP_ILOAD_3:
- replaceIntegerPushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
-
- case InstructionConstants.OP_LLOAD:
- case InstructionConstants.OP_LLOAD_0:
- case InstructionConstants.OP_LLOAD_1:
- case InstructionConstants.OP_LLOAD_2:
- case InstructionConstants.OP_LLOAD_3:
- replaceLongPushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
-
- case InstructionConstants.OP_FLOAD:
- case InstructionConstants.OP_FLOAD_0:
- case InstructionConstants.OP_FLOAD_1:
- case InstructionConstants.OP_FLOAD_2:
- case InstructionConstants.OP_FLOAD_3:
- replaceFloatPushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
-
- case InstructionConstants.OP_DLOAD:
- case InstructionConstants.OP_DLOAD_0:
- case InstructionConstants.OP_DLOAD_1:
- case InstructionConstants.OP_DLOAD_2:
- case InstructionConstants.OP_DLOAD_3:
- replaceDoublePushInstruction(clazz, offset, variableInstruction, variableIndex);
- break;
-
- case InstructionConstants.OP_ALOAD:
- case InstructionConstants.OP_ALOAD_0:
- case InstructionConstants.OP_ALOAD_1:
- case InstructionConstants.OP_ALOAD_2:
- case InstructionConstants.OP_ALOAD_3:
- replaceReferencePushInstruction(clazz, offset, variableInstruction);
- break;
-
- }
- }
+ /**
+ * Replaces the integer pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceIntegerPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ replaceIntegerPushInstruction(clazz,
+ offset,
+ instruction,
+ partialEvaluator.getVariablesBefore(offset).size());
+ }
- public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ /**
+ * Replaces the integer pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceIntegerPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ int maxVariableIndex)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
{
- switch (constantInstruction.opcode)
+ int value = pushedValue.integerValue().value();
+ if (value << 16 >> 16 == value)
{
- case InstructionConstants.OP_GETSTATIC:
- case InstructionConstants.OP_GETFIELD:
- replaceAnyPushInstruction(clazz, offset, constantInstruction);
- break;
-
- case InstructionConstants.OP_INVOKEVIRTUAL:
- case InstructionConstants.OP_INVOKESPECIAL:
- case InstructionConstants.OP_INVOKESTATIC:
- case InstructionConstants.OP_INVOKEINTERFACE:
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
- new ReferencedMemberVisitor(
- new MyUnusedParameterSimplifier(offset,
- constantInstruction)));
-
- if (constantInstruction.stackPushCount(clazz) > 0 &&
- !sideEffectInstructionChecker.hasSideEffects(clazz,
- method,
- codeAttribute,
- offset,
- constantInstruction))
- {
- replaceAnyPushInstruction(clazz, offset, constantInstruction);
- }
-
- break;
-
- case InstructionConstants.OP_CHECKCAST:
- replaceReferencePushInstruction(clazz, offset, constantInstruction);
- break;
+ replaceConstantPushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_SIPUSH,
+ value);
}
- }
-
-
- public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
- {
- switch (branchInstruction.opcode)
+ else
{
- case InstructionConstants.OP_GOTO:
- case InstructionConstants.OP_GOTO_W:
- // Don't replace unconditional branches.
- break;
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
- case InstructionConstants.OP_JSR:
- case InstructionConstants.OP_JSR_W:
- replaceJsrInstruction(clazz, offset, branchInstruction);
- break;
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC,
+ constantPoolEditor.addIntegerConstant(value)).shrink();
- default:
- replaceBranchInstruction(clazz, offset, branchInstruction);
- break;
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
-
-
- public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ else if (pushedValue.isSpecific())
{
- // First try to simplify it to a simple branch.
- replaceBranchInstruction(clazz, offset, switchInstruction);
-
- // Otherwise make sure all branch targets are valid.
- if (!isInstructionSimplified(offset))
+ TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
+ for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
- replaceSwitchInstruction(clazz, offset, switchInstruction);
+ if (pushedValue.equals(variables.load(variableIndex)))
+ {
+ replaceVariablePushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_ILOAD,
+ variableIndex);
+ }
}
}
}
/**
- * This MemberVisitor marks stack entries that aren't necessary because
- * parameters aren't used in the methods that are visited.
+ * Replaces the long pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
*/
- private class MyUnusedParameterSimplifier
- extends SimplifiedVisitor
- implements MemberVisitor
+ private void replaceLongPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
{
- private int invocationOffset;
- private ConstantInstruction invocationInstruction;
-
-
- /**
- * Creates a new MyUnusedParameterSimplifier for the given invocation
- * at the given offset.
- */
- private MyUnusedParameterSimplifier(int invocationOffset,
- ConstantInstruction invocationInstruction)
- {
- this.invocationOffset = invocationOffset;
- this.invocationInstruction = invocationInstruction;
- }
-
-
- // Implementations for MemberVisitor.
-
- public void visitAnyMember(Clazz clazz, Member member) {}
+ replaceLongPushInstruction(clazz,
+ offset,
+ instruction,
+ partialEvaluator.getVariablesBefore(offset).size());
+ }
- public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ /**
+ * Replaces the long pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceLongPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ int maxVariableIndex)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
{
- // Get the total size of the parameters.
- int parameterSize = ParameterUsageMarker.getParameterSize(programMethod);
-
- // Make the method invocation static, if possible.
- if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0 &&
- !ParameterUsageMarker.isParameterUsed(programMethod, 0))
+ long value = pushedValue.longValue().value();
+ if (value == 0L ||
+ value == 1L)
{
- replaceInvocationInstruction(programClass,
- invocationOffset,
- invocationInstruction);
+ replaceConstantPushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_LCONST_0,
+ (int)value);
}
-
- // Remove unused parameters.
- for (int index = 0; index < parameterSize; index++)
+ else
{
- if (!ParameterUsageMarker.isParameterUsed(programMethod, index))
- {
- TracedStack stack =
- partialEvaluator.getStackBefore(invocationOffset);
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
- int stackIndex = stack.size() - parameterSize + index;
-
- if (DEBUG)
- {
- System.out.println(" ["+invocationOffset+"] Ignoring parameter #"+index+" of "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] (stack entry #"+stackIndex+" ["+stack.getBottom(stackIndex)+"])");
- System.out.println(" Full stack: "+stack);
- }
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W,
+ constantPoolEditor.addLongConstant(value)).shrink();
- markStackSimplificationBefore(invocationOffset, stackIndex);
- }
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
- }
-
-
- /**
- * This InstructionVisitor marks the producing instructions and produced
- * variables and stack entries of the instructions that it visits.
- * Simplified method arguments are ignored.
- */
- private class MyProducerMarker
- extends SimplifiedVisitor
- implements InstructionVisitor
- {
- // Implementations for InstructionVisitor.
-
- public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
- {
- markStackProducers(clazz, offset, instruction);
- }
-
-
- public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
- {
- switch (simpleInstruction.opcode)
- {
- case InstructionConstants.OP_DUP:
- conditionallyMarkStackEntryProducers(offset, 0, 0);
- conditionallyMarkStackEntryProducers(offset, 1, 0);
- break;
- case InstructionConstants.OP_DUP_X1:
- conditionallyMarkStackEntryProducers(offset, 0, 0);
- conditionallyMarkStackEntryProducers(offset, 1, 1);
- conditionallyMarkStackEntryProducers(offset, 2, 0);
- break;
- case InstructionConstants.OP_DUP_X2:
- conditionallyMarkStackEntryProducers(offset, 0, 0);
- conditionallyMarkStackEntryProducers(offset, 1, 1);
- conditionallyMarkStackEntryProducers(offset, 2, 2);
- conditionallyMarkStackEntryProducers(offset, 3, 0);
- break;
- case InstructionConstants.OP_DUP2:
- conditionallyMarkStackEntryProducers(offset, 0, 0);
- conditionallyMarkStackEntryProducers(offset, 1, 1);
- conditionallyMarkStackEntryProducers(offset, 2, 0);
- conditionallyMarkStackEntryProducers(offset, 3, 1);
- break;
- case InstructionConstants.OP_DUP2_X1:
- conditionallyMarkStackEntryProducers(offset, 0, 0);
- conditionallyMarkStackEntryProducers(offset, 1, 1);
- conditionallyMarkStackEntryProducers(offset, 2, 2);
- conditionallyMarkStackEntryProducers(offset, 3, 0);
- conditionallyMarkStackEntryProducers(offset, 4, 1);
- break;
- case InstructionConstants.OP_DUP2_X2:
- conditionallyMarkStackEntryProducers(offset, 0, 0);
- conditionallyMarkStackEntryProducers(offset, 1, 1);
- conditionallyMarkStackEntryProducers(offset, 2, 2);
- conditionallyMarkStackEntryProducers(offset, 3, 3);
- conditionallyMarkStackEntryProducers(offset, 4, 0);
- conditionallyMarkStackEntryProducers(offset, 5, 1);
- break;
- case InstructionConstants.OP_SWAP:
- conditionallyMarkStackEntryProducers(offset, 0, 1);
- conditionallyMarkStackEntryProducers(offset, 1, 0);
- break;
- default:
- markStackProducers(clazz, offset, simpleInstruction);
- break;
- }
- }
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- // Is the variable being loaded (or incremented)?
- if (variableInstruction.opcode < InstructionConstants.OP_ISTORE)
- {
- markVariableProducers(offset, variableInstruction.variableIndex);
- }
- else
- {
- markStackProducers(clazz, offset, variableInstruction);
- }
- }
-
-
- public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
- {
- // Mark the initializer invocation, if this is a 'new' instruction.
- if (constantInstruction.opcode == InstructionConstants.OP_NEW)
- {
- markInitialization(offset);
- }
-
- markStackProducers(clazz, offset, constantInstruction);
- }
-
-
- public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
- {
- // Explicitly mark the produced stack entry of a 'jsr' instruction,
- // because the consuming 'astore' instruction of the subroutine is
- // cleared every time it is traced.
- if (branchInstruction.opcode == InstructionConstants.OP_JSR ||
- branchInstruction.opcode == InstructionConstants.OP_JSR_W)
- {
- markStackEntryAfter(offset, 0);
- }
- else
- {
- markStackProducers(clazz, offset, branchInstruction);
- }
- }
- }
-
-
- /**
- * This InstructionVisitor fixes instructions locally, popping any unused
- * produced stack entries after marked instructions, and popping produced
- * stack entries and pushing missing stack entries instead of unmarked
- * instructions.
- */
- private class MyStackConsistencyFixer
- extends SimplifiedVisitor
- implements InstructionVisitor
- {
- // Implementations for InstructionVisitor.
-
- public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
- {
- // Has the instruction been marked?
- if (isInstructionNecessary(offset))
- {
- // Check all stack entries that are popped.
- // Typical case: a freshly marked variable initialization that
- // requires some value on the stack.
- int popCount = instruction.stackPopCount(clazz);
- if (popCount > 0)
- {
- TracedStack tracedStack =
- partialEvaluator.getStackBefore(offset);
-
- int top = tracedStack.size() - 1;
-
- 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))
- {
- // Remember to push it.
- requiredPushCount++;
- }
- }
-
- // Push some necessary stack entries.
- if (requiredPushCount > 0)
- {
- if (DEBUG_ANALYSIS) System.out.print(" Inserting before marked consumer "+instruction.toString(offset));
-
- if (requiredPushCount > (instruction.isCategory2() ? 2 : 1))
- {
- throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"]");
- }
-
- increaseStackSize(offset, tracedStack.getTop(0).computationalType(), false);
- }
- }
-
- // Check all stack entries that are pushed.
- // Typical case: a return value that wasn't really required and
- // that should be popped.
- int pushCount = instruction.stackPushCount(clazz);
- if (pushCount > 0)
- {
- TracedStack tracedStack =
- partialEvaluator.getStackAfter(offset);
-
- int top = tracedStack.size() - 1;
-
- int requiredPopCount = 0;
- for (int stackIndex = 0; stackIndex < pushCount; stackIndex++)
- {
- // Is the stack entry required by consumers?
- if (!isStackEntryNecessaryAfter(offset, top - stackIndex))
- {
- // Remember to pop it.
- requiredPopCount++;
- }
- }
-
- // Pop the unnecessary stack entries.
- if (requiredPopCount > 0)
- {
- if (DEBUG_ANALYSIS) System.out.print(" Inserting after marked producer "+instruction.toString(offset));
-
- decreaseStackSize(offset, requiredPopCount, false, false);
- }
- }
- }
- else
- {
- // Check all stack entries that would be popped.
- // Typical case: a stack value that is required elsewhere and
- // that still has to be popped.
- int popCount = instruction.stackPopCount(clazz);
- if (popCount > 0)
- {
- TracedStack tracedStack =
- partialEvaluator.getStackBefore(offset);
-
- int top = tracedStack.size() - 1;
-
- 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))
- {
- // Remember to pop it.
- expectedPopCount++;
- }
- }
-
- // Pop the unnecessary stack entries.
- if (expectedPopCount > 0)
- {
- if (DEBUG_ANALYSIS) System.out.print(" Replacing unmarked consumer "+instruction.toString(offset));
-
- decreaseStackSize(offset, expectedPopCount, true, true);
- }
- }
-
- // Check all stack entries that would be pushed.
- // Typical case: never.
- int pushCount = instruction.stackPushCount(clazz);
- if (pushCount > 0)
- {
- TracedStack tracedStack =
- partialEvaluator.getStackAfter(offset);
-
- int top = tracedStack.size() - 1;
-
- int expectedPushCount = 0;
- for (int stackIndex = 0; stackIndex < pushCount; stackIndex++)
- {
- // Is the stack entry required by consumers?
- if (isStackEntryNecessaryAfter(offset, top - stackIndex))
- {
- // Remember to push it.
- expectedPushCount++;
- }
- }
-
- // Push some necessary stack entries.
- if (expectedPushCount > 0)
- {
- if (DEBUG_ANALYSIS) System.out.print(" Replacing unmarked producer "+instruction.toString(offset));
-
- increaseStackSize(offset, tracedStack.getTop(0).computationalType(), true);
- }
- }
- }
- }
-
-
- public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
- {
- if (isInstructionNecessary(offset) &&
- isDupOrSwap(simpleInstruction))
- {
- fixDupInstruction(clazz, codeAttribute, offset, simpleInstruction);
- }
- else
- {
- visitAnyInstruction(clazz, method, codeAttribute, offset, simpleInstruction);
- }
- }
- }
-
-
- // Small utility methods.
-
- /**
- * Marks the variable and the corresponding producing instructions
- * of the consumer at the given offset.
- * @param consumerOffset the offset of the consumer.
- * @param variableIndex the index of the variable to be marked.
- */
- private void markVariableProducers(int consumerOffset,
- int variableIndex)
- {
- TracedVariables tracedVariables =
- partialEvaluator.getVariablesBefore(consumerOffset);
-
- // Mark the producer of the loaded value.
- markVariableProducers(tracedVariables.getProducerValue(variableIndex).instructionOffsetValue(),
- variableIndex);
- }
-
-
- /**
- * Marks the variable and its producing instructions at the given offsets.
- * @param producerOffsets the offsets of the producers to be marked.
- * @param variableIndex the index of the variable to be marked.
- */
- private void markVariableProducers(InstructionOffsetValue producerOffsets,
- int variableIndex)
- {
- if (producerOffsets != null)
- {
- int offsetCount = producerOffsets.instructionOffsetCount();
- for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
- {
- // Make sure the variable and the instruction are marked
- // at the producing offset.
- int offset = producerOffsets.instructionOffset(offsetIndex);
-
- markVariableAfter(offset, variableIndex);
- markInstruction(offset);
- }
- }
- }
-
-
- /**
- * Marks the stack entries and their producing instructions of the
- * consumer at the given offset.
- * @param clazz the containing class.
- * @param consumerOffset the offset of the consumer.
- * @param consumer the consumer of the stack entries.
- */
- private void markStackProducers(Clazz clazz,
- int consumerOffset,
- Instruction consumer)
- {
- // Mark the producers of the popped values.
- int popCount = consumer.stackPopCount(clazz);
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
- {
- markStackEntryProducers(consumerOffset, stackIndex);
- }
- }
-
-
- /**
- * Marks the stack entry and the corresponding producing instructions
- * of the consumer at the given offset, if the stack entry of the
- * consumer is marked.
- * @param consumerOffset the offset of the consumer.
- * @param consumerStackIndex the index of the stack entry to be checked
- * (counting from the top).
- * @param producerStackIndex the index of the stack entry to be marked
- * (counting from the top).
- */
- private void conditionallyMarkStackEntryProducers(int consumerOffset,
- int consumerStackIndex,
- int producerStackIndex)
- {
- int top = partialEvaluator.getStackAfter(consumerOffset).size() - 1;
-
- if (isStackEntryNecessaryAfter(consumerOffset, top - consumerStackIndex))
- {
- markStackEntryProducers(consumerOffset, producerStackIndex);
- }
- }
-
-
- /**
- * Marks the stack entry and the corresponding producing instructions
- * of the consumer at the given offset.
- * @param consumerOffset the offset of the consumer.
- * @param stackIndex the index of the stack entry to be marked
- * (counting from the top).
- */
- private void markStackEntryProducers(int consumerOffset,
- int stackIndex)
- {
- TracedStack tracedStack =
- partialEvaluator.getStackBefore(consumerOffset);
-
- int stackBottomIndex = tracedStack.size() - 1 - stackIndex;
-
- if (!isStackSimplifiedBefore(consumerOffset, stackBottomIndex))
- {
- markStackEntryProducers(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(),
- stackBottomIndex);
- }
- }
-
-
- /**
- * Marks the stack entry and its producing instructions at the given
- * offsets.
- * @param producerOffsets the offsets of the producers to be marked.
- * @param stackIndex the index of the stack entry to be marked
- * (counting from the bottom).
- */
- private void markStackEntryProducers(InstructionOffsetValue producerOffsets,
- int stackIndex)
- {
- if (producerOffsets != null)
- {
- int offsetCount = producerOffsets.instructionOffsetCount();
- for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
- {
- // Make sure the stack entry and the instruction are marked
- // at the producing offset.
- int offset = producerOffsets.instructionOffset(offsetIndex);
-
- markStackEntryAfter(offset, stackIndex);
- markInstruction(offset);
- }
- }
- }
-
-
- /**
- * Marks the stack entry and its initializing instruction
- * ('invokespecial *.<init>') for the given 'new' instruction offset.
- * @param newInstructionOffset the offset of the 'new' instruction.
- */
- private void markInitialization(int newInstructionOffset)
- {
- int initializationOffset =
- partialEvaluator.initializationOffset(newInstructionOffset);
-
- TracedStack tracedStack =
- partialEvaluator.getStackAfter(newInstructionOffset);
-
- markStackEntryAfter(initializationOffset, tracedStack.size() - 1);
- markInstruction(initializationOffset);
- }
-
-
- /**
- * Marks the branch instructions of straddling branches, if they straddle
- * some code that has been marked.
- * @param instructionOffset the offset of the branch origin or branch target.
- * @param branchOffsets the offsets of the straddling branch targets
- * or branch origins.
- * @param isPointingToTargets <code>true</code> if the above offsets are
- * branch targets, <code>false</code> if they
- * are branch origins.
- */
- private void markStraddlingBranches(int instructionOffset,
- InstructionOffsetValue branchOffsets,
- boolean isPointingToTargets)
- {
- if (branchOffsets != null)
- {
- // Loop over all branch offsets.
- int branchCount = branchOffsets.instructionOffsetCount();
- for (int branchIndex = 0; branchIndex < branchCount; branchIndex++)
- {
- // Is the branch straddling forward any necessary instructions?
- int branchOffset = branchOffsets.instructionOffset(branchIndex);
-
- // Is the offset pointing to a branch origin or to a branch target?
- if (isPointingToTargets)
- {
- markStraddlingBranch(instructionOffset,
- branchOffset,
- instructionOffset,
- branchOffset);
- }
- else
- {
- markStraddlingBranch(instructionOffset,
- branchOffset,
- branchOffset,
- instructionOffset);
- }
- }
- }
- }
-
-
- private void markStraddlingBranch(int instructionOffsetStart,
- int instructionOffsetEnd,
- int branchOrigin,
- int branchTarget)
- {
- if (!isInstructionNecessary(branchOrigin) &&
- isAnyInstructionNecessary(instructionOffsetStart, instructionOffsetEnd))
- {
- if (DEBUG_ANALYSIS) System.out.print("["+branchOrigin+"->"+branchTarget+"]");
-
- // Mark the branch instruction.
- markInstruction(branchOrigin);
- }
- }
-
-
- /**
- * Marks the specified instruction if it is a required dup/swap instruction,
- * replacing it by an appropriate variant if necessary.
- * @param clazz the class that is being checked.
- * @param codeAttribute the code that is being checked.
- * @param dupOffset the offset of the dup/swap instruction.
- * @param instruction the dup/swap instruction.
- */
- private void fixDupInstruction(Clazz clazz,
- CodeAttribute codeAttribute,
- int dupOffset,
- Instruction instruction)
- {
- int top = partialEvaluator.getStackAfter(dupOffset).size() - 1;
-
- byte oldOpcode = instruction.opcode;
- byte newOpcode = 0;
-
- // Simplify the popping instruction if possible.
- switch (oldOpcode)
- {
- case InstructionConstants.OP_DUP:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent1)
- {
- // Should both the original element and the copy be present?
- if (stackEntryPresent0 &&
- stackEntryPresent1)
- {
- newOpcode = InstructionConstants.OP_DUP;
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP_X1:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent2)
- {
- // Should the copy be present?
- if (stackEntryPresent2)
- {
- // Compute the number of elements to be skipped.
- int skipCount = stackEntryPresent1 ? 1 : 0;
-
- // Should the original element be present?
- if (stackEntryPresent0)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount);
- }
- else if (skipCount == 1)
- {
- // Move the original element.
- newOpcode = InstructionConstants.OP_SWAP;
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP_X2:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, top - 3);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent3)
- {
- // Should the copy be present?
- if (stackEntryPresent3)
- {
- int skipCount = (stackEntryPresent1 ? 1 : 0) +
- (stackEntryPresent2 ? 1 : 0);
-
- // Should the original element be present?
- if (stackEntryPresent0)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount);
- }
- else if (skipCount == 1)
- {
- // Move the original element.
- newOpcode = InstructionConstants.OP_SWAP;
- }
- else if (skipCount == 2)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup_x2 instruction moving original element across two elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntriesPresent23 = isStackEntriesNecessaryAfter(dupOffset, top - 2, top - 3);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent23)
- {
- // Should both the original element and the copy be present?
- if (stackEntriesPresent01 &&
- stackEntriesPresent23)
- {
- newOpcode = InstructionConstants.OP_DUP2;
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2_X1:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntriesPresent34 = isStackEntriesNecessaryAfter(dupOffset, top - 3, top - 4);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent34)
- {
- // Should the copy be present?
- if (stackEntriesPresent34)
- {
- int skipCount = stackEntryPresent2 ? 1 : 0;
-
- // Should the original element be present?
- if (stackEntriesPresent01)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount);
- }
- else if (skipCount > 0)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup2_x1 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2_X2:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, top - 3);
- boolean stackEntriesPresent45 = isStackEntriesNecessaryAfter(dupOffset, top - 4, top - 5);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent45)
- {
- // Should the copy be present?
- if (stackEntriesPresent45)
- {
- int skipCount = (stackEntryPresent2 ? 1 : 0) +
- (stackEntryPresent3 ? 1 : 0);
-
- // Should the original element be present?
- if (stackEntriesPresent01)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount);
- }
- else if (skipCount > 0)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup2_x2 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_SWAP:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
-
- // Will either element be present?
- if (stackEntryPresent0 ||
- stackEntryPresent1)
- {
- // Will both elements be present?
- if (stackEntryPresent0 &&
- stackEntryPresent1)
- {
- newOpcode = InstructionConstants.OP_SWAP;
- }
- }
- break;
- }
- }
-
- if (newOpcode == 0)
- {
- // Delete the instruction.
- codeAttributeEditor.deleteInstruction(dupOffset);
-
- if (extraDeletedInstructionVisitor != null)
- {
- extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, dupOffset, null);
- }
-
- if (DEBUG_ANALYSIS) System.out.println(" Marking but deleting instruction "+instruction.toString(dupOffset));
- }
- else if (newOpcode == oldOpcode)
- {
- // Leave the instruction unchanged.
- codeAttributeEditor.undeleteInstruction(dupOffset);
-
- if (DEBUG_ANALYSIS) System.out.println(" Marking unchanged instruction "+instruction.toString(dupOffset));
- }
- else
- {
- // Replace the instruction.
- Instruction replacementInstruction = new SimpleInstruction(newOpcode);
- codeAttributeEditor.replaceInstruction(dupOffset,
- replacementInstruction);
-
- if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString());
- }
- }
-
-
- /**
- * Puts the required push instruction before the given index. The
- * instruction is marked as necessary.
- * @param offset the offset of the instruction.
- * @param computationalType the computational type on the stack, for
- * push instructions.
- * @param delete specifies whether the instruction should be
- * deleted.
- */
- private void increaseStackSize(int offset,
- int computationalType,
- boolean delete)
- {
- // Mark this instruction.
- markInstruction(offset);
-
- // Create a simple push instrucion.
- Instruction replacementInstruction =
- new SimpleInstruction(pushOpcode(computationalType));
-
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
- // Delete the original instruction if necessary.
- if (delete)
- {
- if (DEBUG_ANALYSIS) System.out.println(" Deleting original instruction at "+offset);
-
- // Replace the push instruction.
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
- }
- else
- {
- // Insert the push instruction.
- codeAttributeEditor.insertBeforeInstruction(offset,
- replacementInstruction);
-
- if (extraAddedInstructionVisitor != null)
- {
- replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
- }
- }
- }
-
-
- /**
- * Returns the opcode of a push instruction corresponding to the given
- * computational type.
- * @param computationalType the computational type to be pushed on the stack.
- */
- private byte pushOpcode(int computationalType)
- {
- switch (computationalType)
- {
- case Value.TYPE_INTEGER: return InstructionConstants.OP_ICONST_0;
- case Value.TYPE_LONG: return InstructionConstants.OP_LCONST_0;
- case Value.TYPE_FLOAT: return InstructionConstants.OP_FCONST_0;
- case Value.TYPE_DOUBLE: return InstructionConstants.OP_DCONST_0;
- case Value.TYPE_REFERENCE:
- case Value.TYPE_INSTRUCTION_OFFSET: return InstructionConstants.OP_ACONST_NULL;
- }
-
- throw new IllegalArgumentException("No push opcode for computational type ["+computationalType+"]");
- }
-
-
- /**
- * Puts the required pop instruction at the given index. The
- * instruction is marked as necessary.
- * @param offset the offset of the instruction.
- * @param popCount the required reduction of the stack size.
- * @param before specifies whether the pop instruction should be inserted
- * before or after the present instruction.
- * @param delete specifies whether the instruction should be deleted.
- */
- private void decreaseStackSize(int offset,
- int popCount,
- boolean before,
- boolean delete)
- {
- // Mark this instruction.
- markInstruction(offset);
-
- boolean after = !before;
-
- int remainingPopCount = popCount;
-
- if (delete)
- {
- // Replace the original instruction.
- int count = remainingPopCount == 1 ? 1 : 2;
-
- // Create a simple pop instrucion.
- byte replacementOpcode = count == 1 ?
- InstructionConstants.OP_POP :
- InstructionConstants.OP_POP2;
-
- Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
-
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
- // Insert the pop instruction.
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- remainingPopCount -= count;
-
- // We may insert other pop instructions before and after this one.
- before = true;
- after = true;
- }
-
- if (before && remainingPopCount > 0)
- {
- // Insert before the original instruction.
- int count = remainingPopCount == 1 ? 1 : 2;
-
- // Create a simple pop instrucion.
- byte replacementOpcode = count == 1 ?
- InstructionConstants.OP_POP :
- InstructionConstants.OP_POP2;
-
- Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
-
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
- // Insert the pop instruction.
- codeAttributeEditor.insertBeforeInstruction(offset,
- replacementInstruction);
-
- remainingPopCount -= count;
-
- if (extraAddedInstructionVisitor != null)
- {
- replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
- }
- }
-
- if (after && remainingPopCount > 0)
- {
- // Insert after the original instruction.
- int count = remainingPopCount == 1 ? 1 : 2;
-
- // Create a simple pop instrucion.
- byte replacementOpcode = count == 1 ?
- InstructionConstants.OP_POP :
- InstructionConstants.OP_POP2;
-
- Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
-
- if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
- // Insert the pop instruction.
- codeAttributeEditor.insertAfterInstruction(offset,
- replacementInstruction);
-
- remainingPopCount -= count;
-
- if (extraAddedInstructionVisitor != null)
- {
- replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
- }
- }
-
- if (remainingPopCount > 0)
- {
- throw new UnsupportedOperationException("Unsupported stack size reduction ["+popCount+"]");
- }
- }
-
-
- // Small utility methods.
-
- /**
- * Replaces the push instruction at the given offset by a simpler push
- * instruction, if possible.
- */
- private void replaceAnyPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- switch (pushedValue.computationalType())
- {
- case Value.TYPE_INTEGER:
- replaceIntegerPushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_LONG:
- replaceLongPushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_FLOAT:
- replaceFloatPushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_DOUBLE:
- replaceDoublePushInstruction(clazz, offset, instruction);
- break;
- case Value.TYPE_REFERENCE:
- replaceReferencePushInstruction(clazz, offset, instruction);
- break;
- }
- }
- }
-
-
- /**
- * Replaces the integer pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceIntegerPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- replaceIntegerPushInstruction(clazz,
- offset,
- instruction,
- partialEvaluator.getVariablesBefore(offset).size());
- }
-
-
- /**
- * Replaces the integer pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceIntegerPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- int maxVariableIndex)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- int value = pushedValue.integerValue().value();
- if (value << 16 >> 16 == value)
- {
- replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_SIPUSH,
- value);
- }
- }
- else if (pushedValue.isSpecific())
- {
- TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
- for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
- {
- if (pushedValue.equals(variables.load(variableIndex)))
- {
- replaceVariablePushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_ILOAD,
- variableIndex);
- }
- }
- }
- }
-
-
- /**
- * Replaces the long pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceLongPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- replaceLongPushInstruction(clazz,
- offset,
- instruction,
- partialEvaluator.getVariablesBefore(offset).size());
- }
-
-
- /**
- * Replaces the long pushing instruction at the given offset by a simpler
- * push instruction, if possible.
- */
- private void replaceLongPushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- int maxVariableIndex)
- {
- Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
- if (pushedValue.isParticular())
- {
- long value = pushedValue.longValue().value();
- if (value == 0L ||
- value == 1L)
- {
- replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_LCONST_0,
- (int)value);
- }
- }
- else if (pushedValue.isSpecific())
+ else if (pushedValue.isSpecific())
{
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
@@ -1821,10 +565,21 @@ implements AttributeVisitor
value == 2f)
{
replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_FCONST_0,
- (int)value);
+ offset,
+ instruction,
+ InstructionConstants.OP_FCONST_0,
+ (int)value);
+ }
+ else
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC,
+ constantPoolEditor.addFloatConstant(value)).shrink();
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
@@ -1877,10 +632,21 @@ implements AttributeVisitor
value == 1.0)
{
replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_DCONST_0,
- (int)value);
+ offset,
+ instruction,
+ InstructionConstants.OP_DCONST_0,
+ (int)value);
+ }
+ else
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W,
+ constantPoolEditor.addDoubleConstant(value)).shrink();
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
@@ -1914,10 +680,10 @@ implements AttributeVisitor
{
// A reference value can only be specific if it is null.
replaceConstantPushInstruction(clazz,
- offset,
- instruction,
- InstructionConstants.OP_ACONST_NULL,
- 0);
+ offset,
+ instruction,
+ InstructionConstants.OP_ACONST_NULL,
+ 0);
}
}
@@ -1932,10 +698,10 @@ implements AttributeVisitor
byte replacementOpcode,
int value)
{
- replacePushInstruction(clazz,
- offset,
- instruction,
- new SimpleInstruction(replacementOpcode, value).shrink());
+ Instruction replacementInstruction =
+ new SimpleInstruction(replacementOpcode, value).shrink();
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
@@ -1944,86 +710,31 @@ implements AttributeVisitor
* of a variable.
*/
private void replaceVariablePushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- byte replacementOpcode,
- int variableIndex)
- {
- replacePushInstruction(clazz,
- offset,
- instruction,
- new VariableInstruction(replacementOpcode, variableIndex).shrink());
-
- // Mark that the instruction has been simplified by loading an aliasing
- // variable.
- setAliasingVariable(offset, variableIndex);
- }
-
-
- /**
- * Replaces the instruction at a given offset by a given push instruction.
- */
- private void replacePushInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- Instruction replacementInstruction)
- {
- if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction at ["+offset+"] by "+replacementInstruction.toString());
-
- codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
-
- // Mark that the instruction has been simplified.
- markSimplification(clazz, offset, instruction);
-
- // Visit the instruction, if required.
- if (extraPushInstructionVisitor != null)
- {
- // Note: we're not passing the right arguments for now, knowing that
- // they aren't used anyway.
- extraPushInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
- }
- }
-
-
- /**
- * Replaces the instruction at a given offset by a static invocation.
- */
- private void replaceInvocationInstruction(Clazz clazz,
- int offset,
- ConstantInstruction constantInstruction)
+ int offset,
+ Instruction instruction,
+ byte replacementOpcode,
+ int variableIndex)
{
- // Remember the replacement instruction.
Instruction replacementInstruction =
- new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
- constantInstruction.constantIndex).shrink();
-
- if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction at ["+offset+"] by "+replacementInstruction.toString());
-
- codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
-
- // Mark that the instruction has been simplified.
- //markSimplification(clazz, offset, constantInstruction);
+ new VariableInstruction(replacementOpcode, variableIndex).shrink();
- // Visit the instruction, if required.
- //if (extraPushInstructionVisitor != null)
- //{
- // // Note: we're not passing the right arguments for now, knowing that
- // // they aren't used anyway.
- // extraPushInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
- //}
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
/**
* Replaces the given 'jsr' instruction by a simpler branch instruction,
- * if possible.
+ * if it jumps to a subroutine that doesn't return or a subroutine that
+ * is only called from one place.
*/
private void replaceJsrInstruction(Clazz clazz,
int offset,
BranchInstruction branchInstruction)
{
// Is the subroutine ever returning?
- if (!partialEvaluator.isSubroutineReturning(offset + branchInstruction.branchOffset))
+ int subroutineStart = offset + branchInstruction.branchOffset;
+ if (!partialEvaluator.isSubroutineReturning(subroutineStart) ||
+ partialEvaluator.branchOrigins(subroutineStart).instructionOffsetCount() == 1)
{
// All 'jsr' instructions to this subroutine can be replaced
// by unconditional branch instructions.
@@ -2039,6 +750,27 @@ implements AttributeVisitor
/**
+ * Deletes the reference popping instruction at the given offset, if
+ * it is at the start of a subroutine that doesn't return or a subroutine
+ * that is only called from one place.
+ */
+ private void deleteReferencePopInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ if (partialEvaluator.isSubroutineStart(offset) &&
+ (!partialEvaluator.isSubroutineReturning(offset) ||
+ partialEvaluator.branchOrigins(offset).instructionOffsetCount() == 1))
+ {
+ if (DEBUG) System.out.println(" Deleting store of subroutine return address "+instruction.toString(offset));
+
+ // A reference value can only be specific if it is null.
+ codeAttributeEditor.deleteInstruction(offset);
+ }
+ }
+
+
+ /**
* Deletes the given branch instruction, or replaces it by a simpler branch
* instruction, if possible.
*/
@@ -2056,7 +788,7 @@ implements AttributeVisitor
int branchOffset = branchTargets.instructionOffset(0) - offset;
if (branchOffset == instruction.length(offset))
{
- if (DEBUG_ANALYSIS) System.out.println(" Ignoring zero branch instruction at ["+offset+"]");
+ if (DEBUG) System.out.println(" Ignoring zero branch instruction at ["+offset+"]");
}
else
{
@@ -2065,19 +797,7 @@ implements AttributeVisitor
new BranchInstruction(InstructionConstants.OP_GOTO_W,
branchOffset).shrink();
- if (DEBUG_ANALYSIS) System.out.println(" Replacing branch instruction at ["+offset+"] by "+replacementInstruction.toString());
-
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- // Mark that the instruction has been simplified.
- markSimplification(clazz, offset, instruction);
-
- // Visit the instruction, if required.
- if (extraBranchInstructionVisitor != null)
- {
- extraBranchInstructionVisitor.visitBranchInstruction(null, null, null, offset, null);
- }
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
}
@@ -2126,18 +846,7 @@ implements AttributeVisitor
if (replacementInstruction != null)
{
- if (DEBUG_ANALYSIS) System.out.println(" Replacing switch instruction at ["+offset+"] by "+replacementInstruction.toString());
-
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- // Visit the instruction, if required.
- if (extraBranchInstructionVisitor != null)
- {
- // Note: we're not passing the right arguments for now,
- // knowing that they aren't used anyway.
- extraBranchInstructionVisitor.visitBranchInstruction(null, null, null, offset, null);
- }
+ replaceInstruction(clazz, offset, switchInstruction, replacementInstruction);
}
}
@@ -2149,504 +858,111 @@ implements AttributeVisitor
int offset,
Instruction instruction)
{
- if (DEBUG_ANALYSIS) System.out.println(" Inserting infinite loop at ["+offset+"]");
-
// Replace the instruction by an infinite loop.
Instruction replacementInstruction =
new BranchInstruction(InstructionConstants.OP_GOTO, 0);
- codeAttributeEditor.replaceInstruction(offset,
- replacementInstruction);
-
- // Mark the instruction.
- markInstruction(offset);
- markSimplification(clazz, offset, instruction);
- }
-
-
- // Small utility methods.
-
- /**
- * Returns whether the given instruction is a dup or swap instruction
- * (dup, dup_x1, dup_x2, dup2, dup2_x1, dup2_x2, swap).
- */
- private boolean isDupOrSwap(Instruction instruction)
- {
- return instruction.opcode >= InstructionConstants.OP_DUP &&
- instruction.opcode <= InstructionConstants.OP_SWAP;
- }
-
-
- /**
- * Returns whether the given instruction is a pop instruction
- * (pop, pop2).
- */
- private boolean isPop(Instruction instruction)
- {
- return instruction.opcode == InstructionConstants.OP_POP ||
- instruction.opcode == InstructionConstants.OP_POP2;
- }
-
-
- /**
- * Returns whether any traced but unnecessary instruction between the two
- * given offsets is branching over the second given offset.
- */
- private boolean isAnyUnnecessaryInstructionBranchingOver(int instructionOffset1,
- int instructionOffset2)
- {
- for (int offset = instructionOffset1; offset < instructionOffset2; offset++)
- {
- // Is it a traced but unmarked straddling branch?
- if (partialEvaluator.isTraced(offset) &&
- !isInstructionNecessary(offset) &&
- isAnyLargerThan(partialEvaluator.branchTargets(offset),
- instructionOffset2))
- {
- return true;
- }
- }
-
- return false;
- }
-
-
- /**
- * Returns whether all of the given instruction offsets (at least one)
- * are smaller than or equal to the given offset.
- */
- private boolean isAllSmallerThanOrEqual(InstructionOffsetValue instructionOffsets,
- int instructionOffset)
- {
- if (instructionOffsets != null)
- {
- // Loop over all instruction offsets.
- int branchCount = instructionOffsets.instructionOffsetCount();
- if (branchCount > 0)
- {
- for (int branchIndex = 0; branchIndex < branchCount; branchIndex++)
- {
- // Is the offset larger than the reference offset?
- if (instructionOffsets.instructionOffset(branchIndex) > instructionOffset)
- {
- return false;
- }
- }
-
- return true;
- }
- }
-
- return false;
- }
+ if (DEBUG) System.out.println(" Replacing unreachable instruction by infinite loop "+replacementInstruction.toString(offset));
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
- /**
- * Returns whether any of the given instruction offsets (at least one)
- * is larger than the given offset.
- */
- private boolean isAnyLargerThan(InstructionOffsetValue instructionOffsets,
- int instructionOffset)
- {
- if (instructionOffsets != null)
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
{
- // Loop over all instruction offsets.
- int branchCount = instructionOffsets.instructionOffsetCount();
- if (branchCount > 0)
- {
- for (int branchIndex = 0; branchIndex < branchCount; branchIndex++)
- {
- // Is the offset larger than the reference offset?
- if (instructionOffsets.instructionOffset(branchIndex) > instructionOffset)
- {
- return true;
- }
- }
- }
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
}
-
- return false;
}
/**
- * Initializes the necessary data structure.
+ * Replaces the instruction at a given offset by a given push instruction.
*/
- private void initializeNecessary(CodeAttribute codeAttribute)
+ private void replaceInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ Instruction replacementInstruction)
{
- int codeLength = codeAttribute.u4codeLength;
- int maxLocals = codeAttribute.u2maxLocals;
- int maxStack = codeAttribute.u2maxStack;
-
- // Create new arrays for storing information at each instruction offset.
- if (variablesNecessaryAfter.length < codeLength ||
- variablesNecessaryAfter[0].length < maxLocals)
- {
- variablesNecessaryAfter = new boolean[codeLength][maxLocals];
- }
- else
- {
- for (int offset = 0; offset < codeLength; offset++)
- {
- for (int index = 0; index < maxLocals; index++)
- {
- variablesNecessaryAfter[offset][index] = false;
- }
- }
- }
+ // Pop unneeded stack entries if necessary.
+ int popCount =
+ instruction.stackPopCount(clazz) -
+ replacementInstruction.stackPopCount(clazz);
- if (stacksNecessaryAfter.length < codeLength ||
- stacksNecessaryAfter[0].length < maxStack)
- {
- stacksNecessaryAfter = new boolean[codeLength][maxStack];
- }
- else
- {
- for (int offset = 0; offset < codeLength; offset++)
- {
- for (int index = 0; index < maxStack; index++)
- {
- stacksNecessaryAfter[offset][index] = false;
- }
- }
- }
+ insertPopInstructions(offset, popCount);
- if (stacksSimplifiedBefore.length < codeLength ||
- stacksSimplifiedBefore[0].length < maxStack)
- {
- stacksSimplifiedBefore = new boolean[codeLength][maxStack];
- }
- else
- {
- for (int offset = 0; offset < codeLength; offset++)
- {
- for (int index = 0; index < maxStack; index++)
- {
- stacksSimplifiedBefore[offset][index] = false;
- }
- }
- }
+ if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)"));
- if (instructionsNecessary.length < codeLength)
- {
- instructionsNecessary = new boolean[codeLength];
- instructionsSimplified = new boolean[codeLength];
- aliasingVariables = new int[codeLength];
- }
- else
- {
- for (int index = 0; index < codeLength; index++)
- {
- instructionsNecessary[index] = false;
- instructionsSimplified[index] = false;
- }
- }
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
- for (int index = 0; index < codeLength; index++)
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
{
- aliasingVariables[index] = -1;
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
}
}
/**
- * Returns whether the given stack entry is present after execution of the
- * instruction at the given offset.
- */
- private boolean isStackEntriesNecessaryAfter(int instructionOffset,
- int stackIndex1,
- int stackIndex2)
- {
- boolean present1 = isStackEntryNecessaryAfter(instructionOffset, stackIndex1);
- boolean present2 = isStackEntryNecessaryAfter(instructionOffset, stackIndex2);
-
-// if (present1 ^ present2)
-// {
-// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
-// }
-
- return present1 || present2;
- }
-
-
- /**
- * Returns whether the specified variable must be initialized at the
- * specified offset, according to the verifier of the JVM.
+ * Pops the given number of stack entries before the instruction at the
+ * given offset.
*/
- private boolean isVariableInitializationNecessary(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- int initializationOffset,
- int variableIndex)
- {
- int codeLength = codeAttribute.u4codeLength;
-
- // Is the variable necessary anywhere at all?
- if (isVariableNecessaryAfterAny(0, codeLength, variableIndex))
- {
- if (DEBUG_ANALYSIS) System.out.println("Simple partial evalutation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
-
- // Lazily compute perform simple partial evaluation, the way the
- // JVM preverifier would do it.
- simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
-
- if (DEBUG_ANALYSIS) System.out.println("End of simple partial evalutation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
-
- // Check if the variable is necessary elsewhere.
- for (int offset = 0; offset < codeLength; offset++)
- {
- if (isInstructionNecessary(offset))
- {
- Value producer = partialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
- if (producer != null)
- {
- Value simpleProducer = simplePartialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
- if (simpleProducer != null)
- {
- InstructionOffsetValue producerOffsets =
- producer.instructionOffsetValue();
- InstructionOffsetValue simpleProducerOffsets =
- simpleProducer.instructionOffsetValue();
-
- // Does the sophisticated partial evaluation have fewer
- // producers than the simple one?
- // And does the simple partial evaluation point to an
- // initialization of the variable?
- if (producerOffsets.instructionOffsetCount() <
- simpleProducerOffsets.instructionOffsetCount() &&
- isVariableNecessaryAfterAny(producerOffsets, variableIndex) &&
- simpleProducerOffsets.contains(initializationOffset))
- {
- // Then the initialization is necessary.
- return true;
- }
- }
- }
- }
- }
- }
-
- return false;
- }
-
-
- private void markVariableAfter(int instructionOffset,
- int variableIndex)
+ private void insertPopInstructions(int offset, int popCount)
{
- if (!isVariableNecessaryAfter(instructionOffset, variableIndex))
+ switch (popCount)
{
- if (DEBUG_ANALYSIS) System.out.print("["+instructionOffset+".v"+variableIndex+"],");
-
- variablesNecessaryAfter[instructionOffset][variableIndex] = true;
-
- if (maxMarkedOffset < instructionOffset)
+ case 0:
{
- maxMarkedOffset = instructionOffset;
+ break;
}
- }
- }
-
-
- /**
- * Returns whether the specified variable is ever necessary after any
- * instruction in the specified block.
- */
- private boolean isVariableNecessaryAfterAny(int startOffset,
- int endOffset,
- int variableIndex)
- {
- for (int offset = startOffset; offset < endOffset; offset++)
- {
- if (isVariableNecessaryAfter(offset, variableIndex))
+ case 1:
{
- return true;
- }
- }
-
- return false;
- }
+ // Insert a single pop instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
-
- /**
- * Returns whether the specified variable is ever necessary after any
- * instruction in the specified set of instructions offsets.
- */
- private boolean isVariableNecessaryAfterAny(InstructionOffsetValue instructionOffsetValue,
- int variableIndex)
- {
- int count = instructionOffsetValue.instructionOffsetCount();
-
- for (int index = 0; index < count; index++)
- {
- if (isVariableNecessaryAfter(instructionOffsetValue.instructionOffset(index),
- variableIndex))
- {
- return true;
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstruction);
+ break;
}
- }
-
- return false;
- }
-
-
- private boolean isVariableNecessaryAfter(int instructionOffset,
- int variableIndex)
- {
- return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
- variablesNecessaryAfter[instructionOffset][variableIndex];
- }
-
-
- private void markStackEntryAfter(int instructionOffset,
- int stackIndex)
- {
- if (!isStackEntryNecessaryAfter(instructionOffset, stackIndex))
- {
- if (DEBUG_ANALYSIS) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
-
- stacksNecessaryAfter[instructionOffset][stackIndex] = true;
-
- if (maxMarkedOffset < instructionOffset)
+ case 2:
{
- maxMarkedOffset = instructionOffset;
- }
- }
- }
+ // Insert a single pop2 instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
-
- private boolean isAnyStackEntryNecessaryAfter(InstructionOffsetValue instructionOffsets,
- int stackIndex)
- {
- int offsetCount = instructionOffsets.instructionOffsetCount();
-
- for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
- {
- if (isStackEntryNecessaryAfter(instructionOffsets.instructionOffset(offsetIndex), stackIndex))
- {
- return true;
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstruction);
+ break;
}
- }
-
- return false;
- }
-
-
- private boolean isStackEntryNecessaryAfter(int instructionOffset,
- int stackIndex)
- {
- return instructionOffset == PartialEvaluator.AT_CATCH_ENTRY ||
- stacksNecessaryAfter[instructionOffset][stackIndex];
- }
-
-
- private void markStackSimplificationBefore(int instructionOffset,
- int stackIndex)
- {
- stacksSimplifiedBefore[instructionOffset][stackIndex] = true;
- }
-
-
- private boolean isStackSimplifiedBefore(int instructionOffset,
- int stackIndex)
- {
- return stacksSimplifiedBefore[instructionOffset][stackIndex];
- }
-
-
- private void markSimplification(Clazz clazz,
- int instructionOffset,
- Instruction instruction)
- {
- // Mark the instruction itself.
- instructionsSimplified[instructionOffset] = true;
-
- // Also mark all stack entries that would be popped.
- TracedStack tracedStack =
- partialEvaluator.getStackBefore(instructionOffset);
-
- int top = tracedStack.size() - 1;
- int popCount = instruction.stackPopCount(clazz);
-
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
- {
- markStackSimplificationBefore(instructionOffset, top - stackIndex);
- }
- }
-
-
- private boolean isInstructionSimplified(int instructionOffset)
- {
- return instructionsSimplified[instructionOffset];
- }
-
-
- private void setAliasingVariable(int instructionOffset,
- int variableIndex)
- {
- aliasingVariables[instructionOffset] = variableIndex;
- }
-
-
- private int getAliasingVariable(int instructionOffset)
- {
- return aliasingVariables[instructionOffset];
- }
-
-
- private void markInstruction(int instructionOffset)
- {
- if (!isInstructionNecessary(instructionOffset))
- {
- if (DEBUG_ANALYSIS) System.out.print(instructionOffset+",");
-
- instructionsNecessary[instructionOffset] = true;
-
- if (maxMarkedOffset < instructionOffset)
+ default:
{
- maxMarkedOffset = instructionOffset;
- }
- }
- }
+ // Insert the specified number of pop instructions.
+ Instruction[] popInstructions =
+ new Instruction[popCount / 2 + popCount % 2];
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
- private boolean isAnyInstructionNecessary(int instructionOffset1,
- int instructionOffset2)
- {
- for (int instructionOffset = instructionOffset1;
- instructionOffset < instructionOffset2;
- instructionOffset++)
- {
- if (isInstructionNecessary(instructionOffset))
- {
- return true;
- }
- }
+ for (int index = 0; index < popCount / 2; index++)
+ {
+ popInstructions[index] = popInstruction;
+ }
- return false;
- }
+ if (popCount % 2 == 1)
+ {
+ popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
+ popInstructions[popCount / 2] = popInstruction;
+ }
- /**
- * Returns the highest offset of an instruction that has been marked as
- * necessary, before the given offset.
- */
- private int lastNecessaryInstructionOffset(int instructionOffset)
- {
- for (int offset = instructionOffset-1; offset >= 0; offset--)
- {
- if (isInstructionNecessary(instructionOffset))
- {
- return offset;
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstructions);
+ break;
}
}
-
- return 0;
- }
-
-
- private boolean isInstructionNecessary(int instructionOffset)
- {
- return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
- instructionsNecessary[instructionOffset];
}
}
diff --git a/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
index e45842d..9915027 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -348,7 +348,7 @@ implements AttributeVisitor,
// Start marking the variable before the load instruction.
alive |= livenessMask;
}
- else if (variableInstruction.opcode != InstructionConstants.OP_IINC)
+ else
{
// Stop marking the variable before the store instruction.
alive &= ~livenessMask;
@@ -429,6 +429,10 @@ implements AttributeVisitor,
}
+ /**
+ * Returns the combined liveness mask of the variables right before the
+ * specified instruction offsets.
+ */
private long combinedLiveness(InstructionOffsetValue instructionOffsetValue)
{
long alive = 0L;
diff --git a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
index 61de720..8379c57 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,12 +35,34 @@ import proguard.evaluation.value.*;
public class LoadingInvocationUnit
extends BasicInvocationUnit
{
+ private boolean loadFieldValues;
+ private boolean loadMethodParameterValues;
+ private boolean loadMethodReturnValues;
+
+
/**
* Creates a new LoadingInvocationUnit with the given value factory.
*/
public LoadingInvocationUnit(ValueFactory valueFactory)
{
+ this(valueFactory, false, false, false);
+ }
+
+
+ /**
+ * Creates a new LoadingInvocationUnit with the given value factory, for
+ * loading the specified values.
+ */
+ public LoadingInvocationUnit(ValueFactory valueFactory,
+ boolean loadFieldValues,
+ boolean loadMethodParameterValues,
+ boolean loadMethodReturnValues)
+ {
super(valueFactory);
+
+ this.loadFieldValues = loadFieldValues;
+ this.loadMethodParameterValues = loadMethodParameterValues;
+ this.loadMethodReturnValues = loadMethodReturnValues;
}
@@ -50,18 +72,21 @@ extends BasicInvocationUnit
RefConstant refConstant,
String type)
{
- // Do we know this field?
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null)
+ if (loadFieldValues)
{
- // Retrieve the stored field class value.
- ReferenceValue value = StoringInvocationUnit.getFieldClassValue((Field)referencedMember);
- if (value != null &&
- value.isParticular())
+ // Do we know this field?
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
{
- return value;
+ // Retrieve the stored field class value.
+ ReferenceValue value = StoringInvocationUnit.getFieldClassValue((Field)referencedMember);
+ if (value != null &&
+ value.isParticular())
+ {
+ return value;
// // Make sure the value is refreshed.
// return refresh(value);
+ }
}
}
@@ -73,18 +98,21 @@ extends BasicInvocationUnit
RefConstant refConstant,
String type)
{
- // Do we know this field?
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null)
+ if (loadFieldValues)
{
- // Retrieve the stored field value.
- Value value = StoringInvocationUnit.getFieldValue((Field)referencedMember);
- if (value != null &&
- value.isParticular())
+ // Do we know this field?
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
{
- return value;
+ // Retrieve the stored field value.
+ Value value = StoringInvocationUnit.getFieldValue((Field)referencedMember);
+ if (value != null &&
+ value.isParticular())
+ {
+ return value;
// // Make sure the value is refreshed.
// return refresh(value);
+ }
}
}
@@ -98,14 +126,17 @@ extends BasicInvocationUnit
String type,
Clazz referencedClass)
{
- // Retrieve the stored method parameter value.
- Value value = StoringInvocationUnit.getMethodParameterValue(method, parameterIndex);
+ if (loadMethodParameterValues)
+ {
+ // Retrieve the stored method parameter value.
+ Value value = StoringInvocationUnit.getMethodParameterValue(method, parameterIndex);
if (value != null &&
value.isParticular())
{
return value;
// // Make sure the value is refreshed.
// return refresh(value);
+ }
}
return super.getMethodParameterValue(clazz,
@@ -120,18 +151,21 @@ extends BasicInvocationUnit
RefConstant refConstant,
String type)
{
- // Do we know this method?
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null)
+ if (loadMethodReturnValues)
{
- // Retrieve the stored method return value.
- Value value = StoringInvocationUnit.getMethodReturnValue((Method)referencedMember);
- if (value != null &&
- value.isParticular())
+ // Do we know this method?
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
{
- return value;
+ // Retrieve the stored method return value.
+ Value value = StoringInvocationUnit.getMethodReturnValue((Method)referencedMember);
+ if (value != null &&
+ value.isParticular())
+ {
+ return value;
// // Make sure the value is refreshed.
// return refresh(value);
+ }
}
}
diff --git a/src/proguard/optimize/evaluation/PartialEvaluator.java b/src/proguard/optimize/evaluation/PartialEvaluator.java
index 12d4cc0..5790a36 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.*;
import proguard.classfile.constant.ClassConstant;
import proguard.classfile.instruction.*;
import proguard.classfile.util.*;
-import proguard.classfile.visitor.ClassPrinter;
+import proguard.classfile.visitor.*;
import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.peephole.BranchTargetFinder;
@@ -72,8 +72,10 @@ implements AttributeVisitor,
private boolean evaluateExceptions;
private final BasicBranchUnit branchUnit;
- private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
-// private ClassCleaner classCleaner = new ClassCleaner();
+ private final BranchTargetFinder branchTargetFinder;
+
+ private final java.util.Stack callingInstructionBlockStack;
+ private final java.util.Stack instructionBlockStack = new java.util.Stack();
/**
@@ -81,7 +83,9 @@ implements AttributeVisitor,
*/
public PartialEvaluator()
{
- this(new ValueFactory(), new BasicInvocationUnit(new ValueFactory()), true);
+ this(new ValueFactory(),
+ new BasicInvocationUnit(new ValueFactory()),
+ true);
}
@@ -92,20 +96,68 @@ implements AttributeVisitor,
* @param invocationUnit the invocation unit that will handle all
* communication with other fields and methods.
* @param evaluateAllCode a flag that specifies whether all branch targets
- * and exception 'catch' blocks should be evaluated,
+ * and exception handlers should be evaluated,
* even if they are unreachable.
*/
public PartialEvaluator(ValueFactory valueFactory,
InvocationUnit invocationUnit,
boolean evaluateAllCode)
{
- this.valueFactory = valueFactory;
- this.invocationUnit = invocationUnit;
- this.evaluateAllCode = evaluateAllCode;
+ this(valueFactory,
+ invocationUnit,
+ evaluateAllCode,
+ evaluateAllCode ?
+ new BasicBranchUnit() :
+ new TracedBranchUnit(),
+ new BranchTargetFinder(),
+ null);
+ }
+
- this.branchUnit = evaluateAllCode ?
- new BasicBranchUnit() :
- new TracedBranchUnit();
+ /**
+ * Creates a new PartialEvaluator, based on an existing one.
+ * @param partialEvaluator the subroutine calling partial evaluator.
+ */
+ private PartialEvaluator(PartialEvaluator partialEvaluator)
+ {
+ this(partialEvaluator.valueFactory,
+ partialEvaluator.invocationUnit,
+ partialEvaluator.evaluateAllCode,
+ partialEvaluator.branchUnit,
+ partialEvaluator.branchTargetFinder,
+ partialEvaluator.instructionBlockStack);
+ }
+
+
+ /**
+ * Creates a new PartialEvaluator.
+ * @param valueFactory the value factory that will create all
+ * values during evaluation.
+ * @param invocationUnit the invocation unit that will handle all
+ * communication with other fields and methods.
+ * @param evaluateAllCode a flag that specifies whether all branch
+ * targets and exception handlers should be
+ * evaluated, even if they are unreachable.
+ * @param branchUnit the branch unit that will handle all
+ * branches.
+ * @param branchTargetFinder the utility class that will find all
+ * branches.
+ */
+ private PartialEvaluator(ValueFactory valueFactory,
+ InvocationUnit invocationUnit,
+ boolean evaluateAllCode,
+ BasicBranchUnit branchUnit,
+ BranchTargetFinder branchTargetFinder,
+ java.util.Stack callingInstructionBlockStack)
+ {
+ this.valueFactory = valueFactory;
+ this.invocationUnit = invocationUnit;
+ this.evaluateAllCode = evaluateAllCode;
+ this.branchUnit = branchUnit;
+ this.branchTargetFinder = branchTargetFinder;
+ this.callingInstructionBlockStack = callingInstructionBlockStack == null ?
+ this.instructionBlockStack :
+ callingInstructionBlockStack;
}
@@ -166,24 +218,13 @@ implements AttributeVisitor,
codeAttribute.accept(clazz, method, branchTargetFinder);
// Start executing the first instruction block.
- evaluateInstructionBlock(clazz,
- method,
- codeAttribute,
- variables,
- stack,
- 0);
-
- // Evaluate the exception catch blocks, until their entry variables
- // have stabilized.
- do
- {
- // Reset the flag to stop evaluating.
- evaluateExceptions = false;
-
- // Evaluate all relevant exception catch blocks once.
- codeAttribute.exceptionsAccept(clazz, method, this);
- }
- while (evaluateExceptions);
+ evaluateInstructionBlockAndExceptionHandlers(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ 0,
+ codeAttribute.u4codeLength);
if (DEBUG_RESULTS)
{
@@ -194,7 +235,7 @@ implements AttributeVisitor,
{
if (isBranchOrExceptionTarget(offset))
{
- System.out.println("Branch target:");
+ System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
if (isTraced(offset))
{
System.out.println(" Vars: "+variablesBefore[offset]);
@@ -265,6 +306,15 @@ implements AttributeVisitor,
/**
+ * Returns whether there is an instruction at the given offset.
+ */
+ public boolean isInstruction(int instructionOffset)
+ {
+ return branchTargetFinder.isInstruction(instructionOffset);
+ }
+
+
+ /**
* Returns whether the instruction at the given offset is the target of a
* branch instruction or an exception.
*/
@@ -286,6 +336,16 @@ implements AttributeVisitor,
/**
+ * Returns whether the instruction at the given offset is a subroutine
+ * invocation.
+ */
+ public boolean isSubroutineInvocation(int instructionOffset)
+ {
+ return branchTargetFinder.isSubroutineInvocation(instructionOffset);
+ }
+
+
+ /**
* Returns whether the instruction at the given offset is part of a
* subroutine.
*/
@@ -429,102 +489,63 @@ implements AttributeVisitor,
}
- // Implementations for ExceptionInfoVisitor.
+ // Utility methods to evaluate instruction blocks.
- public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ /**
+ * Pushes block of instructions to be executed in the calling partial
+ * evaluator.
+ */
+ private void pushCallingInstructionBlock(TracedVariables variables,
+ TracedStack stack,
+ int startOffset)
{
- int startPC = exceptionInfo.u2startPC;
- int endPC = exceptionInfo.u2endPC;
-
- // Do we have to evaluate this exception catch block?
- if (isTraced(startPC, endPC))
- {
- int handlerPC = exceptionInfo.u2handlerPC;
- int catchType = exceptionInfo.u2catchType;
-
- if (DEBUG) System.out.println("Partial evaluation of exception ["+startPC +","+endPC +"] -> ["+handlerPC+"]:");
-
- // Reuse the existing variables and stack objects, ensuring the
- // right size.
- TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
- TracedStack stack = new TracedStack(codeAttribute.u2maxStack);
-
- // Initialize the trace values.
- Value storeValue = new InstructionOffsetValue(AT_CATCH_ENTRY);
- variables.setProducerValue(storeValue);
- stack.setProducerValue(storeValue);
-
- // Initialize the variables by generalizing the variables of the
- // try block. Make sure to include the results of the last
- // instruction for preverification.
- generalizeVariables(startPC,
- endPC,
- evaluateAllCode,
- variables);
-
- // Initialize the the stack.
- //stack.push(valueFactory.createReference((ClassConstant)((ProgramClass)clazz).getConstant(exceptionInfo.u2catchType), false));
- String catchClassName = catchType != 0 ?
- clazz.getClassName(catchType) :
- ClassConstants.INTERNAL_NAME_JAVA_LANG_THROWABLE;
-
- Clazz catchClass = catchType != 0 ?
- ((ClassConstant)((ProgramClass)clazz).getConstant(catchType)).referencedClass :
- null;
-
- stack.push(valueFactory.createReferenceValue(catchClassName,
- catchClass,
- false));
-
- int evaluationCount = evaluationCounts[handlerPC];
-
- // Evaluate the instructions, starting at the entry point.
- evaluateInstructionBlock(clazz,
- method,
- codeAttribute,
- variables,
- stack,
- handlerPC);
-
- // Remember to evaluate all exception handlers once more.
- if (!evaluateExceptions)
- {
- evaluateExceptions = evaluationCount < evaluationCounts[handlerPC];
- }
- }
- else if (evaluateAllCode)
- {
- if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +","+endPC +"] -> ["+exceptionInfo.u2handlerPC+"] yet");
-
- // We don't have any information on the try block yet, but we do
- // have to evaluate the exception handler.
- // Remember to evaluate all exception handlers once more.
- evaluateExceptions = true;
- }
- else
- {
- if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +","+endPC +"] -> ["+exceptionInfo.u2handlerPC+"]");
- }
+ callingInstructionBlockStack.push(new MyInstructionBlock(variables,
+ stack,
+ startOffset));
}
- // Utility methods to evaluate instruction blocks.
-
/**
- * Pushes block of instructions to be executed on the given stack.
+ * Pushes block of instructions to be executed in this partial evaluator.
*/
private void pushInstructionBlock(TracedVariables variables,
TracedStack stack,
- int startOffset,
- java.util.Stack instructionBlocKStack)
+ int startOffset)
{
- instructionBlocKStack.push(new MyInstructionBlock(variables,
+ instructionBlockStack.push(new MyInstructionBlock(variables,
stack,
startOffset));
}
/**
+ * Evaluates the instruction block and the exception handlers covering the
+ * given instruction range in the given code.
+ */
+ private void evaluateInstructionBlockAndExceptionHandlers(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack,
+ int startOffset,
+ int endOffset)
+ {
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ startOffset);
+
+ evaluateExceptionHandlers(clazz,
+ method,
+ codeAttribute,
+ startOffset,
+ endOffset);
+ }
+
+
+ /**
* Evaluates a block of instructions, starting at the given offset and ending
* at a branch instruction, a return instruction, or a throw instruction.
*/
@@ -535,18 +556,13 @@ implements AttributeVisitor,
TracedStack stack,
int startOffset)
{
- // We're now defining out own stack instead of more elegant recursion,
- // in order to avoid stack overflow errors in the VM.
- java.util.Stack instructionBlockStack = new java.util.Stack();
-
// Execute the initial instruction block.
- evaluateInstructionBlock(clazz,
- method,
- codeAttribute,
- variables,
- stack,
- startOffset,
- instructionBlockStack);
+ evaluateSingleInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ startOffset);
// Execute all resulting instruction blocks on the execution stack.
while (!instructionBlockStack.empty())
@@ -556,13 +572,12 @@ implements AttributeVisitor,
MyInstructionBlock instructionBlock =
(MyInstructionBlock)instructionBlockStack.pop();
- evaluateInstructionBlock(clazz,
- method,
- codeAttribute,
- instructionBlock.variables,
- instructionBlock.stack,
- instructionBlock.startOffset,
- instructionBlockStack);
+ evaluateSingleInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ instructionBlock.variables,
+ instructionBlock.stack,
+ instructionBlock.startOffset);
}
}
@@ -573,13 +588,12 @@ implements AttributeVisitor,
* Instruction blocks that are to be evaluated as a result are pushed on
* the given stack.
*/
- private void evaluateInstructionBlock(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- TracedVariables variables,
- TracedStack stack,
- int startOffset,
- java.util.Stack instructionBlockStack)
+ private void evaluateSingleInstructionBlock(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack,
+ int startOffset)
{
byte[] code = codeAttribute.code;
@@ -594,7 +608,11 @@ implements AttributeVisitor,
System.out.println("Init stack: "+stack);
}
- Processor processor = new Processor(variables, stack, valueFactory, branchUnit, invocationUnit);
+ Processor processor = new Processor(variables,
+ stack,
+ valueFactory,
+ branchUnit,
+ invocationUnit);
int instructionOffset = startOffset;
@@ -810,8 +828,7 @@ implements AttributeVisitor,
pushInstructionBlock(new TracedVariables(variables),
new TracedStack(stack),
- branchTargets.instructionOffset(index),
- instructionBlockStack);
+ branchTargets.instructionOffset(index));
}
break;
@@ -823,48 +840,252 @@ implements AttributeVisitor,
// Just continue with the next instruction.
instructionOffset = branchTargets.instructionOffset(0);
- // Clear the context of a subroutine before entering it, in order
- // to avoid context conflicts across different invocations.
+ // Is this a subroutine invocation?
if (instruction.opcode == InstructionConstants.OP_JSR ||
instruction.opcode == InstructionConstants.OP_JSR_W)
{
- // A subroutine has a single entry point and a single exit point,
- // so we can easily loop over its instructions.
- int subroutineEnd = branchTargetFinder.subroutineEnd(instructionOffset);
+ // Evaluate the subroutine, possibly in another partial
+ // evaluator.
+ evaluateSubroutine(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ instructionOffset,
+ instructionBlockStack);
+
+ break;
+ }
+ else if (instruction.opcode == InstructionConstants.OP_RET)
+ {
+ // Let the partial evaluator that has called the subroutine
+ // handle the evaluation after the return.
+ pushCallingInstructionBlock(new TracedVariables(variables),
+ new TracedStack(stack),
+ instructionOffset);
+ break;
+ }
+ }
+
+ if (DEBUG) System.out.println("Ending processing of instruction block starting at ["+startOffset+"]");
+ }
+
+
+ /**
+ * Evaluates a subroutine and its exception handlers, starting at the given
+ * offset and ending at a subroutine return instruction.
+ */
+ private void evaluateSubroutine(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack,
+ int subroutineStart,
+ java.util.Stack instructionBlockStack)
+ {
+ int subroutineEnd = branchTargetFinder.subroutineEnd(subroutineStart);
+
+ if (DEBUG) System.out.println("Evaluating subroutine from "+subroutineStart+" to "+subroutineEnd);
+
+ PartialEvaluator subroutinePartialEvaluator = this;
+
+ // Create a temporary partial evaluator if necessary.
+ if (evaluationCounts[subroutineStart] > 0)
+ {
+ if (DEBUG) System.out.println("Creating new partial evaluator for subroutine");
+
+ subroutinePartialEvaluator = new PartialEvaluator(this);
+
+ subroutinePartialEvaluator.initializeVariables(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack);
+ }
+
+ // Evaluate the subroutine.
+ subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ subroutineStart,
+ subroutineEnd);
+
+ // Merge back the temporary partial evaluator if necessary.
+ if (subroutinePartialEvaluator != this)
+ {
+ generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
+ }
+
+ if (DEBUG) System.out.println("Ending subroutine from "+subroutineStart+" to "+subroutineEnd);
+ }
+
+
+ /**
+ * Generalizes the results of this partial evaluator with those of another
+ * given partial evaluator, over a given range of instructions.
+ */
+ private void generalize(PartialEvaluator other,
+ int codeStart,
+ int codeEnd)
+ {
+ if (DEBUG) System.out.println("Generalizing with temporary partial evaluation");
+
+ for (int offset = codeStart; offset < codeEnd; offset++)
+ {
+ if (other.branchOriginValues[offset] != null)
+ {
+ branchOriginValues[offset] = branchOriginValues[offset] == null ?
+ other.branchOriginValues[offset] :
+ branchOriginValues[offset].generalize(other.branchOriginValues[offset]).instructionOffsetValue();
+ }
- if (DEBUG) System.out.println("Clearing context of subroutine from "+instructionOffset+" to "+subroutineEnd);
+ if (other.isTraced(offset))
+ {
+ if (other.branchTargetValues[offset] != null)
+ {
+ branchTargetValues[offset] = branchTargetValues[offset] == null ?
+ other.branchTargetValues[offset] :
+ branchTargetValues[offset].generalize(other.branchTargetValues[offset]).instructionOffsetValue();
+ }
- for (int offset = instructionOffset; offset < subroutineEnd; offset++)
+ if (evaluationCounts[offset] == 0)
{
- if (branchTargetFinder.isInstruction(offset))
- {
- 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];
+ }
+ else
+ {
+ variablesBefore[offset].generalize(other.variablesBefore[offset], false);
+ stacksBefore[offset] .generalize(other.stacksBefore[offset]);
+ variablesAfter[offset] .generalize(other.variablesAfter[offset], false);
+ stacksAfter[offset] .generalize(other.stacksAfter[offset]);
+ //generalizedContexts[offset]
+ evaluationCounts[offset] += other.evaluationCounts[offset];
+ //initializedVariables[offset]
}
+ }
+ }
+ }
- evaluateInstructionBlock(clazz,
- method,
- codeAttribute,
- new TracedVariables(variables),
- new TracedStack(stack),
- instructionOffset);
- if (DEBUG) System.out.println("Evaluating exceptions of subroutine from "+instructionOffset+" to "+subroutineEnd);
+ /**
+ * Evaluates the exception handlers covering and targeting the given
+ * instruction range in the given code.
+ */
+ private void evaluateExceptionHandlers(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int startOffset,
+ int endOffset)
+ {
+ if (DEBUG) System.out.println("Evaluating exceptions covering ["+startOffset+" -> "+endOffset+"]:");
- // Evaluate all relevant exception catch blocks once.
- codeAttribute.exceptionsAccept(clazz,
- method,
- instructionOffset,
- subroutineEnd,
- this);
+ ExceptionHandlerFilter exceptionEvaluator =
+ new ExceptionHandlerFilter(startOffset,
+ endOffset,
+ this);
- if (DEBUG) System.out.println("Ending subroutine from "+instructionOffset+" to "+subroutineEnd);
+ // Evaluate the exception catch blocks, until their entry variables
+ // have stabilized.
+ do
+ {
+ // Reset the flag to stop evaluating.
+ evaluateExceptions = false;
- break;
- }
+ // Evaluate all relevant exception catch blocks once.
+ codeAttribute.exceptionsAccept(clazz,
+ method,
+ startOffset,
+ endOffset,
+ exceptionEvaluator);
}
+ while (evaluateExceptions);
+ }
- if (DEBUG) System.out.println("Ending processing of instruction block starting at ["+startOffset+"]");
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ int startPC = exceptionInfo.u2startPC;
+ int endPC = exceptionInfo.u2endPC;
+
+ // Do we have to evaluate this exception catch block?
+ if (isTraced(startPC, endPC))
+ {
+ int handlerPC = exceptionInfo.u2handlerPC;
+ int catchType = exceptionInfo.u2catchType;
+
+ if (DEBUG) System.out.println("Evaluating exception ["+startPC +" -> "+endPC +": "+handlerPC+"]:");
+
+ // Reuse the existing variables and stack objects, ensuring the
+ // right size.
+ TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
+ TracedStack stack = new TracedStack(codeAttribute.u2maxStack);
+
+ // Initialize the trace values.
+ Value storeValue = new InstructionOffsetValue(AT_CATCH_ENTRY);
+ variables.setProducerValue(storeValue);
+ stack.setProducerValue(storeValue);
+
+ // Initialize the variables by generalizing the variables of the
+ // try block. Make sure to include the results of the last
+ // instruction for preverification.
+ generalizeVariables(startPC,
+ endPC,
+ evaluateAllCode,
+ variables);
+
+ // Initialize the the stack.
+ //stack.push(valueFactory.createReference((ClassConstant)((ProgramClass)clazz).getConstant(exceptionInfo.u2catchType), false));
+ String catchClassName = catchType != 0 ?
+ clazz.getClassName(catchType) :
+ ClassConstants.INTERNAL_NAME_JAVA_LANG_THROWABLE;
+
+ Clazz catchClass = catchType != 0 ?
+ ((ClassConstant)((ProgramClass)clazz).getConstant(catchType)).referencedClass :
+ null;
+
+ stack.push(valueFactory.createReferenceValue(catchClassName,
+ catchClass,
+ false));
+
+ int evaluationCount = evaluationCounts[handlerPC];
+
+ // Evaluate the instructions, starting at the entry point.
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ handlerPC);
+
+ // Remember to evaluate all exception handlers once more.
+ if (!evaluateExceptions)
+ {
+ evaluateExceptions = evaluationCount < evaluationCounts[handlerPC];
+ }
+ }
+// else if (evaluateAllCode)
+// {
+// if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"] yet");
+//
+// // We don't have any information on the try block yet, but we do
+// // have to evaluate the exception handler.
+// // Remember to evaluate all exception handlers once more.
+// evaluateExceptions = true;
+// }
+ else
+ {
+ if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"]");
+ }
}
diff --git a/src/proguard/optimize/evaluation/StoringInvocationUnit.java b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
index 1511a60..bcbb69f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,12 +36,34 @@ import proguard.optimize.info.*;
public class StoringInvocationUnit
extends BasicInvocationUnit
{
+ private boolean storeFieldValues;
+ private boolean storeMethodParameterValues;
+ private boolean storeMethodReturnValues;
+
+
/**
* Creates a new StoringInvocationUnit with the given value factory.
*/
public StoringInvocationUnit(ValueFactory valueFactory)
{
+ this(valueFactory, true, true, true);
+ }
+
+
+ /**
+ * Creates a new StoringInvocationUnit with the given value factory, for
+ * storing the specified values.
+ */
+ public StoringInvocationUnit(ValueFactory valueFactory,
+ boolean storeFieldValues,
+ boolean storeMethodParameterValues,
+ boolean storeMethodReturnValues)
+ {
super(valueFactory);
+
+ this.storeFieldValues = storeFieldValues;
+ this.storeMethodParameterValues = storeMethodParameterValues;
+ this.storeMethodReturnValues = storeMethodReturnValues;
}
@@ -51,10 +73,13 @@ extends BasicInvocationUnit
RefConstant refConstant,
ReferenceValue value)
{
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null)
+ if (storeFieldValues)
{
- generalizeFieldClassValue((Field)referencedMember, value);
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ generalizeFieldClassValue((Field)referencedMember, value);
+ }
}
}
@@ -63,10 +88,13 @@ extends BasicInvocationUnit
RefConstant refConstant,
Value value)
{
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null)
+ if (storeFieldValues)
{
- generalizeFieldValue((Field)referencedMember, value);
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ generalizeFieldValue((Field)referencedMember, value);
+ }
}
}
@@ -76,12 +104,15 @@ extends BasicInvocationUnit
int parameterIndex,
Value value)
{
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null)
+ if (storeMethodParameterValues)
{
- generalizeMethodParameterValue((Method)referencedMember,
- parameterIndex,
- value);
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ generalizeMethodParameterValue((Method)referencedMember,
+ parameterIndex,
+ value);
+ }
}
}
@@ -90,9 +121,12 @@ extends BasicInvocationUnit
Method method,
Value value)
{
- generalizeMethodReturnValue(method, value);
+ if (storeMethodReturnValues)
+ {
+ generalizeMethodReturnValue(method, value);
+ }
}
-
+
// Small utility methods.
diff --git a/src/proguard/optimize/evaluation/TracedBranchUnit.java b/src/proguard/optimize/evaluation/TracedBranchUnit.java
index 422ce11..fa5bb79 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 c500bdc..b3ae81c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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.evaluation;
import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.editor.VariableRemapper;
@@ -45,7 +46,8 @@ implements AttributeVisitor
private static final int MAX_VARIABLES_SIZE = 64;
- private final boolean reuseThis;
+ private final boolean reuseThis;
+ private final MemberVisitor extraVariableMemberVisitor;
private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
private final VariableRemapper variableRemapper = new VariableRemapper();
@@ -56,10 +58,29 @@ implements AttributeVisitor
/**
* Creates a new VariableOptimizer.
* @param reuseThis specifies whether the 'this' variable can be reused.
+ * Many JVMs for JME and IBM's JVMs for JSE can't handle
+ * such reuse.
*/
public VariableOptimizer(boolean reuseThis)
{
- this.reuseThis = reuseThis;
+ this(reuseThis, null);
+ }
+
+
+ /**
+ * Creates a new VariableOptimizer with an extra visitor.
+ * @param reuseThis specifies whether the 'this' variable
+ * can be reused. Many JVMs for JME and
+ * IBM's JVMs for JSE can't handle such
+ * reuse.
+ * @param extraVariableMemberVisitor an optional extra visitor for all
+ * removed variables.
+ */
+ public VariableOptimizer(boolean reuseThis,
+ MemberVisitor extraVariableMemberVisitor)
+ {
+ this.reuseThis = reuseThis;
+ this.extraVariableMemberVisitor = extraVariableMemberVisitor;
}
@@ -140,6 +161,12 @@ implements AttributeVisitor
variableRemapper.setVariableMap(variableMap);
variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Visit the method, if required.
+ if (extraVariableMemberVisitor != null)
+ {
+ method.accept(clazz, extraVariableMemberVisitor);
+ }
}
}
diff --git a/src/proguard/optimize/info/AccessMethodMarker.java b/src/proguard/optimize/info/AccessMethodMarker.java
index 16319a0..6965cec 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/BackwardBranchMarker.java b/src/proguard/optimize/info/BackwardBranchMarker.java
index d988f8d..9e09b0f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 8830722..3f2a06f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/CaughtClassFilter.java
similarity index 81%
copy from src/proguard/optimize/info/DotClassFilter.java
copy to src/proguard/optimize/info/CaughtClassFilter.java
index 08aa6e5..5e17763 100644
--- a/src/proguard/optimize/info/DotClassFilter.java
+++ b/src/proguard/optimize/info/CaughtClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,18 +25,18 @@ import proguard.classfile.visitor.ClassVisitor;
/**
* This ClassVisitor delegates all its method calls to another ClassVisitor,
- * but only for Clazz objects that are used in a .class construct.
+ * but only for Clazz objects that are caught as exceptions.
*
- * @see DotClassMarker
+ * @see CaughtClassMarker
* @author Eric Lafortune
*/
-public class DotClassFilter
+public class CaughtClassFilter
implements ClassVisitor
{
private final ClassVisitor classVisitor;
- public DotClassFilter(ClassVisitor classVisitor)
+ public CaughtClassFilter(ClassVisitor classVisitor)
{
this.classVisitor = classVisitor;
}
@@ -46,7 +46,7 @@ implements ClassVisitor
public void visitProgramClass(ProgramClass programClass)
{
- if (DotClassMarker.isDotClassed(programClass))
+ if (CaughtClassMarker.isCaught(programClass))
{
classVisitor.visitProgramClass(programClass);
}
@@ -55,7 +55,7 @@ implements ClassVisitor
public void visitLibraryClass(LibraryClass libraryClass)
{
- if (DotClassMarker.isDotClassed(libraryClass))
+ if (CaughtClassMarker.isCaught(libraryClass))
{
classVisitor.visitLibraryClass(libraryClass);
}
diff --git a/src/proguard/optimize/info/DotClassFilter.java b/src/proguard/optimize/info/CaughtClassMarker.java
similarity index 59%
copy from src/proguard/optimize/info/DotClassFilter.java
copy to src/proguard/optimize/info/CaughtClassMarker.java
index 08aa6e5..0cc350e 100644
--- a/src/proguard/optimize/info/DotClassFilter.java
+++ b/src/proguard/optimize/info/CaughtClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,43 +21,43 @@
package proguard.optimize.info;
import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
/**
- * This ClassVisitor delegates all its method calls to another ClassVisitor,
- * but only for Clazz objects that are used in a .class construct.
+ * This InstructionVisitor marks all classes that are used in an 'instanceof'
+ * test by any of the instructions that it visits.
*
- * @see DotClassMarker
* @author Eric Lafortune
*/
-public class DotClassFilter
+public class CaughtClassMarker
implements ClassVisitor
{
- private final ClassVisitor classVisitor;
+ // Implementations for ClassVisitor.
+ public void visitLibraryClass(LibraryClass libraryClass) {}
- public DotClassFilter(ClassVisitor classVisitor)
+ public void visitProgramClass(ProgramClass programClass)
{
- this.classVisitor = classVisitor;
+ setCaught(programClass);
}
- // Implementations for ClassVisitor.
+ // Small utility methods.
- public void visitProgramClass(ProgramClass programClass)
+ private static void setCaught(Clazz clazz)
{
- if (DotClassMarker.isDotClassed(programClass))
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
{
- classVisitor.visitProgramClass(programClass);
+ info.setCaught();
}
}
- public void visitLibraryClass(LibraryClass libraryClass)
+ public static boolean isCaught(Clazz clazz)
{
- if (DotClassMarker.isDotClassed(libraryClass))
- {
- classVisitor.visitLibraryClass(libraryClass);
- }
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isCaught();
}
}
\ No newline at end of file
diff --git a/src/proguard/optimize/info/ClassOptimizationInfo.java b/src/proguard/optimize/info/ClassOptimizationInfo.java
index e848a6e..99b6e7b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +33,7 @@ public class ClassOptimizationInfo
private boolean isInstantiated = false;
private boolean isInstanceofed = false;
private boolean isDotClassed = false;
+ private boolean isCaught = false;
private boolean containsPackageVisibleMembers = false;
private boolean invokesPackageVisibleMembers = false;
private Clazz targetClass;
@@ -74,6 +75,18 @@ public class ClassOptimizationInfo
}
+ public void setCaught()
+ {
+ isCaught = true;
+ }
+
+
+ public boolean isCaught()
+ {
+ return isCaught;
+ }
+
+
public void setContainsPackageVisibleMembers()
{
containsPackageVisibleMembers = true;
@@ -110,6 +123,17 @@ public class ClassOptimizationInfo
}
+ public void merge(ClassOptimizationInfo other)
+ {
+ this.isInstantiated |= other.isInstantiated;
+ this.isInstanceofed |= other.isInstanceofed;
+ this.isDotClassed |= other.isDotClassed;
+ this.isCaught |= other.isCaught;
+ this.containsPackageVisibleMembers |= other.containsPackageVisibleMembers;
+ this.invokesPackageVisibleMembers |= other.invokesPackageVisibleMembers;
+ }
+
+
public static void setClassOptimizationInfo(Clazz clazz)
{
clazz.setVisitorInfo(new ClassOptimizationInfo());
diff --git a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
index 5f5cc5b..9cb167c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 08aa6e5..8cbe7f0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 a5c9395..b5f12a7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,7 +78,7 @@ implements InstructionVisitor,
// Small utility methods.
- public static void setDotClassed(Clazz clazz)
+ private static void setDotClassed(Clazz clazz)
{
ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
if (info != null)
diff --git a/src/proguard/optimize/info/ExceptionInstructionChecker.java b/src/proguard/optimize/info/ExceptionInstructionChecker.java
index 1e7e500..2792d90 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/FieldOptimizationInfo.java b/src/proguard/optimize/info/FieldOptimizationInfo.java
index 706ca0a..7a2d068 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/InstanceofClassFilter.java b/src/proguard/optimize/info/InstanceofClassFilter.java
index 68d114c..35e1d77 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 75be332..c60e1f8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 @@ implements InstructionVisitor,
// Small utility methods.
- public static void setInstanceofed(Clazz clazz)
+ private static void setInstanceofed(Clazz clazz)
{
ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
if (info != null)
diff --git a/src/proguard/optimize/info/InstantiationClassFilter.java b/src/proguard/optimize/info/InstantiationClassFilter.java
index e2dbb53..a24e617 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 caf89ad..124c23b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 @@ implements InstructionVisitor,
// Small utility methods.
- public static void setInstantiated(Clazz clazz)
+ private static void setInstantiated(Clazz clazz)
{
ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
if (info != null)
diff --git a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
index 5c1a1fe..a170a8e 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/MethodInvocationMarker.java b/src/proguard/optimize/info/MethodInvocationMarker.java
index 40a2abe..2528c94 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e48f5aa..d3b1bde 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +256,35 @@ public class MethodOptimizationInfo
}
+ public void merge(MethodOptimizationInfo other)
+ {
+ if (other != null)
+ {
+ this.hasNoSideEffects &= other.hasNoSideEffects;
+ this.hasSideEffects |= other.hasSideEffects;
+ //this.canBeMadePrivate &= other.canBeMadePrivate;
+ this.catchesExceptions |= other.catchesExceptions;
+ this.branchesBackward |= other.branchesBackward;
+ this.invokesSuperMethods |= other.invokesSuperMethods;
+ this.accessesPrivateCode |= other.accessesPrivateCode;
+ this.accessesPackageCode |= other.accessesPackageCode;
+ this.accessesProtectedCode |= other.accessesProtectedCode;
+ }
+ else
+ {
+ this.hasNoSideEffects = false;
+ this.hasSideEffects = true;
+ //this.canBeMadePrivate = false;
+ this.catchesExceptions = true;
+ this.branchesBackward = true;
+ this.invokesSuperMethods = true;
+ this.accessesPrivateCode = true;
+ this.accessesPackageCode = true;
+ this.accessesProtectedCode = true;
+ }
+ }
+
+
public static void setMethodOptimizationInfo(Clazz clazz, Method method)
{
MethodLinker.lastMember(method).setVisitorInfo(new MethodOptimizationInfo(clazz, method));
diff --git a/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
index 4840354..5c78408 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 57dcf72..d451643 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/PackageVisibleMemberContainingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
index 9753812..d40bc6b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -49,7 +49,7 @@ implements MemberVisitor
// Small utility methods.
- public static void setPackageVisibleMembers(Clazz clazz)
+ private static void setPackageVisibleMembers(Clazz clazz)
{
ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
if (info != null)
diff --git a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
index 4dde955..9ec8ec6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,7 +63,7 @@ implements ConstantVisitor
// Small utility methods.
- public static void setInvokesPackageVisibleMembers(Clazz clazz)
+ private static void setInvokesPackageVisibleMembers(Clazz clazz)
{
ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
if (info != null)
diff --git a/src/proguard/optimize/info/ParameterUsageMarker.java b/src/proguard/optimize/info/ParameterUsageMarker.java
index 828f190..15ce88a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,14 @@
package proguard.optimize.info;
import proguard.classfile.*;
+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.optimize.evaluation.PartialEvaluator;
+import proguard.evaluation.value.*;
/**
* This MemberVisitor counts the parameters and marks the used parameters
@@ -33,12 +39,40 @@ import proguard.classfile.visitor.MemberVisitor;
*/
public class ParameterUsageMarker
extends SimplifiedVisitor
-implements MemberVisitor
+implements MemberVisitor,
+ AttributeVisitor,
+ InstructionVisitor
{
private static final boolean DEBUG = false;
- private final VariableUsageMarker variableUsageMarker = new VariableUsageMarker();
+ private final boolean markThisParameter;
+ private final boolean markAllParameters;
+ private final PartialEvaluator partialEvaluator = new PartialEvaluator();
+
+
+ /**
+ * Creates a new ParameterUsageMarker.
+ */
+ public ParameterUsageMarker()
+ {
+ this(false, false);
+ }
+
+
+ /**
+ * Creates a new ParameterUsageMarker that optionally marks all parameters.
+ * @param markThisParameter specifies whether all 'this' parameters should
+ * be marked as being used.
+ * @param markAllParameters specifies whether all other parameters should
+ * be marked as being used.
+ */
+ public ParameterUsageMarker(boolean markThisParameter,
+ boolean markAllParameters)
+ {
+ this.markThisParameter = markThisParameter;
+ this.markAllParameters = markAllParameters;
+ }
// Implementations for MemberVisitor.
@@ -51,8 +85,26 @@ implements MemberVisitor
if (parameterSize > 0)
{
- // Is it a native method?
int accessFlags = programMethod.getAccessFlags();
+
+ // Must we mark the 'this' parameter?
+ if (markThisParameter &&
+ (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) == 0)
+ {
+ // Mark the 'this' parameter.
+ markParameterUsed(programMethod, 0);
+ }
+
+ // Must we mark all other parameters?
+ if (markAllParameters)
+ {
+ // Mark all parameters, without the 'this' parameter.
+ markUsedParameters(programMethod,
+ (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0 ?
+ -1L : -2L);
+ }
+
+ // Is it a native method?
if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0)
{
// Mark all parameters.
@@ -80,45 +132,8 @@ implements MemberVisitor
markParameterUsed(programMethod, 0);
}
- // Figure out the local variables that are used by the code.
- programMethod.attributesAccept(programClass, variableUsageMarker);
-
// Mark the parameters that are used by the code.
- for (int index = 0; index < parameterSize; index++)
- {
- if (variableUsageMarker.isVariableUsed(index))
- {
- markParameterUsed(programMethod, index);
- }
- }
-
- // Mark the category 2 parameters that are half-used.
- InternalTypeEnumeration internalTypeEnumeration =
- new InternalTypeEnumeration(programMethod.getDescriptor(programClass));
-
- // All parameters of non-static methods are shifted by one in
- // the local variable frame.
- int index =
- (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0 ?
- 0 : 1;
-
- while (internalTypeEnumeration.hasMoreTypes())
- {
- String type = internalTypeEnumeration.nextType();
- if (ClassUtil.isInternalCategory2Type(type))
- {
- if (variableUsageMarker.isVariableUsed(index) ||
- variableUsageMarker.isVariableUsed(index+1))
- {
- markParameterUsed(programMethod, index);
- markParameterUsed(programMethod, index+1);
- }
-
- index++;
- }
-
- index++;
- }
+ programMethod.attributesAccept(programClass, this);
}
if (DEBUG)
@@ -145,10 +160,54 @@ implements MemberVisitor
{
// All implementations must keep all parameters of this method,
// including the 'this' parameter.
- long usedParameters = -1L;
+ markUsedParameters(libraryMethod, -1L);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Evaluate the code.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Mark the parameters that are used by the code.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // 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 (partialEvaluator.isTraced(offset) &&
+ variableInstruction.isLoad())
+ {
+ int parameterIndex = variableInstruction.variableIndex;
+ if (parameterIndex < codeAttribute.u2maxLocals)
+ {
+ Value producer =
+ partialEvaluator.getVariablesBefore(offset).getProducerValue(parameterIndex);
+ if (producer != null &&
+ producer.instructionOffsetValue().contains(PartialEvaluator.AT_METHOD_ENTRY))
+ {
+ // Mark the variable.
+ markParameterUsed(method, parameterIndex);
- // Mark it.
- markUsedParameters(libraryMethod, usedParameters);
+ // Account for Category 2 instructions, which take up two entries.
+ if (variableInstruction.isCategory2())
+ {
+ markParameterUsed(method, parameterIndex + 1);
+ }
+ }
+ }
}
}
@@ -223,25 +282,4 @@ implements MemberVisitor
MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
return info != null ? info.getUsedParameters() : -1L;
}
-
-
- /**
- * Returns a bit mask of 1-bits of the given size.
- */
- private int parameterMask(int parameterSize)
- {
- return (1 << parameterSize) - 1;
- }
-
-
- /**
- * Returns the parameter size of the given method, including the 'this'
- * parameter, if any.
- */
- private int parameterSize(Clazz clazz, Method method)
- {
-
- return ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz),
- method.getAccessFlags());
- }
}
diff --git a/src/proguard/optimize/info/ReadWriteFieldMarker.java b/src/proguard/optimize/info/ReadWriteFieldMarker.java
index f082cb1..57d8561 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -41,8 +41,8 @@ implements InstructionVisitor,
MemberVisitor
{
// Parameters for the visitor methods.
- private boolean reading;
- private boolean writing;
+ private boolean reading = true;
+ private boolean writing = true;
// Implementations for InstructionVisitor.
diff --git a/src/proguard/optimize/info/SideEffectInstructionChecker.java b/src/proguard/optimize/info/SideEffectInstructionChecker.java
index da69924..8be9dc1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java
index 221c9df..25fda72 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/SuperInvocationMarker.java b/src/proguard/optimize/info/SuperInvocationMarker.java
index 2125f68..6f3d3bd 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 db0e206..660c4ba 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/BranchTargetFinder.java b/src/proguard/optimize/peephole/BranchTargetFinder.java
index 5279b49..8f650bb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ClassFinalizer.java b/src/proguard/optimize/peephole/ClassFinalizer.java
index 00654ee..b5e54f8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,20 +26,16 @@ import proguard.classfile.visitor.*;
import proguard.optimize.KeepMarker;
/**
- * This <code>ClassVisitor</code> and <code>MemberVisitor</code>
- * makes the classes it visits, and their methods, final, if possible.
+ * This <code>ClassVisitor</code> makes the program classes that it visits
+ * final, if possible.
*
* @author Eric Lafortune
*/
public class ClassFinalizer
extends SimplifiedVisitor
-implements ClassVisitor,
- MemberVisitor
+implements ClassVisitor
{
- private final ClassVisitor extraClassVisitor;
- private final MemberVisitor extraMemberVisitor;
-
- private final MemberFinder memberFinder = new MemberFinder();
+ private final ClassVisitor extraClassVisitor;
/**
@@ -47,22 +43,18 @@ implements ClassVisitor,
*/
public ClassFinalizer()
{
- this(null, null);
+ this(null);
}
/**
* Creates a new ClassFinalizer.
- * @param extraClassVisitor an optional extra visitor for all finalized
- * classes.
- * @param extraMemberVisitor an optional extra visitor for all finalized
- * methods.
+ * @param extraClassVisitor an optional extra visitor for all finalized
+ * classes.
*/
- public ClassFinalizer(ClassVisitor extraClassVisitor,
- MemberVisitor extraMemberVisitor)
+ public ClassFinalizer(ClassVisitor extraClassVisitor)
{
- this.extraClassVisitor = extraClassVisitor;
- this.extraMemberVisitor = extraMemberVisitor;
+ this.extraClassVisitor = extraClassVisitor;
}
@@ -88,40 +80,5 @@ implements ClassVisitor,
extraClassVisitor.visitProgramClass(programClass);
}
}
-
- // Check all methods.
- programClass.methodsAccept(this);
- }
-
-
- // Implementations for MemberVisitor.
-
- public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
- {
- String name = programMethod.getName(programClass);
-
- // If the method is not already private/static/final/abstract,
- // and it is not a constructor,
- // and its class is final,
- // or it is not being kept and it is not overridden,
- // then make it final.
- if ((programMethod.u2accessFlags & (ClassConstants.INTERNAL_ACC_PRIVATE |
- ClassConstants.INTERNAL_ACC_STATIC |
- ClassConstants.INTERNAL_ACC_FINAL |
- ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 &&
- !name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) &&
- ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0 ||
- (!KeepMarker.isKept(programMethod) &&
- (programClass.subClasses == null ||
- !memberFinder.isOverriden(programClass, programMethod)))))
- {
- programMethod.u2accessFlags |= ClassConstants.INTERNAL_ACC_FINAL;
-
- // Visit the method, if required.
- if (extraMemberVisitor != null)
- {
- extraMemberVisitor.visitProgramMethod(programClass, programMethod);
- }
- }
}
}
diff --git a/src/proguard/optimize/peephole/ClassMerger.java b/src/proguard/optimize/peephole/ClassMerger.java
index edd95ec..1e1a950 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,8 +35,11 @@ import java.util.*;
* This ClassVisitor inlines the classes that it visits in a given target class,
* whenever possible.
*
+ * @see RetargetedInnerClassAttributeRemover
* @see TargetClassChanger
* @see ClassReferenceFixer
+ * @see MemberReferenceFixer
+ * @see AccessFixer
* @author Eric Lafortune
*/
public class ClassMerger
@@ -185,6 +188,10 @@ implements ClassVisitor,
// that are tested with 'instanceof'.
instanceofedSuperClasses(programClass).equals(instanceofedSuperClasses(targetClass)) &&
+ // The two classes must have the same superclasses that are caught
+ // as exceptions.
+ caughtSuperClasses(programClass).equals(caughtSuperClasses(targetClass)) &&
+
// The two classes must not both be part of a .class construct.
!(DotClassMarker.isDotClassed(programClass) &&
DotClassMarker.isDotClassed(targetClass)) &&
@@ -258,40 +265,16 @@ implements ClassVisitor,
programClass.fieldsAccept(memberAdder);
programClass.methodsAccept(memberAdder);
-// // Delete any inner classes and enclosing method attributes in
-// // both classes.
-// programClass.attributesAccept(
-// new AttributeNameFilter(new FixedStringMatcher(ClassConstants.ATTR_InnerClasses),
-// new ReferencedClassVisitor(
-// new NamedAttributeDeleter())));
-// AttributesEditor attributesEditor =
-// new AttributesEditor(programClass, false);
-// attributesEditor.deleteAttribute(ClassConstants.ATTR_InnerClasses);
-// attributesEditor.deleteAttribute(ClassConstants.ATTR_EnclosingMethod);
-//
-// attributesEditor =
-// new AttributesEditor((ProgramClass)targetClass, false);
-// attributesEditor.deleteAttribute(ClassConstants.ATTR_InnerClasses);
-// attributesEditor.deleteAttribute(ClassConstants.ATTR_EnclosingMethod);
-
// Copy over the other attributes.
programClass.attributesAccept(
new AttributeAdder(targetClass, true));
// Update the optimization information of the target class.
- if (InstantiationClassMarker.isInstantiated(programClass))
- {
- InstantiationClassMarker.setInstantiated(targetClass);
- }
-
- if (InstanceofClassMarker.isInstanceofed(programClass))
+ ClassOptimizationInfo info =
+ ClassOptimizationInfo.getClassOptimizationInfo(targetClass);
+ if (info != null)
{
- InstanceofClassMarker.setInstanceofed(targetClass);
- }
-
- if (DotClassMarker.isDotClassed(programClass))
- {
- DotClassMarker.setDotClassed(targetClass);
+ info.merge(ClassOptimizationInfo.getClassOptimizationInfo(programClass));
}
// Remember to replace the inlined class by the target class.
@@ -381,6 +364,22 @@ implements ClassVisitor,
/**
+ * Returns the set of superclasses that are caught as exceptions.
+ */
+ private Set caughtSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses, collecting the ones that are caught.
+ clazz.hierarchyAccept(true, true, false, false,
+ new CaughtClassFilter(
+ new ClassCollector(set)));
+
+ return set;
+ }
+
+
+ /**
* Returns whether the given class would introduce any unwanted fields
* in the target class.
*/
@@ -406,6 +405,7 @@ implements ClassVisitor,
MemberCounter counter = new MemberCounter();
// TODO: Currently checking shared methods, not just initializers.
+ // TODO: Allow identical methods.
// Visit all methods, counting the ones that are also present in the
// target class.
clazz.methodsAccept(//new MemberNameFilter(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT),
diff --git a/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java b/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
index 3b367c0..4833275 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,9 +123,9 @@ implements AttributeVisitor,
int deleteOffset = offset - delta;
if (branchTargetFinder.isInstruction(deleteOffset))
{
- codeAttributeEditor.replaceInstruction( deleteOffset, null);
- codeAttributeEditor.insertBeforeInstruction(deleteOffset, null);
- codeAttributeEditor.insertAfterInstruction( deleteOffset, null);
+ codeAttributeEditor.replaceInstruction( deleteOffset, (Instruction)null);
+ codeAttributeEditor.insertBeforeInstruction(deleteOffset, (Instruction)null);
+ codeAttributeEditor.insertAfterInstruction( deleteOffset, (Instruction)null);
codeAttributeEditor.deleteInstruction(deleteOffset);
}
diff --git a/src/proguard/optimize/peephole/GotoGotoReplacer.java b/src/proguard/optimize/peephole/GotoGotoReplacer.java
index 4e9f8ed..7d7e66c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/GotoReturnReplacer.java b/src/proguard/optimize/peephole/GotoReturnReplacer.java
index 71d59a7..5c3eb77 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 b1c52cb..a37b9a5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 70dbf99..b33204b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -97,7 +97,7 @@ public class InstructionSequenceConstants
private static final int TYPE_D = 42;
- public static final Constant[] PATTERN_CONSTANTS = new Constant[]
+ public static final Constant[] CONSTANTS = new Constant[]
{
new IntegerConstant(32768),
new IntegerConstant(65536),
@@ -153,8 +153,7 @@ public class InstructionSequenceConstants
};
- public static final Instruction[][][] INSTRUCTION_SEQUENCES =
- new Instruction[][][]
+ public static final Instruction[][][] VARIABLE = new Instruction[][][]
{
{ // nop = nothing
{
@@ -163,6 +162,46 @@ public class InstructionSequenceConstants
// Nothing.
},
},
+ { // iload/pop = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // lload/pop2 = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },{
+ // Nothing.
+ },
+ },
+ { // fload/pop = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // dload/pop2 = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },{
+ // Nothing.
+ },
+ },
+ { // aload/pop = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
{ // i = i = nothing
{
new VariableInstruction(InstructionConstants.OP_ILOAD, X),
@@ -198,7 +237,7 @@ public class InstructionSequenceConstants
{ // a = a = nothing
{
new VariableInstruction(InstructionConstants.OP_ALOAD, X),
- new VariableInstruction(InstructionConstants.OP_ASTORE, X),
+ new SimpleInstruction(InstructionConstants.OP_POP),
},{
// Nothing.
},
@@ -293,6 +332,10 @@ public class InstructionSequenceConstants
new VariableInstruction(InstructionConstants.OP_ASTORE, X),
},
},
+ };
+
+ public static final Instruction[][][] ARITHMETIC = new Instruction[][][]
+ {
{ // c + i = i + c
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
@@ -2083,6 +2126,10 @@ public class InstructionSequenceConstants
// Nothing.
},
},
+ };
+
+ public static final Instruction[][][] FIELD = new Instruction[][][]
+ {
{ // getfield/putfield = nothing
{
new VariableInstruction(InstructionConstants.OP_ALOAD, X),
@@ -2245,6 +2292,10 @@ public class InstructionSequenceConstants
new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, X),
},
},
+ };
+
+ public static final Instruction[][][] CAST = new Instruction[][][]
+ {
{ // (byte)(byte)... = (byte)...
{
new SimpleInstruction(InstructionConstants.OP_I2B),
@@ -2382,6 +2433,10 @@ public class InstructionSequenceConstants
// new SimpleInstruction(InstructionConstants.OP_SASTORE),
// },
// },
+ };
+
+ public static final Instruction[][][] BRANCH = new Instruction[][][]
+ {
{ // goto +3 = nothing
{
new BranchInstruction(InstructionConstants.OP_GOTO, 3),
@@ -2529,7 +2584,7 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFEQ, X),
},
},
- { // if (0 == i) = aload/getfield/ifeq
+ { // if (0 == i) = getfield/ifeq
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
@@ -2559,7 +2614,7 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFNE, X),
},
},
- { // if (0 != i) = iload/ifeq
+ { // if (0 != i) = getstatic/ifeq
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
@@ -2569,7 +2624,7 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFNE, X),
},
},
- { // if (0 != i) = iload/ifeq
+ { // if (0 != i) = getfield/ifeq
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
@@ -2589,6 +2644,14 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLT, X),
},
},
+ { // if (... < 1) = ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
{ // if (0 > i) = iload/iflt
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2599,7 +2662,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLT, X),
},
},
- { // if (0 > i) = iload/iflt
+ { // if (1 > i) = iload/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (0 > i) = getstatic/iflt
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
@@ -2609,7 +2682,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLT, X),
},
},
- { // if (0 > i) = iload/iflt
+ { // if (1 > i) = getstatic/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (0 > i) = getfield/iflt
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
@@ -2621,6 +2704,18 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLT, X),
},
},
+ { // if (1 > i) = getfield/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
{ // if (... >= 0) = ifge
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2629,6 +2724,14 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGE, X),
},
},
+ { // if (... >= 1) = ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
{ // if (0 <= i) = iload/ifge
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2639,7 +2742,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGE, X),
},
},
- { // if (0 <= i) = iload/ifge
+ { // if (1 <= i) = iload/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (0 <= i) = getstatic/ifge
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
@@ -2649,7 +2762,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGE, X),
},
},
- { // if (0 <= i) = iload/ifge
+ { // if (1 <= i) = getstatic/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (0 <= i) = getfield/ifge
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
@@ -2661,6 +2784,18 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGE, X),
},
},
+ { // if (1 <= i) = getfield/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
{ // if (... > 0) = ifgt
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2669,6 +2804,14 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGT, X),
},
},
+ { // if (... > -1) = ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
{ // if (0 < i) = iload/ifgt
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2679,7 +2822,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGT, X),
},
},
- { // if (0 < i) = iload/ifgt
+ { // if (-1 < i) = iload/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (0 < i) = getstatic/ifgt
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
@@ -2689,7 +2842,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGT, X),
},
},
- { // if (0 < i) = iload/ifgt
+ { // if (-1 < i) = getstatic/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (0 < i) = getfield/ifgt
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
@@ -2701,6 +2864,18 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFGT, X),
},
},
+ { // if (-1 < i) = getfield/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
{ // if (... <= 0) = ifle
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2709,6 +2884,14 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLE, X),
},
},
+ { // if (... <= -1) = iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
{ // if (0 >= i) = iload/ifle
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2719,7 +2902,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLE, X),
},
},
- { // if (0 >= i) = iload/ifle
+ { // if (-1 >= i) = iload/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (0 >= i) = getstatic/ifle
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
@@ -2729,7 +2922,17 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLE, X),
},
},
- { // if (0 >= i) = iload/ifle
+ { // if (-1 >= i) = getstatic/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (0 >= i) = getfield/ifle
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
@@ -2741,6 +2944,18 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFLE, X),
},
},
+ { // if (-1 >= i) = getfield/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
{ // if (... == null) = ifnull
{
new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
@@ -2759,7 +2974,7 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFNULL, X),
},
},
- { // if (null == a) = aload/ifnull
+ { // if (null == a) = getstatic/ifnull
{
new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
@@ -2769,7 +2984,7 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFNULL, X),
},
},
- { // if (null == a) = aload/ifnull
+ { // if (null == a) = getfield/ifnull
{
new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
@@ -2799,7 +3014,7 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
},
},
- { // if (null != a) = aload/ifnonnull
+ { // if (null != a) = getstatic/ifnonnull
{
new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
@@ -2809,7 +3024,7 @@ public class InstructionSequenceConstants
new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
},
},
- { // if (null != a) = aload/ifnonnull
+ { // if (null != a) = getfield/ifnonnull
{
new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
diff --git a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
index eae441e..bce06e2 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/InstructionSequencesReplacer.java b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
index 6aab0a4..f12b51a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/LoadStoreRemover.java b/src/proguard/optimize/peephole/LoadStoreRemover.java
deleted file mode 100644
index e1d5d69..0000000
--- a/src/proguard/optimize/peephole/LoadStoreRemover.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is 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.peephole;
-
-import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.editor.CodeAttributeEditor;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
-
-/**
- * This InstructionVisitor deletes load/store instruction pairs.
- *
- * @author Eric Lafortune
- */
-public class LoadStoreRemover
-extends SimplifiedVisitor
-implements InstructionVisitor
-{
- private final BranchTargetFinder branchTargetFinder;
- private final CodeAttributeEditor codeAttributeEditor;
- private final InstructionVisitor extraInstructionVisitor;
-
-
- /**
- * Creates a new LoadStoreRemover.
- * @param branchTargetFinder a branch target finder that has been
- * initialized to indicate branch targets
- * in the visited code.
- * @param codeAttributeEditor a code editor that can be used for
- * accumulating changes to the code.
- */
- public LoadStoreRemover(BranchTargetFinder branchTargetFinder,
- CodeAttributeEditor codeAttributeEditor)
- {
- this(branchTargetFinder, codeAttributeEditor, null);
- }
-
-
- /**
- * Creates a new LoadStoreRemover.
- * @param branchTargetFinder a branch target finder that has been
- * initialized to indicate branch targets
- * in the visited code.
- * @param codeAttributeEditor a code editor that can be used for
- * accumulating changes to the code.
- * @param extraInstructionVisitor an optional extra visitor for all deleted
- * load instructions.
- */
- public LoadStoreRemover(BranchTargetFinder branchTargetFinder,
- CodeAttributeEditor codeAttributeEditor,
- InstructionVisitor extraInstructionVisitor)
- {
- this.branchTargetFinder = branchTargetFinder;
- this.codeAttributeEditor = codeAttributeEditor;
- this.extraInstructionVisitor = extraInstructionVisitor;
- }
-
-
- // Implementations for InstructionVisitor.
-
- public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- // Is this instruction a load instruction?
- if (variableInstruction.isLoad() &&
- variableInstruction.opcode != InstructionConstants.OP_RET)
- {
- int variableIndex = variableInstruction.variableIndex;
-
- int nextOffset = offset + variableInstruction.length(offset);
-
- if (!codeAttributeEditor.isModified(offset) &&
- !codeAttributeEditor.isModified(nextOffset) &&
- !branchTargetFinder.isTarget(nextOffset))
- {
- // Is the next instruction a corresponding store instruction?
- Instruction nextInstruction = InstructionFactory.create(codeAttribute.code,
- nextOffset);
-
- if (nextInstruction instanceof VariableInstruction)
- {
- variableInstruction = (VariableInstruction)nextInstruction;
- if (!variableInstruction.isLoad() &&
- variableInstruction.opcode != InstructionConstants.OP_IINC &&
- variableInstruction.variableIndex == variableIndex)
- {
- // Delete both instructions.
- codeAttributeEditor.deleteInstruction(offset);
- codeAttributeEditor.deleteInstruction(nextOffset);
-
- // Visit the instruction, if required.
- if (extraInstructionVisitor != null)
- {
- extraInstructionVisitor.visitVariableInstruction(clazz, method, codeAttribute, offset, variableInstruction);
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/proguard/optimize/peephole/MemberPrivatizer.java b/src/proguard/optimize/peephole/MemberPrivatizer.java
index ac2185c..55b2f31 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,9 +27,9 @@ import proguard.classfile.visitor.MemberVisitor;
import proguard.optimize.info.NonPrivateMemberMarker;
/**
- * This MemberVisitor makes all class members that it visits private, unless they
- * have been marked by a NonPrivateMemberMarker. The invocations of the
- * privatized method still have to be fixed.
+ * This MemberVisitor makes all class members that it visits private, unless
+ * they have been marked by a NonPrivateMemberMarker. The invocations of
+ * privatized methods still have to be fixed.
*
* @see NonPrivateMemberMarker
* @see MethodInvocationFixer
@@ -39,8 +39,7 @@ public class MemberPrivatizer
extends SimplifiedVisitor
implements MemberVisitor
{
- private final MemberVisitor extraFieldVisitor;
- private final MemberVisitor extraMethodVisitor;
+ private final MemberVisitor extraMemberVisitor;
/**
@@ -48,22 +47,18 @@ implements MemberVisitor
*/
public MemberPrivatizer()
{
- this(null, null);
+ this(null);
}
/**
* Creates a new MemberPrivatizer.
- * @param extraFieldVisitor an optional extra visitor for all privatized
- * fields.
- * @param extraMethodVisitor an optional extra visitor for all privatized
- * methods.
+ * @param extraMemberVisitor an optional extra visitor for all privatized
+ * class members.
*/
- public MemberPrivatizer(MemberVisitor extraFieldVisitor,
- MemberVisitor extraMethodVisitor)
+ public MemberPrivatizer(MemberVisitor extraMemberVisitor)
{
- this.extraFieldVisitor = extraFieldVisitor;
- this.extraMethodVisitor = extraMethodVisitor;
+ this.extraMemberVisitor = extraMemberVisitor;
}
@@ -80,9 +75,9 @@ implements MemberVisitor
ClassConstants.INTERNAL_ACC_PRIVATE);
// Visit the field, if required.
- if (extraFieldVisitor != null)
+ if (extraMemberVisitor != null)
{
- extraFieldVisitor.visitProgramField(programClass, programField);
+ extraMemberVisitor.visitProgramField(programClass, programField);
}
}
}
@@ -99,9 +94,9 @@ implements MemberVisitor
ClassConstants.INTERNAL_ACC_PRIVATE);
// Visit the method, if required.
- if (extraMethodVisitor != null)
+ if (extraMemberVisitor != null)
{
- extraMethodVisitor.visitProgramMethod(programClass, programMethod);
+ extraMemberVisitor.visitProgramMethod(programClass, programMethod);
}
}
}
diff --git a/src/proguard/optimize/peephole/ClassFinalizer.java b/src/proguard/optimize/peephole/MethodFinalizer.java
similarity index 63%
copy from src/proguard/optimize/peephole/ClassFinalizer.java
copy to src/proguard/optimize/peephole/MethodFinalizer.java
index 00654ee..af1811b 100644
--- a/src/proguard/optimize/peephole/ClassFinalizer.java
+++ b/src/proguard/optimize/peephole/MethodFinalizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,17 +26,15 @@ import proguard.classfile.visitor.*;
import proguard.optimize.KeepMarker;
/**
- * This <code>ClassVisitor</code> and <code>MemberVisitor</code>
- * makes the classes it visits, and their methods, final, if possible.
+ * This <code>MemberVisitor</code> makes the program methods that it visits
+ * final, if possible.
*
* @author Eric Lafortune
*/
-public class ClassFinalizer
+public class MethodFinalizer
extends SimplifiedVisitor
-implements ClassVisitor,
- MemberVisitor
+implements MemberVisitor
{
- private final ClassVisitor extraClassVisitor;
private final MemberVisitor extraMemberVisitor;
private final MemberFinder memberFinder = new MemberFinder();
@@ -45,57 +43,25 @@ implements ClassVisitor,
/**
* Creates a new ClassFinalizer.
*/
- public ClassFinalizer()
+ public MethodFinalizer()
{
- this(null, null);
+ this(null);
}
/**
* Creates a new ClassFinalizer.
- * @param extraClassVisitor an optional extra visitor for all finalized
- * classes.
* @param extraMemberVisitor an optional extra visitor for all finalized
* methods.
*/
- public ClassFinalizer(ClassVisitor extraClassVisitor,
- MemberVisitor extraMemberVisitor)
+ public MethodFinalizer(MemberVisitor extraMemberVisitor)
{
- this.extraClassVisitor = extraClassVisitor;
this.extraMemberVisitor = extraMemberVisitor;
}
- // Implementations for ClassVisitor.
-
- public void visitProgramClass(ProgramClass programClass)
- {
- // If the class is not final/interface/abstract,
- // and it is not being kept,
- // and it doesn't have any subclasses,
- // then make it final.
- if ((programClass.u2accessFlags & (ClassConstants.INTERNAL_ACC_FINAL |
- ClassConstants.INTERNAL_ACC_INTERFACE |
- ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 &&
- !KeepMarker.isKept(programClass) &&
- programClass.subClasses == null)
- {
- programClass.u2accessFlags |= ClassConstants.INTERNAL_ACC_FINAL;
-
- // Visit the class, if required.
- if (extraClassVisitor != null)
- {
- extraClassVisitor.visitProgramClass(programClass);
- }
- }
-
- // Check all methods.
- programClass.methodsAccept(this);
- }
-
-
// Implementations for MemberVisitor.
-
+
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
String name = programMethod.getName(programClass);
@@ -124,4 +90,4 @@ implements ClassVisitor,
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/optimize/peephole/MethodInliner.java b/src/proguard/optimize/peephole/MethodInliner.java
index ebb588c..55f9ccb 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -240,7 +240,7 @@ implements AttributeVisitor,
}
}
- codeAttributeComposer.beginCodeFragment((parameterOffset + parameterCount) * 4);
+ codeAttributeComposer.beginCodeFragment(parameterSize+1);
// Go over the parameter types backward, storing the stack entries
// in their corresponding variables.
@@ -300,8 +300,7 @@ implements AttributeVisitor,
{
// The code may expand, due to expanding constant and variable
// instructions.
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength * MAXIMUM_CODE_EXPANSION +
- MAXIMUM_EXTRA_CODE_LENGTH);
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
// Copy the instructions.
codeAttribute.instructionsAccept(clazz, method, this);
@@ -549,6 +548,14 @@ implements AttributeVisitor,
// Inline the method body.
programMethod.attributesAccept(programClass, this);
+ // Update the optimization information of the target method.
+ MethodOptimizationInfo info =
+ MethodOptimizationInfo.getMethodOptimizationInfo(targetMethod);
+ if (info != null)
+ {
+ info.merge(MethodOptimizationInfo.getMethodOptimizationInfo(programMethod));
+ }
+
inlining = oldInlining;
inliningMethods.pop();
}
diff --git a/src/proguard/optimize/peephole/NopRemover.java b/src/proguard/optimize/peephole/NopRemover.java
index 7d5b12d..69adb30 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 9580862..98f8e8d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/PushPopRemover.java b/src/proguard/optimize/peephole/PushPopRemover.java
deleted file mode 100644
index b3d322a..0000000
--- a/src/proguard/optimize/peephole/PushPopRemover.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is 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.peephole;
-
-import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.editor.CodeAttributeEditor;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
-
-/**
- * This InstructionVisitor deletes all push/pop instruction pairs. In this
- * context, push instructions are instructions that push values onto the stack,
- * like dup and load instructions.
- *
- * @author Eric Lafortune
- */
-public class PushPopRemover
-extends SimplifiedVisitor
-implements InstructionVisitor
-{
- private final BranchTargetFinder branchTargetFinder;
- private final CodeAttributeEditor codeAttributeEditor;
- private final InstructionVisitor extraInstructionVisitor;
-
-
- /**
- * Creates a new PushPopRemover.
- * @param branchTargetFinder a branch target finder that has been
- * initialized to indicate branch targets
- * in the visited code.
- * @param codeAttributeEditor a code editor that can be used for
- * accumulating changes to the code.
- */
- public PushPopRemover(BranchTargetFinder branchTargetFinder,
- CodeAttributeEditor codeAttributeEditor)
- {
- this(branchTargetFinder, codeAttributeEditor, null);
- }
-
-
- /**
- * Creates a new PushPopRemover.
- * @param branchTargetFinder a branch target finder that has been
- * initialized to indicate branch targets
- * in the visited code.
- * @param codeAttributeEditor a code editor that can be used for
- * accumulating changes to the code.
- * @param extraInstructionVisitor an optional extra visitor for all deleted
- * push instructions.
- */
- public PushPopRemover(BranchTargetFinder branchTargetFinder,
- CodeAttributeEditor codeAttributeEditor,
- InstructionVisitor extraInstructionVisitor)
- {
- this.branchTargetFinder = branchTargetFinder;
- this.codeAttributeEditor = codeAttributeEditor;
- this.extraInstructionVisitor = extraInstructionVisitor;
- }
-
-
- // Implementations for InstructionVisitor.
-
- public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
-
-
- public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
- {
- switch (simpleInstruction.opcode)
- {
- case InstructionConstants.OP_ICONST_M1:
- case InstructionConstants.OP_ICONST_0:
- case InstructionConstants.OP_ICONST_1:
- case InstructionConstants.OP_ICONST_2:
- case InstructionConstants.OP_ICONST_3:
- case InstructionConstants.OP_ICONST_4:
- case InstructionConstants.OP_ICONST_5:
- case InstructionConstants.OP_LCONST_0:
- case InstructionConstants.OP_LCONST_1:
- case InstructionConstants.OP_FCONST_0:
- case InstructionConstants.OP_FCONST_1:
- case InstructionConstants.OP_FCONST_2:
- case InstructionConstants.OP_DCONST_0:
- case InstructionConstants.OP_DCONST_1:
-
- case InstructionConstants.OP_DUP:
- case InstructionConstants.OP_DUP2:
- case InstructionConstants.OP_BIPUSH:
- case InstructionConstants.OP_SIPUSH:
- case InstructionConstants.OP_LDC:
- case InstructionConstants.OP_LDC_W:
- case InstructionConstants.OP_LDC2_W:
- // All these simple instructions are pushing instructions.
- deleteWithSubsequentPop(clazz, method, codeAttribute, offset, simpleInstruction);
- break;
- }
- }
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- if (variableInstruction.isLoad() &&
- variableInstruction.opcode != InstructionConstants.OP_RET)
- {
- // All load instructions are pushing instructions.
- deleteWithSubsequentPop(clazz, method, codeAttribute, offset, variableInstruction);
- }
- }
-
-
- // Small utility methods.
-
- /**
- * Deletes the given instruction and its subsequent compatible pop instruction,
- * if any, and if the latter is not a branch target.
- */
- private void deleteWithSubsequentPop(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- int offset,
- Instruction instruction)
- {
- boolean isCategory2 = instruction.isCategory2();
-
- int nextOffset = offset + instruction.length(offset);
-
- if (!codeAttributeEditor.isModified(offset) &&
- !codeAttributeEditor.isModified(nextOffset) &&
- !branchTargetFinder.isTarget(nextOffset))
- {
- Instruction nextInstruction = InstructionFactory.create(codeAttribute.code,
- nextOffset);
- int nextOpcode = nextInstruction.opcode;
- if ((nextOpcode == InstructionConstants.OP_POP ||
- nextOpcode == InstructionConstants.OP_POP2) &&
- nextInstruction.isCategory2() == isCategory2)
- {
- // Delete the pushing instruction and the pop instruction.
- codeAttributeEditor.deleteInstruction(offset);
- codeAttributeEditor.deleteInstruction(nextOffset);
-
- // Visit the instruction, if required.
- if (extraInstructionVisitor != null)
- {
- instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor);
- }
- }
- }
- }
-}
diff --git a/src/proguard/optimize/peephole/ReachableCodeMarker.java b/src/proguard/optimize/peephole/ReachableCodeMarker.java
index d9d9048..d9dbf2d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/RetargetedInnerClassAttributeRemover.java b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
index efb9551..6707a12 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/StoreLoadReplacer.java b/src/proguard/optimize/peephole/StoreLoadReplacer.java
deleted file mode 100644
index 9cf58d6..0000000
--- a/src/proguard/optimize/peephole/StoreLoadReplacer.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is 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.peephole;
-
-import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.editor.CodeAttributeEditor;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
-
-/**
- * This InstructionVisitor replaces store/load instruction pairs by equivalent
- * dup/store instruction pairs.
- *
- * @author Eric Lafortune
- */
-public class StoreLoadReplacer
-extends SimplifiedVisitor
-implements InstructionVisitor
-{
- // Some Instruction objects that can be reused.
- private final Instruction dupInstruction = new SimpleInstruction(InstructionConstants.OP_DUP);
- private final Instruction dup2Instruction = new SimpleInstruction(InstructionConstants.OP_DUP2);
-
- private final BranchTargetFinder branchTargetFinder;
- private final CodeAttributeEditor codeAttributeEditor;
- private final InstructionVisitor extraInstructionVisitor;
-
-
- /**
- * Creates a new StoreLoadReplacer.
- * @param branchTargetFinder a branch target finder that has been
- * initialized to indicate branch targets
- * in the visited code.
- * @param codeAttributeEditor a code editor that can be used for
- * accumulating changes to the code.
- */
- public StoreLoadReplacer(BranchTargetFinder branchTargetFinder,
- CodeAttributeEditor codeAttributeEditor)
- {
- this(branchTargetFinder, codeAttributeEditor, null);
- }
-
-
- /**
- * Creates a new StoreLoadReplacer.
- * @param branchTargetFinder a branch target finder that has been
- * initialized to indicate branch targets
- * in the visited code.
- * @param codeAttributeEditor a code editor that can be used for
- * accumulating changes to the code.
- * @param extraInstructionVisitor an optional extra visitor for all replaced
- * store instructions.
- */
- public StoreLoadReplacer(BranchTargetFinder branchTargetFinder,
- CodeAttributeEditor codeAttributeEditor,
- InstructionVisitor extraInstructionVisitor)
- {
- this.branchTargetFinder = branchTargetFinder;
- this.codeAttributeEditor = codeAttributeEditor;
- this.extraInstructionVisitor = extraInstructionVisitor;
- }
-
-
- // Implementations for InstructionVisitor.
-
- public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- // Is this instruction a regular store instruction?
- if (!variableInstruction.isLoad() &&
- variableInstruction.opcode != InstructionConstants.OP_IINC)
- {
- byte opcode = variableInstruction.opcode;
- int variableIndex = variableInstruction.variableIndex;
-
- int nextOffset = offset + variableInstruction.length(offset);
-
- if (!codeAttributeEditor.isModified(offset) &&
- !codeAttributeEditor.isModified(nextOffset) &&
- !branchTargetFinder.isTarget(nextOffset))
- {
- // Is the next instruction a corresponding load instruction?
- Instruction nextInstruction = InstructionFactory.create(codeAttribute.code,
- nextOffset);
-
- if (nextInstruction instanceof VariableInstruction)
- {
- variableInstruction = (VariableInstruction)nextInstruction;
- if (variableInstruction.isLoad() &&
- variableInstruction.opcode != InstructionConstants.OP_RET &&
- variableInstruction.variableIndex == variableIndex)
- {
- // Replace the store instruction by a matching dup instruction.
- Instruction matchingDupInstruction = variableInstruction.isCategory2() ?
- dup2Instruction :
- dupInstruction;
-
- codeAttributeEditor.replaceInstruction(offset,
- matchingDupInstruction);
-
- // Replace the load instruction by the store instruction.
- Instruction storeInstruction =
- new VariableInstruction(opcode,
- variableInstruction.variableIndex).shrink();
-
- codeAttributeEditor.replaceInstruction(nextOffset,
- storeInstruction);
-
- // Visit the instruction, if required.
- if (extraInstructionVisitor != null)
- {
- extraInstructionVisitor.visitVariableInstruction(clazz, method, codeAttribute, offset, variableInstruction);
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/proguard/optimize/peephole/TargetClassChanger.java b/src/proguard/optimize/peephole/TargetClassChanger.java
index 7d590c5..22fd83d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/UnreachableCodeRemover.java b/src/proguard/optimize/peephole/UnreachableCodeRemover.java
index 72ff728..e8a99ab 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 8cf2576..048f5e3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 8ec1998..45b694f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -101,7 +101,7 @@ implements AttributeVisitor
// Delete unused local variables from the local variable frame.
variableEditor.reset(maxLocals);
- for (int variableIndex = parameterSize+1; variableIndex < maxLocals; variableIndex++)
+ for (int variableIndex = parameterSize; variableIndex < maxLocals; variableIndex++)
{
// Is the variable not required?
if (!variableUsageMarker.isVariableUsed(variableIndex))
diff --git a/src/proguard/optimize/peephole/VerticalClassMerger.java b/src/proguard/optimize/peephole/VerticalClassMerger.java
index b0054f8..29ed6ff 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 b6ca1ac..fa60b9a 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,6 +301,7 @@ implements MemberVisitor,
programMethod,
codeAttribute,
offset,
+ index == 0,
value,
producerValue);
@@ -368,6 +369,7 @@ implements MemberVisitor,
programMethod,
codeAttribute,
offset,
+ false,
value,
producerValue);
@@ -391,6 +393,7 @@ implements MemberVisitor,
ProgramMethod programMethod,
CodeAttribute codeAttribute,
int offset,
+ boolean isVariable0,
Value value,
Value producerValue)
{
@@ -433,32 +436,25 @@ implements MemberVisitor,
producerOffset = producers.instructionOffset(0);
}
- // Special case: in an instance initialization method,
- // before the super initialization, loading "this"
- // produces an uninitialized stack entry.
+ // Are we in an instance initialization method,
+ // before the super initialization, loading "this"?
if (partialEvaluator.isInitializer() &&
offset <= partialEvaluator.superInitializationOffset() &&
- producerOffset > PartialEvaluator.AT_METHOD_ENTRY &&
- codeAttribute.code[producerOffset] == InstructionConstants.OP_ALOAD_0)
+ (isVariable0 ||
+ producerOffset > PartialEvaluator.AT_METHOD_ENTRY &&
+ codeAttribute.code[producerOffset] == InstructionConstants.OP_ALOAD_0))
{
- producerOffset = PartialEvaluator.AT_METHOD_ENTRY;
+ // It's an UninitializedThis type.
+ return VerificationTypeFactory.createUninitializedThisType();
}
- // Is the reference type newly created?
- int initializationOffset = producerOffset == PartialEvaluator.AT_METHOD_ENTRY ?
- partialEvaluator.superInitializationOffset() :
- partialEvaluator.initializationOffset(producerOffset);
-
- if (initializationOffset != PartialEvaluator.NONE)
+ // Is the reference type newly created and still
+ // uninitialized?
+ if (producerOffset > PartialEvaluator.AT_METHOD_ENTRY &&
+ offset <= partialEvaluator.initializationOffset(producerOffset))
{
- // Is the reference type still uninitialized?
- if (offset <= initializationOffset)
- {
- // It's an UninitializedThis or Uninitialized type.
- return producerOffset == PartialEvaluator.AT_METHOD_ENTRY ?
- (VerificationType)VerificationTypeFactory.createUninitializedThisType() :
- (VerificationType)VerificationTypeFactory.createUninitializedType(producerOffset);
- }
+ // It's an Uninitialized type.
+ return VerificationTypeFactory.createUninitializedType(producerOffset);
}
}
}
diff --git a/src/proguard/preverify/CodeSubroutineInliner.java b/src/proguard/preverify/CodeSubroutineInliner.java
index cfc2c25..603eb75 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -68,11 +68,32 @@ implements AttributeVisitor,
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
- if (DEBUG)
+ // TODO: Remove this when the subroutine inliner has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
{
- method.accept(clazz, new ClassPrinter());
+ System.err.println("Unexpected error while inlining subroutines:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ if (DEBUG)
+ {
+ method.accept(clazz, new ClassPrinter());
+ }
+
+ throw ex;
}
+ }
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);
// Don't bother if there aren't any subroutines anyway.
@@ -136,11 +157,6 @@ implements AttributeVisitor,
// End and update the code attribute.
codeAttributeComposer.endCodeFragment();
codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
-
- if (DEBUG)
- {
- method.accept(clazz, new ClassPrinter());
- }
}
@@ -368,7 +384,15 @@ implements AttributeVisitor,
if (DEBUG)
{
- System.out.println(" Appending exception ["+startPC+" -> "+endPC+"] -> "+handlerPC);
+ if (startPC == exceptionInfo.u2startPC &&
+ endPC == exceptionInfo.u2endPC)
+ {
+ System.out.println(" Appending exception ["+startPC+" -> "+endPC+"] -> "+handlerPC);
+ }
+ else
+ {
+ System.out.println(" Appending clipped exception ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+"] ~> ["+startPC+" -> "+endPC+"] -> "+handlerPC);
+ }
}
// Append the exception. Note that exceptions with empty try blocks
diff --git a/src/proguard/preverify/Preverifier.java b/src/proguard/preverify/Preverifier.java
index 55e005f..e071c5c 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/SubroutineInliner.java b/src/proguard/preverify/SubroutineInliner.java
index 65d5803..e28512f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/retrace/ReTrace.java b/src/proguard/retrace/ReTrace.java
index 81b0832..97ab27b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,9 +20,12 @@
*/
package proguard.retrace;
-import proguard.obfuscate.MappingReader;
+import proguard.classfile.util.ClassUtil;
+import proguard.obfuscate.*;
import java.io.*;
+import java.util.*;
+import java.util.regex.*;
/**
@@ -32,46 +35,71 @@ import java.io.*;
* @author Eric Lafortune
*/
public class ReTrace
+implements MappingProcessor
{
+ private static final String REGEX_OPTION = "-regex";
private static final String VERBOSE_OPTION = "-verbose";
+ public static final String STACK_TRACE_EXPRESSION = "(?:\\s*%c:.*)|(?:\\s*at\\s+%c.%m\\s*\\(.*?(?::%l)?\\)\\s*)";
+
+ private static final String REGEX_CLASS = "\\b(?:[A-Za-z0-9_$]+\\.)*[A-Za-z0-9_$]+\\b";
+ private static final String REGEX_CLASS_SLASH = "\\b(?:[A-Za-z0-9_$]+/)*[A-Za-z0-9_$]+\\b";
+ private static final String REGEX_LINE_NUMBER = "\\b[0-9]+\\b";
+ private static final String REGEX_TYPE = REGEX_CLASS + "(?:\\[\\])*";
+ private static final String REGEX_MEMBER = "\\b[A-Za-z0-9_$]+\\b";
+ private static final String REGEX_ARGUMENTS = "(?:" + REGEX_TYPE + "(?:\\s*,\\s*" + REGEX_TYPE + ")*)?";
+
// The class settings.
+ private final String regularExpression;
private final boolean verbose;
private final File mappingFile;
private final File stackTraceFile;
+ private Map classMap = new HashMap();
+ private Map classFieldMap = new HashMap();
+ private Map classMethodMap = new HashMap();
+
/**
* Creates a new ReTrace object to process stack traces on the standard
* input, based on the given mapping file name.
- * @param verbose specifies whether the de-obfuscated stack trace
- * should be verbose.
- * @param mappingFile the mapping file that was written out by ProGuard.
+ * @param regularExpression the regular expression for parsing the lines in
+ * the stack trace.
+ * @param verbose specifies whether the de-obfuscated stack trace
+ * should be verbose.
+ * @param mappingFile the mapping file that was written out by
+ * ProGuard.
*/
- public ReTrace(boolean verbose,
+ public ReTrace(String regularExpression,
+ boolean verbose,
File mappingFile)
{
- this(verbose, mappingFile, null);
+ this(regularExpression, verbose, mappingFile, null);
}
/**
* Creates a new ReTrace object to process a stack trace from the given file,
* based on the given mapping file name.
- * @param verbose specifies whether the de-obfuscated stack trace
- * should be verbose.
- * @param mappingFile the mapping file that was written out by ProGuard.
- * @param stackTraceFile the optional name of the file that contains the
- * stack trace.
+ * @param regularExpression the regular expression for parsing the lines in
+ * the stack trace.
+ * @param verbose specifies whether the de-obfuscated stack trace
+ * should be verbose.
+ * @param mappingFile the mapping file that was written out by
+ * ProGuard.
+ * @param stackTraceFile the optional name of the file that contains the
+ * stack trace.
*/
- public ReTrace(boolean verbose,
+ public ReTrace(String regularExpression,
+ boolean verbose,
File mappingFile,
File stackTraceFile)
{
- this.verbose = verbose;
- this.mappingFile = mappingFile;
- this.stackTraceFile = stackTraceFile;
+ this.regularExpression = regularExpression;
+ this.verbose = verbose;
+ this.mappingFile = mappingFile;
+ this.stackTraceFile = stackTraceFile;
}
@@ -80,17 +108,571 @@ public class ReTrace
*/
public void execute() throws IOException
{
- StackTrace stackTrace = new StackTrace(verbose);
- MappingReader reader = new MappingReader(mappingFile);
+ // Read the mapping file.
+ MappingReader mappingReader = new MappingReader(mappingFile);
+ mappingReader.pump(this);
+
+
+ StringBuffer expressionBuffer = new StringBuffer(regularExpression.length() + 32);
+ char[] expressionTypes = new char[32];
+ int expressionTypeCount = 0;
+ int index = 0;
+ while (true)
+ {
+ int nextIndex = regularExpression.indexOf('%', index);
+ if (nextIndex < 0 ||
+ nextIndex == regularExpression.length()-1 ||
+ expressionTypeCount == expressionTypes.length)
+ {
+ break;
+ }
+
+ expressionBuffer.append(regularExpression.substring(index, nextIndex));
+ expressionBuffer.append('(');
+
+ char expressionType = regularExpression.charAt(nextIndex + 1);
+ switch(expressionType)
+ {
+ case 'c':
+ expressionBuffer.append(REGEX_CLASS);
+ break;
+
+ case 'C':
+ expressionBuffer.append(REGEX_CLASS_SLASH);
+ break;
+
+ case 'l':
+ expressionBuffer.append(REGEX_LINE_NUMBER);
+ break;
+
+ case 't':
+ expressionBuffer.append(REGEX_TYPE);
+ break;
+
+ case 'f':
+ expressionBuffer.append(REGEX_MEMBER);
+ break;
+
+ case 'm':
+ expressionBuffer.append(REGEX_MEMBER);
+ break;
+
+ case 'a':
+ expressionBuffer.append(REGEX_ARGUMENTS);
+ break;
+ }
+
+ expressionBuffer.append(')');
+
+ expressionTypes[expressionTypeCount++] = expressionType;
+
+ index = nextIndex + 2;
+ }
+
+ expressionBuffer.append(regularExpression.substring(index));
+
+ Pattern pattern = Pattern.compile(expressionBuffer.toString());
+
+ // Read the stack trace file.
+ LineNumberReader reader =
+ new LineNumberReader(stackTraceFile == null ?
+ (Reader)new InputStreamReader(System.in) :
+ (Reader)new BufferedReader(new FileReader(stackTraceFile)));
+
+
+ try
+ {
+ StringBuffer outLine = new StringBuffer(256);
+ List extraOutLines = new ArrayList();
+
+ String className = null;
+
+ // Read the line in the stack trace.
+ while (true)
+ {
+ String line = reader.readLine();
+ if (line == null)
+ {
+ break;
+ }
+
+ Matcher matcher = pattern.matcher(line);
+
+ if (matcher.matches())
+ {
+ int lineNumber = 0;
+ String type = null;
+ String arguments = null;
+
+ // Figure out a class name, line number, type, and
+ // arguments beforehand.
+ for (int expressionTypeIndex = 0; expressionTypeIndex < expressionTypeCount; expressionTypeIndex++)
+ {
+ int startIndex = matcher.start(expressionTypeIndex + 1);
+ if (startIndex >= 0)
+ {
+ String match = matcher.group(expressionTypeIndex + 1);
+
+ char expressionType = expressionTypes[expressionTypeIndex];
+ switch (expressionType)
+ {
+ case 'c':
+ className = originalClassName(match);
+ break;
+
+ case 'C':
+ className = originalClassName(ClassUtil.externalClassName(match));
+ break;
+
+ case 'l':
+ lineNumber = Integer.parseInt(match);
+ break;
+
+ case 't':
+ type = originalType(match);
+ break;
+
+ case 'a':
+ arguments = originalArguments(match);
+ break;
+ }
+ }
+ }
+
+ // Actually construct the output line.
+ int lineIndex = 0;
+
+ outLine.setLength(0);
+ extraOutLines.clear();
+
+ for (int expressionTypeIndex = 0; expressionTypeIndex < expressionTypeCount; expressionTypeIndex++)
+ {
+ int startIndex = matcher.start(expressionTypeIndex + 1);
+ if (startIndex >= 0)
+ {
+ int endIndex = matcher.end(expressionTypeIndex + 1);
+ String match = matcher.group(expressionTypeIndex + 1);
+
+ // Copy a literal piece of input line.
+ outLine.append(line.substring(lineIndex, startIndex));
+
+ char expressionType = expressionTypes[expressionTypeIndex];
+ switch (expressionType)
+ {
+ case 'c':
+ className = originalClassName(match);
+ outLine.append(className);
+ break;
+
+ case 'C':
+ className = originalClassName(ClassUtil.externalClassName(match));
+ outLine.append(ClassUtil.internalClassName(className));
+ break;
+
+ case 'l':
+ lineNumber = Integer.parseInt(match);
+ outLine.append(match);
+ break;
+
+ case 't':
+ type = originalType(match);
+ outLine.append(type);
+ break;
+
+ case 'f':
+ originalFieldName(className,
+ match,
+ type,
+ outLine,
+ extraOutLines);
+ break;
- // Read the obfuscated stack trace.
- stackTrace.read(stackTraceFile);
+ case 'm':
+ originalMethodName(className,
+ match,
+ lineNumber,
+ type,
+ arguments,
+ outLine,
+ extraOutLines);
+ break;
- // Resolve the obfuscated stack trace by means of the mapping file.
- reader.pump(stackTrace);
+ case 'a':
+ arguments = originalArguments(match);
+ outLine.append(arguments);
+ break;
+ }
- // Print out the resolved stack trace.
- stackTrace.print();
+ // Skip the original element whose processed version
+ // has just been appended.
+ lineIndex = endIndex;
+ }
+ }
+
+ // Copy the last literal piece of input line.
+ outLine.append(line.substring(lineIndex));
+
+ // Print out the main line.
+ System.out.println(outLine);
+
+ // Print out any additional lines.
+ for (int extraLineIndex = 0; extraLineIndex < extraOutLines.size(); extraLineIndex++)
+ {
+ System.out.println(extraOutLines.get(extraLineIndex));
+ }
+ }
+ else
+ {
+ // Print out the original line.
+ System.out.println(line);
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new IOException("Can't read stack trace (" + ex.getMessage() + ")");
+ }
+ finally
+ {
+ if (stackTraceFile != null)
+ {
+ try
+ {
+ reader.close();
+ }
+ catch (IOException ex)
+ {
+ // This shouldn't happen.
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Finds the original field name(s), appending the first one to the out
+ * line, and any additional alternatives to the extra lines.
+ */
+ private void originalFieldName(String className,
+ String obfuscatedFieldName,
+ String type,
+ StringBuffer outLine,
+ List extraOutLines)
+ {
+ int extraIndent = -1;
+
+ // Class name -> obfuscated field names.
+ Map fieldMap = (Map)classFieldMap.get(className);
+ if (fieldMap != null)
+ {
+ // Obfuscated field names -> fields.
+ Set fieldSet = (Set)fieldMap.get(obfuscatedFieldName);
+ if (fieldSet != null)
+ {
+ // Find all matching fields.
+ Iterator fieldInfoIterator = fieldSet.iterator();
+ while (fieldInfoIterator.hasNext())
+ {
+ FieldInfo fieldInfo = (FieldInfo)fieldInfoIterator.next();
+ if (fieldInfo.matches(type))
+ {
+ // Is this the first matching field?
+ if (extraIndent < 0)
+ {
+ extraIndent = outLine.length();
+
+ // Append the first original name.
+ if (verbose)
+ {
+ outLine.append(fieldInfo.type).append(' ');
+ }
+ outLine.append(fieldInfo.originalName);
+ }
+ else
+ {
+ // Create an additional line with the proper
+ // indentation.
+ StringBuffer extraBuffer = new StringBuffer();
+ for (int counter = 0; counter < extraIndent; counter++)
+ {
+ extraBuffer.append(' ');
+ }
+
+ // Append the alternative name.
+ if (verbose)
+ {
+ extraBuffer.append(fieldInfo.type).append(' ');
+ }
+ extraBuffer.append(fieldInfo.originalName);
+
+ // Store the additional line.
+ extraOutLines.add(extraBuffer);
+ }
+ }
+ }
+ }
+ }
+
+ // Just append the obfuscated name if we haven't found any matching
+ // fields.
+ if (extraIndent < 0)
+ {
+ outLine.append(obfuscatedFieldName);
+ }
+ }
+
+
+ /**
+ * Finds the original method name(s), appending the first one to the out
+ * line, and any additional alternatives to the extra lines.
+ */
+ private void originalMethodName(String className,
+ String obfuscatedMethodName,
+ int lineNumber,
+ String type,
+ String arguments,
+ StringBuffer outLine,
+ List extraOutLines)
+ {
+ int extraIndent = -1;
+
+ // Class name -> obfuscated method names.
+ Map methodMap = (Map)classMethodMap.get(className);
+ if (methodMap != null)
+ {
+ // Obfuscated method names -> methods.
+ Set methodSet = (Set)methodMap.get(obfuscatedMethodName);
+ if (methodSet != null)
+ {
+ // Find all matching methods.
+ Iterator methodInfoIterator = methodSet.iterator();
+ while (methodInfoIterator.hasNext())
+ {
+ MethodInfo methodInfo = (MethodInfo)methodInfoIterator.next();
+ if (methodInfo.matches(lineNumber, type, arguments))
+ {
+ // Is this the first matching method?
+ if (extraIndent < 0)
+ {
+ extraIndent = outLine.length();
+
+ // Append the first original name.
+ if (verbose)
+ {
+ outLine.append(methodInfo.type).append(' ');
+ }
+ outLine.append(methodInfo.originalName);
+ if (verbose)
+ {
+ outLine.append('(').append(methodInfo.arguments).append(')');
+ }
+ }
+ else
+ {
+ // Create an additional line with the proper
+ // indentation.
+ StringBuffer extraBuffer = new StringBuffer();
+ for (int counter = 0; counter < extraIndent; counter++)
+ {
+ extraBuffer.append(' ');
+ }
+
+ // Append the alternative name.
+ if (verbose)
+ {
+ extraBuffer.append(methodInfo.type).append(' ');
+ }
+ extraBuffer.append(methodInfo.originalName);
+ if (verbose)
+ {
+ extraBuffer.append('(').append(methodInfo.arguments).append(')');
+ }
+
+ // Store the additional line.
+ extraOutLines.add(extraBuffer);
+ }
+ }
+ }
+ }
+ }
+
+ // Just append the obfuscated name if we haven't found any matching
+ // methods.
+ if (extraIndent < 0)
+ {
+ outLine.append(obfuscatedMethodName);
+ }
+ }
+
+
+ /**
+ * Returns the original argument types.
+ */
+ private String originalArguments(String obfuscatedArguments)
+ {
+ StringBuffer originalArguments = new StringBuffer();
+
+ int startIndex = 0;
+ while (true)
+ {
+ int endIndex = obfuscatedArguments.indexOf(',', startIndex);
+ if (endIndex < 0)
+ {
+ break;
+ }
+
+ originalArguments.append(originalType(obfuscatedArguments.substring(startIndex, endIndex).trim())).append(',');
+
+ startIndex = endIndex + 1;
+ }
+
+ originalArguments.append(originalType(obfuscatedArguments.substring(startIndex).trim()));
+
+ return originalArguments.toString();
+ }
+
+
+ /**
+ * Returns the original type.
+ */
+ private String originalType(String obfuscatedType)
+ {
+ int index = obfuscatedType.indexOf('[');
+
+ return index >= 0 ?
+ originalClassName(obfuscatedType.substring(0, index)) + obfuscatedType.substring(index) :
+ originalClassName(obfuscatedType);
+ }
+
+
+ /**
+ * Returns the original class name.
+ */
+ private String originalClassName(String obfuscatedClassName)
+ {
+ String originalClassName = (String)classMap.get(obfuscatedClassName);
+
+ return originalClassName != null ?
+ originalClassName :
+ obfuscatedClassName;
+ }
+
+
+ // Implementations for MappingProcessor.
+
+ public boolean processClassMapping(String className, String newClassName)
+ {
+ // Obfuscated class name -> original class name.
+ classMap.put(newClassName, className);
+
+ return true;
+ }
+
+
+ public void processFieldMapping(String className, String fieldType, String fieldName, String newFieldName)
+ {
+ // Original class name -> obfuscated field names.
+ Map fieldMap = (Map)classFieldMap.get(className);
+ if (fieldMap == null)
+ {
+ fieldMap = new HashMap();
+ classFieldMap.put(className, fieldMap);
+ }
+
+ // Obfuscated field name -> fields.
+ Set fieldSet = (Set)fieldMap.get(newFieldName);
+ if (fieldSet == null)
+ {
+ fieldSet = new LinkedHashSet();
+ fieldMap.put(newFieldName, fieldSet);
+ }
+
+ // Add the field information.
+ fieldSet.add(new FieldInfo(fieldType,
+ fieldName));
+ }
+
+
+ public void processMethodMapping(String className, int firstLineNumber, int lastLineNumber, String methodReturnType, String methodName, String methodArguments, String newMethodName)
+ {
+ // Original class name -> obfuscated method names.
+ Map methodMap = (Map)classMethodMap.get(className);
+ if (methodMap == null)
+ {
+ methodMap = new HashMap();
+ classMethodMap.put(className, methodMap);
+ }
+
+ // Obfuscated method name -> methods.
+ Set methodSet = (Set)methodMap.get(newMethodName);
+ if (methodSet == null)
+ {
+ methodSet = new LinkedHashSet();
+ methodMap.put(newMethodName, methodSet);
+ }
+
+ // Add the method information.
+ methodSet.add(new MethodInfo(firstLineNumber,
+ lastLineNumber,
+ methodReturnType,
+ methodArguments,
+ methodName));
+ }
+
+
+ /**
+ * A field record.
+ */
+ private static class FieldInfo
+ {
+ private String type;
+ private String originalName;
+
+
+ private FieldInfo(String type, String originalName)
+ {
+ this.type = type;
+ this.originalName = originalName;
+ }
+
+
+ private boolean matches(String type)
+ {
+ return
+ type == null || type.equals(this.type);
+ }
+ }
+
+
+ /**
+ * A method record.
+ */
+ private static class MethodInfo
+ {
+ private int firstLineNumber;
+ private int lastLineNumber;
+ private String type;
+ private String arguments;
+ private String originalName;
+
+
+ private MethodInfo(int firstLineNumber, int lastLineNumber, String type, String arguments, String originalName)
+ {
+ this.firstLineNumber = firstLineNumber;
+ this.lastLineNumber = lastLineNumber;
+ this.type = type;
+ this.arguments = arguments;
+ this.originalName = originalName;
+ }
+
+
+ private boolean matches(int lineNumber, String type, String arguments)
+ {
+ return
+ (lineNumber == 0 || (firstLineNumber <= lineNumber && lineNumber <= lastLineNumber) || lastLineNumber == 0) &&
+ (type == null || type.equals(this.type)) &&
+ (arguments == null || arguments.equals(this.arguments));
+ }
}
@@ -105,19 +687,33 @@ public class ReTrace
System.exit(-1);
}
- int argumentIndex = 0;
+ String regularExpresssion = STACK_TRACE_EXPRESSION;
+ boolean verbose = false;
- boolean verbose = false;
- if (args[argumentIndex].equals(VERBOSE_OPTION))
+ int argumentIndex = 0;
+ while (argumentIndex < args.length)
{
- verbose = true;
- argumentIndex++;
-
- if (args.length < 2)
+ String arg = args[argumentIndex];
+ if (arg.equals(REGEX_OPTION))
+ {
+ regularExpresssion = args[++argumentIndex];
+ }
+ else if (arg.equals(VERBOSE_OPTION))
+ {
+ verbose = true;
+ }
+ else
{
- System.err.println("Usage: java proguard.ReTrace [-verbose] <mapping_file> [<stacktrace_file>]");
- System.exit(-1);
+ break;
}
+
+ argumentIndex++;
+ }
+
+ if (argumentIndex >= args.length)
+ {
+ System.err.println("Usage: java proguard.ReTrace [-regex <regex>] [-verbose] <mapping_file> [<stacktrace_file>]");
+ System.exit(-1);
}
File mappingFile = new File(args[argumentIndex++]);
@@ -125,7 +721,7 @@ public class ReTrace
new File(args[argumentIndex]) :
null;
- ReTrace reTrace = new ReTrace(verbose, mappingFile, stackTraceFile);
+ ReTrace reTrace = new ReTrace(regularExpresssion, verbose, mappingFile, stackTraceFile);
try
{
diff --git a/src/proguard/retrace/StackTrace.java b/src/proguard/retrace/StackTrace.java
deleted file mode 100644
index 791f21a..0000000
--- a/src/proguard/retrace/StackTrace.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is 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.retrace;
-
-import proguard.obfuscate.MappingProcessor;
-
-import java.io.*;
-import java.util.*;
-
-
-/**
- * This class represents an obfuscated stack trace. It can read, de-obfuscate,
- * and then write its contents.
- *
- * @author Eric Lafortune
- */
-final class StackTrace implements MappingProcessor
-{
- // The stack trace settings.
- private final boolean verbose;
-
- // The stack trace items.
- private final List stackTraceItems = new ArrayList();
-
-
- /**
- * Creates a new StackTrace.
- * @param verbose specifies whether the de-obfuscated stack trace should
- * be verbose.
- */
- public StackTrace(boolean verbose)
- {
- this.verbose = verbose;
- }
-
-
- /**
- * Reads the stack trace file.
- */
- public void read(File stackTraceFile) throws IOException
- {
- LineNumberReader lineNumberReader = null;
-
- try
- {
- Reader reader = stackTraceFile == null ?
- (Reader)new InputStreamReader(System.in) :
- (Reader)new BufferedReader(new FileReader(stackTraceFile));
-
- lineNumberReader = new LineNumberReader(reader);
-
- // Read the line in the stack trace.
- while (true)
- {
- String line = lineNumberReader.readLine();
- if (line == null)
- {
- break;
- }
-
- line = line.trim();
- if (line.length() == 0)
- {
- continue;
- }
-
- // Put the line in a stack trace item.
- StackTraceItem item = new StackTraceItem(verbose);
-
- item.parse(line);
-
- stackTraceItems.add(item);
- }
- }
- catch (IOException ex)
- {
- throw new IOException("Can't read stack trace (" + ex.getMessage() + ")");
- }
- finally
- {
- if (stackTraceFile != null &&
- lineNumberReader != null)
- {
- try
- {
- lineNumberReader.close();
- }
- catch (IOException ex)
- {
- // This shouldn't happen.
- }
- }
- }
- }
-
-
- /**
- * Prints out the de-obfuscated stack trace.
- */
- public void print()
- {
- // Delegate to each of the stack trace items.
- for (int index = 0; index < stackTraceItems.size(); index++)
- {
- StackTraceItem item = (StackTraceItem)stackTraceItems.get(index);
-
- item.print();
- }
- }
-
-
- // Implementations for MappingProcessor.
-
- public boolean processClassMapping(String className,
- String newClassName)
- {
- // Delegate to each of the stack trace items.
- boolean present = false;
- for (int index = 0; index < stackTraceItems.size(); index++)
- {
- StackTraceItem item = (StackTraceItem)stackTraceItems.get(index);
-
- present |= item.processClassMapping(className,
- newClassName);
- }
-
- return present;
- }
-
-
- public void processFieldMapping(String className,
- String fieldType,
- String fieldName,
- String newFieldName)
- {
- // A stack trace never contains any fields.
- }
-
-
- public void processMethodMapping(String className,
- int firstLineNumber,
- int lastLineNumber,
- String methodReturnType,
- String methodNameAndArguments,
- String newMethodName)
- {
- // Delegate to each of the stack trace items.
- for (int index = 0; index < stackTraceItems.size(); index++)
- {
- StackTraceItem item = (StackTraceItem)stackTraceItems.get(index);
-
- item.processMethodMapping(className,
- firstLineNumber,
- lastLineNumber,
- methodReturnType,
- methodNameAndArguments,
- newMethodName);
- }
- }
-}
diff --git a/src/proguard/retrace/StackTraceItem.java b/src/proguard/retrace/StackTraceItem.java
deleted file mode 100644
index 16d13ae..0000000
--- a/src/proguard/retrace/StackTraceItem.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is 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.retrace;
-
-import proguard.obfuscate.MappingProcessor;
-
-import java.io.IOException;
-import java.util.*;
-
-
-/**
- * This class represents an obfuscated stack trace item. It can read, de-obfuscate,
- * and then write its contents.
- *
- * @author Eric Lafortune
- */
-final class StackTraceItem implements MappingProcessor
-{
- // The stack trace settings.
- private final boolean verbose;
-
- public String prefix;
- public String obfuscatedClassName;
- public String obfuscatedMethodName;
- public String sourceFile;
- public int lineNumber;
- public String suffix;
-
- public String originalClassName;
- public List originalMethodNames;
-
- /**
- * Creates a new StackTraceItem.
- * @param verbose specifies whether the de-obfuscated stack trace should
- * be verbose.
- */
- public StackTraceItem(boolean verbose)
- {
- this.verbose = verbose;
- }
-
-
- /**
- * Parses the stack trace
- */
- public void parse(String line) throws IOException
- {
- if (!parseAtLine(line) &&
- !parseExceptionInThreadLine(line))
- {
- parseAnyLine(line);
- }
- }
-
-
- /**
- * Tries to parse "at ___.___(___:___)", containing the class name,
- * the method name, the source file, and the optional line number.
- */
- private boolean parseAtLine(String line)
- {
- if (!line.startsWith("at "))
- {
- return false;
- }
-
- int openParenthesisIndex = line.indexOf('(', 3);
- if (openParenthesisIndex < 0)
- {
- return false;
- }
-
- int colonIndex = line.indexOf(':', openParenthesisIndex + 1);
-
- int closeParenthesisIndex = line.indexOf(')', Math.max(openParenthesisIndex, colonIndex) + 1);
- if (closeParenthesisIndex < 0)
- {
- return false;
- }
-
- int periodIndex = line.lastIndexOf('.', openParenthesisIndex - 1);
- if (periodIndex < 0)
- {
- return false;
- }
-
- prefix = " at ";
- obfuscatedClassName = line.substring(3, periodIndex).trim();
- obfuscatedMethodName = line.substring(periodIndex + 1, openParenthesisIndex).trim();
- sourceFile = line.substring(openParenthesisIndex + 1, colonIndex < 0 ? closeParenthesisIndex : colonIndex).trim();
- lineNumber = colonIndex < 0 ? 0 : Integer.parseInt(line.substring(colonIndex + 1, closeParenthesisIndex).trim());
-
- return true;
- }
-
-
- /**
- * Tries to parse "Exception in thread "___" ___:___" or just "___:___",
- * containing the optional thread name, the exception class name and the
- * exception message.
- */
- private boolean parseExceptionInThreadLine(String line)
- {
- // Trim away the thread message part, if any.
- if (line.startsWith("Exception in thread \""))
- {
- int quote_index = line.indexOf('"', 21);
- if (quote_index < 0)
- {
- return false;
- }
-
- prefix = line.substring(0, quote_index+1) + " ";
- line = line.substring(quote_index+1).trim();
- }
-
- int colonIndex = line.indexOf(':');
- if (colonIndex < 0)
- {
- return false;
- }
-
- int spaceIndex = line.lastIndexOf(' ', colonIndex);
-
- prefix = line.substring(0, spaceIndex+1);
- obfuscatedClassName = line.substring(spaceIndex+1, colonIndex).trim();
- suffix = line.substring(colonIndex);
-
- return true;
- }
-
-
- /**
- * Parses any line.
- */
- private void parseAnyLine(String line)
- {
- prefix = line;
- }
-
-
- /**
- * Prints out the de-obfuscated stack trace.
- */
- public void print()
- {
- // Get the original class name, if we found it.
- String className = originalClassName != null ?
- originalClassName :
- obfuscatedClassName;
-
- // Get the first original method name, if we found it.
- String methodName = originalMethodNames != null ?
- (String)originalMethodNames.get(0) :
- obfuscatedMethodName;
-
- // Compose the source file with the line number, if any.
- String source = lineNumber != 0 ?
- sourceFile + ":" + lineNumber :
- sourceFile;
-
- // Print out the resolved stack trace.
- System.out.print(prefix);
-
- if (className != null)
- {
- System.out.print(className);
-
- if (methodName != null)
- {
- System.out.print("." + methodName + "(" + source + ")");
-
- // Print out alternatives, if any.
- if (originalMethodNames != null)
- {
- for (int otherMethodNameIndex = 1; otherMethodNameIndex < originalMethodNames.size(); otherMethodNameIndex++) {
- String otherMethodName = (String)originalMethodNames.get(otherMethodNameIndex);
- System.out.println();
- printSpaces(className.length()+12);
- System.out.print(otherMethodName);
- }
- }
- }
-
- if (suffix != null)
- {
- System.out.print(suffix);
- }
- }
-
- System.out.println();
- }
-
-
- /**
- * Prints the given number of spaces.
- */
- private void printSpaces(int aCount)
- {
- for (int counter = 0; counter < aCount; counter++)
- System.out.print(' ');
- }
-
-
- // Implementations for MappingProcessor.
-
- public boolean processClassMapping(String className,
- String newClassName)
- {
- boolean present = false;
-
- if (newClassName.equals(obfuscatedClassName))
- {
- originalClassName = className;
- present = true;
- }
-
- return present;
- }
-
-
- public void processFieldMapping(String className,
- String fieldType,
- String fieldName,
- String newFieldName)
- {
- // A stack trace item never contains any fields.
- }
-
-
- public void processMethodMapping(String className,
- int firstLineNumber,
- int lastLineNumber,
- String methodReturnType,
- String methodNameAndArguments,
- String newMethodName)
- {
- if (className.equals(originalClassName) &&
- newMethodName.equals(obfuscatedMethodName) &&
- (lineNumber == 0 ||
- firstLineNumber == 0 ||
- lastLineNumber == 0 ||
- (firstLineNumber <= lineNumber &&
- lastLineNumber >= lineNumber)))
- {
- // Create a List for storing solutions for this
- // method name.
- if (originalMethodNames == null)
- {
- originalMethodNames = new ArrayList();
- }
-
- // Does the method have line numbers?
- if (firstLineNumber != 0 &&
- lastLineNumber != 0 &&
- lineNumber != 0)
- {
- // Then it will be the one and only solution.
- obfuscatedMethodName = null;
- originalMethodNames.clear();
- }
-
- // Include return type and arguments in the method name if
- // we're in verbose mode, otherwise strip the arguments.
- String originalMethodName = verbose ?
- (methodReturnType + " " + methodNameAndArguments) :
- methodNameAndArguments.substring(0, methodNameAndArguments.indexOf('('));
-
- // Add this method name solution to the list.
- originalMethodNames.add(originalMethodName);
- }
- }
-}
diff --git a/src/proguard/shrink/AnnotationUsageMarker.java b/src/proguard/shrink/AnnotationUsageMarker.java
index e4222d2..9aaae34 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ClassShrinker.java b/src/proguard/shrink/ClassShrinker.java
index 024a091..0b5c5b7 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/InnerUsageMarker.java b/src/proguard/shrink/InnerUsageMarker.java
index 2448ad3..b8ca801 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 921e974..7599898 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 bbac60b..757c713 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f1855ff..da8fad3 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 4045f12..db42fe1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 2d35059..edbc27f 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/UsageMarker.java b/src/proguard/shrink/UsageMarker.java
index b2bed5f..e913046 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/UsagePrinter.java b/src/proguard/shrink/UsagePrinter.java
index 35cd1df..294b9e1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 563eecc..ec180bd 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 9738415..755cfd1 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/AndMatcher.java b/src/proguard/util/AndMatcher.java
index 6f645fa..94a37e5 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 4ae3f1b..ee972f0 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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/ConstantMatcher.java
similarity index 71%
copy from src/proguard/util/NotMatcher.java
copy to src/proguard/util/ConstantMatcher.java
index 4c11c99..1764caa 100644
--- a/src/proguard/util/NotMatcher.java
+++ b/src/proguard/util/ConstantMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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,19 +21,21 @@
package proguard.util;
/**
- * This StringMatcher tests whether strings does not match the given
- * StringMatcher.
+ * This StringMatcher matches any string or no string at all.
*
* @author Eric Lafortune
*/
-public class NotMatcher implements StringMatcher
+public class ConstantMatcher implements StringMatcher
{
- private final StringMatcher matcher;
+ private boolean matches;
- public NotMatcher(StringMatcher matcher)
+ /**
+ * Creates a new ConstantMatcher that always returns the given result.
+ */
+ public ConstantMatcher(boolean matches)
{
- this.matcher = matcher;
+ this.matches = matches;
}
@@ -41,6 +43,6 @@ public class NotMatcher implements StringMatcher
public boolean matches(String string)
{
- return !matcher.matches(string);
+ return matches;
}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/util/EmptyStringMatcher.java b/src/proguard/util/EmptyStringMatcher.java
index 3ff5dfc..543f446 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e12da2b..5a9f658 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 2c34fa0..913f22d 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 de94763..c1eb3f4 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 c573fe3..b2559c8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 f411319..cec803b 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -37,6 +37,10 @@ public class ListParser implements StringParser
private final StringParser stringParser;
+ /**
+ * Creates a new ListParser that parses individual elements in the
+ * comma-separated list with the given StringParser.
+ */
public ListParser(StringParser stringParser)
{
this.stringParser = stringParser;
@@ -52,11 +56,11 @@ public class ListParser implements StringParser
}
- // Small utility methods.
-
/**
* Creates a StringMatcher for the given regular expression, which can
* be a list of optionally negated simple entries.
+ * <p>
+ * An empty list results in a StringMatcher that matches any string.
*/
public StringMatcher parse(List regularExpressions)
{
@@ -79,10 +83,12 @@ public class ListParser implements StringParser
(StringMatcher)new OrMatcher(entryMatcher, listMatcher);
}
- return listMatcher;
+ return listMatcher != null ? listMatcher : new ConstantMatcher(true);
}
+ // Small utility methods.
+
/**
* Creates a StringMatcher for the given regular expression, which is a
* an optionally negated simple expression.
diff --git a/src/proguard/util/ListUtil.java b/src/proguard/util/ListUtil.java
index 37aae61..570dbe8 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is 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 ListUtil
buffer.append(',');
}
- buffer.append(list.get(index));
+ buffer.append(quotedString((String)list.get(index)));
}
return buffer.toString();
@@ -69,19 +69,105 @@ public class ListUtil
List list = new ArrayList();
int index = 0;
- while (index < string.length())
+ while ((index = skipWhitespace(string, index)) < string.length())
{
- int nextIndex = string.indexOf(',', index);
- if (nextIndex < 0)
+ int nextIndex;
+
+ // Do we have an opening quote?
+ if (string.charAt(index) == '\'')
{
- nextIndex = string.length();
+ // Parse a quoted string.
+ nextIndex = string.indexOf('\'', index + 1);
+ if (nextIndex < 0)
+ {
+ nextIndex = string.length();
+ }
+
+ list.add(string.substring(index + 1, nextIndex));
}
+ else
+ {
+ // Parse a non-quoted string.
+ nextIndex = string.indexOf(',', index);
+ if (nextIndex < 0)
+ {
+ nextIndex = string.length();
+ }
- list.add(string.substring(index, nextIndex).trim());
+ String substring = string.substring(index, nextIndex).trim();
+ if (substring.length() > 0)
+ {
+ list.add(substring);
+ }
+ }
index = nextIndex + 1;
}
return list;
}
+
+
+ /**
+ * Skips any whitespace characters.
+ */
+ private static int skipWhitespace(String string, int index)
+ {
+ while (index < string.length() &&
+ Character.isWhitespace(string.charAt(index)))
+ {
+ index++;
+ }
+ return index;
+ }
+
+
+ /**
+ * Returns a quoted version of the given string, if necessary.
+ */
+ private static String quotedString(String string)
+ {
+ return string.length() == 0 ||
+ string.indexOf(' ') >= 0 ||
+ string.indexOf('@') >= 0 ||
+ string.indexOf('{') >= 0 ||
+ string.indexOf('}') >= 0 ||
+ string.indexOf('(') >= 0 ||
+ string.indexOf(')') >= 0 ||
+ string.indexOf(':') >= 0 ||
+ string.indexOf(';') >= 0 ||
+ string.indexOf(',') >= 0 ? ("'" + string + "'") :
+ ( string );
+ }
+
+
+ public static void main(String[] args)
+ {
+ if (args.length == 1)
+ {
+ System.out.println("Input string: ["+args[0]+"]");
+
+ List list = commaSeparatedList(args[0]);
+
+ System.out.println("Resulting list:");
+ for (int index = 0; index < list.size(); index++)
+ {
+ System.out.println("["+list.get(index)+"]");
+ }
+ }
+ else
+ {
+ List list = Arrays.asList(args);
+
+ System.out.println("Input list:");
+ for (int index = 0; index < list.size(); index++)
+ {
+ System.out.println("["+list.get(index)+"]");
+ }
+
+ String string = commaSeparatedString(list);
+
+ System.out.println("Resulting string: ["+string+"]");
+ }
+ }
}
diff --git a/src/proguard/util/NameParser.java b/src/proguard/util/NameParser.java
index beda426..e311fbf 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 4c11c99..f2a9a51 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 2a8e625..097c6c6 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 c7ab5c2..9557f62 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 57a9f10..bd66dcc 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 6d635ba..29f4f16 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 526ab4f..1e41323 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute 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 e8665b5..4618437 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-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2009 Eric Lafortune (eric at graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/proguard.git
More information about the pkg-java-commits
mailing list