aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrint E. Kriebel <bekit@cyngn.com>2014-09-29 17:19:43 -0700
committerBrint E. Kriebel <bekit@cyngn.com>2014-09-29 17:19:43 -0700
commitb64a23b7cc2761f03879ceb6b030ae80171f11e2 (patch)
tree86ba49fd1b7275a7e293c3c3bc44e6317bebf67f
parentfe926bab25e3af81265d4e0bbb79bcdb41b10635 (diff)
parent9961286c06c25cd03464d3e2b00bd9b9dedf96ba (diff)
downloadandroid_external_proguard-stable/cm-11.0-XNF9X.tar.gz
android_external_proguard-stable/cm-11.0-XNF9X.tar.bz2
android_external_proguard-stable/cm-11.0-XNF9X.zip
-rw-r--r--Android.mk1
-rw-r--r--README2
-rw-r--r--bin/proguard.bat6
-rwxr-xr-xbin/proguard.sh9
-rw-r--r--bin/proguardgui.bat6
-rwxr-xr-xbin/proguardgui.sh12
-rw-r--r--bin/retrace.bat6
-rwxr-xr-xbin/retrace.sh9
-rw-r--r--build/README40
-rw-r--r--build/build.properties4
-rwxr-xr-xbuild/build.sh16
-rw-r--r--build/build.xml117
-rw-r--r--build/makefile27
-rw-r--r--build/maven/ant/pom.xml78
-rw-r--r--build/maven/base/pom.xml69
-rw-r--r--build/maven/gradle/pom.xml85
-rw-r--r--build/maven/gui/pom.xml78
-rw-r--r--build/maven/pom.xml162
-rw-r--r--build/maven/retrace/pom.xml61
-rw-r--r--build/maven/wtk/pom.xml79
-rw-r--r--docs/FAQ.html203
-rw-r--r--docs/GPL_exception.html21
-rw-r--r--docs/acknowledgements.html72
-rw-r--r--docs/alternatives.html780
-rw-r--r--docs/android_shades.pngbin0 -> 2726 bytes
-rw-r--r--docs/dexguard.pngbin0 -> 5331 bytes
-rw-r--r--docs/downloads.html222
-rw-r--r--docs/feedback.html86
-rw-r--r--docs/index.html48
-rw-r--r--docs/license.html28
-rw-r--r--docs/luciadlogo.pngbin2356 -> 0 bytes
-rw-r--r--docs/main.html78
-rw-r--r--docs/manual/android_small.pngbin0 -> 1106 bytes
-rw-r--r--docs/manual/ant.html110
-rw-r--r--docs/manual/examples.html667
-rw-r--r--docs/manual/gradle.html545
-rw-r--r--docs/manual/gui.html209
-rw-r--r--docs/manual/index.html45
-rw-r--r--docs/manual/introduction.html100
-rw-r--r--docs/manual/limitations.html57
-rw-r--r--docs/manual/optimizations.html50
-rw-r--r--docs/manual/refcard.html51
-rw-r--r--docs/manual/retrace/examples.html37
-rw-r--r--docs/manual/retrace/index.html26
-rw-r--r--docs/manual/retrace/introduction.html21
-rw-r--r--docs/manual/retrace/usage.html31
-rw-r--r--docs/manual/sections.html34
-rw-r--r--docs/manual/style.css69
-rw-r--r--docs/manual/troubleshooting.html417
-rw-r--r--docs/manual/usage.html379
-rw-r--r--docs/manual/wtk.html22
-rw-r--r--docs/quality.html22
-rw-r--r--docs/results.html32
-rw-r--r--docs/saikoalogo.pngbin0 -> 2901 bytes
-rw-r--r--docs/sanawarelogo.pngbin8552 -> 0 bytes
-rw-r--r--docs/screenshots.html27
-rw-r--r--docs/sections.html47
-rw-r--r--docs/style.css16
-rw-r--r--docs/testimonials.html73
-rw-r--r--docs/title.html6
-rw-r--r--examples/android.pro174
-rw-r--r--examples/annotations/examples.pro3
-rw-r--r--examples/annotations/lib/annotations.jarbin6123 -> 6126 bytes
-rw-r--r--examples/ant/applets.xml15
-rw-r--r--examples/ant/applications1.xml2
-rw-r--r--examples/ant/applications2.xml16
-rw-r--r--examples/ant/applications3.xml18
-rw-r--r--examples/ant/midlets.xml15
-rw-r--r--examples/ant/proguard.xml25
-rw-r--r--examples/ant/servlets.xml15
-rw-r--r--examples/applets.pro21
-rw-r--r--examples/applications.pro25
-rw-r--r--[-rwxr-xr-x]examples/dictionaries/shakespeare.txt0
-rw-r--r--examples/gradle/android.gradle195
-rw-r--r--examples/gradle/applets.gradle90
-rw-r--r--examples/gradle/applications.gradle96
-rw-r--r--examples/gradle/library.gradle99
-rw-r--r--examples/gradle/midlets.gradle88
-rw-r--r--examples/gradle/proguard.gradle91
-rw-r--r--examples/gradle/proguardall.gradle93
-rw-r--r--examples/gradle/proguardgui.gradle72
-rw-r--r--examples/gradle/retrace.gradle64
-rw-r--r--examples/gradle/scala.gradle153
-rw-r--r--examples/gradle/servlets.gradle91
-rw-r--r--examples/library.pro3
-rw-r--r--examples/midlets.pro23
-rw-r--r--examples/proguard.pro19
-rw-r--r--examples/proguardall.pro14
-rw-r--r--examples/proguardgui.pro10
-rw-r--r--examples/scala.pro132
-rw-r--r--examples/servlets.pro21
-rw-r--r--lib/proguard.jarbin664512 -> 742666 bytes
-rw-r--r--lib/proguardgui.jarbin137516 -> 138885 bytes
-rw-r--r--lib/retrace.jarbin7556 -> 6974 bytes
-rw-r--r--src/proguard/ArgumentWordReader.java7
-rw-r--r--src/proguard/ClassPath.java2
-rw-r--r--src/proguard/ClassPathEntry.java137
-rw-r--r--src/proguard/ClassSpecification.java2
-rw-r--r--src/proguard/ClassSpecificationVisitorFactory.java5
-rw-r--r--src/proguard/Configuration.java16
-rw-r--r--src/proguard/ConfigurationConstants.java4
-rw-r--r--src/proguard/ConfigurationParser.java300
-rw-r--r--src/proguard/ConfigurationWriter.java44
-rw-r--r--src/proguard/DataEntryReaderFactory.java24
-rw-r--r--src/proguard/DataEntryWriterFactory.java26
-rw-r--r--src/proguard/DescriptorKeepChecker.java62
-rw-r--r--src/proguard/DuplicateClassPrinter.java2
-rw-r--r--src/proguard/FileWordReader.java52
-rw-r--r--src/proguard/FullyQualifiedClassNameChecker.java9
-rw-r--r--src/proguard/GPL.java18
-rw-r--r--src/proguard/Initializer.java109
-rw-r--r--src/proguard/InputReader.java6
-rw-r--r--src/proguard/KeepClassMemberChecker.java88
-rw-r--r--src/proguard/KeepClassSpecification.java2
-rw-r--r--src/proguard/LineWordReader.java74
-rw-r--r--src/proguard/MemberSpecification.java2
-rw-r--r--src/proguard/OutputWriter.java66
-rw-r--r--src/proguard/ParseException.java2
-rw-r--r--src/proguard/ProGuard.java73
-rw-r--r--src/proguard/SeedPrinter.java97
-rw-r--r--src/proguard/SubclassedClassFilter.java2
-rw-r--r--src/proguard/Targeter.java2
-rw-r--r--src/proguard/UpToDateChecker.java219
-rw-r--r--src/proguard/WordReader.java127
-rw-r--r--src/proguard/ant/ClassPathElement.java2
-rw-r--r--src/proguard/ant/ClassSpecificationElement.java3
-rw-r--r--src/proguard/ant/ConfigurationElement.java101
-rw-r--r--src/proguard/ant/ConfigurationTask.java18
-rw-r--r--src/proguard/ant/FilterElement.java2
-rw-r--r--src/proguard/ant/KeepSpecificationElement.java20
-rw-r--r--src/proguard/ant/MemberSpecificationElement.java7
-rw-r--r--src/proguard/ant/ProGuardTask.java49
-rw-r--r--src/proguard/ant/task.properties4
-rw-r--r--src/proguard/classfile/ClassConstants.java126
-rw-r--r--src/proguard/classfile/ClassPool.java30
-rw-r--r--src/proguard/classfile/Clazz.java31
-rw-r--r--src/proguard/classfile/Field.java2
-rw-r--r--src/proguard/classfile/LibraryClass.java61
-rw-r--r--src/proguard/classfile/LibraryField.java2
-rw-r--r--src/proguard/classfile/LibraryMember.java2
-rw-r--r--src/proguard/classfile/LibraryMethod.java2
-rw-r--r--src/proguard/classfile/Member.java2
-rw-r--r--src/proguard/classfile/Method.java2
-rw-r--r--src/proguard/classfile/ProgramClass.java92
-rw-r--r--src/proguard/classfile/ProgramField.java2
-rw-r--r--src/proguard/classfile/ProgramMember.java32
-rw-r--r--src/proguard/classfile/ProgramMethod.java2
-rw-r--r--src/proguard/classfile/VisitorAccepter.java2
-rw-r--r--src/proguard/classfile/attribute/Attribute.java2
-rwxr-xr-xsrc/proguard/classfile/attribute/BootstrapMethodInfo.java89
-rwxr-xr-xsrc/proguard/classfile/attribute/BootstrapMethodsAttribute.java95
-rw-r--r--src/proguard/classfile/attribute/CodeAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/ConstantValueAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/DeprecatedAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/EnclosingMethodAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/ExceptionInfo.java2
-rw-r--r--src/proguard/classfile/attribute/ExceptionsAttribute.java8
-rw-r--r--src/proguard/classfile/attribute/InnerClassesAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/InnerClassesInfo.java11
-rw-r--r--src/proguard/classfile/attribute/LineNumberInfo.java2
-rw-r--r--src/proguard/classfile/attribute/LineNumberTableAttribute.java52
-rw-r--r--src/proguard/classfile/attribute/LocalVariableInfo.java40
-rw-r--r--src/proguard/classfile/attribute/LocalVariableTableAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/LocalVariableTypeInfo.java40
-rw-r--r--src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SignatureAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SourceDirAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SourceFileAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/SyntheticAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/UnknownAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/Annotation.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/AnnotationElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/ArrayElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/ClassElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/ConstantElementValue.java16
-rw-r--r--src/proguard/classfile/attribute/annotation/ElementValue.java4
-rw-r--r--src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java45
-rw-r--r--src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java7
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java201
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java3
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/DoubleType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/FloatType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/FullFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/IntegerType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/LessZeroFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/LongType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/MoreZeroFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/NullType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/ObjectType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/SameOneFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/SameZeroFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/StackMapAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/StackMapFrame.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/TopType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/UninitializedThisType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/UninitializedType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/VerificationType.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java55
-rw-r--r--src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java55
-rw-r--r--src/proguard/classfile/attribute/visitor/AttributeNameFilter.java67
-rw-r--r--src/proguard/classfile/attribute/visitor/AttributeVisitor.java13
-rwxr-xr-xsrc/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java40
-rw-r--r--src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java2
-rw-r--r--src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java11
-rw-r--r--src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java293
-rw-r--r--src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java17
-rw-r--r--src/proguard/classfile/attribute/visitor/StackSizeComputer.java9
-rw-r--r--src/proguard/classfile/constant/ClassConstant.java2
-rw-r--r--src/proguard/classfile/constant/Constant.java2
-rw-r--r--src/proguard/classfile/constant/DoubleConstant.java2
-rw-r--r--src/proguard/classfile/constant/FieldrefConstant.java2
-rw-r--r--src/proguard/classfile/constant/FloatConstant.java2
-rw-r--r--src/proguard/classfile/constant/IntegerConstant.java2
-rw-r--r--src/proguard/classfile/constant/InterfaceMethodrefConstant.java2
-rwxr-xr-xsrc/proguard/classfile/constant/InvokeDynamicConstant.java148
-rw-r--r--src/proguard/classfile/constant/LongConstant.java2
-rwxr-xr-xsrc/proguard/classfile/constant/MethodHandleConstant.java124
-rw-r--r--src/proguard/classfile/constant/MethodTypeConstant.java93
-rw-r--r--src/proguard/classfile/constant/MethodrefConstant.java2
-rw-r--r--src/proguard/classfile/constant/NameAndTypeConstant.java2
-rw-r--r--src/proguard/classfile/constant/RefConstant.java2
-rw-r--r--src/proguard/classfile/constant/StringConstant.java2
-rw-r--r--src/proguard/classfile/constant/Utf8Constant.java2
-rw-r--r--src/proguard/classfile/constant/visitor/AllConstantVisitor.java2
-rw-r--r--src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java100
-rw-r--r--src/proguard/classfile/constant/visitor/ConstantTagFilter.java86
-rw-r--r--src/proguard/classfile/constant/visitor/ConstantVisitor.java5
-rw-r--r--src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java12
-rw-r--r--src/proguard/classfile/constant/visitor/MethodrefTraveler.java (renamed from src/proguard/classfile/visitor/ClassForNameClassVisitor.java)32
-rw-r--r--src/proguard/classfile/editor/AccessFixer.java28
-rw-r--r--src/proguard/classfile/editor/AnnotationAdder.java2
-rw-r--r--src/proguard/classfile/editor/AnnotationsAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/AttributeAdder.java22
-rw-r--r--src/proguard/classfile/editor/AttributeSorter.java2
-rw-r--r--src/proguard/classfile/editor/AttributesEditor.java2
-rw-r--r--src/proguard/classfile/editor/BridgeMethodFixer.java117
-rw-r--r--src/proguard/classfile/editor/ClassEditor.java2
-rw-r--r--src/proguard/classfile/editor/ClassElementSorter.java2
-rw-r--r--src/proguard/classfile/editor/ClassMemberSorter.java2
-rw-r--r--src/proguard/classfile/editor/ClassReferenceFixer.java2
-rw-r--r--src/proguard/classfile/editor/CodeAttributeComposer.java269
-rw-r--r--src/proguard/classfile/editor/CodeAttributeEditor.java400
-rw-r--r--src/proguard/classfile/editor/CodeAttributeEditorResetter.java2
-rw-r--r--src/proguard/classfile/editor/ComparableConstant.java83
-rw-r--r--src/proguard/classfile/editor/ConstantAdder.java47
-rw-r--r--src/proguard/classfile/editor/ConstantPoolEditor.java119
-rw-r--r--src/proguard/classfile/editor/ConstantPoolRemapper.java107
-rw-r--r--src/proguard/classfile/editor/ConstantPoolShrinker.java578
-rw-r--r--src/proguard/classfile/editor/ConstantPoolSorter.java7
-rw-r--r--src/proguard/classfile/editor/ElementValueAdder.java2
-rw-r--r--src/proguard/classfile/editor/ElementValuesEditor.java2
-rw-r--r--src/proguard/classfile/editor/ExceptionAdder.java2
-rw-r--r--src/proguard/classfile/editor/ExceptionInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/ExceptionsAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/InnerClassesAccessFixer.java83
-rw-r--r--src/proguard/classfile/editor/InstructionAdder.java4
-rw-r--r--src/proguard/classfile/editor/InstructionWriter.java60
-rw-r--r--src/proguard/classfile/editor/InterfaceAdder.java2
-rw-r--r--src/proguard/classfile/editor/InterfaceSorter.java119
-rw-r--r--src/proguard/classfile/editor/InterfacesEditor.java2
-rw-r--r--src/proguard/classfile/editor/LineNumberInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/LineNumberTableAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java2
-rw-r--r--src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/MemberAdder.java147
-rw-r--r--src/proguard/classfile/editor/MemberReferenceFixer.java39
-rw-r--r--src/proguard/classfile/editor/MethodInvocationFixer.java65
-rw-r--r--src/proguard/classfile/editor/NameAndTypeShrinker.java (renamed from src/proguard/obfuscate/NameAndTypeUsageMarker.java)101
-rw-r--r--src/proguard/classfile/editor/NamedAttributeDeleter.java2
-rw-r--r--src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java2
-rw-r--r--src/proguard/classfile/editor/StackSizeUpdater.java2
-rw-r--r--src/proguard/classfile/editor/SubclassAdder.java2
-rw-r--r--src/proguard/classfile/editor/SubclassToAdder.java2
-rw-r--r--src/proguard/classfile/editor/Utf8Shrinker.java (renamed from src/proguard/obfuscate/Utf8UsageMarker.java)81
-rw-r--r--src/proguard/classfile/editor/VariableCleaner.java208
-rw-r--r--src/proguard/classfile/editor/VariableEditor.java11
-rw-r--r--src/proguard/classfile/editor/VariableRemapper.java77
-rw-r--r--src/proguard/classfile/editor/VariableSizeUpdater.java13
-rw-r--r--src/proguard/classfile/instruction/BranchInstruction.java5
-rw-r--r--src/proguard/classfile/instruction/ConstantInstruction.java36
-rw-r--r--src/proguard/classfile/instruction/Instruction.java12
-rw-r--r--src/proguard/classfile/instruction/InstructionConstants.java36
-rw-r--r--src/proguard/classfile/instruction/InstructionFactory.java3
-rw-r--r--src/proguard/classfile/instruction/InstructionUtil.java2
-rw-r--r--src/proguard/classfile/instruction/LookUpSwitchInstruction.java2
-rw-r--r--src/proguard/classfile/instruction/SimpleInstruction.java6
-rw-r--r--src/proguard/classfile/instruction/SwitchInstruction.java2
-rw-r--r--src/proguard/classfile/instruction/TableSwitchInstruction.java2
-rw-r--r--src/proguard/classfile/instruction/VariableInstruction.java6
-rw-r--r--src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java2
-rw-r--r--src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java65
-rw-r--r--src/proguard/classfile/instruction/visitor/InstructionCounter.java2
-rw-r--r--src/proguard/classfile/instruction/visitor/InstructionVisitor.java2
-rw-r--r--src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java2
-rw-r--r--src/proguard/classfile/io/LibraryClassReader.java25
-rw-r--r--src/proguard/classfile/io/ProgramClassReader.java81
-rw-r--r--src/proguard/classfile/io/ProgramClassWriter.java53
-rw-r--r--src/proguard/classfile/io/RuntimeDataInput.java2
-rw-r--r--src/proguard/classfile/io/RuntimeDataOutput.java2
-rw-r--r--src/proguard/classfile/util/AccessUtil.java2
-rw-r--r--src/proguard/classfile/util/ClassReferenceInitializer.java137
-rw-r--r--src/proguard/classfile/util/ClassSubHierarchyInitializer.java2
-rw-r--r--src/proguard/classfile/util/ClassSuperHierarchyInitializer.java7
-rw-r--r--src/proguard/classfile/util/ClassUtil.java85
-rw-r--r--src/proguard/classfile/util/DescriptorClassEnumeration.java2
-rw-r--r--src/proguard/classfile/util/DynamicClassReferenceInitializer.java21
-rw-r--r--src/proguard/classfile/util/DynamicMemberReferenceInitializer.java485
-rw-r--r--src/proguard/classfile/util/EnumFieldReferenceInitializer.java150
-rw-r--r--src/proguard/classfile/util/ExternalTypeEnumeration.java2
-rw-r--r--src/proguard/classfile/util/InstructionSequenceMatcher.java182
-rw-r--r--src/proguard/classfile/util/InternalTypeEnumeration.java4
-rw-r--r--src/proguard/classfile/util/MemberFinder.java2
-rw-r--r--src/proguard/classfile/util/MethodLinker.java19
-rw-r--r--src/proguard/classfile/util/SimplifiedVisitor.java28
-rw-r--r--src/proguard/classfile/util/StringReferenceInitializer.java5
-rw-r--r--src/proguard/classfile/util/StringSharer.java21
-rw-r--r--src/proguard/classfile/util/WarningPrinter.java2
-rw-r--r--src/proguard/classfile/visitor/AllClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/AllFieldVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/AllMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/AllMethodVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/BottomClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassAccessFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassCleaner.java2
-rw-r--r--src/proguard/classfile/visitor/ClassCollector.java2
-rw-r--r--src/proguard/classfile/visitor/ClassCounter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassHierarchyTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/ClassNameFilter.java4
-rw-r--r--src/proguard/classfile/visitor/ClassPoolFiller.java2
-rw-r--r--src/proguard/classfile/visitor/ClassPoolVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ClassPresenceFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassPrinter.java70
-rw-r--r--src/proguard/classfile/visitor/ClassVersionFilter.java15
-rw-r--r--src/proguard/classfile/visitor/ClassVersionSetter.java2
-rw-r--r--src/proguard/classfile/visitor/ClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ConcreteClassDownTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/DotClassClassVisitor.java4
-rw-r--r--src/proguard/classfile/visitor/ExceptClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptClassesFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionCounter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionHandlerFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionOffsetFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ExceptionRangeFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ImplementedClassConstantFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ImplementedClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ImplementingClassConstantFilter.java2
-rw-r--r--src/proguard/classfile/visitor/LibraryClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/LibraryMemberFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberAccessFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberClassAccessFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberCollector.java2
-rw-r--r--src/proguard/classfile/visitor/MemberCounter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberDescriptorFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MemberNameFilter.java5
-rw-r--r--src/proguard/classfile/visitor/MemberToClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MethodImplementationFilter.java2
-rw-r--r--src/proguard/classfile/visitor/MethodImplementationTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/MultiClassPoolVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MultiClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/MultiMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/NamedClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/NamedFieldVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/NamedMethodVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/ProgramClassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ProgramMemberFilter.java2
-rw-r--r--src/proguard/classfile/visitor/ReferencedClassVisitor.java9
-rw-r--r--src/proguard/classfile/visitor/ReferencedMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/SimilarMemberVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/SimpleClassPrinter.java2
-rw-r--r--src/proguard/classfile/visitor/SubclassFilter.java2
-rw-r--r--src/proguard/classfile/visitor/SubclassTraveler.java2
-rw-r--r--src/proguard/classfile/visitor/VariableClassVisitor.java2
-rw-r--r--src/proguard/classfile/visitor/VariableMemberVisitor.java2
-rw-r--r--src/proguard/evaluation/BasicBranchUnit.java2
-rw-r--r--src/proguard/evaluation/BasicInvocationUnit.java47
-rw-r--r--src/proguard/evaluation/BranchUnit.java2
-rw-r--r--src/proguard/evaluation/ClassConstantValueFactory.java53
-rw-r--r--src/proguard/evaluation/ConstantValueFactory.java113
-rw-r--r--src/proguard/evaluation/InvocationUnit.java2
-rw-r--r--src/proguard/evaluation/Processor.java101
-rw-r--r--src/proguard/evaluation/Stack.java9
-rw-r--r--src/proguard/evaluation/TracedStack.java2
-rw-r--r--src/proguard/evaluation/TracedVariables.java32
-rw-r--r--src/proguard/evaluation/Variables.java9
-rw-r--r--src/proguard/evaluation/value/Category1Value.java2
-rw-r--r--src/proguard/evaluation/value/Category2Value.java2
-rw-r--r--src/proguard/evaluation/value/ComparisonValue.java10
-rw-r--r--src/proguard/evaluation/value/CompositeDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/CompositeFloatValue.java10
-rw-r--r--src/proguard/evaluation/value/CompositeIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/CompositeLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedByteValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedCharacterValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedFloatValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ConvertedShortValue.java2
-rw-r--r--src/proguard/evaluation/value/DoubleValue.java7
-rw-r--r--src/proguard/evaluation/value/FloatValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedFloatValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedLongValue.java2
-rw-r--r--src/proguard/evaluation/value/IdentifiedReferenceValue.java13
-rw-r--r--src/proguard/evaluation/value/IdentifiedValueFactory.java2
-rw-r--r--src/proguard/evaluation/value/InstructionOffsetValue.java2
-rw-r--r--src/proguard/evaluation/value/IntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/LongValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedFloatValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/NegatedLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ParticularDoubleValue.java25
-rw-r--r--src/proguard/evaluation/value/ParticularFloatValue.java23
-rw-r--r--src/proguard/evaluation/value/ParticularIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/ParticularLongValue.java2
-rw-r--r--src/proguard/evaluation/value/ReferenceValue.java40
-rw-r--r--src/proguard/evaluation/value/SpecificDoubleValue.java11
-rw-r--r--src/proguard/evaluation/value/SpecificFloatValue.java11
-rw-r--r--src/proguard/evaluation/value/SpecificIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/SpecificLongValue.java2
-rw-r--r--src/proguard/evaluation/value/SpecificValueFactory.java14
-rw-r--r--src/proguard/evaluation/value/TopValue.java2
-rw-r--r--src/proguard/evaluation/value/UnknownDoubleValue.java2
-rw-r--r--src/proguard/evaluation/value/UnknownFloatValue.java4
-rw-r--r--src/proguard/evaluation/value/UnknownIntegerValue.java2
-rw-r--r--src/proguard/evaluation/value/UnknownLongValue.java2
-rw-r--r--src/proguard/evaluation/value/Value.java2
-rw-r--r--src/proguard/evaluation/value/ValueFactory.java2
-rw-r--r--src/proguard/gradle/ProGuardTask.java1532
-rw-r--r--src/proguard/gui/ClassPathPanel.java8
-rw-r--r--src/proguard/gui/ClassSpecificationDialog.java22
-rw-r--r--src/proguard/gui/ClassSpecificationsPanel.java2
-rw-r--r--src/proguard/gui/ExtensionFileFilter.java2
-rw-r--r--src/proguard/gui/FilterBuilder.java2
-rw-r--r--src/proguard/gui/FilterDialog.java12
-rw-r--r--src/proguard/gui/GUIResources.java2
-rw-r--r--src/proguard/gui/GUIResources.properties48
-rw-r--r--src/proguard/gui/KeepSpecificationsPanel.java2
-rw-r--r--src/proguard/gui/ListPanel.java2
-rw-r--r--src/proguard/gui/MemberSpecificationDialog.java14
-rw-r--r--src/proguard/gui/MemberSpecificationsPanel.java2
-rw-r--r--src/proguard/gui/MessageDialogRunnable.java2
-rw-r--r--src/proguard/gui/OptimizationsDialog.java2
-rw-r--r--src/proguard/gui/ProGuardGUI.java179
-rw-r--r--src/proguard/gui/ProGuardRunnable.java2
-rw-r--r--src/proguard/gui/ReTraceRunnable.java2
-rw-r--r--src/proguard/gui/SwingUtil.java2
-rw-r--r--src/proguard/gui/TabbedPane.java2
-rw-r--r--src/proguard/gui/TextAreaOutputStream.java2
-rw-r--r--src/proguard/gui/boilerplate.pro26
-rw-r--r--src/proguard/gui/default.pro26
-rw-r--r--src/proguard/gui/splash/BufferedSprite.java2
-rw-r--r--src/proguard/gui/splash/CircleSprite.java2
-rw-r--r--src/proguard/gui/splash/ClipSprite.java2
-rw-r--r--src/proguard/gui/splash/ColorSprite.java2
-rw-r--r--src/proguard/gui/splash/CompositeSprite.java2
-rw-r--r--src/proguard/gui/splash/ConstantColor.java2
-rw-r--r--src/proguard/gui/splash/ConstantDouble.java2
-rw-r--r--src/proguard/gui/splash/ConstantFont.java2
-rw-r--r--src/proguard/gui/splash/ConstantInt.java2
-rw-r--r--src/proguard/gui/splash/ConstantString.java2
-rw-r--r--src/proguard/gui/splash/ConstantTiming.java2
-rw-r--r--src/proguard/gui/splash/FontSprite.java2
-rw-r--r--src/proguard/gui/splash/ImageSprite.java2
-rw-r--r--src/proguard/gui/splash/LinearColor.java2
-rw-r--r--src/proguard/gui/splash/LinearDouble.java2
-rw-r--r--src/proguard/gui/splash/LinearInt.java2
-rw-r--r--src/proguard/gui/splash/LinearTiming.java2
-rw-r--r--src/proguard/gui/splash/OverrideGraphics2D.java2
-rw-r--r--src/proguard/gui/splash/RectangleSprite.java2
-rw-r--r--src/proguard/gui/splash/SawToothTiming.java2
-rw-r--r--src/proguard/gui/splash/ShadowedSprite.java2
-rw-r--r--src/proguard/gui/splash/SineTiming.java2
-rw-r--r--src/proguard/gui/splash/SmoothTiming.java2
-rw-r--r--src/proguard/gui/splash/SplashPanel.java2
-rw-r--r--src/proguard/gui/splash/Sprite.java2
-rw-r--r--src/proguard/gui/splash/TextSprite.java2
-rw-r--r--src/proguard/gui/splash/TimeSwitchSprite.java2
-rw-r--r--src/proguard/gui/splash/Timing.java2
-rw-r--r--src/proguard/gui/splash/TypeWriterString.java2
-rw-r--r--src/proguard/gui/splash/VariableColor.java2
-rw-r--r--src/proguard/gui/splash/VariableDouble.java2
-rw-r--r--src/proguard/gui/splash/VariableFont.java2
-rw-r--r--src/proguard/gui/splash/VariableInt.java2
-rw-r--r--src/proguard/gui/splash/VariableSizeFont.java2
-rw-r--r--src/proguard/gui/splash/VariableString.java2
-rw-r--r--src/proguard/io/CascadingDataEntryWriter.java2
-rw-r--r--src/proguard/io/ClassFilter.java2
-rw-r--r--src/proguard/io/ClassReader.java4
-rw-r--r--src/proguard/io/ClassRewriter.java2
-rw-r--r--src/proguard/io/DataEntry.java2
-rw-r--r--src/proguard/io/DataEntryClassWriter.java85
-rw-r--r--src/proguard/io/DataEntryCopier.java21
-rw-r--r--src/proguard/io/DataEntryDirectoryFilter.java2
-rw-r--r--src/proguard/io/DataEntryFilter.java2
-rw-r--r--src/proguard/io/DataEntryNameFilter.java2
-rw-r--r--src/proguard/io/DataEntryObfuscator.java47
-rw-r--r--src/proguard/io/DataEntryParentFilter.java2
-rw-r--r--src/proguard/io/DataEntryPump.java2
-rw-r--r--src/proguard/io/DataEntryReader.java2
-rw-r--r--src/proguard/io/DataEntryRenamer.java6
-rw-r--r--src/proguard/io/DataEntryRewriter.java2
-rw-r--r--src/proguard/io/DataEntryWriter.java2
-rw-r--r--src/proguard/io/DirectoryFilter.java2
-rw-r--r--src/proguard/io/DirectoryPump.java2
-rw-r--r--src/proguard/io/DirectoryWriter.java2
-rw-r--r--src/proguard/io/FileDataEntry.java2
-rw-r--r--src/proguard/io/FilteredDataEntryReader.java2
-rw-r--r--src/proguard/io/FilteredDataEntryWriter.java2
-rw-r--r--src/proguard/io/Finisher.java2
-rw-r--r--src/proguard/io/JarReader.java2
-rw-r--r--src/proguard/io/JarWriter.java2
-rw-r--r--src/proguard/io/ManifestRewriter.java57
-rw-r--r--src/proguard/io/NameFilter.java2
-rw-r--r--src/proguard/io/ParentDataEntryWriter.java2
-rw-r--r--src/proguard/io/RenamedDataEntry.java2
-rw-r--r--src/proguard/io/ZipDataEntry.java2
-rw-r--r--src/proguard/obfuscate/AttributeShrinker.java9
-rw-r--r--src/proguard/obfuscate/AttributeUsageMarker.java4
-rw-r--r--src/proguard/obfuscate/ClassObfuscator.java24
-rw-r--r--src/proguard/obfuscate/ClassRenamer.java2
-rw-r--r--src/proguard/obfuscate/DictionaryNameFactory.java2
-rw-r--r--src/proguard/obfuscate/MapCleaner.java2
-rw-r--r--src/proguard/obfuscate/MappingKeeper.java2
-rw-r--r--src/proguard/obfuscate/MappingPrinter.java42
-rw-r--r--src/proguard/obfuscate/MappingProcessor.java2
-rw-r--r--src/proguard/obfuscate/MappingReader.java2
-rw-r--r--src/proguard/obfuscate/MemberNameCleaner.java2
-rw-r--r--src/proguard/obfuscate/MemberNameCollector.java2
-rw-r--r--src/proguard/obfuscate/MemberNameConflictFixer.java2
-rw-r--r--src/proguard/obfuscate/MemberNameFilter.java120
-rw-r--r--src/proguard/obfuscate/MemberObfuscator.java2
-rw-r--r--src/proguard/obfuscate/MemberSpecialNameFilter.java12
-rw-r--r--src/proguard/obfuscate/MultiMappingProcessor.java2
-rw-r--r--src/proguard/obfuscate/NameAndTypeShrinker.java112
-rw-r--r--src/proguard/obfuscate/NameFactory.java2
-rw-r--r--src/proguard/obfuscate/NameFactoryResetter.java2
-rw-r--r--src/proguard/obfuscate/NameMarker.java2
-rw-r--r--src/proguard/obfuscate/NumericNameFactory.java2
-rw-r--r--src/proguard/obfuscate/Obfuscator.java105
-rw-r--r--src/proguard/obfuscate/ParameterNameMarker.java128
-rw-r--r--src/proguard/obfuscate/SimpleNameFactory.java2
-rw-r--r--src/proguard/obfuscate/SourceFileRenamer.java2
-rw-r--r--src/proguard/obfuscate/SpecialNameFactory.java2
-rw-r--r--src/proguard/obfuscate/Utf8Shrinker.java110
-rw-r--r--src/proguard/optimize/BootstrapMethodArgumentShrinker.java103
-rw-r--r--src/proguard/optimize/ChangedCodePrinter.java8
-rw-r--r--src/proguard/optimize/ConstantMemberFilter.java2
-rw-r--r--src/proguard/optimize/ConstantParameterFilter.java2
-rw-r--r--src/proguard/optimize/DuplicateInitializerFixer.java34
-rw-r--r--src/proguard/optimize/DuplicateInitializerInvocationFixer.java37
-rw-r--r--src/proguard/optimize/KeepMarker.java12
-rw-r--r--src/proguard/optimize/KeptClassFilter.java69
-rw-r--r--src/proguard/optimize/KeptMemberFilter.java87
-rw-r--r--src/proguard/optimize/MemberDescriptorSpecializer.java4
-rw-r--r--src/proguard/optimize/MethodDescriptorShrinker.java12
-rw-r--r--src/proguard/optimize/MethodStaticizer.java2
-rw-r--r--src/proguard/optimize/OptimizationInfoMemberFilter.java2
-rw-r--r--src/proguard/optimize/Optimizer.java197
-rw-r--r--src/proguard/optimize/ParameterShrinker.java4
-rw-r--r--src/proguard/optimize/TailRecursionSimplifier.java109
-rw-r--r--src/proguard/optimize/WriteOnlyFieldFilter.java2
-rw-r--r--src/proguard/optimize/evaluation/EvaluationShrinker.java1260
-rw-r--r--src/proguard/optimize/evaluation/EvaluationSimplifier.java58
-rw-r--r--src/proguard/optimize/evaluation/LivenessAnalyzer.java12
-rw-r--r--src/proguard/optimize/evaluation/LoadingInvocationUnit.java20
-rw-r--r--src/proguard/optimize/evaluation/PartialEvaluator.java166
-rw-r--r--src/proguard/optimize/evaluation/StoringInvocationUnit.java2
-rw-r--r--src/proguard/optimize/evaluation/TracedBranchUnit.java2
-rw-r--r--src/proguard/optimize/evaluation/VariableOptimizer.java139
-rw-r--r--src/proguard/optimize/info/AccessMethodMarker.java19
-rw-r--r--src/proguard/optimize/info/BackwardBranchMarker.java2
-rw-r--r--src/proguard/optimize/info/CatchExceptionMarker.java2
-rw-r--r--src/proguard/optimize/info/CaughtClassFilter.java2
-rw-r--r--src/proguard/optimize/info/CaughtClassMarker.java7
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfo.java16
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfoSetter.java2
-rw-r--r--src/proguard/optimize/info/DotClassFilter.java2
-rw-r--r--src/proguard/optimize/info/DotClassMarker.java2
-rw-r--r--src/proguard/optimize/info/ExceptionInstructionChecker.java104
-rw-r--r--src/proguard/optimize/info/FieldOptimizationInfo.java56
-rw-r--r--src/proguard/optimize/info/InstanceofClassFilter.java2
-rw-r--r--src/proguard/optimize/info/InstanceofClassMarker.java2
-rw-r--r--src/proguard/optimize/info/InstantiationClassFilter.java2
-rw-r--r--src/proguard/optimize/info/InstantiationClassMarker.java2
-rw-r--r--src/proguard/optimize/info/MemberOptimizationInfoSetter.java18
-rw-r--r--src/proguard/optimize/info/MethodInvocationMarker.java2
-rw-r--r--src/proguard/optimize/info/MethodOptimizationInfo.java6
-rw-r--r--src/proguard/optimize/info/NoSideEffectMethodMarker.java4
-rw-r--r--src/proguard/optimize/info/NonPrivateMemberMarker.java16
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java28
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java72
-rw-r--r--src/proguard/optimize/info/ParameterUsageMarker.java8
-rw-r--r--src/proguard/optimize/info/ReadWriteFieldMarker.java2
-rw-r--r--src/proguard/optimize/info/SideEffectInstructionChecker.java239
-rw-r--r--src/proguard/optimize/info/SideEffectMethodFilter.java73
-rw-r--r--src/proguard/optimize/info/SideEffectMethodMarker.java22
-rw-r--r--src/proguard/optimize/info/StaticInitializerContainingClassFilter.java62
-rw-r--r--src/proguard/optimize/info/StaticInitializerContainingClassMarker.java65
-rw-r--r--src/proguard/optimize/info/SuperInvocationMarker.java2
-rw-r--r--src/proguard/optimize/info/VariableUsageMarker.java11
-rw-r--r--src/proguard/optimize/peephole/BranchTargetFinder.java279
-rw-r--r--src/proguard/optimize/peephole/ClassFinalizer.java2
-rw-r--r--src/proguard/optimize/peephole/ClassMerger.java160
-rw-r--r--src/proguard/optimize/peephole/GotoCommonCodeReplacer.java11
-rw-r--r--src/proguard/optimize/peephole/GotoGotoReplacer.java7
-rw-r--r--src/proguard/optimize/peephole/GotoReturnReplacer.java2
-rw-r--r--src/proguard/optimize/peephole/HorizontalClassMerger.java2
-rw-r--r--src/proguard/optimize/peephole/InstructionSequenceConstants.java1899
-rw-r--r--src/proguard/optimize/peephole/InstructionSequenceReplacer.java166
-rw-r--r--src/proguard/optimize/peephole/InstructionSequencesReplacer.java2
-rw-r--r--src/proguard/optimize/peephole/MemberPrivatizer.java2
-rw-r--r--src/proguard/optimize/peephole/MethodFinalizer.java2
-rw-r--r--src/proguard/optimize/peephole/MethodInliner.java142
-rw-r--r--src/proguard/optimize/peephole/NopRemover.java2
-rw-r--r--src/proguard/optimize/peephole/PeepholeOptimizer.java2
-rw-r--r--src/proguard/optimize/peephole/ReachableCodeMarker.java9
-rw-r--r--src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java46
-rw-r--r--src/proguard/optimize/peephole/TargetClassChanger.java62
-rw-r--r--src/proguard/optimize/peephole/UnreachableCodeRemover.java2
-rw-r--r--src/proguard/optimize/peephole/UnreachableExceptionRemover.java2
-rw-r--r--src/proguard/optimize/peephole/VariableShrinker.java2
-rw-r--r--src/proguard/optimize/peephole/VerticalClassMerger.java2
-rw-r--r--src/proguard/preverify/CodePreverifier.java30
-rw-r--r--src/proguard/preverify/CodeSubroutineInliner.java32
-rw-r--r--src/proguard/preverify/Preverifier.java7
-rw-r--r--src/proguard/preverify/SubroutineInliner.java3
-rw-r--r--src/proguard/retrace/ReTrace.java9
-rw-r--r--src/proguard/shrink/AnnotationUsageMarker.java76
-rw-r--r--src/proguard/shrink/ClassShrinker.java73
-rw-r--r--src/proguard/shrink/InnerUsageMarker.java2
-rw-r--r--src/proguard/shrink/InterfaceUsageMarker.java2
-rw-r--r--src/proguard/shrink/LocalVariableTypeUsageMarker.java178
-rw-r--r--src/proguard/shrink/ShortestUsageMark.java2
-rw-r--r--src/proguard/shrink/ShortestUsageMarker.java2
-rw-r--r--src/proguard/shrink/ShortestUsagePrinter.java56
-rw-r--r--src/proguard/shrink/Shrinker.java43
-rw-r--r--src/proguard/shrink/SignatureUsageMarker.java117
-rw-r--r--src/proguard/shrink/UsageMarker.java250
-rw-r--r--src/proguard/shrink/UsagePrinter.java46
-rw-r--r--src/proguard/shrink/UsedClassFilter.java2
-rw-r--r--src/proguard/shrink/UsedMemberFilter.java4
-rw-r--r--src/proguard/util/AndMatcher.java2
-rw-r--r--src/proguard/util/ArrayUtil.java960
-rw-r--r--src/proguard/util/ClassNameParser.java2
-rw-r--r--src/proguard/util/ConstantMatcher.java2
-rw-r--r--src/proguard/util/EmptyStringMatcher.java2
-rw-r--r--src/proguard/util/ExtensionMatcher.java2
-rw-r--r--src/proguard/util/FileNameParser.java2
-rw-r--r--src/proguard/util/FixedStringMatcher.java2
-rw-r--r--src/proguard/util/ListMatcher.java2
-rw-r--r--src/proguard/util/ListParser.java4
-rw-r--r--src/proguard/util/ListUtil.java15
-rw-r--r--src/proguard/util/NameParser.java2
-rw-r--r--src/proguard/util/NotMatcher.java2
-rw-r--r--src/proguard/util/ObjectUtil.java67
-rw-r--r--src/proguard/util/OrMatcher.java2
-rw-r--r--src/proguard/util/SettableMatcher.java2
-rw-r--r--src/proguard/util/StringMatcher.java2
-rw-r--r--src/proguard/util/StringParser.java2
-rw-r--r--src/proguard/util/VariableStringMatcher.java2
-rw-r--r--src/proguard/wtk/ProGuardObfuscator.java5
690 files changed, 21708 insertions, 5689 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..2a365e2
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1 @@
+# We don't really build anything.
diff --git a/README b/README
index 8766da5..2be6777 100644
--- a/README
+++ b/README
@@ -30,4 +30,4 @@ Enjoy!
http://proguard.sourceforge.net/
-Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
diff --git a/bin/proguard.bat b/bin/proguard.bat
index 9e91ebf..793e719 100644
--- a/bin/proguard.bat
+++ b/bin/proguard.bat
@@ -2,9 +2,13 @@
REM Start-up script for ProGuard -- free class file shrinker, optimizer,
REM obfuscator, and preverifier for Java bytecode.
+REM
+REM Note: when passing file names containing spaces to this script,
+REM you'll have to add escaped quotes around them, e.g.
+REM "\"C:/My Directory/My File.txt\""
IF EXIST "%PROGUARD_HOME%" GOTO home
SET PROGUARD_HOME=..
:home
-java -jar "%PROGUARD_HOME%"\lib\proguard.jar %*
+java -jar "%PROGUARD_HOME%\lib\proguard.jar" %*
diff --git a/bin/proguard.sh b/bin/proguard.sh
index b11495f..3fb9444 100755
--- a/bin/proguard.sh
+++ b/bin/proguard.sh
@@ -2,8 +2,11 @@
#
# Start-up script for ProGuard -- free class file shrinker, optimizer,
# obfuscator, and preverifier for Java bytecode.
+#
+# Note: when passing file names containing spaces to this script,
+# you'll have to add escaped quotes around them, e.g.
+# "\"/My Directory/My File.txt\""
-PROGUARD_HOME=`dirname "$0"`
-PROGUARD_HOME=`dirname "$PROGUARD_HOME"`
+PROGUARD_HOME=`dirname "$0"`/..
-java -Xmx512M -jar "$PROGUARD_HOME"/lib/proguard.jar "$@"
+java -Xmx512M -jar "$PROGUARD_HOME/lib/proguard.jar" "$@"
diff --git a/bin/proguardgui.bat b/bin/proguardgui.bat
index 073d98a..4575aaa 100644
--- a/bin/proguardgui.bat
+++ b/bin/proguardgui.bat
@@ -2,9 +2,13 @@
REM Start-up script for the GUI of ProGuard -- free class file shrinker,
REM optimizer, obfuscator, and preverifier for Java bytecode.
+REM
+REM Note: when passing file names containing spaces to this script,
+REM you'll have to add escaped quotes around them, e.g.
+REM "\"C:/My Directory/My File.txt\""
IF EXIST "%PROGUARD_HOME%" GOTO home
SET PROGUARD_HOME=..
:home
-java -jar "%PROGUARD_HOME%"\lib\proguardgui.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
+java -jar "%PROGUARD_HOME%\lib\proguardgui.jar" %*
diff --git a/bin/proguardgui.sh b/bin/proguardgui.sh
index 5a25d7b..2544f29 100755
--- a/bin/proguardgui.sh
+++ b/bin/proguardgui.sh
@@ -2,8 +2,14 @@
#
# Start-up script for the GUI of ProGuard -- free class file shrinker,
# optimizer, obfuscator, and preverifier for Java bytecode.
+#
+# Note: when passing file names containing spaces to this script,
+# you'll have to add escaped quotes around them, e.g.
+# "\"/My Directory/My File.txt\""
-PROGUARD_HOME=`dirname "$0"`
-PROGUARD_HOME=`dirname "$PROGUARD_HOME"`
+PROGUARD_HOME=`dirname "$0"`/..
-java -jar $PROGUARD_HOME/lib/proguardgui.jar "$@"
+# On Linux, Java 1.6.0_24 and higher hang when starting the GUI:
+# http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7027598
+# We're using the -D option as a workaround.
+java -DsuppressSwingDropSupport=true -jar "$PROGUARD_HOME/lib/proguardgui.jar" "$@"
diff --git a/bin/retrace.bat b/bin/retrace.bat
index 70603d3..7201fb6 100644
--- a/bin/retrace.bat
+++ b/bin/retrace.bat
@@ -2,9 +2,13 @@
REM Start-up script for Retrace -- companion tool for ProGuard, free class file
REM shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
+REM
+REM Note: when passing file names containing spaces to this script,
+REM you'll have to add escaped quotes around them, e.g.
+REM "\"C:/My Directory/My File.txt\""
IF EXIST "%PROGUARD_HOME%" GOTO home
SET PROGUARD_HOME=..
:home
-java -jar "%PROGUARD_HOME%"\lib\retrace.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
+java -jar "%PROGUARD_HOME%\lib\retrace.jar" %*
diff --git a/bin/retrace.sh b/bin/retrace.sh
index 5db744e..83a4d5e 100755
--- a/bin/retrace.sh
+++ b/bin/retrace.sh
@@ -2,8 +2,11 @@
#
# Start-up script for Retrace -- companion tool for ProGuard, free class file
# shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
+#
+# Note: when passing file names containing spaces to this script,
+# you'll have to add escaped quotes around them, e.g.
+# "\"/My Directory/My File.txt\""
-PROGUARD_HOME=`dirname "$0"`
-PROGUARD_HOME=`dirname "$PROGUARD_HOME"`
+PROGUARD_HOME=`dirname "$0"`/..
-java -jar $PROGUARD_HOME/lib/retrace.jar "$@"
+java -jar "$PROGUARD_HOME/lib/retrace.jar" "$@"
diff --git a/build/README b/build/README
new file mode 100644
index 0000000..36a235b
--- /dev/null
+++ b/build/README
@@ -0,0 +1,40 @@
+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
+- maven/pom.xml : a Maven POM for building the Maven artifacts
+
+- 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 ProGuard Gradle task:
+
+ javac -sourcepath src -d classes -classpath ..... \
+ src/proguard/gradle/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-2013 Eric Lafortune (eric@graphics.cornell.edu)
diff --git a/build/build.properties b/build/build.properties
new file mode 100644
index 0000000..a6d2bbf
--- /dev/null
+++ b/build/build.properties
@@ -0,0 +1,4 @@
+# Ant build properties for ProGuard.
+
+gradle.home = /usr/local/java/gradle
+wtk.home = /usr/local/java/wtk
diff --git a/build/build.sh b/build/build.sh
index eb5fcf7..adb2ee7 100755
--- a/build/build.sh
+++ b/build/build.sh
@@ -7,6 +7,7 @@
#
ANT_HOME=${ANT_HOME:-/usr/local/java/ant}
+GRADLE_HOME=${GRADLE_HOME:-/usr/local/java/gradle}
WTK_HOME=${WTK_HOME:-/usr/local/java/wtk}
if [ -z $PROGUARD_HOME ]; then
@@ -24,9 +25,15 @@ PROGUARD=proguard/ProGuard
PROGUARD_GUI=proguard/gui/ProGuardGUI
RETRACE=proguard/retrace/ReTrace
ANT_TASK=proguard/ant/ProGuardTask
+GRADLE_TASK=proguard/gradle/ProGuardTask
WTK_PLUGIN=proguard/wtk/ProGuardObfuscator
ANT_JAR=$ANT_HOME/lib/ant.jar
+GRADLE_PATH=\
+$GRADLE_HOME/lib/plugins/gradle-plugins-1.3.jar:\
+$GRADLE_HOME/lib/gradle-base-services-1.3.jar:\
+$GRADLE_HOME/lib/gradle-core-1.3.jar:\
+$GRADLE_HOME/lib/groovy-all-1.8.6.jar
WTK_JAR=$WTK_HOME/wtklib/kenv.zip
PROGUARD_JAR=$LIB/proguard.jar
@@ -84,6 +91,15 @@ else
echo "if you want to compile the optional ProGuard Ant task."
fi
+if [ -f "${GRADLE_PATH%%:*}" ]; then
+ export CLASSPATH=$GRADLE_PATH
+ compile $GRADLE_TASK
+ updatejar $GRADLE_TASK
+else
+ echo "Please make sure the environment variable GRADLE_HOME is set correctly,"
+ echo "if you want to compile the optional ProGuard Gradle task."
+fi
+
if [ -f "$WTK_JAR" ]; then
export CLASSPATH=$WTK_JAR
compile $WTK_PLUGIN
diff --git a/build/build.xml b/build/build.xml
index a592945..7c67c68 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -9,19 +9,23 @@
<property name = "classes" value = "classes"/>
<property name = "lib" value = "lib"/>
- <property name = "ant.jar" value = "${ant.home}/lib/ant.jar"/>
- <property name = "wtk.jar" value = "${wtk.home}/wtklib/kenv.jar"/>
+ <property name = "gradle.jar1" value = "${gradle.home}/lib/plugins/gradle-plugins-1.3.jar"/>
+ <property name = "gradle.jar2" value = "${gradle.home}/lib/gradle-base-services-1.3.jar"/>
+ <property name = "gradle.jar3" value = "${gradle.home}/lib/gradle-core-1.3.jar"/>
+ <property name = "gradle.jar4" value = "${gradle.home}/lib/groovy-all-1.8.6.jar"/>
+ <property name = "wtk.jar" value = "${wtk.home}/wtklib/kenv.zip"/>
<target name = "all" depends = "basic,options"/>
<target name = "basic" depends = "proguard,proguardgui,retrace"/>
<target name = "options" depends = "anttask,wtkplugin"/>
<target name = "proguard" depends = "classes,lib">
- <javac nowarn = "true"
- deprecation = "false"
- srcdir = "${src}"
- destdir = "${classes}"
- includes = "proguard/ProGuard.java">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/ProGuard.java">
<compilerarg value = "-Xlint:none"/>
</javac>
@@ -41,11 +45,12 @@
</target>
<target name = "proguardgui" depends = "proguard">
- <javac nowarn = "true"
- deprecation = "false"
- srcdir = "${src}"
- destdir = "${classes}"
- includes = "proguard/gui/ProGuardGUI.java">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/gui/ProGuardGUI.java">
<compilerarg value = "-Xlint:none"/>
</javac>
@@ -65,11 +70,12 @@
</target>
<target name = "retrace" depends = "classes,lib">
- <javac nowarn = "true"
- deprecation = "false"
- srcdir = "${src}"
- destdir = "${classes}"
- includes = "proguard/retrace/ReTrace.java">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/retrace/ReTrace.java">
<compilerarg value = "-Xlint:none"/>
</javac>
@@ -89,40 +95,76 @@
</target>
<target name = "anttask" depends = "proguard">
- <fail message="Please set the value of the property ant.home in the file build/build.properties, if you want to build the optional ProGuard Ant task.">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "true"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/ant/ProGuardTask.java">
+ <compilerarg value = "-Xlint:none"/>
+ </javac>
+
+ <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>
+ </copy>
+
+ <jar jarfile = "${lib}/proguard.jar"
+ update = "true"
+ basedir = "${classes}"
+ includes = "proguard/ant/**"/>
+ </target>
+
+ <target name = "gradletask" depends = "proguard">
+ <fail message="Please set the value of the property gradle.home in the file build.properties, if you want to build the optional ProGuard Gradle task.">
<condition>
<not>
- <available file="${ant.jar}"/>
+ <and>
+ <available file="${gradle.jar1}"/>
+ <available file="${gradle.jar2}"/>
+ <available file="${gradle.jar3}"/>
+ <available file="${gradle.jar4}"/>
+ </and>
</not>
</condition>
</fail>
- <javac nowarn = "true"
- deprecation = "false"
- classpath = "${ant.jar}"
- srcdir = "${src}"
- destdir = "${classes}"
- includes = "proguard/ant/ProGuardTask.java">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/gradle/ProGuardTask.java">
<compilerarg value = "-Xlint:none"/>
+ <classpath>
+ <path location="${gradle.jar1}"/>
+ <path location="${gradle.jar2}"/>
+ <path location="${gradle.jar3}"/>
+ <path location="${gradle.jar4}"/>
+ </classpath>
</javac>
<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"/>
+ <include name = "proguard/gradle/*.properties"/>
+ <include name = "proguard/gradle/*.png"/>
+ <include name = "proguard/gradle/*.gif"/>
+ <include name = "proguard/gradle/*.pro"/>
</fileset>
</copy>
<jar jarfile = "${lib}/proguard.jar"
update = "true"
basedir = "${classes}"
- includes = "proguard/ant/**"/>
+ includes = "proguard/gradle/**"/>
</target>
<target name = "wtkplugin" depends = "proguard">
- <fail message="Please set the value of the property wtk.home in the file build/build.properties, if you want to build the optional ProGuard WTK plugin.">
+ <fail message="Please set the value of the property wtk.home in the file build.properties, if you want to build the optional ProGuard WTK plugin.">
<condition>
<not>
<available file="${wtk.jar}"/>
@@ -130,12 +172,13 @@
</condition>
</fail>
- <javac nowarn = "true"
- deprecation = "false"
- classpath = "${wtk.jar}"
- srcdir = "${src}"
- destdir = "${classes}"
- includes = "proguard/wtk/ProGuardObfuscator.java">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ classpath = "${wtk.jar}"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/wtk/ProGuardObfuscator.java">
<compilerarg value = "-Xlint:none"/>
</javac>
diff --git a/build/makefile b/build/makefile
index 0508eb4..264a2ac 100644
--- a/build/makefile
+++ b/build/makefile
@@ -1,25 +1,33 @@
# GNU/Linux makefile for ProGuard.
-ANT_HOME = /usr/local/java/ant
-WTK_HOME = /usr/local/java/wtk
+ANT_HOME = /usr/local/java/ant
+GRADLE_HOME = /usr/local/java/gradle
+WTK_HOME = /usr/local/java/wtk
PROGUARD_HOME := $(subst ./..,..,$(subst /build/..,/,$(dir $(MAKEFILE_LIST))..))
SRC = $(PROGUARD_HOME)/src
CLASSES = $(PROGUARD_HOME)/classes
LIB = $(PROGUARD_HOME)/lib
-ANT_JAR = $(ANT_HOME)/lib/ant.jar
-WTK_JAR = $(WTK_HOME)/wtklib/kenv.zip
+ANT_JAR = $(ANT_HOME)/lib/ant.jar
+GRADLE_JARS = $(GRADLE_HOME)/lib/plugins/gradle-plugins-1.3.jar \
+ $(GRADLE_HOME)/lib/gradle-base-services-1.3.jar \
+ $(GRADLE_HOME)/lib/gradle-core-1.3.jar \
+ $(GRADLE_HOME)/lib/groovy-all-1.8.6.jar
+WTK_JAR = $(WTK_HOME)/wtklib/kenv.zip
-CLASSPATH = $(ANT_JAR):$(WTK_JAR)
+NOTHING:=
+SPACE:=$(NOTHING) $(NOTHING)
+CLASSPATH = $(ANT_JAR):$(subst $(SPACE),:,$(GRADLE_JARS)):$(WTK_JAR)
PROGUARD = proguard/ProGuard
PROGUARD_GUI = proguard/gui/ProGuardGUI
RETRACE = proguard/retrace/ReTrace
ANT_TASK = proguard/ant/ProGuardTask
+GRADLE_TASK = proguard/gradle/ProGuardTask
WTK_PLUGIN = proguard/wtk/ProGuardObfuscator
-TARGETS = $(PROGUARD) $(PROGUARD_GUI) $(RETRACE) $(ANT_TASK) $(WTK_PLUGIN)
+TARGETS = $(PROGUARD) $(PROGUARD_GUI) $(RETRACE) $(ANT_TASK) $(GRADLE_TASK) $(WTK_PLUGIN)
JAVAC_OPTIONS = -nowarn -Xlint:none -classpath $(CLASSPATH) -sourcepath $(SRC) -d $(CLASSES)
@@ -39,7 +47,7 @@ endef
all: basic options
basic: proguard proguardgui retrace
-options: anttask wtkplugin
+options: anttask gradletask wtkplugin
proguard: $(PROGUARD)
$(createjar)
@@ -56,6 +64,11 @@ anttask: $(PROGUARD)
anttask: $(ANT_TASK)
$(updatejar)
+gradletask: $(GRADLE_JARS)
+gradletask: $(PROGUARD)
+gradletask: $(GRADLE_TASK)
+ $(updatejar)
+
wtkplugin: $(WTK_JAR)
wtkplugin: $(PROGUARD)
wtkplugin: $(WTK_PLUGIN)
diff --git a/build/maven/ant/pom.xml b/build/maven/ant/pom.xml
new file mode 100644
index 0000000..ab3bc52
--- /dev/null
+++ b/build/maven/ant/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>4.10</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-anttask</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/ant/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/ant/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.ant</subpackages>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>../../../src</directory>
+ <includes>
+ <include>proguard/ant/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.7.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/build/maven/base/pom.xml b/build/maven/base/pom.xml
new file mode 100644
index 0000000..e61471d
--- /dev/null
+++ b/build/maven/base/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>4.10</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-base</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>proguard/gui/**</exclude>
+ <exclude>proguard/ant/**</exclude>
+ <exclude>proguard/gradle/**</exclude>
+ <exclude>proguard/wtk/**</exclude>
+ <exclude>proguard/retrace/**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>proguard/gui/**</exclude>
+ <exclude>proguard/ant/**</exclude>
+ <exclude>proguard/gradle/**</exclude>
+ <exclude>proguard/wtk/**</exclude>
+ <exclude>proguard/retrace/**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <excludePackageNames>proguard.gui:proguard.ant:proguard.gradle:proguard.wtk:proguard.retrace</excludePackageNames>
+ <!-- sourceFileExcludes doesn't seem to work, so we're using excludePackageNames -->
+ <sourceFileExcludes>
+ <sourceFileExclude>proguard/gui/**</sourceFileExclude>
+ <sourceFileExclude>proguard/ant/**</sourceFileExclude>
+ <sourceFileExclude>proguard/gradle/**</sourceFileExclude>
+ <sourceFileExclude>proguard/wtk/**</sourceFileExclude>
+ <sourceFileExclude>proguard/retrace/**</sourceFileExclude>
+ </sourceFileExcludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>proguard.ProGuard</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/build/maven/gradle/pom.xml b/build/maven/gradle/pom.xml
new file mode 100644
index 0000000..86fa2fc
--- /dev/null
+++ b/build/maven/gradle/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>4.10</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-gradle</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gradle/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gradle/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.gradle</subpackages>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.gradle</groupId>
+ <artifactId>gradle-core</artifactId>
+ <version>1.3</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gradle</groupId>
+ <artifactId>gradle-base-services</artifactId>
+ <version>1.3</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-all</artifactId>
+ <version>2.0.6</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <repositories>
+ <repository>
+ <id>gradle</id>
+ <url>http://repo.gradle.org/gradle/libs-releases-local/</url>
+ </repository>
+ </repositories>
+</project>
diff --git a/build/maven/gui/pom.xml b/build/maven/gui/pom.xml
new file mode 100644
index 0000000..94d0100
--- /dev/null
+++ b/build/maven/gui/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>4.10</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-gui</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gui/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gui/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.gui</subpackages>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <mainClass>proguard.gui.ProGuardGUI</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>../../../src</directory>
+ <includes>
+ <include>proguard/gui/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ <exclude>MANIFEST.MF</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-retrace</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/build/maven/pom.xml b/build/maven/pom.xml
new file mode 100644
index 0000000..8f894ce
--- /dev/null
+++ b/build/maven/pom.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>4.10</version>
+ <packaging>pom</packaging>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+ <description>ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier.</description>
+ <url>http://proguard.sourceforge.net/</url>
+
+ <prerequisites>
+ <maven>3</maven>
+ </prerequisites>
+
+ <developers>
+ <developer>
+ <id>lafortune</id>
+ <name>Eric Lafortune</name>
+ <url>http://www.lafortune.eu/</url>
+ <organization>Saikoa</organization>
+ <organizationUrl>http://www.saikoa.com/</organizationUrl>
+ <roles>
+ <role>Project Administrator</role>
+ <role>Developer</role>
+ </roles>
+ </developer>
+ </developers>
+
+ <licenses>
+ <license>
+ <name>GNU General Public License, Version 2</name>
+ <url>http://www.gnu.org/licenses/gpl-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <issueManagement>
+ <system>SourceForge.net Tracker</system>
+ <url>http://sourceforge.net/p/proguard/bugs/</url>
+ </issueManagement>
+
+ <scm>
+ <url>http://hg.code.sf.net/p/proguard/code</url>
+ <connection>scm:hg:http://hg.code.sf.net/p/proguard/code</connection>
+ </scm>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8.1</version>
+ <configuration>
+ <links>
+ <link>http://download.oracle.com/javase/1.5.0/docs/api/</link>
+ </links>
+ <quiet>true</quiet>
+ </configuration>
+ <executions>
+ <execution>
+ <id>attach-javadoc</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.1.2</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <repository>
+ <id>sonatype-nexus-staging</id>
+ <name>Nexus Release Repository</name>
+ <url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
+ </repository>
+ </distributionManagement>
+
+ <!-- To keep our project layout simple, we're not following the
+ 'one Maven way'. Now Maven is inflicting even more redundant
+ redundancy on us. We're stubborn though. -->
+
+ <modules>
+ <module>base</module>
+ <module>gui</module>
+ <module>ant</module>
+ <module>gradle</module>
+ <module>retrace</module>
+ </modules>
+
+ <profiles>
+ <profile>
+ <id>__wtk_plugin_build__</id>
+ <activation>
+ <file>
+ <exists>${wtk.home}/wtklib/kenv.zip</exists>
+ </file>
+ </activation>
+ <modules>
+ <module>wtk</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
diff --git a/build/maven/retrace/pom.xml b/build/maven/retrace/pom.xml
new file mode 100644
index 0000000..382f9ee
--- /dev/null
+++ b/build/maven/retrace/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>4.10</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-retrace</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/retrace/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/retrace/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.retrace</subpackages>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <mainClass>proguard.retrace.ReTrace</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/build/maven/wtk/pom.xml b/build/maven/wtk/pom.xml
new file mode 100644
index 0000000..fe00533
--- /dev/null
+++ b/build/maven/wtk/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>4.10</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-wtk-plugin</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/wtk/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/wtk/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.wtk</subpackages>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>../../../src</directory>
+ <includes>
+ <include>proguard/wtk/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>wtklib</groupId>
+ <artifactId>kenv</artifactId>
+ <version>2.2</version>
+ <scope>system</scope>
+ <systemPath>${wtk.home}/wtklib/kenv.zip</systemPath>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/docs/FAQ.html b/docs/FAQ.html
index 8f19b15..7727289 100644
--- a/docs/FAQ.html
+++ b/docs/FAQ.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard FAQ</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -13,35 +24,39 @@
<h3>Contents</h3>
<ol>
-<li><a href="#shrinking">What is shrinking?</a>
-<li><a href="#obfuscation">What is obfuscation?</a>
-<li><a href="#preverification">What is preverification?</a>
+<li><a href="#shrinking">What is shrinking?</a></li>
+<li><a href="#obfuscation">What is obfuscation?</a></li>
+<li><a href="#preverification">What is preverification?</a></li>
<li><a href="#optimization">What kind of optimizations does <b>ProGuard</b>
- support?</a>
+ support?</a></li>
<li><a href="#commercial">Can I use <b>ProGuard</b> to process my commercial
- application?</a>
+ application?</a></li>
<li><a href="#jdk1.4">Does <b>ProGuard</b> work with Java 2? Java 5? Java
- 6?</a>
-<li><a href="#jme">Does <b>ProGuard</b> work with Java Micro Edition?</a>
-<li><a href="#android">Does <b>ProGuard</b> work for Google Android code?</a>
-<li><a href="#blackberry">Does <b>ProGuard</b> work for Blackberry code?</a>
-<li><a href="#ant">Does <b>ProGuard</b> have support for Ant?</a>
-<li><a href="#gui">Does <b>ProGuard</b> come with a GUI?</a>
+ 6? Java 7?</a></li>
+<li><a href="#jme">Does <b>ProGuard</b> work with Java Micro Edition?</a></li>
+<li><a href="#android">Does <b>ProGuard</b> work for Google Android
+ code?</a></li>
+<li><a href="#blackberry">Does <b>ProGuard</b> work for Blackberry
+ code?</a></li>
+<li><a href="#ant">Does <b>ProGuard</b> have support for Ant?</a></li>
+<li><a href="#gradle">Does <b>ProGuard</b> have support for Gradle?</a></li>
+<li><a href="#maven">Does <b>ProGuard</b> have support for Maven?</a></li>
+<li><a href="#gui">Does <b>ProGuard</b> come with a GUI?</a></li>
<li><a href="#forname">Does <b>ProGuard</b> handle <code>Class.forName</code>
- calls?</a>
-<li><a href="#resource">Does <b>ProGuard</b> handle resource files?</a>
-<li><a href="#encrypt">Does <b>ProGuard</b> encrypt strings constants?</a>
-<li><a href="#flow">Does <b>ProGuard</b> perform control flow obfuscation?</a>
+ calls?</a></li>
+<li><a href="#resource">Does <b>ProGuard</b> handle resource files?</a></li>
+<li><a href="#encrypt">Does <b>ProGuard</b> encrypt string constants?</a></li>
+<li><a href="#flow">Does <b>ProGuard</b> perform control flow
+ obfuscation?</a></li>
<li><a href="#incremental">Does <b>ProGuard</b> support incremental
- obfuscation?</a>
+ obfuscation?</a></li>
<li><a href="#keywords">Can <b>ProGuard</b> obfuscate using reserved
- keywords?</a>
+ keywords?</a></li>
<li><a href="#stacktrace">Can <b>ProGuard</b> reconstruct obfuscated stack
- traces?</a>
+ traces?</a></li>
</ol>
-<a name="shrinking">&nbsp;</a>
-<h3>What is shrinking?</h3>
+<h3><a name="shrinking">What is shrinking?</a></h3>
Java source code (.java files) is typically compiled to bytecode (.class
files). Bytecode is more compact than Java source code, but it may still
@@ -50,8 +65,7 @@ Shrinking programs such as <b>ProGuard</b> can analyze bytecode and remove
unused classes, fields, and methods. The program remains functionally
equivalent, including the information given in exception stack traces.
-<a name="obfuscation">&nbsp;</a>
-<h3>What is obfuscation?</h3>
+<h3><a name="obfuscation">What is obfuscation?</a></h3>
By default, compiled bytecode still contains a lot of debugging information:
source file names, line numbers, field names, method names, argument names,
@@ -63,8 +77,7 @@ it much harder to reverse-engineer the code. It further compacts the code as a
bonus. The program remains functionally equivalent, except for the class
names, method names, and line numbers given in exception stack traces.
-<a name="preverification">&nbsp;</a>
-<h3>What is preverification?</h3>
+<h3><a name="preverification">What is preverification?</a></h3>
When loading class files, the class loader performs some sophisticated
verification of the byte code. This analysis makes sure the code can't
@@ -77,8 +90,7 @@ then be loaded faster and in a more memory-efficient way. <b>ProGuard</b> can
perform the preverification step too, for instance allowing to retarget older
class files at Java 6.
-<a name="optimization">&nbsp;</a>
-<h3>What kind of optimizations does <b>ProGuard</b> support?</h3>
+<h3><a name="optimization">What kind of optimizations does <b>ProGuard</b> support?</a></h3>
Apart from removing unused classes, fields, and methods in the shrinking step,
<b>ProGuard</b> can also perform optimizations at the bytecode level, inside
@@ -87,24 +99,24 @@ analysis, partial evaluation, static single assignment, global value numbering,
and liveness analysis, <b>ProGuard</b> can:
<ul>
-<li>Evaluate constant expressions.
-<li>Remove unnecessary field accesses and method calls.
-<li>Remove unnecessary branches.
-<li>Remove unnecessary comparisons and instanceof tests.
-<li>Remove unused code blocks.
-<li>Merge identical code blocks.
-<li>Reduce variable allocation.
-<li>Remove write-only fields and unused method parameters.
-<li>Inline constant fields, method parameters, and return values.
-<li>Inline methods that are short or only called once.
-<li>Simplify tail recursion calls.
-<li>Merge classes and interfaces.
-<li>Make methods private, static, and final when possible.
-<li>Make classes static and final when possible.
-<li>Replace interfaces that have single implementations.
+<li>Evaluate constant expressions.</li>
+<li>Remove unnecessary field accesses and method calls.</li>
+<li>Remove unnecessary branches.</li>
+<li>Remove unnecessary comparisons and instanceof tests.</li>
+<li>Remove unused code blocks.</li>
+<li>Merge identical code blocks.</li>
+<li>Reduce variable allocation.</li>
+<li>Remove write-only fields and unused method parameters.</li>
+<li>Inline constant fields, method parameters, and return values.</li>
+<li>Inline methods that are short or only called once.</li>
+<li>Simplify tail recursion calls.</li>
+<li>Merge classes and interfaces.</li>
+<li>Make methods private, static, and final when possible.</li>
+<li>Make classes static and final when possible.</li>
+<li>Replace interfaces that have single implementations.</li>
<li>Perform over 200 peephole optimizations, like replacing ...*2 by
- ...&lt;&lt;1.
-<li>Optionally remove logging code.
+ ...&lt;&lt;1.</li>
+<li>Optionally remove logging code.</li>
</ul>
The positive effects of these optimizations will depend on your code and on
the virtual machine on which the code is executed. Simple virtual machines may
@@ -113,27 +125,28 @@ At the very least, your bytecode may become a bit smaller.
<p>
Some notable optimizations that aren't supported yet:
<ul>
-<li>Moving constant expressions out of loops.
-<li>Optimizations that require escape analysis.
+<li>Moving constant expressions out of loops.</li>
+<li>Optimizations that require escape analysis
+ (<a href="http://www.saikoa.com/dexguard" target="_top">DexGuard</a>
+ does).</li>
</ul>
-<a name="commercial">&nbsp;</a>
-<h3>Can I use <b>ProGuard</b> to process my commercial application?</h3>
+<h3><a name="commercial">Can I use <b>ProGuard</b> to process my commercial application?</a></h3>
Yes, you can. <b>ProGuard</b> itself is distributed under the GPL, but this
doesn't affect the programs that you process. Your code remains yours, and
its license can remain the same.
-<a name="jdk1.4">&nbsp;</a>
-<h3>Does <b>ProGuard</b> work with Java 2? Java 5? Java 6?</h3>
+<h3><a name="jdk1.4">Does <b>ProGuard</b> work with Java 2? Java 5? Java 6? Java 7?</a></h3>
-Yes, <b>ProGuard</b> supports all JDKs from 1.1 up to and including 6.0. Java 2
+Yes, <b>ProGuard</b> supports all JDKs from 1.1 up to and including 7.0. Java 2
introduced some small differences in the class file format. Java 5 added
-attributes for generics and for annotations. Java 6 introduced preverification
-attributes. <b>ProGuard</b> handles all versions correctly.
+attributes for generics and for annotations. Java 6 introduced optional
+preverification attributes. Java 7 made preverification obligatory and
+introduced support for dynamic languages. <b>ProGuard</b> handles all versions
+correctly.
-<a name="jme">&nbsp;</a>
-<h3>Does <b>ProGuard</b> work with Java Micro Edition?</h3>
+<h3><a name="jme">Does <b>ProGuard</b> work with Java Micro Edition?</a></h3>
Yes. <b>ProGuard</b> itself runs in Java Standard Edition, but you can freely
specify the run-time environment at which your programs are targeted,
@@ -144,16 +157,17 @@ preverifier.
<b>ProGuard</b> also comes with an obfuscator plug-in for the JME Wireless
Toolkit.
-<a name="android">&nbsp;</a>
-<h3>Does <b>ProGuard</b> work for Google Android code?</h3>
+<h3><a name="android">Does <b>ProGuard</b> work for Google Android code?</a></h3>
Yes. Google's <code>dx</code> compiler converts ordinary jar files into files
that run on Android devices. By preprocessing the original jar files,
<b>ProGuard</b> can significantly reduce the file sizes and boost the run-time
-performance of the code.
+performance of the code. It is distributed as part of the Android SDK.
+<a href="http://www.saikoa.com/dexguard" target="_top"><b>DexGuard</b></a>,
+<b>ProGuard</b>'s closed-source sibling for Android, offers additional
+optimizations and more application protection.
-<a name="blackberry">&nbsp;</a>
-<h3>Does <b>ProGuard</b> work for Blackberry code?</h3>
+<h3><a name="blackberry">Does <b>ProGuard</b> work for Blackberry code?</a></h3>
It should. RIM's proprietary <code>rapc</code> compiler converts ordinary JME
jar files into cod files that run on Blackberry devices. The compiler performs
@@ -163,24 +177,40 @@ percent. However, the <code>rapc</code> compiler also seems to contain some
bugs. It sometimes fails on obfuscated code that is valid and accepted by other
JME tools and VMs. Your mileage may therefore vary.
-<a name="ant">&nbsp;</a>
-<h3>Does <b>ProGuard</b> have support for Ant?</h3>
+<h3><a name="ant">Does <b>ProGuard</b> have support for Ant?</a></h3>
Yes. <b>ProGuard</b> provides an Ant task, so that it integrates seamlessly
-into your Ant build processes. You can still use configurations in
+into your Ant build process. You can still use configurations in
<b>ProGuard</b>'s own readable format. Alternatively, if you prefer XML, you
can specify the equivalent XML configuration.
-<a name="gui">&nbsp;</a>
-<h3>Does <b>ProGuard</b> come with a GUI?</h3>
+<h3><a name="gradle">Does <b>ProGuard</b> have support for Gradle?</a></h3>
+
+Yes. <b>ProGuard</b> also provides a Gradle task, so that it integrates into
+your Gradle build process. You can specify configurations in
+<b>ProGuard</b>'s own format or embedded in the Groovy configuration.
+
+<h3><a name="maven">Does <b>ProGuard</b> have support for Maven?</a></h3>
+
+<b>ProGuard</b>'s jar files are also distributed as artefacts from
+the <a href="http://search.maven.org/#search|ga|1|g:%22net.sf.proguard%22"
+target="other">Maven Central</a> repository. There are some third-party
+plugins that support <b>ProGuard</b>, such as the
+<a href="http://code.google.com/p/maven-android-plugin/"
+target="other">android-maven-plugin</a> and the
+<a href="http://mavenproguard.sourceforge.net/" target="other">IDFC Maven
+ProGuard Plug-in</a>.
+<a href="http://www.saikoa.com/dexguard" target="_top"><b>DexGuard</b></a>
+also comes with a Maven plugin.
+
+<h3><a name="gui">Does <b>ProGuard</b> come with a GUI?</a></h3>
Yes. First of all, <b>ProGuard</b> is perfectly usable as a command-line tool
that can easily be integrated into any automatic build process. For casual
users, there's also a graphical user interface that simplifies creating,
loading, editing, executing, and saving ProGuard configurations.
-<a name="forname">&nbsp;</a>
-<h3>Does <b>ProGuard</b> handle <code>Class.forName</code> calls?</h3>
+<h3><a name="forname">Does <b>ProGuard</b> handle <code>Class.forName</code> calls?</a></h3>
Yes. <b>ProGuard</b> automatically handles constructs like
<code>Class.forName("SomeClass")</code> and <code>SomeClass.class</code>. The
@@ -192,25 +222,24 @@ possible values. They might be read from a configuration file, for instance.
However, <b>ProGuard</b> will note a number of constructs like
"<code>(SomeClass)Class.forName(variable).newInstance()</code>". These might
be an indication that the class or interface <code>SomeClass</code> and/or its
-implementations may need to be preserved. The user can adapt his configuration
-accordingly.
+implementations may need to be preserved. The developer can adapt his
+configuration accordingly.
-<a name="resource">&nbsp;</a>
-<h3>Does <b>ProGuard</b> handle resource files?</h3>
+<h3><a name="resource">Does <b>ProGuard</b> handle resource files?</a></h3>
Yes. <b>ProGuard</b> copies all non-class resource files, optionally adapting
their names and their contents to the obfuscation that has been applied.
-<a name="encrypt">&nbsp;</a>
-<h3>Does <b>ProGuard</b> encrypt strings constants?</h3>
+<h3><a name="encrypt">Does <b>ProGuard</b> encrypt string constants?</a></h3>
-No. Storing encrypted string constants in program code is fairly futile, since
-the encryption has to be perfectly reversible by definition. Moreover, the
-decryption costs additional memory and computation at run-time. If this feature
-is ever incorporated, I'll provide a tool to decrypt the strings as well.
+No. String encryption in program code has to be perfectly reversible by
+definition, so it only improves the obfuscation level. It increases the
+footprint of the code. However, by popular demand, <b>ProGuard</b>'s
+closed-source sibling for Android, <a href="http://www.saikoa.com/dexguard"
+target="_top"><b>DexGuard</b></a>, does provide string encryption, along with
+more protection techniques against static and dynamic analysis.
-<a name="flow">&nbsp;</a>
-<h3>Does <b>ProGuard</b> perform flow obfuscation?</h3>
+<h3><a name="flow">Does <b>ProGuard</b> perform flow obfuscation?</a></h3>
Not explicitly. Control flow obfuscation injects additional branches into the
bytecode, in an attempt to fool decompilers. <b>ProGuard</b> does not do this,
@@ -218,15 +247,13 @@ in order to avoid any negative effects on performance and size. However, the
optimization step often already restructures the code to the point where most
decompilers get confused.
-<a name="incremental">&nbsp;</a>
-<h3>Does <b>ProGuard</b> support incremental obfuscation?</h3>
+<h3><a name="incremental">Does <b>ProGuard</b> support incremental obfuscation?</a></h3>
Yes. This feature allows you to specify a previous obfuscation mapping file in
a new obfuscation step, in order to produce add-ons or patches for obfuscated
code.
-<a name="keywords">&nbsp;</a>
-<h3>Can <b>ProGuard</b> obfuscate using reserved keywords?</h3>
+<h3><a name="keywords">Can <b>ProGuard</b> obfuscate using reserved keywords?</a></h3>
Yes. You can specify your own obfuscation dictionary, such as a list of
reserved key words, identifiers with foreign characters, random source files,
@@ -234,8 +261,7 @@ or a text by Shakespeare. Note that this hardly improves the obfuscation.
Decent decompilers can automatically replace reserved keywords, and the effect
can be undone fairly easily, by obfuscating again with simpler names.
-<a name="stacktrace">&nbsp;</a>
-<h3>Can <b>ProGuard</b> reconstruct obfuscated stack traces?</h3>
+<h3><a name="stacktrace">Can <b>ProGuard</b> reconstruct obfuscated stack traces?</a></h3>
Yes. <b>ProGuard</b> comes with a companion tool, <b>ReTrace</b>, that can
'de-obfuscate' stack traces produced by obfuscated applications. The
@@ -245,10 +271,11 @@ names is presented for each obfuscated method name that has an ambiguous
reverse mapping. Please refer to the <a href="manual/index.html">ProGuard User
Manual</a> for more details.
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/GPL_exception.html b/docs/GPL_exception.html
index 0a44d66..d610af8 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 &copy; 2002-2009 Eric Lafortune
+Copyright &copy; 2002-2013 Eric Lafortune
</P>
<P>
@@ -33,13 +33,18 @@ Place, Suite 330, Boston, MA 02111-1307 USA
In addition, as a special exception, Eric Lafortune gives permission to link
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
-<li>the Javaground Tools,
+<li>Apache Ant,</li>
+<li>Apache Maven,</li>
+<li>the Google Android SDK,</li>
+<li>the Eclipse ProGuardDT GUI,</li>
+<li>the EclipseME JME IDE,</li>
+<li>the Oracle NetBeans Java IDE,</li>
+<li>the Oracle JME Wireless Toolkit,</li>
+<li>the Intel TXE SDK,</li>
+<li>the Simple Build Tool for Scala (and its scripts),</li>
+<li>the NeoMAD Tools by Neomades,</li>
+<li>the Javaground Tools, and</li>
+<li>the Sanaware Tools,</li>
</ul>
and distribute linked combinations including the two. You must obey the GNU
General Public License in all respects for all of the code used other than
diff --git a/docs/acknowledgements.html b/docs/acknowledgements.html
index af19461..14fdc74 100644
--- a/docs/acknowledgements.html
+++ b/docs/acknowledgements.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Acknowledgements</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -12,7 +23,7 @@
The first versions of <b>ProGuard</b> grew out of <b>RetroGuard</b>, which its
author Mark Welsh kindly made available under the GNU Lesser General Public
-License. <b>RetroGuard</b> is a very nice piece of code, but it only performed
+License. RetroGuard is a very nice piece of code, but it only performed
obfuscation. I started from the class file parsing code and wrote my own
shrinker, optimizer, obfuscator, and preverifier. As of version 4.0, all of the
original code has been rewritten, so the most obvious remaining similarity are
@@ -24,44 +35,53 @@ task. I have rewritten the implementation for version 3.0, but the XML schema
is still based on his work.
<p>
-Since its first public release, many people have expressed their enthusiasm and
-have chimed in with interesting ideas, bug reports, and bug fixes: Thorsten
-Heit, Oliver Retzl, Jonathan Knudsen, Tarcisio Camara, Bob Drury, Dave Jarvis,
-Marc Chapman, Dave Morehouse, Richard Osbaldeston, Peter Hawkins, Mark
-Sherington, David Sitsky, James Manning, Ptolemy Oberin, Frank-Michael Moser,
-QZ Shines, Thomas Singer, Michele Puccini, Roman Bednarek, Natalia Pujol,
-Daniel Sj&ouml;blom, Jan Filipsky, Charles Smith, Gerrit Telkamp, Noel
-Grandin, Torbj&ouml;rn S&ouml;derstedt, Clemens Eisserer, Clark Bassett,
-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.
+Marcel Patzlaff has initiated a series of artifacts in the Maven Central
+repository. I am now maintaining them as part of the official builds.
<p>
-I am developing ProGuard in my spare time, which is possible thanks to my
-day-time job at <a href="http://www.luciad.com/" target="other">Luciad</a>.
+Many other people have expressed their enthusiasm and have chimed in with
+interesting ideas, bug reports, and bug fixes: Thorsten Heit, Oliver Retzl,
+Jonathan Knudsen, Tarcisio Camara, Bob Drury, Dave Jarvis, Marc Chapman, Dave
+Morehouse, Richard Osbaldeston, Peter Hawkins, Mark Sherington, David Sitsky,
+James Manning, Ptolemy Oberin, Frank-Michael Moser, QZ Shines, Thomas Singer,
+Michele Puccini, Roman Bednarek, Natalia Pujol, Daniel Sj&ouml;blom, Jan
+Filipsky, Charles Smith, Gerrit Telkamp, Noel Grandin, Torbj&ouml;rn
+S&ouml;derstedt, Clemens Eisserer, Clark Bassett, Eduard Welch, Dawid Weiss,
+Andrew Wilson, Sean Owen, Niels Gron, Ishan Mehta, Steven Adams, Xavier Kral,
+Stefan Martin, Toby Reyelts, Bernhard Eder, Manfred Moser, Marco Bl&uuml;mel,
+David Reiss,
+and many more. Thanks! Your feedback has been invaluable.
+<p>
+
+<a href="http://www.saikoa.com/" target="_top">Saikoa</a> is providing the
+financial resources for this project. At Saikoa, we're also developing
+ProGuard's sibling for Android,
+<a href="http://www.saikoa.com/dexguard" target="_top">DexGuard</a>.
<p>
<a href="http://sourceforge.net/projects/proguard/"
-target="other">SourceForge</a> is generously providing the resources for
-hosting this project and many other projects.
+target="other">SourceForge</a> is providing the resources for hosting this
+project and many other projects.
<p>
-JetBrains is kindly providing a license for its IntelliJ IDEA development
-environment.
+<a href="http://www.sonatype.com/" target="other">Sonatype</a> and
+the <a href="http://search.maven.org/#search|ga|1|g:%22net.sf.proguard%22"
+target="other">Maven Central</a> repository are hosting the Maven artifacts.
<p>
-The code and these web pages were written using Sun's JDKs, Linux, IntelliJ
-IDEA, GNU emacs, bash, sed, awk, and a whole host of other tools that continue
-to make programming interesting.
+The code and these web pages were written using Oracle/Sun's JDKs, Linux,
+IntelliJ IDEA, GNU emacs, bash, sed, awk, and a whole host of other tools that
+continue to make programming interesting.
<p>
-And finally, I'm a great fan of the <a
+And finally, I'm a great fan of Sanaware's <a
href="http://www.javadocking.com/" target="other">Java Docking Library</a>.
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/alternatives.html b/docs/alternatives.html
index fa5db0c..7aeffad 100644
--- a/docs/alternatives.html
+++ b/docs/alternatives.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Alternatives</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -34,612 +45,702 @@ below is incorrect.
</tr>
<tr>
-<td><a target="other" href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a></td>
+<td><a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a></td>
<td><a target="_top" href="http://proguard.sourceforge.net/">ProGuard</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
<td>Free (GPL)</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.informatik.uni-oldenburg.de/leute/hoenicke.html">Jochen Hoenicke</a></td>
<td><a target="other" href="http://jode.sourceforge.net/">Jode</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>Free (GPL)</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.nq4.de/">NQ4</a></td>
-<td><a target="other" href="http://www.nq4.de/">Joga</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
-<td>Free (no source)</td>
-</tr>
-
-<tr>
<td><a target="other" rel="nofollow" href="http://www.cs.cornell.edu/nystrom/">Nate Nystrom</a></td>
<td><a target="other" href="http://www.cs.purdue.edu/homes/hosking/bloat/">Bloat</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
<td>Free</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://sourceforge.net/users/hchacha/">Hidetoshi Ohuchi</a></td>
<td><a target="other" href="http://jarg.sourceforge.net/">Jarg</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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 align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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 (BSD)</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.geocities.com/CapeCanaveral/Hall/2334/resume.html">Alexander Shvets</a></td>
-<td><a target="other" href="http://www.geocities.com/CapeCanaveral/Hall/2334/Programs/cafebabe.html">CafeBabe</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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</td>
-</tr>
-
-<tr>
<td><a target="other" rel="nofollow" href="http://www.yworks.com/">yWorks</a></td>
<td><a target="other" href="http://www.yworks.com/en/products_yguard_about.htm">yGuard</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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 align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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 (no source)</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.cs.purdue.edu/homes/grothoff/">Christian Grothoff</a></td>
-<td><a target="other" href="http://www.ovmj.org/jamit/">Jamit</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
-<td>Free (GPL)</td>
-</tr>
-
-<tr>
<td><a target="other" rel="nofollow" href="http://mojo.codehaus.org/">Mojo</a></td>
<td><a target="other" href="http://mojo.codehaus.org/minijar-maven-plugin/">Minijar</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></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 align="center"><br /></td>
+<td align="center"><br /></td>
<td>Free (Apache)</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.riggshill.com/">RiggsHill Software</a></td>
<td><a target="other" href="http://genjar.sourceforge.net/">GenJar</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></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 align="center"><br /></td>
+<td align="center"><br /></td>
<td>Free (Apache)</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://ant.apache.org/">Apache</a></td>
-<td><a target="other" href="http://ant.apache.org/manual/OptionalTypes/classfileset.html">Ant Classfileset</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
+<td><a target="other" href="http://ant.apache.org/manual/Types/classfileset.html">Ant Classfileset</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (Apache)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.celton.mobi/">Carsten Elton S&oslash;rensen</a></td>
+<td><a target="other" href="http://code.google.com/p/treeshaker/">Treeshaker</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
<td>Free (Apache)</td>
</tr>
<tr>
+<td><a target="other" rel="nofollow" href="http://www.ucdetector.org/">J&ouml;rg Spieler</a></td>
+<td><a target="other" href="http://www.ucdetector.org/">UCDetector</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (EPL)</td>
+</tr>
+
+<tr>
<td><a target="other" rel="nofollow" href="http://www.curious-creature.org/">Romain Guy</a></td>
<td><a target="other" href="http://www.jroller.com/gfx/entry/get_what_you_need_from">Harvester</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></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 align="center"><br /></td>
+<td align="center"><br /></td>
<td>Free (BSD)</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="https://dcd.dev.java.net/">Emeric Vernat</a></td>
-<td><a target="other" href="https://dcd.dev.java.net/">DCD</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
+<td><a target="other" rel="nofollow" href="http://java.net/projects/dcd/">Emeric Vernat</a></td>
+<td><a target="other" href="http://java.net/projects/dcd/">DCD</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
<td>Free (LGPL)</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://sadun-util.sourceforge.net/">Cristiano Sadun</a></td>
<td><a target="other" href="http://sadun-util.sourceforge.net/pack.html">Pack</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
-<td align="center"><br></td>
-<td>Free (LGPL)</td>
-</tr>
-
-<tr>
-<td><a target="other" rel="nofollow" href="http://darcs.brianweb.net/">Brian Alliet</a></td>
-<td><a target="other" href="http://darcs.brianweb.net/gcclass/">Gcclass</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></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 align="center"><br /></td>
+<td align="center"><br /></td>
<td>Free (LGPL)</td>
</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/soot/">Soot</a></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 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 align="center"><br /></td>
<td>Free (LGPL)</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.garret.ru/~knizhnik/">Konstantin Knizhnik</a></td>
<td><a target="other" href="http://www.garret.ru/~knizhnik/javago/ReadMe.htm">JavaGO</a></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 align="center"><br></td>
-<td>Free</td>
-</tr>
-
-<tr>
-<td><a target="other" rel="nofollow" href="http://donquixote.cafebabe.jp/">Haruaki Tamada</a></td>
-<td><a target="other" href="http://donquixote.cafebabe.jp/">DonQuixote</a></td>
-<td align="center"><br></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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 align="center"><br /></td>
<td>Free</td>
</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 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://classencrypt.sourceforge.net/">Jeffrey Wheaton</a></td>
+<td><a target="other" href="http://classencrypt.sourceforge.net/">ClassEncrypt</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 (GPL)</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>
-<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 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://mwobfu.sourceforge.net/">Patrick Mueller</a></td>
<td><a target="other" href="http://mwobfu.sourceforge.net/">Mwobfu</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 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 (GPL)</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.elegant-software.com/">Elegant Software</a></td>
-<td><a target="other" href="http://www.elegant-software.com/software/jmangle/">JMangle</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</td>
-</tr>
-
-<tr>
<td><a target="other" rel="nofollow" href="http://www.bebbosoft.de/">BebboSoft</a></td>
-<td><a target="other" href="http://www.bebbosoft.de/index.html#java/mug/index.html">Bb_mug</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><a target="other" href="http://www.bebbosoft.de/#java/mug/index.wiki">Bb_mug</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 (no source)</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.drjava.de/">Dr. Java</a></td>
-<td><a target="other" href="http://www.drjava.de/obfuscator/">Marvin Obfuscator</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 (no source)</td>
+<td><a target="other" rel="nofollow" href="http://github.com/v6ak">V&iacute;t &Scaron;est&aacute;k</a></td>
+<td><a target="other" href="http://github.com/v6ak/Preverifier/">Preverifier</a></td>
+<td align="center"><br /></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>Free (EPL)</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.ibm.com/">IBM</a></td>
-<td><a target="other" href="http://www-306.ibm.com/software/wireless/wsdd/">WSDD</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td><a target="_top" href="http://www.saikoa.com/">Saikoa</a></td>
+<td><a target="_top" href="http://www.saikoa.com/dexguard">DexGuard</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.preemptive.com/">PreEmptive</a></td>
<td><a target="other" href="http://www.preemptive.com/products/dasho/index.html">DashOPro</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.zelix.com/">Zelix</a></td>
<td><a target="other" href="http://www.zelix.com/klassmaster/index.html">KlassMaster</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
-<td>Commercial</td>
-</tr>
-
-<tr>
-<td><a target="other" rel="nofollow" href="http://www.s5systems.com/">S5 Systems</a></td>
-<td><a target="other" href="http://www.s5systems.com/jPresto.htm">jPresto</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.s-cradle.com/english/index.html">Sophia Cradle</a></td>
<td><a target="other" href="http://www.s-cradle.com/english/products/sophiacompress_java/index.html">SophiaCompress</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.retrologic.com/">RetroLogic</a></td>
-<td><a target="other" href="http://www.retrologic.com/">RetroGuard</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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>Commercial</td>
-</tr>
-
-<tr>
-<td><a target="other" rel="nofollow" href="http://www.codingart.com/">CodingArt</a></td>
-<td><a target="other" href="http://www.codingart.com/codeshield.html">CodeShield</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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><a target="other" rel="nofollow" href="http://shield4j.com/">Eduardo Coca</a></td>
+<td><a target="other" href="http://shield4j.com/">Shield4J</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.e-t.com/">Eastridge Technology</a></td>
<td><a target="other" href="http://www.e-t.com/jshrink.html">Jshrink</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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>Commercial</td>
-</tr>
-
-<tr>
-<td><a target="other" rel="nofollow" href="http://www.helseth.com/">Helseth</a></td>
-<td><a target="other" href="http://www.helseth.com/HJO.htm">JObfuscator</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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 align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.leesw.com/">LeeSoftware</a></td>
<td><a target="other" href="http://www.leesw.com/">Smokescreen Obfuscator</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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>Commercial</td>
-</tr>
-
-<tr>
-<td><a target="other" rel="nofollow" href="http://www.vegatech.com/">Vega Technologies</a></td>
-<td><a target="other" href="http://www.vegatech.com/jzipper/">JZipper</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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 align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.innaworks.com/">Innaworks</a></td>
-<td><a target="other" href="http://www.innaworks.com/">mBooster</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
+<td><a target="other" href="http://www.innaworks.com/mBooster">mBooster</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
<td>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.uni-vologda.ac.ru/~c3c/">Sergey Sverdlov</a></td>
<td><a target="other" href="http://www.uni-vologda.ac.ru/~c3c/jco/">J.Class Optimizer</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
<td>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.smardec.com/">Smardec</a></td>
-<td><a target="other" href="//www.allatori.com/">Allatori</a></td>
-<td align="center"><br></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td><a target="other" href="http://www.allatori.com/">Allatori</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://cs.arizona.edu/">U. of Arizona</a></td>
<td><a target="other" href="http://sandmark.cs.arizona.edu/">SandMark</a></td>
-<td align="center"><br></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.force5.com/">Force 5</a></td>
-<td><a target="other" href="http://www.force5.com/">JCloak</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><a target="other" rel="nofollow" href="http://zenofx.com/">Zenofx</a></td>
+<td><a target="other" href="http://zenofx.com/classguard/">ClassGuard</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>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.semdesigns.com/">Semantic Designs</a></td>
-<td><a target="other" href="http://www.semdesigns.com/Products/Obfuscators/JavaObfuscator.html">Obfuscator</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><a target="other" rel="nofollow" href="http://www.bisguard.com/">BIS Guard &amp; Co.</a></td>
+<td><a target="other" href="http://www.bisguard.com/java.html">Java Antidecompiler</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>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.duckware.com/">Duckware</a></td>
-<td><a target="other" href="http://www.duckware.com/jobfuscate/">Jobfuscate</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><a target="other" rel="nofollow" href="http://www.force5.com/">Force 5</a></td>
+<td><a target="other" href="http://www.force5.com/JCloak/ProductJCloak.html">JCloak</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>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.jproof.com/">JProof</a></td>
-<td><a target="other" href="http://www.jproof.com/">JProof</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><a target="other" rel="nofollow" href="http://www.semdesigns.com/">Semantic Designs</a></td>
+<td><a target="other" href="http://www.semdesigns.com/Products/Obfuscators/JavaObfuscator.html">Obfuscator</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>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.solutia.ro/">GITS</a></td>
-<td><a target="other" href="http://www.solutia.ro/pages/javadc/">Blurfuscator</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><a target="other" rel="nofollow" href="http://www.duckware.com/">Duckware</a></td>
+<td><a target="other" href="http://www.duckware.com/jobfuscate/">Jobfuscate</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>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://www.chainkey.com/">ChainKey</a></td>
-<td><a target="other" href="http://www.chainkey.com/en/jcp/">Java Code Protector</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><a target="other" rel="nofollow" href="http://secureteam.net/index.aspx">Secureteam</a></td>
+<td><a target="other" href="http://secureteam.net/Java-Obfuscator-Features.aspx">Jfuscator</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>Commercial</td>
</tr>
<tr>
-<td><a target="other" rel="nofollow" href="http://sourceforge.net/projects/flmobf/">Alain Moran</a></td>
-<td><a target="other" href="http://sourceforge.net/projects/flmobf/">flmObf</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 (BSD)</td>
+<td><a target="other" rel="nofollow" href="http://www.arxan.com/">Arxan</a></td>
+<td><a target="other" href="http://www.arxan.com/products/guardit-for-java/">GuardIT</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>Commercial</td>
</tr>
<tr>
<td><a target="other" rel="nofollow" href="http://www.chez.com/vasile/">Vasile Calmatui</a></td>
<td><a target="other" href="http://www.chez.com/vasile/obfu/VasObfuLite.html">VasObfuLite</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 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</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.alphaworks.ibm.com/">IBM AlphaWorks</a></td>
<td><a target="other" href="http://www.research.ibm.com/jax/">JAX</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
<td>(discontinued)</td>
</tr>
<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.nq4.de/">NQ4</a></td>
+<td><a target="other" rel="nofollow" href="http://www.nq4.de/">Joga</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www-i2.informatik.rwth-aachen.de/~markusj/">Markus Jansen</a></td>
<td><a target="other" rel="nofollow" href="http://www-i2.informatik.rwth-aachen.de/~markusj/jopt/">Jopt</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.geocities.com/CapeCanaveral/Hall/2334/resume.html">Alexander Shvets</a></td>
+<td><a target="other" rel="nofollow" href="http://www.geocities.com/CapeCanaveral/Hall/2334/Programs/cafebabe.html">CafeBabe</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://darcs.brianweb.net/">Brian Alliet</a></td>
+<td><a target="other" rel="nofollow" href="http://darcs.brianweb.net/gcclass/">Gcclass</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.cs.purdue.edu/homes/grothoff/">Christian Grothoff</a></td>
+<td><a target="other" rel="nofollow" href="http://www.ovmj.org/jamit/">Jamit</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://donquixote.cafebabe.jp/">Haruaki Tamada</a></td>
+<td><a target="other" rel="nofollow" href="http://donquixote.cafebabe.jp/">DonQuixote</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.utdallas.edu/~gxz014000/">Bajie</a></td>
+<td><a target="other" rel="nofollow" href="http://www.utdallas.edu/~gxz014000/jcmp/">JCMP</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.elegant-software.com/">Elegant Software</a></td>
+<td><a target="other" rel="nofollow" href="http://www.elegant-software.com/software/jmangle/">JMangle</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>(disappeared?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.primenet.com/~ej">Eron Jokipii</a></td>
<td><a target="other" rel="nofollow" href="http://www.primenet.com/~ej">Jobe</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 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>(disappeared?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://jrc.krdl.org.sg/">JRC</a></td>
<td><a target="other" rel="nofollow" href="http://jrc.krdl.org.sg/decaf/">DeCaf</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 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>(disappeared?)</td>
</tr>
<tr class="disappeared">
-<td><a target="other" rel="nofollow" href="http://www.utdallas.edu/~gxz014000/">Bajie</a></td>
-<td><a target="other" rel="nofollow" href="http://www.utdallas.edu/~gxz014000/jcmp/">JCMP</a></td>
-<td align="center"><br></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></td>
-<td align="center"><br></td>
+<td><a target="other" rel="nofollow" href="http://www.drjava.de/">Dr. Java</a></td>
+<td><a target="other" rel="nofollow" href="http://www.drjava.de/obfuscator/">Marvin Obfuscator</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>(disappeared?)</td>
</tr>
<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.ibm.com/">IBM</a></td>
+<td><a target="other" rel="nofollow" href="http://www-306.ibm.com/software/wireless/wsdd/">WSDD</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.s5systems.com/">S5 Systems</a></td>
+<td><a target="other" rel="nofollow" href="http://www.s5systems.com/jPresto.htm">jPresto</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.plumbdesign.com/">Plumb Design</a></td>
<td><a target="other" rel="nofollow" href="http://www.condensity.com/">Condensity</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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 align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial (discontinued)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.4thpass.com/">4th Pass</a></td>
<td><a target="other" rel="nofollow" href="http://www.4thpass.com/">SourceGuard</a></td>
-<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x"></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 align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.codingart.com/">CodingArt</a></td>
+<td><a target="other" rel="nofollow" href="http://www.codingart.com/codeshield.html">CodeShield</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial (discontinued?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.software4j.com/">Software4j</a></td>
<td><a target="other" rel="nofollow" href="http://www.software4j.com/obfuscate4j/">Obfuscate4j</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 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>Commercial (discontinued?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.jammconsulting.com/">JAMM Consulting</a></td>
<td><a target="other" rel="nofollow" href="http://www.jammconsulting.com/jamm/servlet/com.jammconsulting.servlet.JAMMServlet?pageId=ObfuscateProPage">ObfuscatePro</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 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>Commercial (discontinued?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.jdevelop.com/">JDevelop</a></td>
<td><a target="other" rel="nofollow" href="http://www.jdevelop.com/best-java-obfuscator.html">JSCO</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 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>Commercial (discontinued?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.4fang.net/">4Fang</a></td>
<td><a target="other" rel="nofollow" href="http://www.4fang.net/jmix/">JMix</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 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>Commercial (discontinued?)</td>
</tr>
<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.retrologic.com/">RetroLogic</a></td>
+<td><a target="other" rel="nofollow" href="http://www.retrologic.com/">RetroGuard</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.helseth.com/">Helseth</a></td>
+<td><a target="other" rel="nofollow" href="http://www.helseth.com/HJO.htm">JObfuscator</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.vegatech.com/">Vega Technologies</a></td>
+<td><a target="other" rel="nofollow" href="http://www.vegatech.com/jzipper/">JZipper</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></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>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.jproof.com/">JProof</a></td>
+<td><a target="other" rel="nofollow" href="http://www.jproof.com/">JProof</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>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.chainkey.com/">ChainKey</a></td>
+<td><a target="other" rel="nofollow" href="http://www.chainkey.com/en/jcp/">Java Code Protector</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>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.2lkit.com/">2LKit</a></td>
<td><a target="other" rel="nofollow" href="http://www.2lkit.com/products/2LKitObf/index.htm">2LKit Obfuscator</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 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>Commercial (disappeared?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.wingsoft.com/">WingSoft</a></td>
<td><a target="other" rel="nofollow" href="http://www.wingsoft.com/wingguard.html">WingGuard</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 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>Commercial (disappeared?)</td>
</tr>
<tr class="disappeared">
<td><a target="other" rel="nofollow" href="http://www.sbktech.org/">HashJava</a></td>
<td><a target="other" rel="nofollow" href="http://www.sbktech.org/">HashJava</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 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>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.solutia.ro/">GITS</a></td>
+<td><a target="other" rel="nofollow" href="http://www.solutia.ro/pages/javadc/">Blurfuscator</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>Commercial (disappeared?)</td>
</tr>
@@ -647,10 +748,11 @@ below is incorrect.
<p>
All trademarks are property of their respective holders.
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/android_shades.png b/docs/android_shades.png
new file mode 100644
index 0000000..96e54f0
--- /dev/null
+++ b/docs/android_shades.png
Binary files differ
diff --git a/docs/dexguard.png b/docs/dexguard.png
new file mode 100644
index 0000000..ed8f1f4
--- /dev/null
+++ b/docs/dexguard.png
Binary files differ
diff --git a/docs/downloads.html b/docs/downloads.html
index ebd1b28..2baa929 100644
--- a/docs/downloads.html
+++ b/docs/downloads.html
@@ -1,11 +1,22 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Downloads</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -16,33 +27,201 @@ License. Please consult the <a href="license.html">license page</a> for more
details.
<p>
<b>ProGuard</b> is written in Java, so it requires a Java Runtime Environment
- (JRE 1.4 or higher).
+ (JRE 1.5 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
+You can download the latest release (containing the program jars, the
+documentation that you're reading now, examples, and the source code) from this
location:
<p>
-<center><a href="http://sourceforge.net/project/showfiles.php?group_id=54750"
-target="other">Download section</a> (at <a
-href="http://sourceforge.net/projects/proguard/"
-target="other">SourceForge</a>)</center>
+<center><a href="http://sourceforge.net/projects/proguard/files/"
+target="other">Download section at SourceForge</a></center>
<p>
+The <a href="http://sourceforge.net/projects/proguard/files/proguard/"
+target="other">proguard</a> section contains major releases and updates with
+sub-minor version numbers, for applying emergency fixes. The
+<a href="http://sourceforge.net/projects/proguard/files/proguard%20beta/"
+target="other">proguard beta</a> section contains beta releases. These include
+new features and any less urgent bug fixes collected since the previous
+release.
+<p>
If you're still working with an older version of <b>ProGuard</b>, check out
the summary of changes below, to see if you're missing something essential.
Better look at the up-to-date <a
href="http://proguard.sourceforge.net/downloads.html">on-line version</a> if
-you're reading a local copy of this page.
-<p>
-The download section may also contain updates with sub-minor version numbers.
-These versions are typically released shortly after their parent versions, for
-applying emergency fixes. Please make sure to look at those if you are
-encountering any problems with recent releases.
-<p>
-Finally, there may be beta versions of upcoming releases. They may be of
-interest too, because they typically contain any less urgent bug fixes
-collected since the previous release.
+you're reading a local copy of this page. Unless noted otherwise,
+<b>ProGuard</b> remains compatible across versions, so don't be afraid to
+update.
<p>
+If you're only interested in individual jar files for your build process, you
+can also download them from the Maven Central repository, with GroupId
+<a href="http://search.maven.org/#search|ga|1|g:%22net.sf.proguard%22"
+target="other">net.sf.proguard</a> and ArtifactIds
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-parent%22"
+target="other">proguard-parent</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-base%22"
+target="other">proguard-base</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-gui%22"
+target="other">proguard-gui</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-anttask%22"
+target="other">proguard-anttask</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-gradle%22"
+target="other">proguard-gradle</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-wtk-plugin%22"
+target="other">proguard-wtk-plugin</a>, and
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-retrace%22"
+target="other">proguard-retrace</a>.
+
+<h3><div>Jul 2013</div> Version 4.10</h3>
+<ul>
+<li>Made Gradle task resolve files lazily.
+<li>Enabled as-needed execution in Gradle task.
+<li>Using standard string interpolation for Gradle configuration.
+<li>Reduced log levels for console output in Gradle task.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Mar 2013</div> Version 4.9</h3>
+<ul>
+<li>Added Gradle task.
+<li>Added more peephole optimizations for strings.
+<li>Improved optimization of classes with static initializers.
+<li>Improved processing of finally blocks compiled with JDK 1.4 or older.
+<li>Fixed shrinking of access widening abstract methods, for the Dalvik VM.
+<li>Fixed overly aggressive shrinking of class annotations.
+<li>Fixed processing of unused classes in generic signatures.
+<li>Fixed merging of classes with similar class members.
+<li>Added java system property <code>optimize.conservatively</code> to allow
+ for instructions intentionally throwing <code>NullPointerException</code>,
+ <code>ArrayIndexOutOfBoundsException</code>, or
+ <code>ClassCastException</code> without other useful effects.
+<li>Fixed optimization of unnecessary variable initializations.
+<li>Fixed optimization of code involving NaN.
+<li>Fixed inlining of methods that are supposed to be kept.
+<li>Fixed preverification of artificially convoluted dup constructs.
+<li>Fixed quotes for java commands in .bat scripts.
+<li>Improved handling of non-sequential line number information.
+<li>Now requiring Java 5 or higher for running ProGuard.
+<li>Updated build files.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>May 2012</div> Version 4.8</h3>
+<ul>
+<li>Added more peephole optimizations for strings.
+<li>Added support for multiple external configuration files in Ant
+ configurations.
+<li>Added support for Ant properties in external configuration files.
+<li>Fixed parsing of empty file filters on input and output.
+<li>Fixed parsing of '*' wildcard for file filters and name filters.
+<li>Fixed obfuscation of private methods that are overridden in concrete
+ classes with intermediary abstract classes and interfaces (workaround
+ for Oracle bugs #6691741 and #6684387).
+<li>Fixed optimization of complex finally blocks, compiled with JDK 1.4 or
+ earlier.
+<li>Fixed optimizing signatures of methods that are marked as not having
+ side effects.
+<li>Fixed optimization of long local variables possibly causing verification
+ error for register pairs.
+<li>Fixed merging of classes defined inside methods.
+<li>Fixed stack consistency in optimization step.
+<li>No longer removing debug information about unused parameters, for
+ <code>-keepparameternames</code> or <code>-keepattributes</code>.
+<li>Fixed updating manifest files with carriage return characters.
+<li>Now removing unreachable code in preverification step.
+<li>Improved default regular expression for stack traces in ReTrace.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2011</div> Version 4.7</h3>
+<ul>
+<li>Added support for Java 7.
+<li>Parsing unquoted file names with special characters more leniently.
+<li>Added support for instance methods overriding class methods.
+<li>Added removal of unused parameterless constructors.
+<li>Added removal of empty class initializers.
+<li>Added peephole optimizations for constant strings.
+<li>Avoiding idle optimization passes.
+<li>Improved removal of unused constants after obfuscation.
+<li>Fixed removal of unused classes referenced by annotations.
+<li>Fixed simplifying parameters of constructors that should actually be
+ preserved.
+<li>Fixed simplifying parameters of large numbers of similar constructors.
+<li>Fixed exceptions in optimization of unusual obfuscated code.
+<li>Fixed NullPointerException when specifying <code>-keepclassmembers</code>
+ without specific class or class members.
+<li>Fixed potential problems with mixed-case class name dictionaries when not
+ allowing mixed-case class names.
+<li>Fixed obfuscation of classes with EnclosingMethod attributes that don't
+ specify methods.
+<li>Fixed preverification of returning try blocks with finally blocks, inside
+ try blocks, when compiled with JDK 1.4.
+<li>Fixed sorting of interfaces containing generics.
+<li>Fixed paths in shell scripts.
+<li>Fixed filling in of text fields showing class obfuscation dictionary and
+ package obfuscation dictionary from configuration in GUI.
+<li>Worked around Oracle Java 6/7 bug #7027598 that locked the GUI on Linux.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Feb 2011</div> Version 4.6</h3>
+<ul>
+<li>Added support for synthetic, bridge, and varargs modifiers in configuration.
+<li>Added detection of atomic updater construction with constant arguments.
+<li>Fixed merging of package visible classes.
+<li>Fixed optimization of fields that are only accessed by reflection.
+<li>Fixed optimization of read-only or write-only fields that are volatile.
+<li>Fixed handling of side-effects due to static initializers.
+<li>Fixed handling of bridge flags in obfuscation step.
+<li>Fixed handling of super flag when merging classes.
+<li>Fixed updating of variable tables when optimizing variables.
+<li>Fixed removal of unused parameters with 32 or more parameters.
+<li>Fixed incorrect removal of exception handler for instanceof instruction.
+<li>Fixed inlining of methods with unusual exception handlers.
+<li>Fixed optimization of unusual code causing stack underflow.
+<li>Fixed keeping of constructor parameter names.
+<li>Fixed unwanted wrapping of non-standard META-INF files.
+<li>Fixed filtering of warnings about references to array types.
+<li>Fixed overriding of warning option and note option in Ant task.
+<li>Improved detection of file name extensions for canonical paths.
+<li>Improved printing of seeds specified by <code>-keep</code> options.
+<li>Improved printing of notes about unkept classes.
+<li>Improved checking whether output is up to date.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jun 2010</div> Version 4.5</h3>
+<ul>
+<li>Added option <code>-keepparameternames</code>.
+<li><code>-dontskipnonpubliclibraryclasses</code> is now set by default. Added
+ <code>-skipnonpubliclibraryclasses</code> as an option.
+<li>Made processing independent of order of input classes to get even more
+ deterministic output.
+<li>Improved constant field propagation.
+<li>Improved renaming of resource files in subdirectories of packages.
+<li>Avoiding making fields in interfaces private.
+<li>Optimizing exception handlers for monitorexit instruction.
+<li>Reduced maximum allowed code length after inlining from 8000 bytes to
+ 7000 bytes.
+<li>Fixed missing warnings about missing library classes.
+<li>Fixed shrinking of annotations with arrays of length 0.
+<li>Fixed handling of -0.0 and NaN values when simplifying expressions.
+<li>Fixed copying of exception handlers when simplifying tail recursion calls.
+<li>Fixed optimization of introspected fields.
+<li>Fixed simplification of unnecessary variable initializations.
+<li>Fixed evaluation of subroutines in pre-JDK 1.5 code.
+<li>Fixed updating of access flags in inner classes information.
+<li>Fixed disabling of field privatization.
+<li>Fixed invocations of privatized methods.
+<li>Fixed updating of local variable debug information in optimization step.
+<li>Fixed print settings without file name in GUI.
+<li>Fixed field privatization setting in GUI.
+<li>Fixed saving incorrectly quoted arguments in GUI.
+<li>Fixed handling of regular expressions with only negators.
+<li>Fixed unwanted wrapping of non-standard META-INF files.
+<li>Fixed regular expression pattern for constructors in ReTrace.
+<li>Updated documentation and examples.
+</ul>
<h3><div>Jul 2009</div> Version 4.4</h3>
<ul>
@@ -511,10 +690,11 @@ Upgrade considerations:
<b>RetroGuard</b>.
</ul>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/feedback.html b/docs/feedback.html
index a7e770b..dd9c509 100644
--- a/docs/feedback.html
+++ b/docs/feedback.html
@@ -1,4 +1,4 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
@@ -6,52 +6,63 @@
<meta http-equiv="content-style-type" content="text/css">
<link rel="stylesheet" type="text/css" href="style.css">
<title>ProGuard Feedback</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
<h2>Feedback</h2>
-By now, I've invested a fair amount of time in <b>ProGuard</b>. You can help
-by providing feedback! If you have problems, bugs, bug fixes, ideas,
+By now, I've invested an enormous amount of time in <b>ProGuard</b>. You can
+help by providing feedback! If you have problems, bugs, bug fixes, ideas,
encouragements, etc., please let me know:
<p>
-<ul>
-<li>The <a href="http://sourceforge.net/forum/forum.php?forum_id=182456"
- target="other">help forum</a> (at SourceForge) is the right place to ask
- questions about any problems you might have configuring and running
- <b>ProGuard</b>.
- <p>
+<ul class="spacious">
+<li>Through
+ <a href="http://www.saikoa.com/proguard/support" target="_top">Saikoa</a>,
+ we provide professional support for ProGuard. If you find ProGuard useful
+ and you would like to have some professional backing, this is the place to
+ go.</li>
-<li>The <a href="http://sourceforge.net/forum/forum.php?forum_id=182455"
- target="other">open discussion forum</a> (at SourceForge) offers a place
- to share your thoughts and discuss new ideas.
- <p>
-
-<li>The <a
+<li>The <a href="https://sourceforge.net/projects/proguard/forums/forum/182456"
+ target="other">help forum</a> (at SourceForge)
+ and <a href="http://stackoverflow.com/questions/tagged/proguard"
+ target="other">Stack Overflow</a> are common places to ask questions about
+ any problems you might have configuring and running ProGuard. At this
+ time, I can generally only assist other open source projects though. If
+ you're working on commercial software, please consider our professional
+ support above.</li>
- href="http://sourceforge.net/tracker/?atid=474704&group_id=54750&func=browse"
- target="other">bug tracking page</a> (at SourceForge) allows you to submit
- and consult bug reports. Please make sure the reports are complete and
- concise. If I can't reproduce the problem, I most likely can't fix it
- either.
- <p>
+<li>The <a href="https://sourceforge.net/projects/proguard/forums/forum/182455"
+ target="other">open discussion forum</a> (at SourceForge) offers a place
+ to share your thoughts and discuss new ideas.</li>
-<li>The <a
+<li>The <a href="http://sourceforge.net/p/proguard/bugs/" target="other">bug
+ tracking page</a> (at SourceForge) allows you to submit and consult bug
+ reports. Please make sure the reports are complete and concise. If I can't
+ reproduce the problem, I most likely can't fix it either.</li>
- href="http://sourceforge.net/tracker/?atid=474707&group_id=54750&func=browse"
+<li>The <a href="http://sourceforge.net/p/proguard/feature-requests/"
target="other">feature request page</a> (at SourceForge) allows you to
submit and consult feature requests. I generally have my own road map in
mind, but this is the place express your interest in new and existing
- ideas.
- <p>
+ ideas.</li>
-<li>The <a href="http://sourceforge.net/project/showfiles.php?group_id=54750"
+<li>The <a href="https://sourceforge.net/projects/proguard/files/"
target="other">download section</a> at SourceForge and the <a
- href="http://software.freshmeat.net/projects/proguard/"
- target="other">project page</a> at FreshMeat offer the possibility to
- subscribe to the announcements of new releases. They are the most
- efficient way to stay abreast of the latest developments.
- <p>
+ href="http://software.freecode.com/projects/proguard"
+ target="other">project page</a> at Freecode (Freshmeat) offer the
+ possibility to subscribe to the announcements of new releases. They are
+ the most efficient way to stay abreast of the latest developments.</li>
<li>For anything that doesn't fall in the above categories, you can mail me
directly at
@@ -84,11 +95,11 @@ document.write("</a>");
<em>or</em> at
&lt;&nbsp;eric&nbsp;&#64;&nbsp;graphics&nbsp;.&nbsp;cornell&nbsp;.&nbsp;edu&nbsp;&gt; (please remove the spaces)
</noscript>
-.
+.</li>
</ul>
<p>
-I can't promise a swift answer, or any answer at all, for that matter, but I
-like seeing any constructive comments.
+I can't promise a swift answer, or any answer at all, for that matter, but it's
+always great to see constructive comments.
<p>
<b>ProGuard</b> isn't a typical open source project, in the sense that I am
@@ -96,10 +107,11 @@ like seeing any constructive comments.
do things my way, without the overhead and compromises associated with larger
projects.
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/index.html b/docs/index.html
index 771bb6a..ba40d16 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,4 +1,4 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
@@ -11,18 +11,38 @@
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
<title>ProGuard</title>
</head>
+
+<script type="text/javascript" language="JavaScript">
+//<!--
+ var destWindowHash = window.location.hash;
+ function mainFrameLoaded() {
+ if (destWindowHash.length > 1) {
+ var destFrameFile = destWindowHash.substring(1);
+ var currFrameFile = frames["main"].location.href.replace(window.location.href.replace(/index.html.*/, ""), "");
+ if (currFrameFile != destFrameFile) {
+ frames["main"].location.replace(destFrameFile);
+ if (destFrameFile.search("manual/") >= 0)
+ frames["sections"].location.replace("manual/sections.html");
+ }
+ destWindowHash = "";
+ }
+ }
+//-->
+</script>
+
<frameset
rows="50,*"
framespacing="0"
frameborder="no">
<frame
+ id="title"
name="title"
src="title.html"
scrolling="no"
marginwidth="0"
marginheight="0"
- noresize>
+ noresize="noresize" />
<frameset
cols="120,*"
@@ -30,20 +50,23 @@
frameborder="no">
<frame
+ id="sections"
name="sections"
src="sections.html"
scrolling="no"
marginwidth="0"
marginheight="0"
- noresize>
+ noresize="noresize" />
<frame
+ id="main"
name="main"
src="main.html"
scrolling="auto"
marginwidth="10"
marginheight="10"
- noresize>
+ noresize="noresize"
+ onload="mainFrameLoaded()" />
</frameset>
</frameset>
@@ -51,21 +74,22 @@
<noframes>
<body>
<p class="intro">
-<b>ProGuard</b> is a free Java class file shrinker, optimizer, and obfuscator.
-It can detect and remove unused classes, fields, methods, and attributes. It
-can then optimize bytecode and remove unused instructions. Finally, it can
-rename the remaining classes, fields, and methods using short meaningless
-names. The resulting jars are smaller and harder to reverse-engineer.
+<b>ProGuard</b> is a free Java class file shrinker, optimizer, obfuscator, and
+preverifier. It detects and removes unused classes, fields, methods, and
+attributes. It optimizes bytecode and removes unused instructions. It renames
+the remaining classes, fields, and methods using short meaningless names.
+Finally, it preverifies the processed code for Java 6 or for Java Micro
+Edition.
</p>
<p>
Your browser doesn't support frames, but that's cool.
<p>
You can go straight to the <a href="main.html">main page</a>.
-<hr>
+<hr />
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</noframes>
diff --git a/docs/license.html b/docs/license.html
index b4654fd..d1077b8 100644
--- a/docs/license.html
+++ b/docs/license.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard License</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -29,19 +40,22 @@ 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"
target="other">FSF</a>), for combinations with the following stand-alone
-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.
+applications: Apache Ant, Apache Maven, the Google Android SDK, the Eclipse
+ProGuardDT GUI, the EclipseME JME IDE, the Oracle NetBeans Java IDE, the
+Oracle JME Wireless Toolkit, the Intel TXE SDK, the Simple Build Tool for
+Scala, the NeoMAD Tools by Neomades, the Javaground Tools, and the Sanaware
+Tools.
<p>
The <b>ProGuard user documentation</b> represents an important part of this
work. It may only be redistributed without changes, along with the unmodified
version of the code.
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/luciadlogo.png b/docs/luciadlogo.png
deleted file mode 100644
index 0147ce3..0000000
--- a/docs/luciadlogo.png
+++ /dev/null
Binary files differ
diff --git a/docs/main.html b/docs/main.html
index e988c79..988d87c 100644
--- a/docs/main.html
+++ b/docs/main.html
@@ -1,4 +1,4 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
@@ -8,6 +8,16 @@
<meta name="keywords" content="java obfuscator, optimizer, shrinker, preverfier">
<link rel="stylesheet" type="text/css" href="style.css">
<title>ProGuard Main</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ if (window.top.location.hash!="")
+ window.top.location.hash="";
+}
+//-->
+</script>
</head>
<body>
@@ -18,32 +28,28 @@
preverifier. It detects and removes unused classes, fields, methods, and
attributes. It optimizes bytecode and removes unused instructions. It renames
the remaining classes, fields, and methods using short meaningless names.
-Finally, it preverifies the processed code for Java 6 or for Java Micro
-Edition.
+Finally, it preverifies the processed code for Java 6 or higher, or for Java
+Micro Edition.
</p>
Some uses of <b>ProGuard</b> are:
<ul>
<li>Creating more compact code, for smaller code archives, faster transfer
- across networks, faster loading, and smaller memory footprints.
+ across networks, faster loading, and smaller memory footprints.</li>
-<li>Making programs and libraries harder to reverse-engineer.
+<li>Making programs and libraries harder to reverse-engineer.</li>
-<li>Listing dead code, so it can be removed from the source code.
+<li>Listing dead code, so it can be removed from the source code.</li>
-<li>Retargeting and preverifying existing class files for Java 6, to take full
- advantage of Java 6's faster class loading.
+<li>Retargeting and preverifying existing class files for Java 6 or higher, to
+ take full advantage of their faster class loading.</li>
</ul>
<p>
<b>ProGuard</b>'s main advantage compared to other Java obfuscators is
probably its compact template-based configuration. A few intuitive command
-line options or a simple configuration file are usually sufficient. For
-instance, the following configuration option preserves all applets in a jar:
-<pre>
- -keep public class * extends java.applet.Applet
-</pre>
-The user manual explains all available options and shows more examples of this
+line options or a simple configuration file are usually sufficient.
+The user manual explains all available options and shows examples of this
powerful configuration style.
<p>
<b>ProGuard</b> is fast. It only takes seconds to process programs and
@@ -51,42 +57,48 @@ libraries of several megabytes. The results section presents actual figures
for a number of applications.
<p>
<b>ProGuard</b> is a command-line tool with an optional graphical user
-interface. It also comes with plugins for Ant and for the JME Wireless
-Toolkit.
+interface. It also comes with plugins for Ant, for Gradle, and for the JME
+Wireless Toolkit.
<p>
<p class="intro">
-Version 4.0 introduced preverification and more bytecode optimizations. Please
-report any problems, so they can be fixed soon.
+<a href="http://www.saikoa.com/dexguard" target="_top">
+<img align="left" src="android_shades.png" width="64" height="64" /></a>
+<b>ProGuard</b> now has a sibling optimizer and obfuscator for Android:
+<a href="http://www.saikoa.com/dexguard" target="_top"><b>DexGuard</b></a>. It
+focuses on code protection, with additional features like string encryption
+and class encryption. It directly targets Dalvik bytecode and streamlines the
+Android build process.
</p>
The following sections provide more detailed information:
<ul>
-<li><a href="main.html">Main</a>: this overview page.
+<li><a href="main.html">Main</a>: this overview page.</li>
<li><a href="results.html">Results</a>: some results obtained with
- <b>ProGuard</b>, including timings and memory usage.
-<li><a href="FAQ.html">FAQ</a>: answers to some Frequently Asked Questions.
+ <b>ProGuard</b>, including timings and memory usage.</li>
+<li><a href="FAQ.html">FAQ</a>: answers to some Frequently Asked Questions.</li>
<li><a href="manual/index.html">Manual</a>: the complete <b>ProGuard</b> user
- manual, with examples and troubleshooting tips.
+ manual, with examples and troubleshooting tips.</li>
<li><a href="quality.html">Quality</a>: a discussion of the (excellent) quality
- of <b>ProGuard</b>'s code.
-<li><a href="screenshots.html">Screenshots</a>: some impressions of what <b>ProGuard</b> looks like.
+ of <b>ProGuard</b>'s code.</li>
+<li><a href="screenshots.html">Screenshots</a>: some impressions of what <b>ProGuard</b> looks like.</li>
<li><a href="testimonials.html">Testimonials</a>: what users think of
- <b>ProGuard</b>.
+ <b>ProGuard</b>.</li>
<li><a href="license.html">License</a>: <b>ProGuard</b> is free, under a GPL
- license.
+ license.</li>
<li><a href="downloads.html">Downloads</a>: download the <b>ProGuard</b>
- package yourself.
+ package yourself.</li>
<li><a href="feedback.html">Feedback</a>: tell me about your experiences, or
- learn from others on our forums.
+ learn from others on our forums.</li>
<li><a href="acknowledgements.html">Acknowledgements</a>: people who have been
- helpful.
+ helpful.</li>
<li><a href="alternatives.html">Alternatives</a>: other Java obfuscators,
- optimizers, and shrinkers.
+ optimizers, and shrinkers.</li>
</ul>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/android_small.png b/docs/manual/android_small.png
new file mode 100644
index 0000000..0313515
--- /dev/null
+++ b/docs/manual/android_small.png
Binary files differ
diff --git a/docs/manual/ant.html b/docs/manual/ant.html
index bc3a3b4..0837bbb 100644
--- a/docs/manual/ant.html
+++ b/docs/manual/ant.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>Ant Task</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -28,10 +39,14 @@ this new task. The easiest way is to add the following line to your
Please make sure the class path is set correctly for your system.
<p>
-There are three ways to configure the ProGuard task: using an external
-configuration file, using embedded ProGuard configuration options, or using
-the equivalent XML configuration tags. These three ways can be combined,
-depending on practical circumstances and personal preference.
+There are three ways to configure the ProGuard task:
+<ol>
+<li>using an external configuration file,</li>
+<li>using embedded ProGuard configuration options, or</li>
+<li>using the equivalent XML configuration tags.</li>
+</ol>
+These three ways can be combined, depending on practical circumstances and
+personal preference.
<p>
<h3>1. An external ProGuard configuration file</h3>
@@ -89,11 +104,11 @@ can be removed.
<p>
Secondly, the use of <code>&lt;</code> and <code>&gt;</code> characters would
-upset the structure of the XML build file. Environment variables are now
-enclosed by an opening <code>${</code> and a closing <code>}</code>. This
-syntax also allows you to use Ant properties within the ProGuard
-configuration. Other occurrences of <code>&lt;</code> and <code>&gt;</code>
-have to be encoded as <code>&amp;lt;</code> and <code>&amp;gt;</code>.
+upset the structure of the XML build file. Environment variables can be
+specified with the usual Ant style <code>${...}</code>, instead of the ProGuard
+style <code>&lt;...&gt;</code>. Other occurrences of <code>&lt;</code> and
+<code>&gt;</code> have to be encoded as <code>&amp;lt;</code> and
+<code>&amp;gt;</code> respectively.
<p>
<h3>3. XML configuration tags</h3>
@@ -107,8 +122,7 @@ 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>
-<a name="proguard">&nbsp;</a>
-<h2>Task Attributes and Nested Elements</h2>
+<h2><a name="proguard">Task Attributes and Nested Elements</a></h2>
The <code><b>&lt;proguard&gt;</b></code> task and the
<code><b>&lt;proguardconfiguration&gt;</b></code> task can have the following
@@ -120,13 +134,14 @@ elements:
<dt><a name="configuration_attribute"><code><b>configuration</b></code></a>
= "<i>filename</i>"</dt>
<dd>Read and merge options from the given ProGuard-style configuration
- file. Note: for reading XML-style configurations, use the <a
+ file. Note: for reading multiple configuration files or XML-style
+ configurations, use the <a
href="#configuration_element"><code>configuration</code></a>
<i>element</i>.</dd>
-<dt><a href="usage.html#dontskipnonpubliclibraryclasses"><code><b>skipnonpubliclibraryclasses</b></code></a>
+<dt><a href="usage.html#skipnonpubliclibraryclasses"><code><b>skipnonpubliclibraryclasses</b></code></a>
= "<i>boolean</i>"
- (default = true)</dt>
+ (default = false)</dt>
<dd>Ignore non-public library classes.</dd>
<dt><a href="usage.html#dontskipnonpubliclibraryclassmembers"><code><b>skipnonpubliclibraryclassmembers</b></code></a>
@@ -242,6 +257,11 @@ elements:
<dd>Repackage all class files that are renamed into the single given
package.</dd>
+<dt><a href="usage.html#keepparameternames"><code><b>keepparameternames</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Keep the parameter names and types of methods that are kept.</dd>
+
<dt><a href="usage.html#renamesourcefileattribute"><code><b>renamesourcefileattribute</b></code></a>
= "<i>string</i>"
(default = none)</dt>
@@ -257,7 +277,7 @@ elements:
<dt><a href="usage.html#microedition"><code><b>microedition</b></code></a>
= "<i>boolean</i>"
(default = false)</dt>
-<dd>Targets the processed class files at Java Micro Edition.</dd>
+<dd>Target the processed class files at Java Micro Edition.</dd>
<dt><a href="usage.html#verbose"><code><b>verbose</b></code></a>
= "<i>boolean</i>"
@@ -305,7 +325,7 @@ elements:
<dt><a href="usage.html#outjars"><code><b>&lt;outjar</b></code></a>
<a href="#classpath"><i>class_path</i></a>
<code><b>/&gt;</b></code></dt>
-<dd>Specifies the name of the output jars (or wars, ears, zips, or
+<dd>Specifies the names of the output jars (or wars, ears, zips, or
directories).</dd>
<dt><a href="usage.html#libraryjars"><code><b>&lt;libraryjar</b></code></a>
@@ -436,23 +456,27 @@ elements:
filter. <i>Only use this option if you know what you're doing!</i></dd>
<dt><a name="configuration_element"><code><b>&lt;configuration refid = </b></code></a>"<i>ref_id</i>"
+ <code><b>/&gt;</b></code><br/>
+ <code><b>&lt;configuration file = </b></code>"<i>name</i>"
<code><b>/&gt;</b></code></dt>
-<dd>Includes the configuration specified in the
+<dd>The first form includes the XML-style configuration specified in a
<code>&lt;proguardconfiguration&gt;</code> task (or
- <code>&lt;proguard&gt;</code> task) with the attribute <code>id</code> =
- "<i>ref_id</i>". Note that only the nested elements of this configuration
- are considered, not the attributes. Also note: for reading ProGuard-style
- configuration files, use the <a
- href="#configuration_attribute"><code>configuration</code></a>
- <i>attribute</i>.</dd>
+ <code>&lt;proguard&gt;</code> task) with attribute <code>id</code> =
+ "<i>ref_id</i>". Only the nested elements of this configuration are
+ considered, not the attributes.
+ <p>
+ The second form includes the ProGuard-style configuration from the specified
+ file. The element is actually a <code>fileset</code> element and supports
+ all of its attributes and nested elements, including multiple files.
+ </dd>
</dl>
-<a name="classpath">&nbsp;</a>
-<h2>Class Path Attributes and Nested Elements</h2>
+<h2><a name="classpath">Class Path Attributes and Nested Elements</a></h2>
-The jar tags are path tags, so they can have any of the path attributes (or
-nested elements). The most common attributes are:
+The jar elements are <code>path</code> elements, so they can have any of the
+standard <code>path</code> attributes and nested elements. The most common
+attributes are:
<dl>
@@ -472,7 +496,7 @@ nested elements). The most common attributes are:
</dl>
-In addition, the jar tags can have ProGuard-style filter attributes:
+In addition, the jar elements can have ProGuard-style filter attributes:
<dl>
@@ -499,8 +523,7 @@ In addition, the jar tags can have ProGuard-style filter attributes:
</dl>
-<a name="keepmodifier">&nbsp;</a>
-<h2>Keep Modifier Attributes</h2>
+<h2><a name="keepmodifier">Keep Modifier Attributes</a></h2>
The keep tags can have the following <i>modifier</i> attributes:
@@ -526,8 +549,7 @@ The keep tags can have the following <i>modifier</i> attributes:
</dl>
-<a name="classspecification">&nbsp;</a>
-<h2>Class Specification Attributes and Nested Elements</h2>
+<h2><a name="classspecification">Class Specification Attributes and Nested Elements</a></h2>
The keep tags can have the following <i>class_specification</i> attributes and
<i>class_member_specifications</i> nested elements:
@@ -538,6 +560,10 @@ The keep tags can have the following <i>class_specification</i> attributes and
<dd>The optional access modifiers of the class. Any space-separated list of
"public", "final", and "abstract", with optional negators "!".</dd>
+<dt><code><b>annotation</b></code> = "<i>annotation_name</i>"</dt>
+<dd>The optional fully qualified name of an annotation of the class, with
+ optional wildcards.</dd>
+
<dt><code><b>type</b></code> = "<i>type</i>"</dt>
<dd>The optional type of the class: one of "class", "interface", or
"!interface".</dd>
@@ -546,6 +572,10 @@ The keep tags can have the following <i>class_specification</i> attributes and
<dd>The optional fully qualified name of the class, with optional
wildcards.</dd>
+<dt><code><b>extendsannotation</b></code> = "<i>annotation_name</i>"</dt>
+<dd>The optional fully qualified name of an annotation of the the class that
+ the specified classes must extend, with optional wildcards.</dd>
+
<dt><code><b>extends</b></code> = "<i>class_name</i>"</dt>
<dd>The optional fully qualified name of the class the specified classes
must extend, with optional wildcards.</dd>
@@ -571,8 +601,7 @@ The keep tags can have the following <i>class_specification</i> attributes and
</dl>
-<a name="classmemberspecification">&nbsp;</a>
-<h2>Class Member Specification Attributes</h2>
+<h2><a name="classmemberspecification">Class Member Specification Attributes</a></h2>
The class member tags can have the following <i>class_member_specification</i>
attributes:
@@ -584,6 +613,10 @@ attributes:
"public", "protected", "private", "static", etc., with optional negators
"!".</dd>
+<dt><code><b>annotation</b></code> = "<i>annotation_name</i>"</dt>
+<dd>The optional fully qualified name of an annotation of the class member,
+ with optional wildcards.</dd>
+
<dt><code><b>type</b></code> = "<i>type</i>"</dt>
<dd>The optional fully qualified type of the class member, with optional
wildcards. Not applicable for constructors, but required for methods for
@@ -601,10 +634,11 @@ attributes:
</dl>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/examples.html b/docs/manual/examples.html
index 3f47fca..804ae17 100644
--- a/docs/manual/examples.html
+++ b/docs/manual/examples.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Examples</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -12,76 +23,84 @@
Some typical useful configurations:
<ol>
-<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="#native">Processing native methods</a>
-<li><a href="#callback">Processing callback methods</a>
-<li><a href="#enumerations">Processing enumeration classes</a>
-<li><a href="#serializable">Processing serializable classes</a>
-<li><a href="#beans">Processing bean classes</a>
-<li><a href="#annotations">Processing annotations</a>
-<li><a href="#database">Processing database drivers</a>
-<li><a href="#componentui">Processing ComponentUI classes</a>
-<li><a href="#rmi">Processing RMI code</a>
-<li><a href="#resourcefiles">Processing resource files</a>
-<li><a href="#stacktrace">Producing useful obfuscated stack traces</a>
-<li><a href="#repackaging">Obfuscating package names</a>
-<li><a href="#restructuring">Restructuring the output archives</a>
-<li><a href="#filtering">Filtering the input and the output</a>
-<li><a href="#multiple">Processing multiple applications at once</a>
-<li><a href="#incremental">Incremental obfuscation</a>
-<li><a href="#microedition">Preverifying class files for Java Micro Edition</a>
-<li><a href="#upgrade">Upgrading class files to Java 6</a>
-<li><a href="#deadcode">Finding dead code</a>
-<li><a href="#structure">Printing out the internal structure of class files</a>
-<li><a href="#annotated">Using annotations to configure ProGuard</a>
+<li><a href="#application">A typical application</a></li>
+<li><a href="#applet">A typical applet</a></li>
+<li><a href="#midlet">A typical midlet</a></li>
+<li><a href="#jcapplet">A typical Java Card applet</a></li>
+<li><a href="#xlet">A typical xlet</a></li>
+<li><a href="#androidactivity">A simple Android activity</a></li>
+<li><a href="#androidapplication">A complete Android application</a></li>
+<li><a href="#library">A typical library</a></li>
+<li><a href="#applications">All possible applications in the input jars</a></li>
+<li><a href="#applets">All possible applets in the input jars</a></li>
+<li><a href="#midlets">All possible midlets in the input jars</a></li>
+<li><a href="#jcapplets">All possible Java Card applets in the input jars</a></li>
+<li><a href="#xlets">All possible xlets in the input jars</a></li>
+<li><a href="#servlets">All possible servlets in the input jars</a></li>
+<li><a href="#scala">Scala applications with the Scala runtime</a></li>
+<li><a href="#native">Processing native methods</a></li>
+<li><a href="#callback">Processing callback methods</a></li>
+<li><a href="#enumerations">Processing enumeration classes</a></li>
+<li><a href="#serializable">Processing serializable classes</a></li>
+<li><a href="#beans">Processing bean classes</a></li>
+<li><a href="#annotations">Processing annotations</a></li>
+<li><a href="#database">Processing database drivers</a></li>
+<li><a href="#componentui">Processing ComponentUI classes</a></li>
+<li><a href="#rmi">Processing RMI code</a></li>
+<li><a href="#injection">Processing resource injection</a></li>
+<li><a href="#resourcefiles">Processing resource files</a></li>
+<li><a href="#manifestfiles">Processing manifest files</a></li>
+<li><a href="#stacktrace">Producing useful obfuscated stack traces</a></li>
+<li><a href="#repackaging">Obfuscating package names</a></li>
+<li><a href="#logging">Removing logging code</a></li>
+<li><a href="#restructuring">Restructuring the output archives</a></li>
+<li><a href="#filtering">Filtering the input and the output</a></li>
+<li><a href="#multiple">Processing multiple applications at once</a></li>
+<li><a href="#incremental">Incremental obfuscation</a></li>
+<li><a href="#microedition">Preverifying class files for Java Micro Edition</a></li>
+<li><a href="#upgrade">Upgrading class files to Java 6</a></li>
+<li><a href="#deadcode">Finding dead code</a></li>
+<li><a href="#structure">Printing out the internal structure of class files</a></li>
+<li><a href="#annotated">Using annotations to configure ProGuard</a></li>
</ol>
You can find some sample configuration files in the <code>examples</code>
directory of the ProGuard distribution.
-<a name="application">&nbsp;</a>
-<h3>A typical application</h3>
-To shrink, optimize, and obfuscate the ProGuard application itself, one would
-typically create a configuration file <code>proguard.pro</code> and then type:
+<h3><a name="application">A typical application</a></h3>
+
+To shrink, optimize, and obfuscate a simple Java application, you typically
+create a configuration file like <code>myconfig.pro</code>, which can be used
+with
<pre>
-java -jar proguard.jar @proguard.pro
+bin/proguard @myconfig.pro
</pre>
<p>
-The configuration file would contain the following options:
+The configuration file specifies the input, the output, and the entry points
+of the application:
<pre>
--injars proguard.jar
--outjars proguard_out.jar
+-injars myapplication.jar
+-outjars myapplication_out.jar
-libraryjars &lt;java.home&gt;/lib/rt.jar
--printmapping proguard.map
+-printmapping myapplication.map
--keep public class proguard.ProGuard {
+-keep public class mypackage.MyMain {
public static void main(java.lang.String[]);
}
</pre>
<p>
-Note the use of the <code>&lt;java.home&gt;</code> system property; it is
-replaced automatically.
-<p>
-Also note that all type names are fully specified:
-<code>proguard.ProGuard</code> and <code>java.lang.String[]</code>.
+Note the use of the <code>&lt;java.home&gt;</code> system property. ProGuard
+automatically replaces it when parsing the file.
<p>
+The <a href="usage.html#keep"><code>-keep</code></a> option specifies the
+entry point of the application that has to be preserved.
The access modifiers <code>public</code> and <code>static</code> are not
really required in this case, since we know a priori that the specified class
and method have the proper access flags. It just looks more familiar this way.
<p>
+Note that all type names are fully specified:
+<code>mypackage.MyMain</code> and <code>java.lang.String[]</code>.
+<p>
We're writing out an obfuscation mapping file with <a
href="usage.html#printmapping"><code>-printmapping</code></a>, for
de-obfuscating any stack traces later on, or for incremental obfuscation of
@@ -103,11 +122,10 @@ href="#native">native methods</a>, <a href="#callback">callback methods</a>,
<a href="#enumerations">enumerations</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
-files</a>. For processing 'simple' applications like ProGuard, that is not
-required.
+files</a>.
+
+<h3><a name="applet">A typical applet</a></h3>
-<a name="applet">&nbsp;</a>
-<h3>A typical applet</h3>
These options shrink, optimize, and obfuscate the applet
<code>mypackage.MyApplet</code>:
<pre>
@@ -129,15 +147,15 @@ classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
-<a name="midlet">&nbsp;</a>
-<h3>A typical midlet</h3>
+<h3><a name="midlet">A typical midlet</a></h3>
+
These options shrink, optimize, obfuscate, and preverify the midlet
<code>mypackage.MyMIDlet</code>:
<pre>
-injars in.jar
-outjars out.jar
--libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
--libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
@@ -172,8 +190,8 @@ methods</a> and <a href="#resourcefiles">resource files</a>.
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">&nbsp;</a>
-<h3>A typical Java Card applet</h3>
+<h3><a name="jcapplet">A typical Java Card applet</a></h3>
+
These options shrink, optimize, and obfuscate the Java Card applet
<code>mypackage.MyApplet</code>:
<pre>
@@ -192,8 +210,8 @@ 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">&nbsp;</a>
-<h3>A typical xlet</h3>
+<h3><a name="xlet">A typical xlet</a></h3>
+
These options shrink, optimize, and obfuscate the xlet
<code>mypackage.MyXlet</code>:
<pre>
@@ -212,15 +230,16 @@ These options shrink, optimize, and obfuscate the xlet
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">&nbsp;</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>:
+<h3><a name="androidactivity">A simple Android activity</a></h3>
+
+These options shrink, optimize, and obfuscate the single Android
+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
+-injars bin/classes
+-outjars bin/classes-processed.jar
+-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar
+
+-dontpreverify
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic
@@ -228,27 +247,180 @@ based on a single activity <code>mypackage.MyActivity</code>:
-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.
+We're targeting the Android run-time and keeping the activity as an entry
+point.
+<p>
+Preverification is irrelevant for the dex compiler and the Dalvik VM, so we
+can switch it off with the
+<a href="usage.html#dontpreverify"><code>-dontpreverify</code></a> option.
<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.
+Note that the Dalvik VM also can't
+handle <a href="usage.html#overloadaggressively">aggressive overloading</a>
+(of static fields).
<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>.
+methods</a>, <a href="#callback">callback methods</a>,
+<a href="#enumerations">enumerations</a>,
+<a href="#annotations">annotations</a>, and
+<a href="#resourcefiles">resource files</a>.
+
+<h3><a name="androidapplication">A complete Android application</a></h3>
+
+<img class="float" src="attention.gif" width="64" height="64" alt="attention" />
+The Ant and Eclipse build processes of the Android SDK already integrate
+ProGuard by default, with all the proper settings. You only need to enable
+ProGuard (for release builds), by uncommenting the line
+"<code>proguard.config=.....</code>" in the file
+<code>project.properties</code> (created or updated by Android SDK revision 17
+or higher). Notes:
+<ul>
+<li>In case of problems, you may want to check if the configuration files that
+ are listed on this line (<code>proguard-project.txt</code>,...) contain
+ the necessary settings for your application.</li>
+<li>Android SDK revision 20 and higher have a different configuration file for
+ enabling optimization:
+ <code>${sdk.dir}/tools/proguard/proguard-android-optimize.txt</code>
+ instead of the default
+ <code>${sdk.dir}/tools/proguard/proguard-android.txt</code>.</li>
+<li>The build processes are already setting the necessary program jars,
+ library jars, and output jars for you &mdash; don't specify them again.</li>
+<li>If you get warnings about missing referenced classes: it's all too common
+ that libraries refer to missing classes.
+ See <a href="troubleshooting.html#unresolvedclass">"Warning: can't find
+ referenced class"</a> in the Troubleshooting section.</li>
+</ul>
+<p>
+For more information, you can consult the official <a target="other"
+href="http://developer.android.com/guide/developing/tools/proguard.html">Developer
+Guide</a> in the Android SDK.
+<p>
+If you're constructing a build process from scratch: these options shrink,
+optimize, and obfuscate all public activities, services, broadcast receivers,
+and content providers from the compiled classes and external libraries:
+<pre>
+-injars bin/classes
+-injars libs
+-outjars bin/classes-processed.jar
+-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar
+
+-dontpreverify
+-repackageclasses ''
+-allowaccessmodification
+-optimizations !code/simplification/arithmetic
+-keepattributes *Annotation*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+
+-keep public class * extends android.view.View {
+ public &lt;init&gt;(android.content.Context);
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet);
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);
+ public void set*(...);
+}
+
+-keepclasseswithmembers class * {
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.content.Context {
+ public void *(android.view.View);
+ public void *(android.view.MenuItem);
+}
+
+-keepclassmembers class * implements android.os.Parcelable {
+ static android.os.Parcelable$Creator CREATOR;
+}
+
+-keepclassmembers class **.R$* {
+ public static &lt;fields&gt;;
+}
+
+-keepclassmembers class * {
+ @android.webkit.JavascriptInterface &lt;methods&gt;;
+}
+</pre>
+<p>
+Most importantly, we're keeping all fundamental classes that may be referenced
+by the <code>AndroidManifest.xml</code> file of the application. If your
+manifest file contains other classes and methods, you may have to specify
+those as well.
+<p>
+We're keeping annotations, since they might be used by custom
+<code>RemoteViews</code>.
+<p>
+We're keeping any custom <code>View</code> extensions and other classes with
+typical constructors, since they might be referenced from XML layout files.
+<p>
+We're also keeping possible <code>onClick</code> handlers in
+custom <code>Context</code> extensions, since they might be referenced from
+XML layout files.
+<p>
+We're also keeping the required static fields in <code>Parcelable</code>
+implementations, since they are accessed by introspection.
+<p>
+We're keeping the static fields of referenced inner classes of auto-generated
+ <code>R</code> classes, just in case your code is accessing those fields by
+introspection. Note that the compiler already inlines primitive fields, so
+ProGuard can generally remove all these classes entirely anyway (because the
+classes are not referenced and therefore not required).
+<p>
+Finally, we're keeping annotated Javascript interface methods, so they can be
+exported and accessed by their original names. Javascript interface methods
+that are not annotated (in code targeted at Android versions older than 4.2)
+still need to be preserved manually.
+<p>
+If you're using additional Google APIs, you'll have to specify
+those as well, for instance:
+<pre>
+-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar
+</pre>
+<p>
+If you're using Google's optional License Verification Library, you can
+obfuscate its code along with your own code. You do have to preserve
+its <code>ILicensingService</code> interface for the library to work:
+<pre>
+-keep public interface com.android.vending.licensing.ILicensingService
+</pre>
+<p>
+If you're using the Android Compatibility library, you should add the
+following line, to let ProGuard know it's ok that the library references some
+classes that are not available in all versions of the API:
+<pre>
+-dontwarn android.support.**
+</pre>
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>,
+<a href="#enumerations">enumerations</a>,
+and <a href="#resourcefiles">resource files</a>. You may also want to add
+options for producing <a href="#stacktrace">useful stack traces</a> and
+to <a href="#logging">remove logging</a>. You can find a complete sample
+configuration in <code>examples/android.pro</code> in the ProGuard
+distribution.
+
+<h3><a name="library">A typical library</a></h3>
-<a name="library">&nbsp;</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:
+serialization code. The processed version of the library can then still be
+used as such, for developing code based on its public API.
<pre>
-injars in.jar
-outjars out.jar
-libraryjars &lt;java.home&gt;/lib/rt.jar
-printmapping out.map
+-keepparameternames
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
@@ -273,6 +445,7 @@ serialization code:
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
@@ -289,12 +462,12 @@ 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.
+<code>jikes</code> compiler respectively, in JDK 1.2 and older, to implement
+the <code>.class</code> construct. ProGuard will automatically detect them and
+deal with them, even when their names have been obfuscated. However, 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.
@@ -307,6 +480,11 @@ classes otherwise.
The "Signature" attribute is required to be able to access generic types when
compiling in JDK 5.0 and higher.
<p>
+The <a href="usage.html#keepparameternames"><code>-keepparameternames</code></a>
+option keeps the parameter names in the "LocalVariableTable" and
+"LocalVariableTypeTable" attributes of public library methods. Some IDEs can
+present these names to the developers who use the library.
+<p>
Finally, we're keeping the "Deprecated" attribute and the attributes for
producing <a href="#stacktrace">useful stack traces</a>.
<p>
@@ -316,8 +494,8 @@ href="#serializable">serializable classes</a>, and <a
href="#annotations">annotations</a>, which are all discussed in their
respective examples.
-<a name="applications">&nbsp;</a>
-<h3>All possible applications in the input jars</h3>
+<h3><a name="applications">All possible applications in the input jars</a></h3>
+
These options shrink, optimize, and obfuscate all public applications in
<code>in.jar</code>:
<pre>
@@ -347,8 +525,8 @@ classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
-<a name="applets">&nbsp;</a>
-<h3>All possible applets in the input jars</h3>
+<h3><a name="applets">All possible applets in the input jars</a></h3>
+
These options shrink, optimize, and obfuscate all public applets in
<code>in.jar</code>:
<pre>
@@ -372,15 +550,15 @@ classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
-<a name="midlets">&nbsp;</a>
-<h3>All possible midlets in the input jars</h3>
+<h3><a name="midlets">All possible midlets in the input jars</a></h3>
+
These options shrink, optimize, obfuscate, and preverify all public midlets in
<code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
--libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
--libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
@@ -412,8 +590,8 @@ methods</a> and <a href="#resourcefiles">resource files</a>.
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">&nbsp;</a>
-<h3>All possible Java Card applets in the input jars</h3>
+<h3><a name="jcapplets">All possible Java Card applets in the input jars</a></h3>
+
These options shrink, optimize, and obfuscate all public Java Card applets in
<code>in.jar</code>:
<pre>
@@ -435,8 +613,8 @@ interface.
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which applets exactly will be preserved.
-<a name="xlets">&nbsp;</a>
-<h3>All possible xlets in the input jars</h3>
+<h3><a name="xlets">All possible xlets in the input jars</a></h3>
+
These options shrink, optimize, and obfuscate all public xlets in
<code>in.jar</code>:
<pre>
@@ -458,38 +636,8 @@ We're simply keeping all classes that implement the <code>Xlet</code> interface.
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which xlets exactly will be preserved.
-<a name="androidapplications">&nbsp;</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>.
+<h3><a name="servlets">All possible servlets in the input jars</a></h3>
-<a name="servlets">&nbsp;</a>
-<h3>All possible servlets in the input jars</h3>
These options shrink, optimize, and obfuscate all public servlets in
<code>in.jar</code>:
<pre>
@@ -521,8 +669,77 @@ classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
-<a name="native">&nbsp;</a>
-<h3>Processing native methods</h3>
+<h3><a name="scala">Scala applications with the Scala runtime</a></h3>
+
+These options shrink, optimize, and obfuscate all public Scala applications in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-injars /usr/local/java/scala-2.9.1/lib/scala-library.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+
+-dontwarn scala.**
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+-keep class * implements org.xml.sax.EntityResolver
+
+-keepclassmembers class * {
+ ** MODULE$;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool {
+ long eventCount;
+ int workerCounts;
+ int runControl;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread {
+ int base;
+ int sp;
+ int runState;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask {
+ int status;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue {
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe;
+}
+</pre>
+<p>
+The configuration is essentially the same as
+for <a href="#applications">processing applications</a>, because Scala is
+compiled to ordinary Java bytecode. However, the example processes the Scala
+runtime library as well. The processed jar can be an order of magnitude
+smaller and a few times faster than the original code (for the Scala code
+examples, for instance).
+<p>
+The <a href="usage.html#dontwarn"><code>-dontwarn</code></a> option tells
+ProGuard not to complain about some artefacts in the Scala runtime, the way it
+is compiled by the <code>scalac</code> compiler (at least in Scala 2.9.1 and
+older). Note that this option should always be used with care.
+<p>
+The additional <a href="usage.html#keepoverview"><code>-keep</code></a>
+options make sure that some classes and some fields that are accessed by means
+of introspection are not removed or renamed.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, <a
+href="#enumerations">enumerations</a>, <a href="#serializable">serializable
+classes</a>, <a href="#beans">bean classes</a>, <a
+href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
+files</a>.
+<h3><a name="native">Processing native methods</a></h3>
+
If your application, applet, servlet, library, etc., contains native methods,
you'll want to preserve their names and their classes' names, so they can
still be linked to the native library. The following additional option will
@@ -543,8 +760,8 @@ the classes or class members that are invoked by the native code. These are
entry points, which you'll have to specify explicitly. <a
href="callback">Callback methods</a> are discussed below as a typical example.
-<a name="callback">&nbsp;</a>
-<h3>Processing callback methods</h3>
+<h3><a name="callback">Processing callback methods</a></h3>
+
If your application, applet, servlet, library, etc., contains callback
methods, which are called from external code (native code, scripts,...),
you'll want to preserve them, and probably their classes too. They are just
@@ -559,8 +776,8 @@ the following option will keep the callback class and method:
<p>
This will preserve the given class and method from being removed or renamed.
-<a name="enumerations">&nbsp;</a>
-<h3>Processing enumeration classes</h3>
+<h3><a name="enumerations">Processing enumeration classes</a></h3>
+
If your application, applet, servlet, library, etc., contains enumeration
classes, you'll have to preserve some special methods. Enumerations were
introduced in Java 5. The java compiler translates enumerations into classes
@@ -576,8 +793,8 @@ removed or obfuscated:
}
</pre>
-<a name="serializable">&nbsp;</a>
-<h3>Processing serializable classes</h3>
+<h3><a name="serializable">Processing serializable classes</a></h3>
+
More complex applications, applets, servlets, libraries, etc., may contain
classes that are serialized. Depending on the way in which they are used, they
may require special attention:
@@ -589,6 +806,7 @@ may require special attention:
<pre>
-keepclassmembers class * implements java.io.Serializable {
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
@@ -602,8 +820,7 @@ may require special attention:
option makes sure that any serialization methods are kept. By using this
option instead of the basic <code>-keep</code> option, we're not
forcing preservation of <i>all</i> serializable classes, just preservation
- of the listed members of classes that are actually used.
- <p>
+ of the listed members of classes that are actually used.</li>
<li>Sometimes, the serialized data are stored, and read back later into newer
versions of the serializable classes. One then has to take care the classes
@@ -617,7 +834,7 @@ may require special attention:
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
- static final java.io.ObjectStreamField[] serialPersistentFields;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient &lt;fields&gt;;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
@@ -632,7 +849,7 @@ may require special attention:
The <code>&lt;fields&gt;</code> line preserves all non-static,
non-transient fields, with their original names. The introspection of the
serialization process and the de-serialization process will then find
- consistent names.
+ consistent names.</li>
<li>Occasionally, the serialized data have to remain compatible, but the
classes involved lack <code>serialVersionUID</code> fields. I imagine the
@@ -651,7 +868,7 @@ may require special attention:
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
- static final java.io.ObjectStreamField[] serialPersistentFields;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient &lt;fields&gt;;
!private &lt;fields&gt;;
!private &lt;methods&gt;;
@@ -668,7 +885,7 @@ may require special attention:
interfaces of the serializable classes (using something like "<code>-keep
interface MyInterface</code>"), since these names are also used when
computing the UID. A fast but sub-optimal alternative would be simply
- keeping all interfaces with "<code>-keep interface *</code>".
+ keeping all interfaces with "<code>-keep interface *</code>".</li>
</ul>
<p>
@@ -679,8 +896,8 @@ the <code>Serialization</code> interface, yet only a small number may actually
ever be serialized. Knowing your application and tuning the configuration
often produces more compact results.
-<a name="beans">&nbsp;</a>
-<h3>Processing bean classes</h3>
+<h3><a name="beans">Processing bean classes</a></h3>
+
If your application, applet, servlet, library, etc., makes extensive use of
introspection on bean classes to find bean editor classes, or getter and
setter methods, then configuration may become painful. There's not much else
@@ -696,8 +913,8 @@ names don't change. For instance:
</pre>
<p>
If there are too many elements to list explicitly, wildcards in class names
-and method signatures might be helpful. This example should encompasses all
-possible setters and getters in classes in the package <code>mybeans</code>:
+and method signatures might be helpful. This example preserves all possible
+setters and getters in classes in the package <code>mybeans</code>:
<pre>
-keep class mybeans.** {
void set*(***);
@@ -715,8 +932,8 @@ The '<code>***</code>' wildcard matches any type (primitive or non-primitive,
array or non-array). The methods with the '<code>int</code>' arguments matches
properties that are lists.
-<a name="annotations">&nbsp;</a>
-<h3>Processing annotations</h3>
+<h3><a name="annotations">Processing annotations</a></h3>
+
If your application, applet, servlet, library, etc., uses annotations, you may
want to preserve them in the processed output. Annotations are represented by
attributes that have no direct effect on the execution of the code. However,
@@ -744,8 +961,8 @@ has to be preserved as well:
-keepattributes EnclosingMethod
</pre>
-<a name="database">&nbsp;</a>
-<h3>Processing database drivers</h3>
+<h3><a name="database">Processing database drivers</a></h3>
+
Database drivers are implementations of the <code>Driver</code> interface.
Since they are often created dynamically, you may want to preserve any
implementations that you are processing as entry points:
@@ -758,8 +975,8 @@ This option also gets rid of the note that ProGuard prints out about
instantiating a driver in your code (without necessarily implementing any
drivers yourself).
-<a name="componentui">&nbsp;</a>
-<h3>Processing ComponentUI classes</h3>
+<h3><a name="componentui">Processing ComponentUI classes</a></h3>
+
Swing UI look and feels are implemented as extensions of the
<code>ComponentUI</code> class. For some reason, these have to contain a
static method <code>createUI</code>, which the Swing API invokes using
@@ -773,8 +990,8 @@ point, for instance like this:
<p>
This option also keeps the classes themselves.
-<a name="rmi">&nbsp;</a>
-<h3>Processing RMI code</h3>
+<h3><a name="rmi">Processing RMI code</a></h3>
+
Reportedly, the easiest way to handle RMI code is to process the code with
ProGuard first and then invoke the <code>rmic</code> tool. If that is not
possible, you may want to try something like this:
@@ -798,8 +1015,29 @@ The <code>Exceptions</code> attribute has to be kept too, because the RMI
handling code performs introspection to check whether the method signatures
are compatible.
-<a name="resourcefiles">&nbsp;</a>
-<h3>Processing resource files</h3>
+<h3><a name="injection">Processing resource injection</a></h3>
+
+If your application is using JEE-style resource injection, the application
+container will automatically assign instances of resource classes to fields and
+methods that are annotated with <code>@Resource</code>. The container applies
+introspection, even accessing private class members directly. It typically
+constructs a resource name based on the type name and the class member name.
+We then have to avoid that such class members are removed or renamed:
+<pre>
+-keepclassmembers class * {
+ @javax.annotation.Resource *;
+}
+</pre>
+<p>
+The Spring framework has another similar annotation <code>@Autowired</code>:
+<pre>
+-keepclassmembers class * {
+ @org.springframework.beans.factory.annotation.Autowired *;
+}
+</pre>
+
+<h3><a name="resourcefiles">Processing resource files</a></h3>
+
If your application, applet, servlet, library, etc., contains resource files,
it may be necessary to adapt their names and/or their contents when the
application is obfuscated. The following two options can achieve this
@@ -818,8 +1056,31 @@ 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.
-<a name="stacktrace">&nbsp;</a>
-<h3>Producing useful obfuscated stack traces</h3>
+<h3><a name="manifestfiles">Processing manifest files</a></h3>
+
+As illustrated in the previous section, manifest files can be treated like
+ordinary resource files. ProGuard can adapt obfuscated class names in the
+files, but it won't make any other changes. If you want anything else, you
+should apply an external tool. For instance, if a manifest file contains
+signing information, you should sign the jar again after it has been
+processed.
+<p>
+If you're merging several input jars into a single output jar, you'll have to
+pick one, typically by specifying <a href="usage.html#filters">filters</a>:
+<pre>
+-injars in1.jar
+-injars in2.jar(!META-INF/MANIFEST.MF)
+-injars in3.jar(!META-INF/MANIFEST.MF)
+-outjars out.jar
+</pre>
+<p>
+The filters will let ProGuard copy the manifest file from the first jar and
+ignore any manifest files in the second and third input jars. Note that
+ProGuard will leave the order of the files in the jars unchanged; manifest
+files are not necessarily put first.
+
+<h3><a name="stacktrace">Producing useful obfuscated stack traces</a></h3>
+
These options let obfuscated applications or libraries produce stack traces
that can still be deciphered later on:
<pre>
@@ -844,8 +1105,8 @@ their original names, so we're saving the mapping to a file
<code>out.map</code>. The information can then be used by the <a
href="retrace/index.html">ReTrace</a> tool to restore the original stack trace.
-<a name="repackaging">&nbsp;</a>
-<h3>Obfuscating package names</h3>
+<h3><a name="repackaging">Obfuscating package names</a></h3>
+
Package names can be obfuscated in various ways, with increasing levels of
obfuscation and compactness. For example, consider the following classes:
<pre>
@@ -951,8 +1212,37 @@ Note that not all levels of obfuscation of package names may be acceptable for
all code. Notably, you may have to take into account that your application may
contain <a href="#resourcefiles">resource files</a> that have to be adapted.
-<a name="restructuring">&nbsp;</a>
-<h3>Restructuring the output archives</h3>
+<h3><a name="logging">Removing logging code</a></h3>
+
+You can let ProGuard remove logging code. The trick is to specify that the
+logging methods don't have side-effects &mdash; even though they actually do,
+since they write to the console or to a log file. ProGuard will take your word
+for it and remove the invocations (in the optimization step) and if possible
+the logging classes and methods themselves (in the shrinking step).
+<p>
+For example, this configuration removes invocations of the Android logging
+methods:
+<pre>
+-assumenosideeffects class android.util.Log {
+ public static boolean isLoggable(java.lang.String, int);
+ public static int v(...);
+ public static int i(...);
+ public static int w(...);
+ public static int d(...);
+ public static int e(...);
+}
+</pre>
+<p>
+The wildcards are a shortcut to match all versions of the methods.
+<p>
+Note that you generally can't remove logging code that uses
+<code>System.out.println</code>, since you would be removing all invocations
+of <code>java.io.PrintStream#println</code>, which could break your
+application. You can work around it by creating your own logging methods and
+let ProGuard remove those.
+
+<h3><a name="restructuring">Restructuring the output archives</a></h3>
+
In simple applications, all output classes and resources files are merged into
a single jar. For example:
<pre>
@@ -1022,12 +1312,12 @@ This grouping, archiving, and flattening can be arbitrarily complex. ProGuard
always tries to package output archives in a sensible way, reconstructing the
input entries as much as required.
-<a name="filtering">&nbsp;</a>
-<h3>Filtering the input and the output</h3>
+<h3><a name="filtering">Filtering the input and the output</a></h3>
-If you want even greater control, you can add filters to the input and the
-output, filtering out zips, ears, wars, jars, and/or ordinary files. For
-example, if you want to disregard certain files from an input jar:
+If you want even greater control, you can add
+<a href="usage.html#filters">filters</a> to the input and the output,
+filtering out zips, ears, wars, jars, and/or ordinary files. For example, if
+you want to disregard certain files from an input jar:
<pre>
-injars in.jar(!images/**)
-outjars out.jar
@@ -1080,10 +1370,10 @@ files to <code>code_out.jar</code>, and all remaining files to
<code>resources_out.jar</code>.
<p>
Again, the filtering can be arbitrarily complex, especially when combined with
-the grouping of input and output.
+grouping input and output.
+
+<h3><a name="multiple">Processing multiple applications at once</a></h3>
-<a name="multiple">&nbsp;</a>
-<h3>Processing multiple applications at once</h3>
You can process several dependent or independent applications (or applets,
midlets,...) in one go, in order to save time and effort. ProGuard's input and
output handling offers various ways to keep the output nicely structured.
@@ -1100,10 +1390,10 @@ just the input and output options:
</pre>
<p>
After processing, the directory <code>processed_applications</code> will
-contain the processed application jars, with their original names.
+contain processed versions of application jars, with their original names.
+
+<h3><a name="incremental">Incremental obfuscation</a></h3>
-<a name="incremental">&nbsp;</a>
-<h3>Incremental obfuscation</h3>
After having <a href="#application">processed an application</a>, e.g.
ProGuard itself, you can still incrementally add other pieces of code that
depend on it, e.g. the ProGuard GUI:
@@ -1149,18 +1439,18 @@ jar as a library jar:
}
</pre>
-<a name="microedition">&nbsp;</a>
-<h3>Preverifying class files for Java Micro Edition</h3>
+<h3><a name="microedition">Preverifying class files for Java Micro Edition</a></h3>
+
Even if you're not interested in shrinking, optimizing, and obfuscating your
midlets, as shown in the <a href="#midlets">midlets example</a>, you can still
use ProGuard to preverify the class files for Java Micro Edition. ProGuard
-produces slightly more compact results compared to the traditional external
+produces slightly more compact results than the traditional external
preverifier.
<pre>
-injars in.jar
-outjars out.jar
--libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
--libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
-dontshrink
-dontoptimize
@@ -1175,8 +1465,8 @@ href="usage.html#microedition"><code>-microedition</code></a> option. Note
that we don't need any <code>-keep</code> options to specify entry points; all
class files are simply preverified.
-<a name="upgrade">&nbsp;</a>
-<h3>Upgrading class files to Java 6</h3>
+<h3><a name="upgrade">Upgrading class files to Java 6</a></h3>
+
The following options upgrade class files to Java 6, by updating their
internal version numbers and preverifying them. The class files can then be
loaded more efficiently by the Java 6 Virtual Machine.
@@ -1198,8 +1488,8 @@ automatically be preverified for Java 6 as a result. Note that we don't need
any <code>-keep</code> options to specify entry points; all class files are
simply updated and preverified.
-<a name="deadcode">&nbsp;</a>
-<h3>Finding dead code</h3>
+<h3><a name="deadcode">Finding dead code</a></h3>
+
These options list unused classes, fields, and methods in the application
<code>mypackage.MyApplication</code>:
<pre>
@@ -1232,8 +1522,8 @@ that keeps those fields a priori, in order to avoid having them listed:
}
</pre>
-<a name="structure">&nbsp;</a>
-<h3>Printing out the internal structure of class files</h3>
+<h3><a name="structure">Printing out the internal structure of class files</a></h3>
+
These options print out the internal structure of all class files in the input
jar:
<pre>
@@ -1250,8 +1540,7 @@ jar:
Note how we don't need to specify the Java run-time jar, because we're not
processing the input jar at all.
-<a name="annotated">&nbsp;</a>
-<h3>Using annotations to configure ProGuard</h3>
+<h3><a name="annotated">Using annotations to configure ProGuard</a></h3>
The traditional ProGuard configuration allows to keep a clean separation
between the code and the configuration for shrinking, optimization, and
@@ -1291,12 +1580,12 @@ href="#annotations">annotations</a>.
<p>
The directory <code>examples/annotations</code> contains more examples that
illustrate some of the possibilities.
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/gradle.html b/docs/manual/gradle.html
new file mode 100644
index 0000000..3e0e500
--- /dev/null
+++ b/docs/manual/gradle.html
@@ -0,0 +1,545 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>Gradle Task</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top) {
+ history.go(-1);
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+} else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
+</head>
+<body>
+
+<h2>Gradle Task</h2>
+
+<b>ProGuard</b> can be run as a task in the Java-based build tool Gradle
+(version 1.3 or higher).
+<p>
+
+Before you can use the <code>proguard</code> task, you have to make sure
+Gradle can find it in its class path at build time. One way is to add the
+following line to your <code>build.gradle</code> file:
+<p>
+
+<pre>
+buildscript {
+ repositories {
+ flatDir dirs: '/usr/local/java/proguard/lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+</pre>
+<p>
+
+Please make sure the class path is set correctly for your system.
+<p>
+
+You can then define a task:
+<p>
+<pre>
+task myProguardTask(type: proguard.gradle.ProGuardTask) {
+ .....
+}
+</pre>
+<p>
+
+The embedded configuration is much like a standard ProGuard configuration.
+Notable similarities and differences:
+<ul>
+<li>Like in ProGuard-style configurations, we're using all lower-case names
+ for the settings.</li>
+<li>The options don't have a dash as prefix.</li>
+<li>Arguments typically have quotes.</li>
+<li>Some settings are specified as named arguments.</li>
+</ul>
+<p>
+You can find some sample build files in the <code>examples/gradle</code>
+directory of the ProGuard distribution.
+<p>
+If you prefer a more verbose configuration derived from the Ant task, you can
+import the Ant task as a <a href="#anttask">Gradle task</a>.
+
+<h2><a name="proguard">Settings</a></h2>
+
+The ProGuard task supports the following settings in its closure:
+
+<dl>
+
+<dt><a name="configuration_attribute"><code><b>configuration</b></code></a>
+ <a href="#file"><i>files</i></a></dt>
+<dd>Read and merge options from the given ProGuard-style configuration
+ files. The files are resolved and parsed lazily, during the execution
+ phase.</dd>
+
+<dt><a href="usage.html#injars"><code><b>injars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+<dd>Specifies the program jars (or wars, ears, zips, or directories). The files
+ are resolved and read lazily, during the execution phase.</dd>
+
+<dt><a href="usage.html#outjars"><code><b>outjars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+<dd>Specifies the names of the output jars (or wars, ears, zips, or
+ directories). The files are resolved and written lazily, during the
+ execution phase.</dd>
+
+<dt><a href="usage.html#libraryjars"><code><b>libraryjars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+<dd>Specifies the library jars (or wars, ears, zips, or directories). The files
+ are resolved and read lazily, during the execution phase.</dd>
+
+<dt><a href="usage.html#skipnonpubliclibraryclasses"><code><b>skipnonpubliclibraryclasses</b></code></a></dt>
+<dd>Ignore non-public library classes.</dd>
+
+<dt><a href="usage.html#dontskipnonpubliclibraryclassmembers"><code><b>dontskipnonpubliclibraryclassmembers</b></code></a></dt>
+<dd>Don't ignore package visible library class members.</dd>
+
+<dt><a href="usage.html#keepdirectories"><code><b>keepdirectories</b></code></a>
+ ['<a href="usage.html#filefilters"><i>directory_filter</i></a>']</dt>
+<dd>Keep the specified directories in the output jars (or wars, ears, zips,
+ or directories).</dd>
+
+<dt><a href="usage.html#target"><code><b>target</b></code></a>
+ '<i>version</i>'</dt>
+<dd>Set the given version number in the processed classes.</dd>
+
+<dt><a href="usage.html#forceprocessing"><code><b>forceprocessing</b></code></a></dt>
+<dd>Process the input, even if the output seems up to date.</dd>
+
+<dt><a href="usage.html#keep"><code><b>keep</b></code></a>
+ [<a href="#keepmodifier"><i>modifier</i>,...</a>]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the specified classes <i>and</i> class members.</dd>
+
+<dt><a href="usage.html#keepclassmembers"><code><b>keepclassmembers</b></code></a>
+ [<a href="#keepmodifier"><i>modifier</i>,...</a>]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the specified class members, if their classes are preserved as
+ well.</dd>
+
+<dt><a href="usage.html#keepclasseswithmembers"><code><b>keepclasseswithmembers</b></code></a>
+ [<a href="#keepmodifier"><i>modifier</i>,...</a>]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the specified classes <i>and</i> class members, if all of the
+ specified class members are present.</dd>
+
+<dt><a href="usage.html#keepnames"><code><b>keepnames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the names of the specified classes <i>and</i> class members (if
+ they aren't removed in the shrinking step).</dd>
+
+<dt><a href="usage.html#keepclassmembernames"><code><b>keepclassmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the names of the specified class members (if they aren't removed
+ in the shrinking step).</dd>
+
+<dt><a href="usage.html#keepclasseswithmembernames"><code><b>keepclasseswithmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the names of the specified classes <i>and</i> class members, if
+ all of the specified class members are present (after the shrinking
+ step).</dd>
+
+<dt><a href="usage.html#printseeds"><code><b>printseeds</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>List classes and class members matched by the various <code>keep</code>
+ commands, to the standard output or to the given file.</dd>
+
+<dt><a href="usage.html#dontshrink"><code><b>dontshrink</b></code></a></dt>
+<dd>Don't shrink the input class files.</dd>
+
+<dt><a href="usage.html#printusage"><code><b>printusage</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>List dead code of the input class files, to the standard output or to the
+ given file.</dd>
+
+<dt><a href="usage.html#whyareyoukeeping"><code><b>whyareyoukeeping</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Print details on why the given classes and class members are being kept in
+ the shrinking step.</dd>
+
+<dt><a href="usage.html#dontoptimize"><code><b>dontoptimize</b></code></a></dt>
+<dd>Don't optimize the input class files.</dd>
+
+<dt><a href="usage.html#optimizations"><code><b>optimizations</b></code></a> '<a href="optimizations.html"><i>optimization_filter</i></a>'</dt>
+<dd>Perform only the specified optimizations.</dd>
+
+<dt><a href="usage.html#optimizationpasses"><code><b>optimizationpasses</b></code></a>
+ <i>n</i></dt>
+<dd>The number of optimization passes to be performed.</dd>
+
+<dt><a href="usage.html#assumenosideeffects"><code><b>assumenosideeffects</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Assume that the specified methods don't have any side effects, while
+ optimizing. <i>Only use this option if you know what you're
+ doing!</i></dd>
+
+<dt><a href="usage.html#allowaccessmodification"><code><b>allowaccessmodification</b></code></a></dt>
+<dd>Allow the access modifiers of classes and class members to be modified,
+ while optimizing.</dd>
+
+<dt><a href="usage.html#mergeinterfacesaggressively"><code><b>mergeinterfacesaggressively</b></code></a></dt>
+<dd>Allow any interfaces to be merged, while optimizing.</dd>
+
+<dt><a href="usage.html#dontobfuscate"><code><b>dontobfuscate</b></code></a></dt>
+<dd>Don't obfuscate the input class files.</dd>
+
+<dt><a href="usage.html#printmapping"><code><b>printmapping</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>Print the mapping from old names to new names for classes and class members
+ that have been renamed, to the standard output or to the given file.</dd>
+
+<dt><a href="usage.html#applymapping"><code><b>applymapping</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Reuse the given mapping, for incremental obfuscation.</dd>
+
+<dt><a href="usage.html#obfuscationdictionary"><code><b>obfuscationdictionary</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Use the words in the given text file as obfuscated field names and method
+ names.</dd>
+
+<dt><a href="usage.html#classobfuscationdictionary"><code><b>classobfuscationdictionary</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Use the words in the given text file as obfuscated class names.</dd>
+
+<dt><a href="usage.html#packageobfuscationdictionary"><code><b>packageobfuscationdictionary</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Use the words in the given text file as obfuscated package names.</dd>
+
+<dt><a href="usage.html#overloadaggressively"><code><b>overloadaggressively</b></code></a></dt>
+<dd>Apply aggressive overloading while obfuscating.</dd>
+
+<dt><a href="usage.html#useuniqueclassmembernames"><code><b>useuniqueclassmembernames</b></code></a></dt>
+<dd>Ensure uniform obfuscated class member names for subsequent incremental
+ obfuscation.</dd>
+
+<dt><a href="usage.html#dontusemixedcaseclassnames"><code><b>dontusemixedcaseclassnames</b></code></a></dt>
+<dd>Don't generate mixed-case class names while obfuscating.</dd>
+
+<dt><a href="usage.html#keeppackagenames"><code><b>keeppackagenames</b></code></a> ['<a href="usage.html#filters"><i>package_filter</i></a>']</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#flattenpackagehierarchy"><code><b>flattenpackagehierarchy</b></code></a>
+ '<i>package_name</i>'</dt>
+<dd>Repackage all packages that are renamed into the single given parent
+ package.</dd>
+
+<dt><a href="usage.html#repackageclasses"><code><b>repackageclasses</b></code></a>
+ ['<i>package_name</i>']</dt>
+<dd>Repackage all class files that are renamed into the single given
+ package.</dd>
+
+<dt><a href="usage.html#keepattributes"><code><b>keepattributes</b></code></a> ['<a href="usage.html#filters"><i>attribute_filter</i></a>']</dt>
+<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#keepparameternames"><code><b>keepparameternames</b></code></a></dt>
+<dd>Keep the parameter names and types of methods that are kept.</dd>
+
+<dt><a href="usage.html#renamesourcefileattribute"><code><b>renamesourcefileattribute</b></code></a>
+ ['<i>string</i>']</dt>
+<dd>Put the given constant string in the <code>SourceFile</code>
+ attributes.</dd>
+
+<dt><a href="usage.html#adaptclassstrings"><code><b>adaptclassstrings</b></code></a>
+ ['<a href="usage.html#filters"><i>class_filter</i></a>']</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</b></code></a>
+ ['<a href="usage.html#filefilters"><i>file_filter</i></a>']</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</b></code></a>
+ ['<a href="usage.html#filefilters"><i>file_filter</i></a>']</dt>
+<dd>Update the contents of the specified resource files, based on the
+ obfuscated names of the processed classes.</dd>
+
+<dt><a href="usage.html#dontpreverify"><code><b>dontpreverify</b></code></a></dt>
+<dd>Don't preverify the processed class files if they are targeted at Java Micro
+ Edition or at Java 6 or higher.</dd>
+
+<dt><a href="usage.html#microedition"><code><b>microedition</b></code></a></dt>
+<dd>Target the processed class files at Java Micro Edition.</dd>
+
+<dt><a href="usage.html#verbose"><code><b>verbose</b></code></a></dt>
+<dd>Write out some more information during processing.</dd>
+
+<dt><a href="usage.html#dontnote"><code><b>dontnote</b></code></a> '<a href="usage.html#filters"><i>class_filter</i></a>'</dt>
+<dd>Don't print notes about classes matching the specified class name
+ filter.</dd>
+
+<dt><a href="usage.html#dontwarn"><code><b>dontwarn</b></code></a> '<a href="usage.html#filters"><i>class_filter</i></a>'</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 href="usage.html#ignorewarnings"><code><b>ignorewarnings</b></code></a></dt>
+<dd>Print warnings about unresolved references, but continue processing
+ anyhow. <i>Only use this option if you know what you're doing!</i></dd>
+
+<dt><a href="usage.html#printconfiguration"><code><b>printconfiguration</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>Write out the entire configuration in traditional ProGuard style, to the
+ standard output or to the given file. Useful to replace unreadable
+ XML configurations.</dd>
+
+<dt><a href="usage.html#dump"><code><b>dump</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>Write out the internal structure of the processed class files, to the
+ standard output or to the given file.</dd>
+
+</dl>
+
+<h2><a name="classpath">Class Paths</a></h2>
+
+Class paths are specified as Gradle file collections, which means they can be
+specified as simple strings, with <code>files(Object)</code>, etc.
+<p>
+In addition, they can have ProGuard-style filters, specified as
+comma-separated named arguments after the file:
+
+<dl>
+
+<dt><code><b>filter:</b></code>
+ '<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#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#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#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#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all zip names that are encountered.</dd>
+
+</dl>
+
+<h2><a name="file">Files</a></h2>
+
+Files are specified as Gradle files, which means they can be specified
+as simple strings, as File instances, with <code>file(Object)</code>, etc.
+<p>
+In Gradle, file names (any strings really) in double quotes can contain
+properties or code inside <code>${...}</code>. These are automatically
+expanded.
+<p>
+For example, <code>"${System.getProperty('java.home')}/lib/rt.jar"</code> is
+expanded to something like <code>'/usr/local/java/jdk/jre/lib/rt.jar'</code>.
+Similarly, <code>System.getProperty('user.home')</code> is expanded to the
+user's home directory, and <code>System.getProperty('user.dir')</code> is
+expanded to the current working directory.
+
+<h2><a name="keepmodifier">Keep Modifiers</a></h2>
+
+The keep settings can have the following named arguments that modify their
+behaviors:
+
+<dl>
+
+<dt><a href="usage.html#allowshrinking"><code><b>allowshrinking:</b></code></a>
+ <i>boolean</i>
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ shrunk.</dd>
+
+<dt><a href="usage.html#allowoptimization"><code><b>allowoptimization:</b></code></a>
+ <i>boolean</i>
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ optimized.</dd>
+
+<dt><a href="usage.html#allowobfuscation"><code><b>allowobfuscation:</b></code></a>
+ <i>boolean</i>
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ obfuscated.</dd>
+
+</dl>
+
+Names arguments are comma-separated, as usual.
+
+<h2><a name="classspecification">Class Specifications</a></h2>
+
+A class specification is a template of classes and class members (fields and methods). There are two alternative ways to specify such a template:
+
+<ol>
+<li>As a string containing a ProGuard-style class specification. This is the
+ most compact and most readable way. The specification looks like a Java
+ declaration of a class with fields and methods. For example:
+<pre>
+keep 'public class mypackage.MyMainClass { \
+ public static void main(java.lang.String[]); \
+}'
+</pre></li>
+<li>As a Gradle-style setting: a method calls with named arguments and a
+ closure. This is more verbose, but it might be useful for programmatic
+ specifications. For example:
+<pre>
+keep access: 'public',
+ name: 'mypackage.MyMainClass', {
+ method access: 'public static',
+ type: 'void',
+ name: 'main',
+ parameters: 'java.lang.String[]'
+}
+</pre></li>
+</ol>
+<p>
+
+The <a href="usage.html#classspecification">ProGuard-style class
+specification</a> is described on the traditional Usage page.
+<p>
+A Gradle-style class specification can have the following named arguments:
+
+<dl>
+
+<dt><code><b>access:</b></code> '<i>access_modifiers</i>'</dt>
+<dd>The optional access modifiers of the class. Any space-separated list of
+ "public", "final", and "abstract", with optional negators "!".</dd>
+
+<dt><code><b>annotation:</b></code> '<i>annotation_name</i>'</dt>
+<dd>The optional fully qualified name of an annotation of the class, with
+ optional wildcards.</dd>
+
+<dt><code><b>type:</b></code> '<i>type</i>'</dt>
+<dd>The optional type of the class: one of "class", "interface", or
+ "!interface".</dd>
+
+<dt><code><b>name:</b></code> '<i>class_name</i>'</dt>
+<dd>The optional fully qualified name of the class, with optional
+ wildcards.</dd>
+
+<dt><code><b>extendsannotation:</b></code> '<i>annotation_name</i>'</dt>
+<dd>The optional fully qualified name of an annotation of the the class that
+ the specified classes must extend, with optional wildcards.</dd>
+
+<dt><code><b>'extends':</b></code> '<i>class_name</i>'</dt>
+<dd>The optional fully qualified name of the class the specified classes
+ must extend, with optional wildcards.</dd>
+
+<dt><code><b>'implements':</b></code> '<i>class_name</i>'</dt>
+<dd>The optional fully qualified name of the class the specified classes
+ must implement, with optional wildcards.</dd>
+
+</dl>
+
+The named arguments are optional. Without any arguments, there are no
+constraints, so the settings match all classes.
+<p>
+
+<h3><a name="cl">Gradle-style Class Member Specifications</h3>
+
+The closure of a Gradle-style class specification can specify class members
+with these settings:
+
+<dl>
+
+<dt><code><b>field</b></code> <i>field_constraints</i></dt>
+<dd>Specifies a field.</dd>
+
+<dt><code><b>method</b></code> <i>method_constraints</i></dt>
+<dd>Specifies a method.</dd>
+
+<dt><code><b>constructor</b></code> <i>constructor_constraints</i></dt>
+<dd>Specifies a constructor.</dd>
+
+</dl>
+
+A class member setting can have the following named arguments to express
+constraints:
+
+<dl>
+
+<dt><code><b>access:</b></code> '<i>access_modifiers</i>'</dt>
+<dd>The optional access modifiers of the class. Any space-separated list of
+ "public", "protected", "private", "static", etc., with optional negators
+ "!".</dd>
+
+<dt><code><b>'annotation':</b></code> '<i>annotation_name</i>'</dt>
+<dd>The optional fully qualified name of an annotation of the class member,
+ with optional wildcards.</dd>
+
+<dt><code><b>type:</b></code> '<i>type</i>'</dt>
+<dd>The optional fully qualified type of the class member, with optional
+ wildcards. Not applicable for constructors, but required for methods for
+ which the <code>parameters</code> argument is specified.</dd>
+
+<dt><code><b>name:</b></code> '<i>name</i>'</dt>
+<dd>The optional name of the class member, with optional wildcards. Not
+ applicable for constructors.</dd>
+
+<dt><code><b>parameters:</b></code> '<i>parameters</i>'</dt>
+<dd>The optional comma-separated list of fully qualified method parameters,
+ with optional wildcards. Not applicable for fields, but required for
+ constructors, and for methods for which the <code>type</code> argument is
+ specified.</dd>
+
+</dl>
+
+The named arguments are optional. Without any arguments, there are no
+constraints, so the settings match all constructors, fields, or methods.
+<p>
+A class member setting doesn't have a closure.
+
+<h2><a name="anttask">Alternative: imported Ant task</a></h2>
+
+Instead of using the Gradle task, you could also integrate the Ant task in
+your Gradle build file:
+<p>
+<pre>
+ant.project.basedir = '../..'
+
+ant.taskdef(resource: 'proguard/ant/task.properties',
+ classpath: '/usr/local/java/proguard/lib/proguard.jar')
+</pre>
+<p>
+
+Gradle automatically converts the elements and attributes to Groovy methods,
+so converting the configuration is essentially mechanical. The one-on-one
+mapping can be useful, but the resulting configuration is more verbose. For
+instance:
+<pre>
+task proguard << {
+ ant.proguard(printmapping: 'proguard.map',
+ overloadaggressively: 'on',
+ repackageclasses: '',
+ renamesourcefileattribute: 'SourceFile') {
+
+ injar(file: 'application.jar')
+ injar(file: 'gui.jar', filter: '!META-INF/**')
+
+ .....
+ }
+}
+</pre>
+<p>
+
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
+<address>
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
+</address>
+</body>
+</html>
diff --git a/docs/manual/gui.html b/docs/manual/gui.html
index 37684a6..6677aaf 100644
--- a/docs/manual/gui.html
+++ b/docs/manual/gui.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard GUI</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -15,10 +26,12 @@ ProGuard distribution. To run the ProGuard graphical user interface, just type:
<p class="code">
<code><b>java -jar proguardgui.jar</b> [-nosplash] </code>[<i>configuration_file</i>]
</p>
-The GUI will pop up in a window. With the <code>-nosplash</code> option, you
-can switch off the short opening animation. If you have specified a ProGuard
-configuration file, it will be loaded. The GUI works like a wizard. You can
-edit the configuration and execute ProGuard through a few tabs:
+Alternatively, the <code>bin</code> directory contains some short Linux and
+Windows scripts containing this command. The GUI will pop up in a window. With
+the <code>-nosplash</code> option, you can switch off the short opening
+animation. If you have specified a ProGuard configuration file, it will be
+loaded. The GUI works like a wizard. You can edit the configuration and
+execute ProGuard through a few tabs:
<p>
<table cellspacing="5" cellpadding="5">
@@ -57,8 +70,7 @@ process is assumed. Please refer to the <a
href="introduction.html">Introduction</a> of this manual.
<p>
-<a name="proguard">&nbsp;</a>
-<h2>The ProGuard Tab</h2>
+<h2><a name="proguard">The ProGuard Tab</a></h2>
The <i>ProGuard</i> tab presents a welcome message and one important button at
the bottom:
@@ -75,8 +87,7 @@ If you don't want to load an existing configuration, you can just continue
creating a new configuration from scratch.
<p>
-<a name="inputoutput">&nbsp;</a>
-<h2>The Input/Output Tab</h2>
+<h2><a name="inputoutput">The Input/Output Tab</a></h2>
The <i>Input/Output</i> tab contains two lists, respectively to specify the
program jars (or wars, ears, zips, or directories), and the library jars (or
@@ -88,12 +99,12 @@ wars, ears, zips, or directories).
entries specify the destinations to which the processed results will be
written. They are preceded by arrows, to distinguish them from input
entries. The results of each consecutive list of input entries will be
- written to the subsequent consecutive list of output entries.
+ written to the subsequent consecutive list of output entries.</li>
<li>The library jars are not copied to the output jars; they contain class
files that are used by class files in the program jars and that are
necessary for correct processing. This list typically at least contains the
- targeted Java runtime jar.
+ targeted Java runtime jar.</li>
</ul>
<p>
@@ -145,16 +156,15 @@ any duplicate entries gets precedence, just as in conventional class paths.
Corresponding configuration options:
<ul type="none">
-<li>-<a href="usage.html#injars">injars</a>
-<li>-<a href="usage.html#outjars">outjars</a>
-<li>-<a href="usage.html#libraryjars">libraryjars</a>
-<li><a href="usage.html#classpath"><i>class_path</i></a>
-<li><a href="usage.html#filters"><i>filters</i></a>
+<li>-<a href="usage.html#injars">injars</a></li>
+<li>-<a href="usage.html#outjars">outjars</a></li>
+<li>-<a href="usage.html#libraryjars">libraryjars</a></li>
+<li><a href="usage.html#classpath"><i>class_path</i></a></li>
+<li><a href="usage.html#filters"><i>filters</i></a></li>
</ul>
<p>
-<a name="shrinking">&nbsp;</a>
-<h2>The Shrinking Tab</h2>
+<h2><a name="shrinking">The Shrinking Tab</a></h2>
The <i>Shrinking</i> tab presents a number of options that affect the
shrinking step. The basic options are followed by a few lists of classes and
@@ -224,41 +234,41 @@ advanced options.
<ul>
<li>The <b>Comments</b> text field allows to add optional comments to this
entry. The comments will identify the entry in the list and they will
- appear as comments in the configuration file.
+ appear as comments in the configuration file.</li>
<li>The <b>Keep</b> selection allows to specify whether you want to protect
the specified classes and their specified class members, or just the
specified class members from the specified classes, or the specified
classes and the specified class members, if the class members are present.
Note that class members will only be protected if they are explicitly
- specified, even if only by means of a wildcard.
+ specified, even if only by means of a wildcard.</li>
<li>The <b>Allow</b> selection allows to specify whether you want to allow the
the specified classes and their specified class members to be shrunk,
- optimized and/or obfuscated.
+ optimized and/or obfuscated.</li>
<li>The <b>Access</b> selections allows to specify constraints on the class or
- classes, based on their access modifiers.
+ classes, based on their access modifiers.</li>
<li>The <b>Annotation</b> text field takes the fully-qualified name of an
annotation that is required for matching classes. The annotation name can
contain wildcards. This is an advanced option for defining <i>keep</i>
- annotations.
+ annotations.</li>
<li>The <b>Class</b> text field takes the fully-qualified name of the class or
- classes. The class name can contain wildcards.
+ classes. The class name can contain wildcards.</li>
<li>The <b>Annotation</b> text field takes the fully-qualified name of an
annotation that is required for the class or interface that the above
class must extend. The annotation name can contain wildcards. This is an
- advanced option for defining <i>keep</i> annotations.
+ advanced option for defining <i>keep</i> annotations.</li>
<li>The <b>Extends/implements class</b> text field takes the fully-qualified
- name of the class or interface that the above classes must extend.
+ name of the class or interface that the above classes must extend.</li>
<li>The <b>Class members</b> list allows to specify a list of fields and
methods to keep. It can be edited by means of a list of buttons on the
- right-hand side.
+ right-hand side.</li>
</ul>
<p>
@@ -270,18 +280,18 @@ advanced options.
<ul>
<li>The <b>Access</b> selections allows to specify constraints on the field or
- fields, based on their access modifiers.
+ fields, based on their access modifiers.</li>
<li>The <b>Annotation</b> text field takes the fully-qualified name of an
annotation that is required for matching fields. The annotation name can
contain wildcards. This is an advanced option for defining <i>keep</i>
- annotations.
+ annotations.</li>
<li>The <b>Return type</b> text field takes the fully-qualified type of the
- field or fields. The type can contain wildcards.
+ field or fields. The type can contain wildcards.</li>
<li>The <b>Name</b> text field takes the name of the field or fields. The field
- name can contain wildcards.
+ name can contain wildcards.</li>
</ul>
<p>
@@ -293,36 +303,35 @@ to toggle showing the advanced options.
<ul>
<li>The <b>Access</b> selections allows to specify constraints on the method or
- methods, based on their access modifiers.
+ methods, based on their access modifiers.</li>
<li>The <b>Annotation</b> text field takes the fully-qualified name of an
annotation that is required for matching methods. The annotation name can
contain wildcards. This is an advanced option for defining <i>keep</i>
- annotations.
+ annotations.</li>
-<li>The <b>Return type</b> text field takes the fully-qualified type of the method or methods. The type can contain wildcards.
+<li>The <b>Return type</b> text field takes the fully-qualified type of the method or methods. The type can contain wildcards.</li>
<li>The <b>Name</b> text field takes the name of the method or methods. The
- method name can contain wildcards.
+ method name can contain wildcards.</li>
<li>The <b>Arguments</b> text field takes the comma-separated list of
fully-qualified method arguments. Each of these arguments can contain
- wildcards.
+ wildcards.</li>
</ul>
<p>
Corresponding configuration options:
<ul type="none">
-<li>-<a href="usage.html#dontshrink">dontshrink</a>
-<li>-<a href="usage.html#printusage">printusage</a>
-<li>-<a href="usage.html#keep">keep</a>
-<li>-<a href="usage.html#keepclassmembers">keepclassmembers</a>
-<li>-<a href="usage.html#keepclasseswithmembers">keepclasseswithmembers</a>
+<li>-<a href="usage.html#dontshrink">dontshrink</a></li>
+<li>-<a href="usage.html#printusage">printusage</a></li>
+<li>-<a href="usage.html#keep">keep</a></li>
+<li>-<a href="usage.html#keepclassmembers">keepclassmembers</a></li>
+<li>-<a href="usage.html#keepclasseswithmembers">keepclasseswithmembers</a></li>
</ul>
<p>
-<a name="obfuscation">&nbsp;</a>
-<h2>The Obfuscation Tab</h2>
+<h2><a name="obfuscation">The Obfuscation Tab</a></h2>
The <i>Obfuscation</i> tab presents a number of options that affect the
obfuscation step. The basic options are followed by a few lists of classes and
@@ -336,32 +345,32 @@ href="#shrinking">Shrinking Tab</a>.
Corresponding configuration options:
<ul type="none">
-<li>-<a href="usage.html#dontobfuscate">dontobfuscate</a>
-<li>-<a href="usage.html#printmapping">printmapping</a>
-<li>-<a href="usage.html#applymapping">applymapping</a>
-<li>-<a href="usage.html#obfuscationdictionary">obfuscationdictionary</a>
-<li>-<a href="usage.html#classobfuscationdictionary">classobfuscationdictionary</a>
-<li>-<a href="usage.html#packageobfuscationdictionary">packageobfuscationdictionary</a>
-<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>
-<li>-<a href="usage.html#keepclassmembernames">keepclassmembernames</a>
-<li>-<a href="usage.html#keepclasseswithmembernames">keepclasseswithmembernames</a>
-<li><a href="usage.html#classspecification"><i>class_specification</i></a>
+<li>-<a href="usage.html#dontobfuscate">dontobfuscate</a></li>
+<li>-<a href="usage.html#printmapping">printmapping</a></li>
+<li>-<a href="usage.html#applymapping">applymapping</a></li>
+<li>-<a href="usage.html#obfuscationdictionary">obfuscationdictionary</a></li>
+<li>-<a href="usage.html#classobfuscationdictionary">classobfuscationdictionary</a></li>
+<li>-<a href="usage.html#packageobfuscationdictionary">packageobfuscationdictionary</a></li>
+<li>-<a href="usage.html#overloadaggressively">overloadaggressively</a></li>
+<li>-<a href="usage.html#useuniqueclassmembernames">useuniqueclassmembernames</a></li>
+<li>-<a href="usage.html#dontusemixedcaseclassnames">dontusemixedcaseclassnames</a></li>
+<li>-<a href="usage.html#keeppackagenames">keeppackagenames</a></li>
+<li>-<a href="usage.html#flattenpackagehierarchy">flattenpackagehierarchy</a></li>
+<li>-<a href="usage.html#repackageclasses">repackageclasses</a></li>
+<li>-<a href="usage.html#keepattributes">keepattributes</a></li>
+<li>-<a href="usage.html#keepparameternames">keepparameternames</a></li>
+<li>-<a href="usage.html#renamesourcefileattribute">renamesourcefileattribute</a></li>
+<li>-<a href="usage.html#adaptclassstrings">adaptclassstrings</a></li>
+<li>-<a href="usage.html#adaptresourcefilenames">adaptresourcefilenames</a></li>
+<li>-<a href="usage.html#adaptresourcefilecontents">adaptresourcefilecontents</a></li>
+<li>-<a href="usage.html#keepnames">keepnames</a></li>
+<li>-<a href="usage.html#keepclassmembernames">keepclassmembernames</a></li>
+<li>-<a href="usage.html#keepclasseswithmembernames">keepclasseswithmembernames</a></li>
+<li><a href="usage.html#classspecification"><i>class_specification</i></a></li>
</ul>
<p>
-<a name="optimization">&nbsp;</a>
-<h2>The Optimization Tab</h2>
+<h2><a name="optimization">The Optimization Tab</a></h2>
The <i>Optimization</i> tab presents a number of options that affect the
optimization step. The basic options are followed by a few lists of class
@@ -375,18 +384,17 @@ 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>
-<li>-<a href="usage.html#assumenosideeffects">assumenosideeffects</a>
-<li><a href="usage.html#classspecification"><i>class_specification</i></a>
+<li>-<a href="usage.html#dontoptimize">dontoptimize</a></li>
+<li>-<a href="usage.html#optimizations">optimizations</a></li>
+<li>-<a href="usage.html#optimizationpasses">optimizationpasses</a></li>
+<li>-<a href="usage.html#allowaccessmodification">allowaccessmodification</a></li>
+<li>-<a href="usage.html#mergeinterfacesaggressively">mergeinterfacesaggressively</a></li>
+<li>-<a href="usage.html#assumenosideeffects">assumenosideeffects</a></li>
+<li><a href="usage.html#classspecification"><i>class_specification</i></a></li>
</ul>
<p>
-<a name="information">&nbsp;</a>
-<h2>The Information Tab</h2>
+<h2><a name="information">The Information Tab</a></h2>
The <i>Information</i> tab presents a number of options for preverification
and targeting, and for the information that ProGuard returns when processing
@@ -396,26 +404,26 @@ classes and class members are being kept in the shrinking step.
Corresponding configuration options:
<ul type="none">
-<li>-<a href="usage.html#dontpreverify">dontpreverify</a>
-<li>-<a href="usage.html#microedition">microedition</a>
-<li>-<a href="usage.html#target">target</a>
-<li>-<a href="usage.html#verbose">verbose</a>
-<li>-<a href="usage.html#dontnote">dontnote</a>
-<li>-<a href="usage.html#dontwarn">dontwarn</a>
-<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>
-<li>-<a href="usage.html#dump">dump</a>
-<li>-<a href="usage.html#whyareyoukeeping">whyareyoukeeping</a>
+<li>-<a href="usage.html#dontpreverify">dontpreverify</a></li>
+<li>-<a href="usage.html#microedition">microedition</a></li>
+<li>-<a href="usage.html#target">target</a></li>
+<li>-<a href="usage.html#verbose">verbose</a></li>
+<li>-<a href="usage.html#dontnote">dontnote</a></li>
+<li>-<a href="usage.html#dontwarn">dontwarn</a></li>
+<li>-<a href="usage.html#ignorewarnings">ignorewarnings</a></li>
+<li>-<a href="usage.html#skipnonpubliclibraryclasses">skipnonpubliclibraryclasses</a></li>
+<li>-<a href="usage.html#dontskipnonpubliclibraryclasses">dontskipnonpubliclibraryclasses</a></li>
+<li>-<a href="usage.html#dontskipnonpubliclibraryclassmembers">dontskipnonpubliclibraryclassmembers</a></li>
+<li>-<a href="usage.html#keepdirectories">keepdirectories</a></li>
+<li>-<a href="usage.html#forceprocessing">forceprocessing</a></li>
+<li>-<a href="usage.html#printseeds">printseeds</a></li>
+<li>-<a href="usage.html#printconfiguration">printconfiguration</a></li>
+<li>-<a href="usage.html#dump">dump</a></li>
+<li>-<a href="usage.html#whyareyoukeeping">whyareyoukeeping</a></li>
</ul>
<p>
-<a name="process">&nbsp;</a>
-<h2>The Process Tab</h2>
+<h2><a name="process">The Process Tab</a></h2>
The <i>Process</i> tab has an output console for displaying the configuration
and the messages while processing. There are three important buttons at the
@@ -433,8 +441,7 @@ bottom:
</table>
<p>
-<a name="retrace">&nbsp;</a>
-<h2>The ReTrace Tab</h2>
+<h2><a name="retrace">The ReTrace Tab</a></h2>
The <i>ReTrace</i> tab has a panel with a few settings, an input text area for
the obfuscated stack trace, and an output console to view the de-obfuscated
@@ -442,16 +449,16 @@ stack trace:
<ul>
<li>The <b>Verbose</b> check box in the settings panel allows to toggle between
- normal mode and verbose mode.
+ normal mode and verbose mode.</li>
<li>The <b>Mapping file</b> text field takes the name of the required mapping
file that ProGuard wrote while processing the original code. The file name
can be entered manually or by means of the <b>Browse...</b> button that
- opens a file chooser.
+ opens a file chooser.</li>
<li>The <b>Obfuscated stack trace</b> text area allows to enter the stack
trace, typically by copying and pasting it from elsewhere. Alternatively,
- it can be loaded from a file by means of the load button below.
+ it can be loaded from a file by means of the load button below.</li>
</ul>
There are two buttons at the bottom:
@@ -463,12 +470,12 @@ There are two buttons at the bottom:
<tr><td class="button">ReTrace!</td>
<td>executes ReTrace with the current settings.</td></tr>
</table>
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/index.html b/docs/manual/index.html
index 397b910..643a216 100644
--- a/docs/manual/index.html
+++ b/docs/manual/index.html
@@ -1,39 +1,52 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Manual</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
<h2>ProGuard</h2>
<ol>
-<li><a href="introduction.html">Introduction</a>
-<li><a href="usage.html">Usage</a>
-<li><a href="limitations.html">Limitations</a>
-<li><a href="examples.html">Examples</a>
-<li><a href="troubleshooting.html">Troubleshooting</a>
-<li><a href="refcard.html">Reference Card</a>
-<li><a href="gui.html">Graphical User Interface</a>
-<li><a href="ant.html">Ant Task</a>
-<li><a href="wtk.html">JME Wireless Toolkit Integration</a>
+<li><a href="introduction.html">Introduction</a></li>
+<li><a href="usage.html">Usage</a></li>
+<li><a href="limitations.html">Limitations</a></li>
+<li><a href="examples.html">Examples</a></li>
+<li><a href="troubleshooting.html">Troubleshooting</a></li>
+<li><a href="refcard.html">Reference Card</a></li>
+<li><a href="gui.html">Graphical User Interface</a></li>
+<li><a href="ant.html">Ant Task</a></li>
+<li><a href="gradle.html">Gradle Task</a></li>
+<li><a href="wtk.html">JME Wireless Toolkit Integration</a></li>
</ol>
<h2>ReTrace</h2>
<ol>
-<li><a href="retrace/introduction.html">Introduction</a>
-<li><a href="retrace/usage.html">Usage</a>
-<li><a href="retrace/examples.html">Examples</a>
+<li><a href="retrace/introduction.html">Introduction</a></li>
+<li><a href="retrace/usage.html">Usage</a></li>
+<li><a href="retrace/examples.html">Examples</a></li>
</ol>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/introduction.html b/docs/manual/introduction.html
index cdab330..3f18114 100644
--- a/docs/manual/introduction.html
+++ b/docs/manual/introduction.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Introduction</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -17,8 +28,7 @@ bytecode of the methods. The obfuscation step renames the remaining classes,
fields, and methods using short meaningless names. These first steps make the
code base smaller, more efficient, and harder to reverse-engineer. The final
preverification step adds preverification information to the classes, which is
-required for Java Micro Edition or which improves the start-up time for Java
-6.
+required for Java Micro Edition and for Java 6 and higher.
<p>
Each of these steps is optional. For instance, ProGuard can also be used to
just list dead code in an application, or to preverify class files for
@@ -62,13 +72,13 @@ efficient use in Java 6.
</table>
<p>
-ProGuard typically reads the <b>input jars</b> (or wars, ears, zips, or
-directories). It then shrinks, optimizes, obfuscates, and preverifies them.
-Optionally, multiple optimization passes can be performed, each typically
-followed by another shrinking step. ProGuard writes the processed results to
-one or more <b>output jars</b> (or wars, ears, zips, or directories). The
-input may contain resource files, whose names and contents can optionally be
-updated to reflect the obfuscated class names.
+ProGuard first reads the <b>input jars</b> (or wars, ears, zips, or
+directories). It then subsequently shrinks, optimizes, obfuscates, and
+preverifies them. You can optionally let ProGuard perform multiple
+optimization passes. ProGuard writes the processed results to one or
+more <b>output jars</b> (or wars, ears, zips, or directories). The input may
+contain resource files, whose names and contents can optionally be updated to
+reflect the obfuscated class names.
<p>
ProGuard requires the <b>library jars</b> (or wars, ears, zips, or
directories) of the input jars to be specified. These are essentially the
@@ -76,63 +86,69 @@ libraries that you would need for compiling the code. ProGuard uses them to
reconstruct the class dependencies that are necessary for proper processing.
The library jars themselves always remain unchanged. You should still put them
in the class path of your final application.
-<p>
+
+<h3>Entry points</h3>
+
In order to determine which code has to be preserved and which code can be
discarded or obfuscated, you have to specify one or more <i>entry points</i> to
your code. These entry points are typically classes with main methods, applets,
-midlets, etc.
+midlets, activities, etc.
<ul>
<li>In the <b>shrinking step</b>, ProGuard starts from these seeds and
recursively determines which classes and class members are used. All other
- classes and class members are discarded.
+ classes and class members are discarded.</li>
<li>In the <b>optimization step</b>, ProGuard further optimizes the code.
Among other optimizations, classes and methods that are not entry points
can be made private, static, or final, unused parameters can be removed,
- and some methods may be inlined.
+ and some methods may be inlined.</li>
<li>In the <b>obfuscation step</b>, ProGuard renames classes and class members
that are not entry points. In this entire process, keeping the entry
- points ensures that they can still be accessed by their original names.
+ points ensures that they can still be accessed by their original names.</li>
<li>The <b>preverification step</b> is the only step that doesn't have to know
- the entry points.
+ the entry points.</li>
</ul>
<p>
The <a href="usage.html">Usage section</a> of this manual describes the
necessary <a href="usage.html#keepoptions"><code>-keep</code> options</a> and
the <a href="examples.html">Examples section</a> provides plenty of examples.
-<h3>Introspection</h3>
-
-Introspection presents particular problems for any automatic processing of
-code. In ProGuard, classes or class members in your code that are created or
-invoked dynamically (that is, by name) have to be specified as entry points
-too. For example, <code>Class.forName()</code> constructs may refer to any
-class at run-time. It is generally impossible to foresee which classes have to
-be preserved (with their original names), since the class names might be read
-from a configuration file, for instance. You therefore have to specify them in
-your ProGuard configuration, with the same simple <code>-keep</code> options.
+<h3>Reflection</h3>
+
+Reflection and introspection present particular problems for any automatic
+processing of code. In ProGuard, classes or class members in your code that
+are created or invoked dynamically (that is, by name) have to be specified as
+entry points too. For example, <code>Class.forName()</code> constructs may
+refer to any class at run-time. It is generally impossible to compute which
+classes have to be preserved (with their original names), since the class
+names might be read from a configuration file, for instance. You therefore
+have to specify them in your ProGuard configuration, with the same
+simple <code>-keep</code> options.
<p>
However, ProGuard will already detect and handle the following cases for you:
<ul>
-<li><code>Class.forName("SomeClass")</code>
-<li><code>SomeClass.class</code>
-<li><code>SomeClass.class.getField("someField")</code>
-<li><code>SomeClass.class.getDeclaredField("someField")</code>
-<li><code>SomeClass.class.getMethod("someMethod", new Class[] {})</code>
-<li><code>SomeClass.class.getMethod("someMethod", new Class[] { A.class })</code>
-<li><code>SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })</code>
-<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})</code>
-<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })</code>
-<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })</code>
+<li><code>Class.forName("SomeClass")</code></li>
+<li><code>SomeClass.class</code></li>
+<li><code>SomeClass.class.getField("someField")</code></li>
+<li><code>SomeClass.class.getDeclaredField("someField")</code></li>
+<li><code>SomeClass.class.getMethod("someMethod", new Class[] {})</code></li>
+<li><code>SomeClass.class.getMethod("someMethod", new Class[] { A.class })</code></li>
+<li><code>SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })</code></li>
+<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})</code></li>
+<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })</code></li>
+<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })</code></li>
+<li><code>AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")</code></li>
+<li><code>AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")</code></li>
+<li><code>AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")</code></li>
</ul>
The names of the classes and class members may of course be different, but the
constructs should be literally the same for ProGuard to recognize them. The
referenced classes and class members are preserved in the shrinking phase, and
-the string arguments are properly replaced in the obfuscation phase.
+the string arguments are properly updated in the obfuscation phase.
<p>
Furthermore, ProGuard will offer some suggestions if keeping some classes or
class members appears necessary. For example, ProGuard will note constructs
@@ -142,15 +158,15 @@ and/or its implementations may need to be preserved. You can then adapt your
configuration accordingly.
<p>
For proper results, you should at least be somewhat familiar with the code
-that you are processing. Obfuscating code that performs a lot of introspection
+that you are processing. Obfuscating code that performs a lot of reflection
may require trial and error, especially without the necessary information
about the internals of the code.
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/limitations.html b/docs/manual/limitations.html
index cfe0ff5..6b69410 100644
--- a/docs/manual/limitations.html
+++ b/docs/manual/limitations.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Limitations</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -13,16 +24,7 @@
When using ProGuard, you should be aware of a few technical issues, all of
which are easily avoided or resolved:
<p>
-<ul>
-
-<li>For efficiency, ProGuard always ignores any <b>private or package visible
- library classes</b> while reading library jars. If any of them are
- extended by public library classes, and then extended again by input
- classes, ProGuard will complain it can't find them. In that case, you'll
- have to use the <code>-dontskipnonpubliclibraryclasses</code> option, and
- maybe even the <code>-dontskipnonpubliclibraryclassmembers</code> option.
- The graphical user interface has checkboxes for these settings.
- <p>
+<ul class="spacious">
<li>For best results, ProGuard's optimization algorithms assume that the
processed code never <b>intentionally throws NullPointerExceptions</b> or
@@ -33,32 +35,35 @@ which are easily avoided or resolved:
<code>myObject</code> might be null, causing a NullPointerException. In
some way this is a good thing: optimized code may throw fewer exceptions.
Should this entire assumption be false, you'll have to switch off
- optimization using the <code>-dontoptimize</code> option.
- <p>
+ optimization using the <code>-dontoptimize</code> option.</li>
+
+<li>ProGuard's optimization algorithms currently also assume that the
+ processed code never creates <b>busy-waiting loops</b> without at least
+ testing on a volatile field. Again, it may remove such loops. Should this
+ assumption be false, you'll have to switch off optimization using
+ the <code>-dontoptimize</code> option.</li>
<li>If an input jar and a library jar contain classes in the <b>same
package</b>, the obfuscated output jar may contain class names that
overlap with class names in the library jar. This is most likely if the
library jar has been obfuscated before, as it will then probably contain
classes named 'a', 'b', etc. Packages should therefore never be split
- across input jars and library jars.
- <p>
+ across input jars and library jars.</li>
-<li>When obfuscating, ProGuard will write out class files named
- "<code>a.class</code>", "<code>b.class</code>", etc. If there is a large
- numbers of classes in the same package, it may also write out
- <b>"<code>aux.class</code>"</b>. Windows doesn't allow creating files with
- this reserved name (among a few other names), so it's generally better to
- write the output to a jar, in order to avoid such problems.
- <p>
+<li>When obfuscating, ProGuard writes out class files named
+ "<code>a.class</code>", "<code>b.class</code>", etc. If a package contains
+ a large number of classes, ProGuard may also write out
+ <b>"<code>aux.class</code>"</b>. Inconveniently, Windows refuses to create
+ files with this reserved name (among a few other names). It's generally
+ better to write the output to a jar, in order to avoid such problems.</li>
</ul>
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/optimizations.html b/docs/manual/optimizations.html
index 9c20571..e4c96b6 100644
--- a/docs/manual/optimizations.html
+++ b/docs/manual/optimizations.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -124,6 +135,9 @@ are added and reorganized.
<code><b>code/simplification/branch</b></code></dt>
<dd>Performs peephole optimizations for branch instructions.</dd>
+<dt><code><b>code/simplification/string</b></code></dt>
+<dd>Performs peephole optimizations for constant strings.</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
@@ -142,17 +156,43 @@ are added and reorganized.
<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>
+<dd>Removes exceptions with empty try blocks.</dd>
<dt><code><b>code/allocation/variable</b></code></dt>
<dd>Optimizes variable allocation on the local variable frame.</dd>
</dl>
<p>
-<hr>
+ProGuard also provides some unofficial settings to control optimizations, that
+may disappear in future versions. These are Java system properties, which
+can be set as JVM arguments (with <code>-D.....)</code>:
+<dl>
+<dt><code><b>maximum.inlined.code.length</b></code> (default = 8 bytes)</dt>
+<dd>Specifies the maximum code length (expressed in bytes) of short methods
+ that are eligible to be inlined. Inlining methods that are too long may
+ unnecessarily inflate the code size.</dd>
+
+<dt><code><b>maximum.resulting.code.length</b></code> (default = 8000 bytes
+ for JSE, 2000 bytes for JME)</dt>
+<dd>Specifies the maximum resulting code length (expressed in bytes) allowed
+ when inlining methods. Many Java virtual machines do not apply just-in-time
+ compilation to methods that are too long, so it's important not to let them
+ grow too large.</dd>
+
+<dt><code><b>optimize.conservatively</b></code> (default = unset)</dt>
+<dd>Allows input code with ordinary instructions intentionally throwing
+ <code>NullPointerException</code>,
+ <code>ArrayIndexOutOfBoundsException</code>, or
+ <code>ClassCastException</code>, without any other useful purposes. By
+ default, ProGuard may just discard such seemingly useless instructions,
+ resulting in better optimization of most common code.</dd>
+</dl>
+
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/refcard.html b/docs/manual/refcard.html
index 236f049..d9301bd 100644
--- a/docs/manual/refcard.html
+++ b/docs/manual/refcard.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Reference Card</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -52,7 +63,7 @@
<tr>
<td valign="top"><a href="usage.html#outjars"><code><b>-outjars</b></code></a>
<a href="usage.html#classpath"><i>class_path</i></a></td>
-<td>Specifies the name of the output jars (or wars, ears, zips, or
+<td>Specifies the names of the output jars (or wars, ears, zips, or
directories).</td>
</tr>
@@ -63,8 +74,13 @@
</tr>
<tr>
+<td valign="top"><a href="usage.html#skipnonpubliclibraryclasses"><code><b>-skipnonpubliclibraryclasses</b></code></a></td>
+<td>Ignore non-public library classes.</td>
+</tr>
+
+<tr>
<td valign="top"><a href="usage.html#dontskipnonpubliclibraryclasses"><code><b>-dontskipnonpubliclibraryclasses</b></code></a></td>
-<td>Don't ignore non-public library classes.</td>
+<td>Don't ignore non-public library classes (the default).</td>
</tr>
<tr>
@@ -281,6 +297,11 @@
</tr>
<tr>
+<td valign="top"><a href="usage.html#keepparameternames"><code><b>-keepparameternames</b></code></a></td>
+<td>Keep the parameter names and types of methods that are kept.</td>
+</tr>
+
+<tr>
<td valign="top"><a href="usage.html#renamesourcefileattribute"><code><b>-renamesourcefileattribute</b></code></a>
[<i>string</i>]</td>
<td>Put the given constant string in the <code>SourceFile</code>
@@ -345,14 +366,14 @@
<tr>
<td valign="top"><a href="usage.html#printconfiguration"><code><b>-printconfiguration</b></code></a>
[<a href="usage.html#filename"><i>filename</i></a>]</td>
-<td>Write out the internal structure of the processed class files, to the
+<td>Write out the entire configuration in traditional ProGuard style, to the
standard output or to the given file.</td>
</tr>
<tr>
<td valign="top"><a href="usage.html#dump"><code><b>-dump</b></code></a>
[<a href="usage.html#filename"><i>filename</i></a>]</td>
-<td>Write out the entire configuration in traditional ProGuard style, to the
+<td>Write out the internal structure of the processed class files, to the
standard output or to the given file.</td>
</tr>
@@ -362,11 +383,11 @@ Notes:
<ul>
<li><i>class_path</i> is a list of jars, wars, ears, zips, and directories,
- with optional filters, separated by path separators.
+ with optional filters, separated by path separators.</li>
<li><i>filename</i> can contain Java system properties delimited by
- '<b>&lt;</b>' and '<b>&gt;</b>'.
+ '<b>&lt;</b>' and '<b>&gt;</b>'.</li>
<li>If <i>filename</i> contains special characters, the entire name
- should be quoted with single or double quotes.
+ should be quoted with single or double quotes.</li>
</ul>
<p>
@@ -443,23 +464,23 @@ Notes:
Notes:
<ul>
<li>Class names must always be fully qualified, i.e. including their package
- names.
+ names.</li>
<li>Types in <i>classname</i>, <i>annotationtype</i>, <i>returntype</i>, and
<i>argumenttype</i> can contain wildcards: '<code><b>?</b></code>' for a
single character, '<code><b>*</b></code>' for any number of characters
(but not the package separator), '<code><b>**</b></code>' for any number
of (any) characters, '<code><b>%</b></code>' for any primitive type,
- '<code><b>***</b></code>' for any type, and '<code><b>...</b></code>' for any number of arguments..
+ '<code><b>***</b></code>' for any type, and '<code><b>...</b></code>' for any number of arguments.</li>
<li><i>fieldname</i> and <i>methodname</i> can contain wildcards as well:
'<code><b>?</b></code>' for a single character and '<code><b>*</b></code>'
- for any number of characters.
+ for any number of characters.</li>
</ul>
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/retrace/examples.html b/docs/manual/retrace/examples.html
index 211017b..2137e3a 100644
--- a/docs/manual/retrace/examples.html
+++ b/docs/manual/retrace/examples.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ReTrace Examples</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -12,13 +23,13 @@
Some typical example uses:
<ol>
-<li><a href="#with">Restoring a stack trace with line numbers</a>
-<li><a href="#withverbose">Restoring a stack trace with line numbers (verbose)</a>
-<li><a href="#without">Restoring a stack trace without line numbers</a>
+<li><a href="#with">Restoring a stack trace with line numbers</a></li>
+<li><a href="#withverbose">Restoring a stack trace with line numbers
+ (verbose)</a></li>
+<li><a href="#without">Restoring a stack trace without line numbers</a></li>
</ol>
-<a name="with">&nbsp;</a>
-<h3>Restoring a stack trace with line numbers</h3>
+<h3><a name="with">Restoring a stack trace with line numbers</a></h3>
Assume for instance ProGuard itself has been obfuscated using the following
extra options:
@@ -133,8 +144,7 @@ Exception in thread "main" java.lang.Error: Random exception
at proguard.ProGuard.main(ProGuard:429)
</pre>
-<a name="withverbose">&nbsp;</a>
-<h3>Restoring a stack trace with line numbers (verbose)</h3>
+<h3><a name="withverbose">Restoring a stack trace with line numbers (verbose)</a></h3>
In the previous example, we could also use the verbose flag:
<pre>
@@ -189,8 +199,7 @@ Exception in thread "main" java.lang.Error: Random exception
</pre>
-<a name="without">&nbsp;</a>
-<h3>Restoring a stack trace without line numbers</h3>
+<h3><a name="without">Restoring a stack trace without line numbers</a></h3>
Assume for instance ProGuard itself has been obfuscated using the following
extra options, this time without preserving the line number tables:
@@ -324,12 +333,12 @@ Exception in thread "main" java.lang.Error: Random exception
execute
at proguard.ProGuard.main(Unknown Source)
</pre>
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/retrace/index.html b/docs/manual/retrace/index.html
index ebb23ac..47209df 100644
--- a/docs/manual/retrace/index.html
+++ b/docs/manual/retrace/index.html
@@ -1,25 +1,37 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ReTrace Manual</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
<h2>ReTrace</h2>
<ol>
-<li><a href="introduction.html">Introduction</a>
-<li><a href="usage.html">Usage</a>
-<li><a href="examples.html">Examples</a>
+<li><a href="introduction.html">Introduction</a></li>
+<li><a href="usage.html">Usage</a></li>
+<li><a href="examples.html">Examples</a></li>
</ol>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/retrace/introduction.html b/docs/manual/retrace/introduction.html
index 19f9471..381ad1f 100644
--- a/docs/manual/retrace/introduction.html
+++ b/docs/manual/retrace/introduction.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ReTrace Introduction</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -56,12 +67,12 @@ ReTrace can read an obfuscated stack trace and restore it to what it would
look like without obfuscation. The restoration is based on the mapping file
that ProGuard can write out during obfuscation. The mapping file links the
original class names and class member names to their obfuscated names.
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/retrace/usage.html b/docs/manual/retrace/usage.html
index 88587ff..6e7f6a8 100644
--- a/docs/manual/retrace/usage.html
+++ b/docs/manual/retrace/usage.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ReTrace Usage</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -17,7 +28,8 @@ ProGuard distribution. To run ReTrace, just type:
<code><b>java -jar retrace.jar </b></code>[<i>options...</i>]
<i>mapping_file</i> [<i>stacktrace_file</i>]
</p>
-These are the arguments:
+Alternatively, the <code>bin</code> directory contains some short Linux and
+Windows scripts containing this command. These are the arguments:
<dl>
<dt><i>mapping_file</i></dt>
@@ -48,7 +60,7 @@ The following options are supported:
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*)
+ (?:.*?\bat\s+%c.%m\s*\(.*?(?::%l)?\)\s*)|(?:(?:.*?[:"]\s+)?%c(?::.*)?)
</pre>
The regular expression is a Java regular expression (cfr. the documentation
of <code>java.util.regex.Pattern</code>), with a few additional wildcards:
@@ -87,14 +99,13 @@ the obfuscated class files:
<ul>
<li>If all line numbers have been preserved while obfuscating the application,
- ReTrace will be able to restore the stack trace completely.
- <p>
+ ReTrace will be able to restore the stack trace completely.</li>
<li>If the line numbers have been removed, mapping obfuscated method names
back to their original names has become ambiguous. Retrace will list all
possible original method names for each line in the stack trace. The user
can then try to deduce the actual stack trace manually, based on the logic
- of the program.
+ of the program.</li>
</ul>
<p>
@@ -105,12 +116,12 @@ href="../examples.html#stacktrace">example</a> in the ProGuard User Manual.
Unobfuscated elements and obfuscated elements for which no mapping is available
will be left unchanged.
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/sections.html b/docs/manual/sections.html
index 62df9c3..1a6693d 100644
--- a/docs/manual/sections.html
+++ b/docs/manual/sections.html
@@ -1,4 +1,4 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
@@ -21,6 +21,7 @@
<li><a target="main" href="refcard.html">Ref Card</a></li>
<li><a target="main" href="gui.html">GUI</a></li>
<li><a target="main" href="ant.html">Ant Task</a></li>
+<li><a target="main" href="gradle.html">Gradle Task</a></li>
<li><a target="main" href="wtk.html">JME WTK</a></li>
<li class="title">ReTrace Manual</li>
@@ -31,33 +32,22 @@
<p>
<center>
-<small>With support of</small>
+<small>More Android code protection:</small>
<p>
+<a href="http://www.saikoa.com/dexguard" target="_top">
+<img src="../dexguard.png" width="88" height="55" alt="DexGuard" /></a>
-<a href="http://sourceforge.net/projects/proguard/" target="other">
-
-<script type="text/javascript" language="JavaScript">
-<!--
-document.write("<img src=\"");
-document.write(document.location.hostname == "proguard.sourceforge.net" ?
- "http://sourceforge.net/sflogo.php?group_id=54750&amp;type=1" :
- "../sflogo.png");
-document.write("\" width=\"88\" height=\"31\" alt=\"SourceForge\">");
-//-->
-</script>
-<noscript>
-<img src="../sflogo.png" width="88" height="31" alt="SourceForge">
-</noscript>
+<p>
+<small>With support of</small>
+<p>
-</a>
+<a href="http://www.saikoa.com/" target="_top">
+<img src="../saikoalogo.png" width="88" height="19" alt="Saikoa" /></a>
<p>
-<a href="http://www.luciad.com/" target="other">
-<img src="../luciadlogo.png" width="88" height="24" alt="Luciad"></a>
+<a href="http://sourceforge.net/projects/proguard/" target="other">
+<img src="../sflogo.png" width="88" height="31" alt="SourceForge" /></a>
-<p>
-<a href="http://www.javadocking.com/" target="other">
-<img src="../sanawarelogo.png" width="88" height="24" alt="Luciad"></a>
</center>
</body>
diff --git a/docs/manual/style.css b/docs/manual/style.css
index 28fc112..8dae87d 100644
--- a/docs/manual/style.css
+++ b/docs/manual/style.css
@@ -2,20 +2,24 @@
/* Global settings. */
-body {
+body
+{
background: #FFFFFF;
}
-h1 {
+h1
+{
text-align: center;
}
-h2 {
+h2
+{
background: #EEEEFF;
padding: 10px;
}
-dt {
+dt
+{
padding: 6px;
}
@@ -25,23 +29,50 @@ dt div
float: right;
}
-dd {
+dd
+{
padding: 6px;
}
-pre {
+pre
+{
padding: 10px;
background: #E0E0E0;
}
+.spacious li
+{
+ padding: 8px;
+}
+
+.shifted li
+{
+ margin-left: 50px;
+}
+
+img.float
+{
+ float: left;
+}
+
a
{
text-decoration: none;
}
+a.button
+{
+ color: #000000;
+ text-decoration: none;
+ background: #E0E0E0;
+ border: 1px outset #FFFFFF;
+ float: right;
+}
+
/* Settings for variable width code. */
-p.code {
+p.code
+{
padding: 10px;
background: #E0E0E0;
}
@@ -49,34 +80,39 @@ p.code {
/* Settings for diagrams. */
-table.diagram {
+table.diagram
+{
padding: 8px;
border: none;
border-spacing: 2px;
}
-td.transparentblock {
+td.transparentblock
+{
text-align: center;
padding: 10px 0px;
}
-td.whiteblock {
+td.whiteblock
+{
width: 100px;
text-align: center;
- border: solid #C0C0C0 1px;
+ border: 1px solid #C0C0C0;
background: #E0E0E0;
padding: 10px 0px;
}
-td.lightblock {
+td.lightblock
+{
width: 100px;
text-align: center;
- border: solid #8888FF 1px;
+ border: 1px solid #8888FF;
background: #BBBBFF;
padding: 20px 0px;
}
-td.darkblock {
+td.darkblock
+{
width: 100px;
text-align: center;
background: #8888FF;
@@ -85,8 +121,9 @@ td.darkblock {
/* Settings for buttons. */
-td.button {
+td.button
+{
background: #E0E0E0;
- border: outset #FFFFFF 1px;
+ border: 1px outset #FFFFFF;
font-weight: bold;
}
diff --git a/docs/manual/troubleshooting.html b/docs/manual/troubleshooting.html
index d3ed14e..964a25e 100644
--- a/docs/manual/troubleshooting.html
+++ b/docs/manual/troubleshooting.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Troubleshooting</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -15,23 +26,32 @@ few problems. The following sections discuss some common issues and solutions:
<h3><a href="#processing">Problems while processing</a></h3>
<ul>
-<li><a href="#dynamicalclass">Note: can't find dynamically referenced class</a></li>
+<li><a href="#dynamicalclass">Note: can't find dynamically referenced class ...</a></li>
<li><a href="#dynamicalclasscast">Note: ... calls '(...)Class.forName(variable).newInstance()'</a></li>
<li><a href="#dynamicalclassmember">Note: ... accesses a field/method '...' dynamically</a></li>
+<li><a href="#unknownclass">Note: the configuration refers to the unknown class '...'</a></li>
<li><a href="#descriptorclass">Note: the configuration keeps the entry point '...', but not the descriptor class '...'</a></li>
+<li><a href="#classmembers">Note: the configuration doesn't specify which class members to keep for class '...'</a></li>
<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="#superclass">Error: Can't find any super classes of ... (not even immediate super class ...)</a></li>
+<li><a href="#superclass">Error: Can't find common super class of ... and ...</a></li>
+<li><a href="#unresolvedprogramclassmember">Warning: can't find referenced field/method '...' in program class ...</a></li>
+<li><a href="#unresolvedlibraryclassmember">Warning: can't find referenced field/method '...' in library class ...</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>
<li><a href="#unexpectedclass">Warning: class file ... unexpectedly contains class ...</a></li>
<li><a href="#mappingconflict1">Warning: ... is not being kept as ..., but remapped to ...</a></li>
<li><a href="#mappingconflict2">Warning: field/method ... can't be mapped to ...</a></li>
+<li><a href="#unsupportedclassversion">Error: Unsupported class version number</a></li>
<li><a href="#keep">Error: You have to specify '-keep' options</a></li>
<li><a href="#filename">Error: Expecting class path separator ';' before 'Files\Java\...' (in Windows)</a></li>
<li><a href="#macosx">Error: Can't read [.../lib/rt.jar] (No such file or directory) (in MacOS X)</a></li>
+<li><a href="#cantread">Error: Can't read ...</a></li>
+<li><a href="#cantwrite">Error: Can't write ...</a></li>
+<li><a href="#startinggui">Internal problem starting the ProGuard GUI (Cannot write XdndAware property) (in Linux)</a></li>
<li><a href="#outofmemoryerror">OutOfMemoryError</a></li>
<li><a href="#stackoverflowerror">StackOverflowError</a></li>
<li><a href="#unexpectederror">Unexpected error</a></li>
@@ -45,6 +65,13 @@ few problems. The following sections discuss some common issues and solutions:
<li><a href="#notobfuscated">Variable names not being obfuscated</a></li>
</ul>
+<h3><a href="#dalvik">Problems while converting to Android Dalvik bytecode</a></h3>
+
+<ul>
+<li><a href="#simexception">SimException: local variable type mismatch</a></li>
+<li><a href="#conversionerror">Conversion to Dalvik format failed with error 1</a></li>
+</ul>
+
<h3><a href="#preverifying">Problems while preverifying for Java Micro Edition</a></h3>
<ul>
@@ -56,9 +83,12 @@ few problems. The following sections discuss some common issues and solutions:
<li><a href="#stacktraces">Stack traces without class names or line numbers</a></li>
<li><a href="#noclassdeffounderror">NoClassDefFoundError</a></li>
<li><a href="#classnotfoundexception">ClassNotFoundException</a></li>
+<li><a href="#nosuchfieldexception">NoSuchFieldException</a></li>
<li><a href="#nosuchmethodexception">NoSuchMethodException</a></li>
<li><a href="#missingresourceexception">MissingResourceException or NullPointerException</a></li>
+<li><a href="#disappearingannotations">Disappearing annotations</a></li>
<li><a href="#invalidjarfile">Invalid or corrupt jarfile</a></li>
+<li><a href="#invalidjarindexexception">InvalidJarIndexException: Invalid index</a></li>
<li><a href="#invalidclassexception2">InvalidClassException, class loading error, or verification error (in Java Micro Edition)</a></li>
<li><a href="#nosuchfieldormethod">Error: No Such Field or Method, Error verifying method (in a Java Micro Edition emulator)</a></li>
<li><a href="#failingmidlets">Failing midlets (on a Java Micro Edition device)</a></li>
@@ -67,23 +97,23 @@ few problems. The following sections discuss some common issues and solutions:
<li><a href="#classcastexception">ClassCastException: class not an enum</a></li><li><a href="#classcastexception">IllegalArgumentException: class not an enum type</a></li>
<li><a href="#arraystoreexception">ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy</a></li>
<li><a href="#compilererror">CompilerError: duplicate addition</a></li>
-<li><a href="#classformaterror">ClassFormatError: repetitive field name/signature</a></li>
+<li><a href="#classformaterror1">ClassFormatError: repetitive field name/signature</a></li>
+<li><a href="#classformaterror2">ClassFormatError: Invalid index in LocalVariableTable in class file</a></li>
<li><a href="#nosuchmethoderror">NoSuchMethodError or AbstractMethodError</a></li>
<li><a href="#verifyerror">VerifyError</a></li>
</ul>
-<a name="processing">&nbsp;</a>
-<h2>Problems while processing</h2>
+<h2><a name="processing">Problems while processing</a></h2>
ProGuard may print out some notes and non-fatal warnings:
<dl>
-<dt><a name="dynamicalclass"><b>Note: can't find dynamically referenced class</b></a></dt>
+<dt><a name="dynamicalclass"><b>Note: can't find dynamically referenced class ...</b></a></dt>
<dd>ProGuard can't find a class or interface that your code is accessing by
- means of introspection. You should check if you want to add the jar that
- contains this class.</dd>
+ means of introspection. You should consider adding the jar that contains
+ this class.</dd>
<dt><a name="dynamicalclasscast"><b>Note: ... calls '(...)Class.forName(variable).newInstance()'</b></a></dt>
@@ -107,6 +137,13 @@ ProGuard may print out some notes and non-fatal warnings:
notes by specifying the <a
href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+<dt><a name="unknownclass"><b>Note: the configuration refers to the unknown class '...'</b></a></dt>
+
+<dd>Your configuration refers to the name of a class that is not present in
+ the program jars or library jars. You should check whether the name is
+ correct. Notably, you should make sure that you always specify
+ fully-qualified names, not forgetting the package names.</dd>
+
<dt><a name="descriptorclass"><b>Note: the configuration keeps the entry point '...', but not the descriptor class '...'</b></a></dt>
<dd>Your configuration contains a <code>-keep</code> option to preserve the
@@ -118,6 +155,21 @@ ProGuard may print out some notes and non-fatal warnings:
API. You can switch off these notes by specifying the <a
href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+<dt><a name="classmembers"><b>Note: the configuration doesn't specify which class members to keep for class '...'</b></a></dt>
+
+<dd>Your configuration contains
+ a <a href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a>/<a href="usage.html#keepclasseswithmembers">-keepclasseswithmembers</code></a>
+ option to preserve fields or methods in the given class, but it doesn't
+ specify which fields or methods. This way, the option simply won't have
+ any effect. You probably want to specify one or more fields or methods, as
+ usual between curly braces. You can specify all fields or methods with a
+ wildcard "<code>*;</code>". You should also consider if you just need the
+ more common <a href="usage.html#keep"><code>-keep</code></a> option, which
+ preserves all specified classes <i>and</i> class members.
+ The <a href="usage.html#keepoverview">overview of all <code>keep</code>
+ options</a> can help. You can switch off these notes by specifying
+ the <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
<dt><a name="duplicateclass"><b>Note: duplicate definition of program/library class</b></a></dt>
<dd>Your program jars or library jars contain multiple definitions of the
@@ -126,7 +178,21 @@ ProGuard may print out some notes and non-fatal warnings:
though, so it's advisable to remove the duplicates. A convenient way to do
so is by specifying filters on the input jars or library jars. You can
switch off these notes by specifying the <a
- href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+ href="usage.html#dontnote"><code>-dontnote</code></a> option.
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> The standard Android build process automatically
+ specifies the input jars for you. There may not be an easy way to filter
+ them to remove these notes. You could remove the duplicate classes
+ manually from your libraries. You should never explicitly specify the
+ input jars yourself (with <code>-injars</code> or
+ <code>-libraryjars</code>), since you'll then get duplicate definitions.
+ You should also not add libraries to your application that are already
+ part of the Android run-time (notably <code>org.w3c.dom</code>,
+ <code>org.xml.sax</code>, <code>org.xmlpull.v1</code>,
+ <code>org.apache.commons.logging.Log</code>, <code>org.apache.http</code>,
+ and <code>org.json</code>). They are possibly inconsistent, and the
+ run-time libraries would get precedence anyway.</dd>
<dt><a name="duplicatezipentry"><b>Warning: can't write resource ... Duplicate zip entry</b></a></dt>
@@ -135,7 +201,13 @@ ProGuard may print out some notes and non-fatal warnings:
with previously used names. Once more, the warning may be an indication of
some problem though, so it's advisable to remove the duplicates. A
convenient way to do so is by specifying filters on the input jars. There
- is no option to switch off these warnings.</dd>
+ is no option to switch off these warnings.
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> The standard Android build process automatically
+ specifies the input jars for you. There may not be an easy way to filter
+ them to remove these warnings. You could remove the duplicate resource files
+ manually from the input and the libraries.</dd>
</dl>
<p>
@@ -146,60 +218,133 @@ some more serious warnings:
<dl>
<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 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.
+<dd>A class in one of your program jars or library jars is referring to a
+ class or interface that is missing from the input. The warning lists both
+ the referencing class(es) and the missing referenced class(es). There can
+ be a few reasons, with their own solutions:
<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. 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.
+ <ol>
+ <li>If the missing class is referenced from your own code, you may have
+ forgotten to specify an essential library. Just like when compiling
+ all code from scratch, you must specify all libraries that the code is
+ referencing, directly or indirectly. If the library should be
+ processed and included in the output, you should specify it with
+ <a href="usage.html#injars"><code>-injars</code></a>, otherwise you
+ should specify it with
+ <a href="usage.html#libraryjars"><code>-libraryjars</code></a>.
+ <p>
+ For example, if ProGuard complains that it can't find a
+ <code>java.lang</code> class, you have to make sure that you are
+ specifying the run-time library of your platform. For JSE, these are
+ typically packaged in <code>lib/rt.jar</code> (<code>vm.jar</code> for
+ IBM's JVM, and <code>classes.jar</code> in MacOS X). Other platforms
+ like JME and Android have their own run-time libraries.
+ The <a href="examples.html">examples section</a> provides more details
+ for the various platforms.
+ <p>
+ If ProGuard still complains that it can't find a
+ <code>javax.crypto</code> class, you probably still have to specify
+ <code>jce.jar</code>, next to the more common <code>rt.jar</code>.</li>
+ <li>If the missing class is referenced from a pre-compiled third-party
+ library, and your original code runs fine without it, then the missing
+ dependency doesn't seem to hurt. The cleanest solution is to
+ <a href="usage.html#filters">filter out</a> the <i>referencing</i>
+ class or classes from the input, with a filter like "<code>-libraryjars
+ mylibrary.jar(!somepackage/SomeUnusedReferencingClass.class)</code>".
+ ProGuard will then skip this class entirely in the input, and it will
+ not bump into the problem of its missing reference. However, you may
+ then have to filter out other classes that are in turn referencing the
+ removed class. In practice, this works best if you can filter out
+ entire unused packages at once, with a wildcard filter like
+ "<code>-libraryjars
+ mylibrary.jar(!someunusedpackage/**)</code>".<p></li>
+ <li>If you don't feel like filtering out the problematic classes, 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.
+ Only use these options if you really know what you're doing though.</li>
+ </ol>
<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. 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>
-
-<dd>If there are unresolved references to class members in input classes, your
- class files are most likely inconsistent. Possibly, some class file didn't
- get recompiled properly, or some class file was left behind after its
- source file was removed. Try removing all class files, recompiling them,
- zipping them up, and running ProGuard again.
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> The standard Android build process automatically
+ specifies the input jars for you. Unfortunately, many pre-compiled
+ third-party libraries refer to other libraries that are not actually used
+ and therefore not present. This works fine in debug builds, but in release
+ builds, ProGuard expects all libraries, so it can perform a proper static
+ analysis. For example, if ProGuard complains that it can't find
+ a <code>java.awt</code> class, then some library that you are using is
+ referring to <code>java.awt</code>. This is a bit shady, since Android
+ doesn't have this package at all, but if your application works anyway,
+ you can let ProGuard accept it with "<code>-dontwarn java.awt.**</code>",
+ for instance.</dd>
+
+<dt><a name="superclass"><b>Error: Can't find any super classes of ... (not even immediate super class ...)</b><br/><b>Error: Can't find common super class of ... and ...</b></a></dt>
+
+<dd>It seems like you tried to avoid the warnings from the previous paragraph
+ by specifying
+ <a href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a>
+ or <a href="usage.html#dontwarn"><code>-dontwarn</code></a>, but it didn't
+ work out. ProGuard's optimization step and preverification step really
+ need the missing classes to make sense of the code. Preferably, you would
+ solve the problem by adding the missing library, as discussed. If you're
+ sure the class that references the missing class isn't used either, you
+ could also try filtering it out from the input, by adding a filter to the
+ corresponding <a href="usage.html#injars"><code>-injars</code></a> option:
+ "<code>-injars
+ myapplication.jar(!somepackage/SomeUnusedClass.class)</code>". As a final
+ solution, you could switch off optimization
+ (<a href="usage.html#dontoptimize"><code>-dontoptimize</code></a>) and
+ preverification
+ (<a href="usage.html#dontpreverify"><code>-dontpreverify</code></a>).</dd>
+
+<dt><a name="unresolvedprogramclassmember"><b>Warning: can't find referenced field/method '...' in program class ...</b></a></dt>
+
+<dd>A program class is referring to a field or a method that is missing from
+ another program class. The warning lists both the referencing class and
+ the missing referenced class member. Your compiled class files are most
+ likely inconsistent. Possibly, some class file didn't get recompiled
+ properly, or some class file was left behind after its source file was
+ removed. Try removing all compiled class files and rebuilding your
+ project.</dd>
+
+<dt><a name="unresolvedlibraryclassmember"><b>Warning: can't find referenced field/method '...' in library class ...</b></a></dt>
+
+<dd>A program class is referring to a field or a method that is missing from a
+ library class. The warning lists both the referencing class and the
+ missing referenced class member. Your compiled class files are
+ inconsistent with the libraries. You may need to recompile the class
+ files, or otherwise upgrade the libraries to consistent versions.
<p>
- If the class member that is reported as missing is actually implemented in
- a non-public library class, you should specify the
- <a href="usage.html#dontskipnonpubliclibraryclasses"><code>-dontskipnonpubliclibraryclasses</code></a> option. A common example is
- the method <code>setLength(int)</code> in the public class
- <code>java.lang.StringBuilder</code>. This method is actually defined in
- the package visible superclass
- <code>java.lang.AbstractStringBuilder</code>, which ProGuard ignores by
- default.
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> If you're developing for Android and ProGuard complains
+ that it can't find a method that is only available in a recent version of
+ the Android run-time, you should change the build target in your
+ <code>project.properties</code> file or <code>build.gradle</code> file to
+ that recent version. You can still specify a different
+ <code>minSdkVersion</code> and a different <code>targetSdkVersion</code>
+ in your <code>AndroidManifest.xml</code> file.
<p>
- If your program classes reside in the same packages as library classes,
- and refer to their package visible class members, then you should specify
- the <a
- href="usage.html#dontskipnonpubliclibraryclassmembers"><code>-dontskipnonpubliclibraryclassmembers</code></a>
+ Alternatively, you may get away with ignoring the inconsistency with the
+ options
+ <a href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a> or
+ even
+ <a href="usage.html#dontwarn"><code>-dontwarn</code></a>. For instance, you
+ can specify "<code>-dontwarn mypackage.MyInconsistentClass</code>".
+ <p>
+ Finally, should your program classes reside in the same packages as
+ library classes and should they refer to their package visible class
+ members, then you should also specify the
+ <a href="usage.html#dontskipnonpubliclibraryclassmembers"><code>-dontskipnonpubliclibraryclassmembers</code></a>
option.</dd>
<dt><a name="unresolvedenclosingmethod"><b>Warning: can't find enclosing class/method</b></a></dt>
<dd>If there are unresolved references to classes that are defined inside
- methods in your input, once more, your class files are most likely
+ methods in your input, once more, your compiled class files are most likely
inconsistent. Possibly, some class file didn't get recompiled properly, or
some class file was left behind after its source file was removed. Try
- removing all class files, recompiling them, zipping them up, and running
- ProGuard again.</dd>
+ removing all compiled class files and rebuilding your project.</dd>
<dt><a name="dependency"><b>Warning: library class ... depends on program class ...</b></a></dt>
@@ -210,7 +355,20 @@ some more serious warnings:
classes always remain unchanged. It is therefore impossible to adapt
references from library classes to program classes, for instance if the
program classes are renamed. You should define a clean separation between
- program code and library code, and try again.</dd>
+ program code (specified with <a
+ href="usage.html#injars"><code>-injars</code></a>) and library code
+ (specified with <a
+ href="usage.html#libraryjars"><code>-libraryjars</code></a>), and try
+ again.
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> In Android development, sloppy libraries may contain
+ duplicates of classes that are already present in the Android run-time
+ (notably <code>org.w3c.dom</code>, <code>org.xml.sax</code>,
+ <code>org.xmlpull.v1</code>, <code>org.apache.commons.logging.Log</code>,
+ <code>org.apache.http</code>, and <code>org.json</code>). You must remove
+ these classes from your libraries, since they are possibly inconsistent,
+ and the run-time libraries would get precedence anyway.</dd>
<dt><a name="unexpectedclass"><b>Warning: class file ... unexpectedly contains class ...</b></a></dt>
@@ -257,6 +415,13 @@ some more serious warnings:
option in the initial obfuscation step, in order to reduce the risk of
conflicts.</dd>
+<dt><a name="unsupportedclassversion"><b>Error: Unsupported class version number</b></a></dt>
+
+<dd>You are trying to process class files compiled for a recent version of
+ Java that your copy of ProGuard doesn't support yet. You
+ should <a href="http://proguard.sourceforge.net/downloads.html">check
+ on-line</a> if there is a more recent release.</dd>
+
<dt><a name="keep"><b>Error: You have to specify '-keep' options</b></a></dt>
<dd>You either forgot to specify <a
@@ -266,7 +431,6 @@ some more serious warnings:
these. Without the proper seed specifications, ProGuard would shrink,
optimize, or obfuscate all class files away.</dd>
-
<dt><a name="filename"><b>Error: Expecting class path separator ';' before 'Files\Java\</b>...<b>'</b> (in Windows)</a></dt>
<dd>If the path of your run-time jar contains spaces, like in "Program Files",
@@ -282,6 +446,30 @@ some more serious warnings:
the path <code>&lt;java.home&gt;/lib/rt.jar</code> by
<code>&lt;java.home&gt;/../Classes/classes.jar</code>.</dd>
+<dt><a name="cantread"><b>Error: Can't read ...</b></a></dt>
+
+<dd>ProGuard can't read the specified file or directory. Double-check that the
+ name is correct in your configuration, that the file is readable, and that
+ it is not corrupt. An additional message "Unexpected end of ZLIB input
+ stream" suggests that the file is truncated. You should then make sure
+ that the file is complete on disk when ProGuard starts (asynchronous
+ copying? unflushed buffer or cache?), and that it is not somehow
+ overwritten by ProGuard's own output.</dd>
+
+<dt><a name="cantwrite"><b>Error: Can't write ...</b></a></dt>
+
+<dd>ProGuard can't write the specified file or directory. Double-check that
+ the name is correct in your configuration and that the file is
+ writable.</dd>
+
+<dt><a name="startinggui"><b>Internal problem starting the ProGuard GUI (Cannot write XdndAware property)</b> (in Linux)</a></dt>
+
+<dd>In Linux, at least with Java 6, the GUI may not start properly, due to
+ <a href="http://bugs.sun.com/view_bug.do?bug_id=7027598">Sun
+ Bug #7027598</a>. The work-around at this time is to specify the JVM
+ option <code>-DsuppressSwingDropSupport=true</code> when running the
+ GUI.</dd>
+
</dl>
<p>
@@ -304,7 +492,7 @@ Should ProGuard crash while processing your application:
size of the Java virtual machine (with the usual <code>-Xss</code> option)
should help too. In practice however, the <code>-Xss</code> setting
doesn't have any effect on the main thread, due to <a
- href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4362291">Sun Bug
+ href="http://bugs.sun.com/view_bug.do?bug_id=4362291">Sun Bug
#4362291</a>. As a result, this solution will only work when running
ProGuard in a different thread, e.g. from its GUI.</dd>
@@ -326,8 +514,7 @@ Should ProGuard crash while processing your application:
</dl>
<p>
-<a name="afterprocessing">&nbsp;</a>
-<h2>Unexpected observations after processing</h2>
+<h2><a name="afterprocessing">Unexpected observations after processing</a></h2>
If ProGuard seems to run fine, but your processed code doesn't look right,
there might be a couple of reasons:
@@ -363,7 +550,14 @@ there might be a couple of reasons:
<p>
If you are using marker interfaces to keep other classes, the marker
interfaces themselves are probably being removed in the shrinking step.
- You should therefore always explicitly keep any marker interfaces.</dd>
+ You should therefore always explicitly keep any marker interfaces, with
+ an option like "<code>-keep interface MyMarkerInterface</code>".
+ <p>
+ Similarly, if you are keeping classes based on annotations, you may have
+ to avoid that the annotation classes themselves are removed in the
+ shrinking step. You should package the annotation classes as a library, or
+ explicitly keep them in your program code with an option like "<code>-keep
+ @interface *</code>".</dd>
<dt><a name="notobfuscated"><b>Variable names not being obfuscated</b></a></dt>
@@ -377,8 +571,37 @@ there might be a couple of reasons:
</dl>
-<a name="preverifying">&nbsp;</a>
-<h2>Problems while preverifying for Java Micro Edition</h2>
+<h2><a name="dalvik">Problems while converting to Android Dalvik bytecode</a></h2>
+
+If ProGuard seems to run fine, but the dx tool in the Android SDK subsequently
+fails with an error:
+
+<dl>
+<dt><a name="simexception"><b>SimException: local variable type mismatch</b></a></dt>
+
+<dd>This error indicates that ProGuard's optimization step has not been able
+ to maintain the correct debug information about local variables. This can
+ happen if some code is optimized radically. Possible work-arounds: let the
+ java compiler not produce debug information (<code>-g:none</code>), or let
+ ProGuard's obfuscation step remove the debug information again
+ (by <i>not</i> keeping the attributes <code>LocalVariableTable</code>
+ and <code>LocalVariableTypeTable</code>
+ with <a href="usage.html#keepattributes"><code>-keepattributes</code></a>),
+ or otherwise just disable optimization
+ (<a href="usage.html#dontoptimize"><code>-dontoptimize</code></a>).</dd>
+
+<dt><a name="conversionerror"><b>Conversion to Dalvik format failed with error 1</b></a></dt>
+
+<dd>This error may have various causes, but if dx is tripping over some code
+ processed by ProGuard, you should make sure that you are using the latest
+ version of ProGuard. You can just copy the ProGuard jars
+ to <code>android-sdk/tools/proguard/lib</code>. If that doesn't help,
+ please report the problem, preferably with the simplest example that still
+ brings out the error.</dd>
+
+</dl>
+
+<h2><a name="preverifying">Problems while preverifying for Java Micro Edition</a></h2>
If ProGuard seems to run fine, but the external preverifier subsequently
produces errors, it's usually for a single reason:
@@ -409,8 +632,7 @@ Note that it is no longer necessary to use an external preverifier. With the
ProGuard will preverify the class files for Java Micro Edition.
<p>
-<a name="runtime">&nbsp;</a>
-<h2>Problems at run-time</h2>
+<h2><a name="runtime">Problems at run-time</a></h2>
If ProGuard runs fine, but your processed application doesn't work, there
might be several reasons:
@@ -439,14 +661,30 @@ might be several reasons:
class mypackage.MyClass</code>" or "<code>-keep class * implements
mypackage.MyInterface</code>".</dd>
+<dt><a name="nosuchfieldexception"><b>NoSuchFieldException</b></a></dt>
+
+<dd>Your code is probably calling something like
+ <code>myClass.getField</code>, trying to find some field dynamically.
+ Since ProGuard can't always detect this automatically, you have to keep
+ the missing field in using the
+ appropriate <a href="usage.html#keep"><code>-keep</code></a> option, e.g.
+ "<code>-keepclassmembers class mypackage.MyClass { int myField;
+ }</code>".</dd>
+
<dt><a name="nosuchmethodexception"><b>NoSuchMethodException</b></a></dt>
<dd>Your code is probably calling something like
<code>myClass.getMethod</code>, trying to find some method dynamically.
- Since ProGuard isn't detecting this (yet), you have to keep the missing
- method in using the appropriate <a
- href="usage.html#keep"><code>-keep</code></a> option, e.g. "<code>-keep
- class mypackage.MyClass { void myMethod(); }</code>".</dd>
+ Since ProGuard can't always detect this automatically, you have to keep
+ the missing method in using the
+ appropriate <a href="usage.html#keep"><code>-keep</code></a> option, e.g.
+ "<code>-keepclassmembers class mypackage.MyClass { void myMethod();
+ }</code>".
+ <p>
+ More specifically, if the method reported as missing is
+ <code>values</code> or <code>valueOf</code>, you probably have to keep
+ some methods related to <a
+ href="examples.html#enumerations">enumerations</a>.</dd>
<dt><a name="missingresourceexception"><b>MissingResourceException</b> or <b>NullPointerException</b></a></dt>
@@ -460,7 +698,18 @@ might be several reasons:
<p>
Furthermore, directory entries in jar files aren't copied, unless you
specify the option <a
- href="usage.html#keepdirectories"><code>-keepdirectories</code></a>.</dd>
+ href="usage.html#keepdirectories"><code>-keepdirectories</code></a>.
+ Note that Sun advises against calling <code>Class.getResource()</code> for
+ directories (<a href="http://bugs.sun.com/view_bug.do?bug_id=4761949">Sun
+ Bug #4761949</a>).</dd>
+
+<dt><a name="disappearingannotations"><b>Disappearing annotations</b></a></dt>
+
+<dd>By default, the obfuscation step removes all annotations. If your
+ application relies on annotations to function properly, you should
+ explicitly keep them with
+ <code><a href="usage.html#keepattributes">-keepattributes</a>
+ *Annotation*</code>.</dd>
<dt><a name="invalidjarfile"><b>Invalid or corrupt jarfile</b></a></dt>
@@ -474,6 +723,17 @@ might be several reasons:
manifest file is the one that is copied (the first manifest file that is
encountered), and that the main class is kept in your configuration,</dd>
+<dt><a name="invalidjarindexexception"><b>InvalidJarIndexException: Invalid index</b></a></dt>
+
+<dd>At least one of your processed jar files contains an index file
+ <code>META-INF/INDEX.LIST</code>, listing all class files in the jar.
+ ProGuard by default copies files like these unchanged. ProGuard may however
+ remove or rename classes, thus invalidating the file. You should filter the
+ index file out of the input
+ (<code>-injars in.jar(!META-INF/INDEX.LIST)</code>) or update the file
+ after having applied ProGuard (<code>jar -i out.jar</code>).
+ </dd>
+
<dt><a name="invalidclassexception2"><b>InvalidClassException</b>, <b>class loading error</b>, or <b>verification error</b> (in Java Micro Edition)</a></dt>
<dd>If you get such an error in Java Micro Edition, you may have forgotten to
@@ -526,7 +786,7 @@ might be several reasons:
<dd>You may have forgotten to sign your program jar <i>after</i> having
processed it with ProGuard.</dd>
-<dt><a name="classcastexception"><b>ClassCastException: class not an enum</b>, or <br><b>IllegalArgumentException: class not an enum type</b></a></dt>
+<dt><a name="classcastexception"><b>ClassCastException: class not an enum</b>, or <br /><b>IllegalArgumentException: class not an enum type</b></a></dt>
<dd>You should make sure you're preserving the special methods of enumeration
types, which the run-time environment calls by introspection. The required
@@ -548,7 +808,7 @@ might be several reasons:
<code>sun.tools.java.MethodSet.add</code> in Sun's JDK 1.2.2, which is
used for (dynamic) compilation. You should then avoid this option.</dd>
-<dt><a name="classformaterror"><b>ClassFormatError: repetitive field name/signature</b></a></dt>
+<dt><a name="classformaterror1"><b>ClassFormatError: repetitive field name/signature</b></a></dt>
<dd>You are probably processing some code that has been obfuscated before with
the <a
@@ -556,6 +816,14 @@ might be several reasons:
option. You should then use the same option again in the second processing
round.</dd>
+<dt><a name="classformaterror2"><b>ClassFormatError: Invalid index in LocalVariableTable in class file</b></a></dt>
+
+<dd>If you are keeping the <code>LocalVariableTable</code> or
+ <code>LocalVariableTypeTable</code> attributes, ProGuard's optimizing step
+ is sometimes unable to update them consistently. You should then let the
+ obfuscation step remove these attributes or disable the optimization
+ step.</dd>
+
<dt><a name="nosuchmethoderror"><b>NoSuchMethodError</b> or <b>AbstractMethodError</b></a></dt>
<dd>You should make sure you're not writing your output class files to a
@@ -583,10 +851,11 @@ might be several reasons:
</dl>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/usage.html b/docs/manual/usage.html
index 8be8d60..7d3a5bb 100644
--- a/docs/manual/usage.html
+++ b/docs/manual/usage.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Usage</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -15,55 +26,53 @@ To run ProGuard, just type:
<code><b>java -jar proguard.jar </b></code><i>options</i> ...
</p>
You can find the ProGuard jar in the <code>lib</code> directory of the
-ProGuard distribution. Options can also be put in one or more configuration
-files. Typically, you'll put most options in a configuration file (say,
-<code>myconfig.pro</code>), and just call:
+ProGuard distribution. Alternatively, the <code>bin</code> directory contains
+some short Linux and Windows scripts containing this command. Typically, you'll
+put most options in a configuration file (say, <code>myconfig.pro</code>), and
+just call:
<p class="code">
<code><b>java -jar proguard.jar @myconfig.pro</b></code>
</p>
-You can combine command line options and options from configuration files, for
+You can combine command line options and options from configuration files. For
instance:
<p class="code">
<code><b>java -jar proguard.jar @myconfig.pro -verbose</b></code>
</p>
<p>
-In a configuration file, a <code><b>#</b></code> sign and all remaining
-characters on that line are ignored, allowing you to add comments.
+You can add comments in a configuration file, starting with a
+<code><b>#</b></code> character and continuing until the end of the line.
<p>
-Extra whitespace between words and delimiters is ignored. To specify file
-names with spaces or special characters, words can be quoted with single or
-double quotes. Note that the quotes may need to be escaped when used on the
-command line, to avoid them being gobbled by the shell.
+Extra whitespace between words and delimiters is ignored. File names with
+spaces or special characters should be quoted with single or double quotes.
<p>
Options can be grouped arbitrarily in arguments on the command line and in
-lines in configuration files. This means that you can quote any arbitrary
-section of command line options, to avoid shell expansion of special
-characters, for instance.
+lines in configuration files. This means that you can quote arbitrary sections
+of command line options, to avoid shell expansion of special characters, for
+instance.
<p>
-The order of the options is generally irrelevant. They can be abbreviated to
-their first unique characters.
+The order of the options is generally irrelevant. For quick experiments, you
+can abbreviate them to their first unique characters.
<p>
The sections below provide more details:
<ul>
-<li><a href="#iooptions">Input/Output Options</a>
-<li><a href="#keepoptions">Keep Options</a>
-<li><a href="#shrinkingoptions">Shrinking Options</a>
-<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>
-<li><a href="#classspecification">Class Specifications</a>
+<li><a href="#iooptions">Input/Output Options</a></li>
+<li><a href="#keepoptions">Keep Options</a></li>
+<li><a href="#shrinkingoptions">Shrinking Options</a></li>
+<li><a href="#optimizationoptions">Optimization Options</a></li>
+<li><a href="#obfuscationoptions">Obfuscation Options</a></li>
+<li><a href="#preverificationoptions">Preverification Options</a></li>
+<li><a href="#generaloptions">General Options</a></li>
+<li><a href="#classpath">Class Paths</a></li>
+<li><a href="#filename">File Names</a></li>
+<li><a href="#filefilters">File Filters</a></li>
+<li><a href="#filters">Filters</a></li>
+<li><a href="#keepoverview">Overview of <code>Keep</code> Options</a></li>
+<li><a href="#keepoptionmodifiers">Keep Option Modifiers</a></li>
+<li><a href="#classspecification">Class Specifications</a></li>
</ul>
-<a name="iooptions">&nbsp;</a>
-<h2>Input/Output Options</h2>
+<h2><a name="iooptions">Input/Output Options</a></h2>
<dl>
<dt><a name="at"><code><b>@</b></code></a><a href="#filename"><i>filename</i></a></dt>
@@ -132,27 +141,32 @@ The sections below provide more details:
Although this may seem cumbersome, it allows you to process applications
targeted at different run-time environments. For example, you can process
<a href="examples.html#application">J2SE applications</a> as well as <a
- href="examples.html#midlet">JME midlets</a>, just by specifying the
- appropriate run-time jar.</dd>
+ href="examples.html#midlet">JME midlets</a> or <a
+ href="examples.html#androidapplication">Android apps</a>, just by
+ specifying the appropriate run-time jar.</dd>
+
+<dt><a name="skipnonpubliclibraryclasses"><code><b>-skipnonpubliclibraryclasses</b></code></a></dt>
+
+<dd>Specifies to skip non-public classes while reading library jars, to speed
+ up processing and reduce memory usage of ProGuard. By default, ProGuard
+ reads non-public and public library classes alike. However, non-public
+ classes are often not relevant, if they don't affect the actual program
+ code in the input jars. Ignoring them then speeds up ProGuard, without
+ affecting the output. Unfortunately, some libraries, including recent JSE
+ run-time libraries, contain non-public library classes that are extended
+ by public library classes. You then can't use this option. ProGuard will
+ print out warnings if it can't find classes due to this option being
+ set.</dd>
<dt><a name="dontskipnonpubliclibraryclasses"><code><b>-dontskipnonpubliclibraryclasses</b></code></a></dt>
-<dd>Specifies not to ignore non-public library classes. By default, non-public
- library classes are skipped while parsing library jars. The classes are
- typically not relevant during processing, since they don't affect the
- actual program code in the input jars. Ignoring them reduces memory usage
- and processing time. Occasionally, a badly designed library may contain a
- non-public library class that is extended/implemented by a public library
- class. If the latter library class in turn is extended/implemented by a
- program class, ProGuard will complain that it can't find the non-public
- library class, which it had ignored during parsing. This option will
- overcome that problem, at the cost of greater memory usage and longer
- processing time.</dd>
+<dd>Specifies not to ignore non-public library classes. As of version 4.5, this
+ is the default setting.</dd>
<dt><a name="dontskipnonpubliclibraryclassmembers"><code><b>-dontskipnonpubliclibraryclassmembers</b></code></a></dt>
<dd>Specifies not to ignore package visible library class members (fields and
- methods). By default, these class members are skipped while parsing
+ methods). By default, ProGuard skips these class members while parsing
library classes, as program classes will generally not refer to them.
Sometimes however, program classes reside in the same packages as library
classes, and they do refer to their package visible class members. In
@@ -162,23 +176,26 @@ The sections below provide more details:
<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>
+<dd>Specifies the directories to be kept in the output jars (or wars, ears,
+ zips, or directories). By default, directory entries are removed. This
+ reduces the jar size, but it may break your program if the code tries to
+ find them with constructs like
+ "<code>mypackage.MyClass.class.getResource("")</code>". You'll then want to
+ keep the directory corresponding to the package, "<code>-keepdirectories
+ mypackage</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
version number can be one of <code>1.0</code>, <code>1.1</code>,
<code>1.2</code>, <code>1.3</code>, <code>1.4</code>, <code>1.5</code> (or
- just <code>5</code>), or <code>1.6</code> (or just <code>6</code>). By
- default, the version numbers of the class files are left unchanged. For
- example, you may want to <a href="examples.html#upgrade">upgrade class
- files to Java 6</a>, by changing their version numbers and having them
- preverified.</dd>
+ just <code>5</code>), <code>1.6</code> (or just <code>6</code>), or
+ <code>1.7</code> (or just <code>7</code>). By default, the version numbers
+ of the class files are left unchanged. For example, you may want to
+ <a href="examples.html#upgrade">upgrade class files to Java 6</a>, by
+ changing their version numbers and having them preverified.</dd>
<dt><a name="forceprocessing"><code><b>-forceprocessing</b></code></a></dt>
@@ -189,8 +206,7 @@ The sections below provide more details:
</dl>
<p>
-<a name="keepoptions">&nbsp;</a>
-<h2>Keep Options</h2>
+<h2><a name="keepoptions">Keep Options</a></h2>
<dl>
<dt><a name="keep"><code><b>-keep</b></code></a>
@@ -245,11 +261,11 @@ The sections below provide more details:
<p>
Specifies class members whose names are to be preserved, if they aren't
removed in the shrinking phase. For example, you may want to preserve the
- name of the synthetic <code>class$</code> methods when <a
- href="examples.html#library">processing a library</a>, so obfuscators can
- detect it again when processing an application that uses the processed
- library (although ProGuard itself doesn't need this). Only applicable when
- obfuscating.</dd>
+ name of the synthetic <code>class$</code> methods
+ when <a href="examples.html#library">processing a library</a> compiled by
+ JDK 1.2 or older, so obfuscators can detect it again when processing an
+ application that uses the processed library (although ProGuard itself
+ doesn't need this). Only applicable when obfuscating.</dd>
<dt><a name="keepclasseswithmembernames"><code><b>-keepclasseswithmembernames</b></code></a>
<a href="#classspecification"><i>class_specification</i></a></dt>
@@ -280,8 +296,7 @@ The sections below provide more details:
</dl>
<p>
-<a name="shrinkingoptions">&nbsp;</a>
-<h2>Shrinking Options</h2>
+<h2><a name="shrinkingoptions">Shrinking Options</a></h2>
<dl>
<dt><a name="dontshrink"><code><b>-dontshrink</b></code></a></dt>
@@ -319,8 +334,7 @@ The sections below provide more details:
</dl>
<p>
-<a name="optimizationoptions">&nbsp;</a>
-<h2>Optimization Options</h2>
+<h2><a name="optimizationoptions">Optimization Options</a></h2>
<dl>
<dt><a name="dontoptimize"><code><b>-dontoptimize</b></code></a></dt>
@@ -348,14 +362,16 @@ The sections below provide more details:
<dd>Specifies methods that don't have any side effects (other than maybe
returning a value). In the optimization step, ProGuard will then remove
calls to such methods, if it can determine that the return values aren't
- used. Note that ProGuard will analyze your program code to find such
- methods automatically. It will not analyze library code, for which this
- option can thus be useful. For example, you could specify the method
+ used. ProGuard will analyze your program code to find such methods
+ automatically. It will not analyze library code, for which this option can
+ therefore be useful. For example, you could specify the method
<code>System.currentTimeMillis()</code>, so that any idle calls to it will
- be removed. Note that ProGuard applies the option to the entire hierarchy
- of the specified methods. Only applicable when optimizing. In general,
- making assumptions can be dangerous; you can easily break the processed
- code. <i>Only use this option if you know what you're doing!</i></dd>
+ be removed. With some care, you can also use the option to
+ <a href="examples.html#logging">remove logging code</a>. Note that
+ ProGuard applies the option to the entire hierarchy of the specified
+ methods. Only applicable when optimizing. In general, making assumptions
+ can be dangerous; you can easily break the processed code. <i>Only use
+ this option if you know what you're doing!</i></dd>
<dt><a name="allowaccessmodification"><code><b>-allowaccessmodification</b></code></a></dt>
@@ -401,14 +417,13 @@ The sections below provide more details:
<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.
+ without implementations) in a class.</li>
</ul></dd>
</dl>
<p>
-<a name="obfuscationoptions">&nbsp;</a>
-<h2>Obfuscation Options</h2>
+<h2><a name="obfuscationoptions">Obfuscation Options</a></h2>
<dl>
<dt><a name="dontobfuscate"><code><b>-dontobfuscate</b></code></a></dt>
@@ -440,10 +455,12 @@ The sections below provide more details:
mapping may refer to input classes as well as library classes. This option
can be useful for <a href="examples.html#incremental">incremental
obfuscation</a>, i.e. processing add-ons or small patches to an existing
- piece of code. In such cases, you should consider whether you also need
- the option <a
- href="#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>.
- Only applicable when obfuscating.</dd>
+ piece of code. If the structure of the code changes fundamentally,
+ ProGuard may print out warnings that applying a mapping is causing
+ conflicts. You may be able to reduce this risk by specifying the option <a
+ href="#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>
+ in both obfuscation runs. Only a single mapping file is allowed. Only
+ applicable when obfuscating.</dd>
<dt><a name="obfuscationdictionary"><code><b>-obfuscationdictionary</b></code></a>
<a href="#filename"><i>filename</i></a></dt>
@@ -506,13 +523,13 @@ The sections below provide more details:
<ul>
<li>Sun's JDK 1.2.2 <code>javac</code> compiler produces an exception when
compiling with such a library (cfr. <a href=
- "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4216736">Bug
- #4216736</a>). You probably shouldn't use this option for processing
- libraries.
+ "http://bugs.sun.com/view_bug.do?bug_id=4216736">Bug #4216736</a>).
+ You probably shouldn't use this option for processing libraries.</li>
<li>Sun's JRE 1.4 and later fail to serialize objects with overloaded
- primitive fields.
+ primitive fields.</li>
<li>Sun's JRE 1.5 <code>pack200</code> tool reportedly has problems with
- overloaded class members.
+ overloaded class members.</li>
+ <li>Google's Dalvik VM can't handle overloaded static fields.</li>
</ul></dd>
<dt><a name="useuniqueclassmembernames"><code><b>-useuniqueclassmembernames</b></code></a></dt>
@@ -548,16 +565,16 @@ The sections below provide more details:
filing system (say, Windows), the unpacking tool may let similarly named
class files overwrite each other. Code that self-destructs when it's
unpacked! Developers who really want to unpack their jars on Windows can
- use this option to switch off this behavior. Note that the obfuscated jars
- will become larger as a result. Only applicable when obfuscating.</dd>
+ use this option to switch off this behavior. Obfuscated jars will become
+ slightly 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>
+<dd>Specifies not to 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>
@@ -608,12 +625,24 @@ The sections below provide more details:
name can be specified as well, referring to the source name part of this
attribute. For example, you should at least keep the
<code>Exceptions</code>, <code>InnerClasses</code>, and
- <code>Signature</code> attributes when <a
- href="examples.html#library">processing a library</a>. As another example,
- you should keep the <code>SourceFile</code> and
- <code>LineNumberTable</code> attributes for <a
- href="examples.html#stacktrace">producing useful obfuscated stack
- traces</a>. Only applicable when obfuscating.</dd>
+ <code>Signature</code> attributes
+ when <a href="examples.html#library">processing a library</a>. You should
+ also keep the <code>SourceFile</code> and
+ <code>LineNumberTable</code> attributes
+ for <a href="examples.html#stacktrace">producing useful obfuscated stack
+ traces</a>. Finally, you may want
+ to <a href="examples.html#annotations">keep annotations</a> if your code
+ depends on them. Only applicable when obfuscating.</dd>
+
+<dt><a name="keepparameternames"><code><b>-keepparameternames</b></code></a></dt>
+
+<dd>Specifies to keep the parameter names and types of methods that are kept.
+ This option actually keeps trimmed versions of the debugging attributes
+ <code>LocalVariableTable</code> and
+ <code>LocalVariableTypeTable</code>. It can be useful when
+ <a href="examples.html#library">processing a library</a>. Some IDEs can
+ use the information to assist developers who use the library, for example
+ with tool tips or autocompletion. Only applicable when obfuscating.</dd>
<dt><a name="renamesourcefileattribute"><code><b>-renamesourcefileattribute</b></code></a>
[<i>string</i>]</dt>
@@ -665,8 +694,7 @@ The sections below provide more details:
</dl>
<p>
-<a name="preverificationoptions">&nbsp;</a>
-<h2>Preverification Options</h2>
+<h2><a name="preverificationoptions">Preverification Options</a></h2>
<dl>
<dt><a name="dontpreverify"><code><b>-dontpreverify</b></code></a></dt>
@@ -675,9 +703,10 @@ The sections below provide more details:
files are preverified if they are targeted at Java Micro Edition or at
Java 6 or higher. For Java Micro Edition, preverification is required, so
you will need to run an external preverifier on the processed code if you
- specify this option. For Java 6, preverification is not required (yet),
- but it improves the efficiency of the class loading in the Java Virtual
- Machine.</dd>
+ specify this option. For Java 6, preverification is optional, but as of
+ Java 7, it is required. Only when eventually targeting Android, it is not
+ necessary, so you can then switch it off to reduce the processing time a
+ bit.</dd>
<dt><a name="microedition"><code><b>-microedition</b></code></a></dt>
@@ -690,8 +719,7 @@ The sections below provide more details:
</dl>
<p>
-<a name="generaloptions">&nbsp;</a>
-<h2>General Options</h2>
+<h2><a name="generaloptions">General Options</a></h2>
<dl>
<dt><a name="verbose"><code><b>-verbose</b></code></a></dt>
@@ -749,8 +777,7 @@ The sections below provide more details:
</dl>
<p>
-<a name="classpath">&nbsp;</a>
-<h2>Class Paths</h2>
+<h2><a name="classpath">Class Paths</a></h2>
ProGuard accepts a generalization of class paths to specify input files and
output files. A class path consists of entries, separated by the traditional
@@ -759,12 +786,12 @@ The order of the entries determines their priorities, in case of duplicates.
<p>
Each input entry can be:
<ul>
-<li>A class file or resource file.
-<li>A jar file, containing any of the above,
-<li>A war file, containing any of the above,
-<li>An ear file, containing any of the above,
-<li>A zip file, containing any of the above,
-<li>A directory (structure), containing any of the above.
+<li>A class file or resource file,</li>
+<li>A jar file, containing any of the above,</li>
+<li>A war file, containing any of the above,</li>
+<li>An ear file, containing any of the above,</li>
+<li>A zip file, containing any of the above,</li>
+<li>A directory (structure), containing any of the above.</li>
</ul>
<p>
The paths of directly specified class files and resource files is ignored, so
@@ -776,11 +803,11 @@ any additional directory prefixes inside the archives or directories.
Each output entry can be:
<ul>
<li>A jar file, in which all processed class files and resource files will be
- collected.
-<li>A war file, in which any and all of the above will be collected,
-<li>An ear file, in which any and all of the above will be collected,
-<li>A zip file, in which any and all of the above will be collected,
-<li>A directory, in which any and all of the above will be collected.
+ collected.</li>
+<li>A war file, in which any and all of the above will be collected,</li>
+<li>An ear file, in which any and all of the above will be collected,</li>
+<li>A zip file, in which any and all of the above will be collected,</li>
+<li>A directory, in which any and all of the above will be collected.</li>
</ul>
<p>
When writing output entries, ProGuard will generally package the results in a
@@ -801,12 +828,12 @@ 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 zip names that are encountered,</li>
+<li>A filter for all ear names that are encountered,</li>
+<li>A filter for all war names that are encountered,</li>
+<li>A filter for all jar names that are encountered,</li>
<li>A filter for all class file names and resource file names that are
- encountered.
+ encountered.</li>
</ul>
<p>
If fewer than 5 filters are specified, they are assumed to be the latter
@@ -826,8 +853,8 @@ 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.
+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
@@ -840,40 +867,37 @@ possibilities. The Examples section provides a few more examples
for <a href="examples.html#filtering">filtering input and output</a>.
<p>
-<a name="filename">&nbsp;</a>
-<h2>File Names</h2>
+<h2><a name="filename">File Names</a></h2>
ProGuard accepts absolute paths and relative paths for the various file names
and directory names. A relative path is interpreted as follows:
<ul>
-<li>relative to the base directory, if set, or otherwise
+<li>relative to the base directory, if set, or otherwise</li>
<li>relative to the configuration file in which it is specified, if any, or
- otherwise
-<li>relative to the working directory.
+ otherwise</li>
+<li>relative to the working directory.</li>
</ul>
<p>
-The names can contain Java system properties delimited by '<b>&lt;</b>' and
-'<b>&gt;</b>'. The system properties
-are automatically replaced by their respective values.
+The names can contain Java system properties (or Ant properties, when using
+Ant), delimited by angular brackets, '<b>&lt;</b>' and '<b>&gt;</b>'. The
+properties are automatically replaced by their corresponding values.
<p>
-For example, <code>&lt;java.home&gt;/lib/rt.jar</code> will automatically be
+For example, <code>&lt;java.home&gt;/lib/rt.jar</code> is automatically
expanded to something like <code>/usr/local/java/jdk/jre/lib/rt.jar</code>.
-Similarly, <code>&lt;user.home&gt;</code> will be expanded to the user's home
-directory, and <code>&lt;user.dir&gt;</code> will be expanded to the current
+Similarly, <code>&lt;user.home&gt;</code> is expanded to the user's home
+directory, and <code>&lt;user.dir&gt;</code> is expanded to the current
working directory.
<p>
Names with special characters like spaces and parentheses must be quoted with
-single or double quotes. Note that each file name in a list of names has to be
-quoted individually. Also note that the quotes themselves may need to be
-escaped when used on the command line, to avoid them being gobbled by the
-shell.
+single or double quotes. Each file name in a list of names has to be quoted
+individually. Note that the quotes themselves may need to be escaped when used
+on the command line, to avoid them being gobbled by the shell.
<p>
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="filefilters">&nbsp;</a>
-<h2>File Filters</h2>
+<h2><a name="filefilters">File Filters</a></h2>
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
@@ -905,8 +929,7 @@ For example, "<code>!**.gif,images/**</code>" matches all files in the
The Examples section provides a few more examples for <a
href="examples.html#filtering">filtering input and output</a>.
-<a name="filters">&nbsp;</a>
-<h2>Filters</h2>
+<h2><a name="filters">Filters</a></h2>
ProGuard offers options with filters for many different aspects of the
configuration: names of files, directories, classes, packages, attributes,
@@ -944,8 +967,7 @@ For example, "<code>!foobar,*bar</code>" matches all names ending with
<code>bar</code>, except <code>foobar</code>.
<p>
-<a name="keepoverview">&nbsp;</a>
-<h2>Overview of <code>Keep</code> Options</h2>
+<h2><a name="keepoverview">Overview of <code>Keep</code> Options</a></h2>
The various <code>-keep</code> options for shrinking and obfuscation may seem
a bit confusing at first, but there's actually a pattern behind them. The
@@ -989,24 +1011,17 @@ If you're not sure which option you need, you should probably simply use
<code>-keep</code>. It will make sure the specified classes and class members
are not removed in the shrinking step, and not renamed in the obfuscation step.
<p>
-<table>
-<tr><td valign="top">
-<img src="attention.gif" width="64" height="64"alt="attention">
-</td><td>
-Always remember:
-<ul>
-<li>Specifying a class without class members only preserves the class as an
- entry point &mdash; any class members may then still be removed, optimized,
- or obfuscated.</li>
-<li>Specifying a class member only preserves the class member as an entry
- point &mdash; any associated code may still be optimized and adapted.</li>
+<img class="float" src="attention.gif" width="64" height="64" alt="attention" />
+<ul class="shifted">
+<li>If you specify a class, without class members, ProGuard only preserves the
+ class and its parameterless constructor as entry points. It may
+ still remove, optimize, or obfuscate its other class members.</li>
+<li>If you specify a method, ProGuard only preserves the method as an entry
+ point. Its code may still be optimized and adapted.</li>
</ul>
-</td></tr>
-</table>
<p>
-<a name="keepoptionmodifiers">&nbsp;</a>
-<h2>Keep Option Modifiers</h2>
+<h2><a name="keepoptionmodifiers">Keep Option Modifiers</a></h2>
<dl>
<dt><a name="allowshrinking"><code><b>allowshrinking</b></code></a></dt>
@@ -1035,8 +1050,7 @@ Always remember:
</dl>
<p>
-<a name="classspecification">&nbsp;</a>
-<h2>Class Specifications</h2>
+<h2><a name="classspecification">Class Specifications</a></h2>
A class specification is a template of classes and class members (fields and
methods). It is used in the various <code>-keep</code> options and in the
@@ -1071,18 +1085,20 @@ of the specification that belong together. The indentation tries to clarify
the intended meaning, but white-space is irrelevant in actual configuration
files.
<p>
-<ul>
+<ul class="spacious">
<li>The <code><b>class</b></code> keyword refers to any interface or class.
The <code><b>interface</b></code> keyword restricts matches to interface
classes. The <code><b>enum</b></code> keyword restricts matches to
enumeration classes. Preceding the <code><b>interface</b></code> or
<code><b>enum</b></code> keywords by a <code><b>!</b></code> restricts
- matches to classes that are not interfaces or enumerations, respectively.
- <p>
+ matches to classes that are not interfaces or enumerations,
+ respectively.</li>
<li>Every <i>classname</i> must be fully qualified, e.g.
- <code>java.lang.String</code>. Class names may be specified as regular
+ <code>java.lang.String</code>. Inner classes are separated by a dollar sign
+ "<code>$</code>", e.g. <code>java.lang.Thread$State</code>. Class names
+ may be specified as regular
expressions containing the following wildcards:
<table cellspacing="10">
@@ -1120,22 +1136,19 @@ files.
should be used with moderation.
<p>
For convenience and for backward compatibility, the class name
- <code><b>*</b></code> refers to any class, irrespective of its package.
- <p>
+ <code><b>*</b></code> refers to any class, irrespective of its package.</li>
<li>The <code><b>extends</b></code> and <code><b>implements</b></code>
specifications are typically used to restrict classes with wildcards. They
are currently equivalent, specifying that only classes extending or
implementing the given class qualify. Note that the given class itself is
not included in this set. If required, it should be specified in a
- separate option.
- <p>
+ separate option.</li>
<li>The <code><b>@</b></code> specifications can be used to restrict classes
and class members to the ones that are annotated with the specified
annotation types. An <i>annotationtype</i> is specified just like a
- <i>classname</i>.
- <p>
+ <i>classname</i>.</li>
<li>Fields and methods are specified much like in Java, except that method
argument lists don't contain argument names (just like in other tools
@@ -1198,13 +1211,11 @@ files.
<code>***</code> wildcards will match array types of any dimension. For
example, "<code>** get*()</code>" matches "<code>java.lang.Object
getObject()</code>", but not "<code>float getFloat()</code>", nor
- "<code>java.lang.Object[] getObjects()</code>".
- <p>
+ "<code>java.lang.Object[] getObjects()</code>".</li>
<li>Constructors can also be specified using their short class names (without
package) or using their full class names. As in the Java language, the
- constructor specification has an argument list, but no return type.
- <p>
+ constructor specification has an argument list, but no return type.</li>
<li>The class access modifiers and class member access modifiers are typically
used to restrict wildcarded classes and class members. They specify that
@@ -1218,14 +1229,18 @@ files.
which case at least one of them has to be set (e.g. at least
<code>public</code>
<i>or</i> <code>protected</code>).
+ <p>
+ ProGuard supports the additional modifiers <code><b>synthetic</b></code>,
+ <code><b>bridge</b></code>, and <code><b>varargs</b></code>, which may be
+ set by compilers.</li>
</ul>
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/manual/wtk.html b/docs/manual/wtk.html
index b8c70b5..a7ea0b8 100644
--- a/docs/manual/wtk.html
+++ b/docs/manual/wtk.html
@@ -1,16 +1,27 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard JME Wireless Toolkit Integration</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("../index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
<h2>JME Wireless Toolkit Integration</h2>
-<b>ProGuard</b> can be seamlessly integrated in Sun's Wireless Toolkit (WTK)
+<b>ProGuard</b> can be seamlessly integrated in Oracle's Wireless Toolkit (WTK)
for Java Micro Edition (JME).
<p>
@@ -49,10 +60,11 @@ Should you ever need to customize your ProGuard configuration for the JME WTK,
you can adapt the configuration file <code>proguard/wtk/default.pro</code>
that's inside the <code>proguard.jar</code>.
-<hr>
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/quality.html b/docs/quality.html
index 29889e3..d9935fc 100644
--- a/docs/quality.html
+++ b/docs/quality.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Quality</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -31,14 +42,15 @@ full-screen size.
<p>
In addition, <b>ProGuard</b> is tested against a constantly growing test suite
-(more than 500 tests at this time of writing). These small programs contain a
+(more than 1500 tests at this time of writing). These small programs contain a
wide range of common and uncommon constructs, in order to detect any regression
problems as soon as possible.
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/results.html b/docs/results.html
index 480cd4f..eee8aa6 100644
--- a/docs/results.html
+++ b/docs/results.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Results</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -31,7 +42,7 @@ presents some typical results:
</tr>
<tr>
-<td><a target="other" href="http://java.sun.com/j2me/">Worm</a>, a sample midlet from Sun's JME</td>
+<td><a target="other" href="http://www.oracle.com/technetwork/java/javame/index,html">Worm</a>, a sample midlet from Oracle's JME</td>
<td align="center">10.3 K</td>
<td align="center">9.8 K</td>
<td align="center">9.6 K</td>
@@ -75,7 +86,7 @@ presents some typical results:
</tr>
<tr>
-<td><a target="other" href="http://java.sun.com/javase/6/">the run-time classes</a> from Sun's Java 6</td>
+<td><a target="other" href="ihttp://www.oracle.com/technetwork/java/javase/overview/index.html">the run-time classes</a> from Oracle's Java 6</td>
<td align="center">53 M</td>
<td align="center">23 M</td>
<td align="center">22 M</td>
@@ -86,7 +97,7 @@ presents some typical results:
</tr>
<tr>
-<td><a target="other" href="http://jakarta.apache.org/tomcat/index.html">Tomcat</a>, the Apache servlet container</td>
+<td><a target="other" href="http://tomcat.apache.org/">Tomcat</a>, the Apache servlet container</td>
<td align="center">1.1 M</td>
<td align="center">466 K</td>
<td align="center">426 K</td>
@@ -97,7 +108,7 @@ presents some typical results:
</tr>
<tr>
-<td><a target="other" href="http://www.kclee.com/clemens/java/javancss/">JavaNCSS</a>, a Java source metrics tool</td>
+<td><a target="other" href="http://javancss.codehaus.org/">JavaNCSS</a>, a Java source metrics tool</td>
<td align="center">632 K</td>
<td align="center">242 K</td>
<td align="center">212 K</td>
@@ -121,7 +132,8 @@ presents some typical results:
</table>
<p>
Results were measured with ProGuard 4.0 on a 2.6 GHz Pentium 4 with 512 MB
-of memory, using Sun JDK 1.5.0 in Fedora Core 3 Linux.
+of memory, using Sun JDK 1.5.0 in Fedora Core 3 Linux. All of this technology
+and software has evolved since, but the gist of the results remains the same.
<p>
The program sizes include companion libraries. The shrinking step produces the
best results for programs that use only small parts of their libraries. The
@@ -145,10 +157,12 @@ minutes.
Memory usage (the amount of physical memory used by ProGuard while processing)
is governed by the basic java virtual machine and by the total size of the
library jars and program jars.
-<hr>
+
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/saikoalogo.png b/docs/saikoalogo.png
new file mode 100644
index 0000000..5b34172
--- /dev/null
+++ b/docs/saikoalogo.png
Binary files differ
diff --git a/docs/sanawarelogo.png b/docs/sanawarelogo.png
deleted file mode 100644
index bf7218b..0000000
--- a/docs/sanawarelogo.png
+++ /dev/null
Binary files differ
diff --git a/docs/screenshots.html b/docs/screenshots.html
index 8718839..31c1296 100644
--- a/docs/screenshots.html
+++ b/docs/screenshots.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Screenshots</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -13,7 +24,7 @@
<table><tr><td>
<a href="screenshot_gui1.gif" target="other">
<img src="screenshots_gui_small.gif" width="320" height="223" align="right"
- alt="GUI screenshot" usemap="#guimap"></a>
+ alt="GUI screenshot" usemap="#guimap" /></a>
<map id="guimap" name="guimap">
<area shape="rect" coords="2,7,46,16" alt="ProGuard" href="screenshot_gui1.gif" target="other">
@@ -36,21 +47,21 @@ tabs.
<tr><td>
<a href="screenshot_console.gif" target="other">
<img src="screenshot_console_small.gif" width="320" height="268" align="left"
- alt="Console screenshot"></a>
+ alt="Console screenshot" /></a>
Of course, real developers don't need all this point-and-click fluff. They
-write a short configuration file using their favorite text editor and invoke
+write short configuration files using their favorite text editors and invoke
<b>ProGuard</b> from the command-line.
<p>
You can click on the image to see the full-size version.
</td></tr></table>
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
</html>
diff --git a/docs/sections.html b/docs/sections.html
index d955d33..7a2ab8a 100644
--- a/docs/sections.html
+++ b/docs/sections.html
@@ -1,4 +1,4 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
@@ -26,37 +26,32 @@
<p>
<center>
-<small>With support of</small>
+<small>More Android code protection:</small>
<p>
+<a href="http://www.saikoa.com/dexguard" target="_top">
+<img src="dexguard.png" width="88" height="55" alt="Saikoa" /></a>
-<a href="http://sourceforge.net/projects/proguard/" target="other">
-
-<script type="text/javascript" language="JavaScript">
-<!--
-document.write("<img src=\"");
-document.write(document.location.hostname == "proguard.sourceforge.net" ?
- "http://sourceforge.net/sflogo.php?group_id=54750&amp;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>
-<img src="sflogo.png" width="88" height="31" alt="SourceForge">
-</noscript>
-
-</a>
+<p>
+<small>With support of</small>
<p>
-<a href="http://www.luciad.com/" target="other">
-<img src="luciadlogo.png" width="88" height="24" alt="Luciad"></a>
+<a href="http://www.saikoa.com/" target="_top">
+<img src="saikoalogo.png" width="88" height="19" alt="DexGuard" /></a>
+
<p>
-<a href="http://www.javadocking.com/" target="other">
-<img src="sanawarelogo.png" width="88" height="24" alt="Sanaware"></a>
+<a href="http://sourceforge.net/projects/proguard/" target="other">
+<img src="sflogo.png" width="88" height="31" alt="SourceForge" /></a>
+
</center>
+<script type="text/javascript">
+base = "http://sourceforge.net/apps/piwik/proguard/";
+if (document.location.hostname == "proguard.sourceforge.net")
+ document.write(unescape("%3Cscript src='"+base+"piwik.js' type='text/javascript'%3E%3C/script%3E"));
+</script><script type="text/javascript">
+if (document.location.hostname == "proguard.sourceforge.net")
+ piwik_log('', 1, base+"piwik.php");
+</script>
+
</body>
</html>
diff --git a/docs/style.css b/docs/style.css
index c9798db..71d69d7 100644
--- a/docs/style.css
+++ b/docs/style.css
@@ -52,6 +52,11 @@ td
padding: 8px;
}
+ul.spacious li
+{
+ padding: 8px;
+}
+
a
{
text-decoration: none;
@@ -62,13 +67,21 @@ img
border: none;
}
+a.button {
+ color: #000000;
+ text-decoration: none;
+ background: #E0E0E0;
+ border: 1px outset #FFFFFF;
+ float: right;
+}
+
/* Settings for the introductory paragraph. */
p.intro
{
background: #EEEEFF;
padding: 10px;
- border: solid #000000 1px
+ border: 1px solid #000000;
}
/* Settings for the title frame. */
@@ -115,6 +128,7 @@ body.navigation
{
margin: 0px;
padding: 0px;
+ background: #F8F8F8;
}
ul.navigation
diff --git a/docs/testimonials.html b/docs/testimonials.html
index 6971617..f6e2cd7 100644
--- a/docs/testimonials.html
+++ b/docs/testimonials.html
@@ -1,10 +1,21 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>ProGuard Testimonials</title>
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ window.top.location.replace("index.html#"+window.location.pathname+window.location.hash);
+else {
+ var hash="#"+window.location.pathname.replace(window.top.location.pathname.replace("index.html", ""), "");
+ if (window.top.location.hash!=hash)
+ window.top.location.hash=hash;
+}
+//-->
+</script>
</head>
<body>
@@ -14,11 +25,11 @@ And now for some shameless self-glorification and name-dropping...
<p>
<b>ProGuard</b> is probably the most popular java shrinker, optimizer, and
obfuscator world-wide. It is being used by developers at companies and
-organizations like Sun, IBM, HP, Siemens, Nokia, Google, and NATO. It is the
-default tool in many development environments like Sun's Wireless Toolkit,
-Netbeans, EclipseME, and more. Although the quotes below probably don't
-represent official views of any kind, encouragements like these do keep me
-happy.
+organizations like IBM, HP, Siemens, Nokia, Google, Intel, and NATO. It is the
+default tool in many development environments like Oracle's Wireless Toolkit,
+Netbeans, EclipseME, Google's Android SDK, and more. Although the quotes below
+probably don't represent official views of any kind, encouragements like these
+do keep me happy.
<p>
<center><table class="note">
@@ -26,9 +37,9 @@ happy.
ProGuard is <b>the</b> ultimate java obfuscator!
</cite></p>
<p class="author">P.S, IBM</p></td>
-<td class="shadow8"><img src="drop2.gif" width="8" height="100"></td></tr><tr>
-<td class="shadow400"><img src="drop1.gif" width="400" height="8"></td>
-<td class="shadow8"><img src="drop3.gif" width="8" height="8"></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
</tr></table></center>
<p>
@@ -38,9 +49,9 @@ Also:
ProGuard is pure quality - powerful and trouble-free.
</cite></p>
<p class="author">M.B., Statestep</p></td>
-<td class="shadow8"><img src="drop2.gif" width="8" height="100"></td></tr><tr>
-<td class="shadow400"><img src="drop1.gif" width="400" height="8"></td>
-<td class="shadow8"><img src="drop3.gif" width="8" height="8"></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
</tr></table></center>
<p>
@@ -50,9 +61,9 @@ And:
It is the simplest and most robust obfuscator we have ever used.
</cite></p>
<p class="author">I.I., Hewlett-Packard</p></td>
-<td class="shadow8"><img src="drop2.gif" width="8" height="100"></td></tr><tr>
-<td class="shadow400"><img src="drop1.gif" width="400" height="8"></td>
-<td class="shadow8"><img src="drop3.gif" width="8" height="8"></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
</tr></table></center>
<p>
@@ -62,9 +73,9 @@ And indeed:
ProGuard rules. Much easier to use than the commercial alternatives.
</cite></p>
<p class="author">B.G., Quiotix Corp.</p></td>
-<td class="shadow8"><img src="drop2.gif" width="8" height="100"></td></tr><tr>
-<td class="shadow400"><img src="drop1.gif" width="400" height="8"></td>
-<td class="shadow8"><img src="drop3.gif" width="8" height="8"></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
</tr></table></center>
<p>
@@ -77,9 +88,9 @@ obfuscators and shrinkers, ProGuard stands out as the simplest, most robust,
and accurate shrinker of them all.
</cite></p>
<p class="author">D.J., Joot</p></td>
-<td class="shadow8"><img src="drop2.gif" width="8" height="100"></td></tr><tr>
-<td class="shadow400"><img src="drop1.gif" width="400" height="8"></td>
-<td class="shadow8"><img src="drop3.gif" width="8" height="8"></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
</tr></table></center>
<p>
@@ -93,9 +104,9 @@ powerful configuration options make it an excellent addition to your MIDlet
development toolbox.
</cite></p>
<p class="author">J.K., Sun</p></td>
-<td class="shadow8"><img src="drop2.gif" width="8" height="100"></td></tr><tr>
-<td class="shadow400"><img src="drop1.gif" width="400" height="8"></td>
-<td class="shadow8"><img src="drop3.gif" width="8" height="8"></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
</tr></table></center>
<p>
@@ -106,16 +117,16 @@ And, of course, the price is stunning:
You could've been rich.
</cite></p>
<p class="author">My mother</p></td>
-<td class="shadow8"><img src="drop2.gif" width="8" height="100"></td></tr><tr>
-<td class="shadow400"><img src="drop1.gif" width="400" height="8"></td>
-<td class="shadow8"><img src="drop3.gif" width="8" height="8"></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
</tr></table></center>
-<p>
-<hr>
+<hr />
+<noscript><div><a target="_top" href="index.html" class="button">Show menu</a></div></noscript>
<address>
-Copyright &copy; 2002-2009
-<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
+Copyright &copy; 2002-2013
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a>.
</address>
</body>
diff --git a/docs/title.html b/docs/title.html
index 33171b5..80e2c42 100644
--- a/docs/title.html
+++ b/docs/title.html
@@ -1,4 +1,4 @@
-<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
@@ -9,8 +9,8 @@
<body class="title">
<div class="title">
-<h1><img src="title.gif" width="154" height="29" alt="ProGuard"></h1>
-<div>Version 4.4</div>
+<h1><img src="title.gif" width="154" height="29" alt="ProGuard" /></h1>
+<div>Version 4.10</div>
</div>
</body>
diff --git a/examples/android.pro b/examples/android.pro
new file mode 100644
index 0000000..234dad4
--- /dev/null
+++ b/examples/android.pro
@@ -0,0 +1,174 @@
+#
+# This ProGuard configuration file illustrates how to process Android
+# applications.
+# Usage:
+# java -jar proguard.jar @android.pro
+#
+# If you're using the Android SDK, the Ant release build and Eclipse export
+# already take care of the proper settings. You only need to enable ProGuard
+# by commenting in the corresponding line in project.properties. You can still
+# add project-specific configuration in proguard-project.txt.
+#
+# This configuration file is for custom, stand-alone builds.
+
+# Specify the input jars, output jars, and library jars.
+# Note that ProGuard works with Java bytecode (.class),
+# before the dex compiler converts it into Dalvik code (.dex).
+
+-injars bin/classes
+-injars libs
+-outjars bin/classes-processed.jar
+
+-libraryjars /usr/local/android-sdk/platforms/android-9/android.jar
+#-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar
+# ...
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on.
+
+-printmapping bin/classes-processed.map
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds bin/classes-processed.seeds
+
+# Preverification is irrelevant for the dex compiler and the Dalvik VM.
+
+-dontpreverify
+
+# Reduce the size of the output some more.
+
+-repackageclasses ''
+-allowaccessmodification
+
+# Switch off some optimizations that trip older versions of the Dalvik VM.
+
+-optimizations !code/simplification/arithmetic
+
+# Keep a fixed source file attribute and all line number tables to get line
+# numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+# RemoteViews might need annotations.
+
+-keepattributes *Annotation*
+
+# Preserve all fundamental application classes.
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+
+# Preserve all View implementations, their special context constructors, and
+# their setters.
+
+-keep public class * extends android.view.View {
+ public <init>(android.content.Context);
+ public <init>(android.content.Context, android.util.AttributeSet);
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+ public void set*(...);
+}
+
+# Preserve all classes that have special context constructors, and the
+# constructors themselves.
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+# Preserve all classes that have special context constructors, and the
+# constructors themselves.
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+# Preserve all possible onClick handlers.
+
+-keepclassmembers class * extends android.content.Context {
+ public void *(android.view.View);
+ public void *(android.view.MenuItem);
+}
+
+# Preserve the special fields of all Parcelable implementations.
+
+-keepclassmembers class * implements android.os.Parcelable {
+ static android.os.Parcelable$Creator CREATOR;
+}
+
+# Preserve static fields of inner classes of R classes that might be accessed
+# through introspection.
+
+-keepclassmembers class **.R$* {
+ public static <fields>;
+}
+
+# Preserve annotated Javascript interface methods.
+
+-keepclassmembers class * {
+ @android.webkit.JavascriptInterface <methods>;
+}
+
+# Preserve the required interface from the License Verification Library
+# (but don't nag the developer if the library is not used at all).
+
+-keep public interface com.android.vending.licensing.ILicensingService
+
+-dontnote com.android.vending.licensing.ILicensingService
+
+# The Android Compatibility library references some classes that may not be
+# present in all versions of the API, but we know that's ok.
+
+-dontwarn android.support.**
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers class * extends java.lang.Enum {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your application doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your application may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
+
+# If you wish, you can let the optimization step remove Android logging calls.
+
+#-assumenosideeffects class android.util.Log {
+# public static boolean isLoggable(java.lang.String, int);
+# public static int v(...);
+# public static int i(...);
+# public static int w(...);
+# public static int d(...);
+# public static int e(...);
+#}
diff --git a/examples/annotations/examples.pro b/examples/annotations/examples.pro
index 270092a..3a47183 100644
--- a/examples/annotations/examples.pro
+++ b/examples/annotations/examples.pro
@@ -8,8 +8,7 @@
# Specify the input, output, and library jars.
# This is assuming the code has been compiled in the examples directory.
-#-injars examples(*.class)
--injars classes(*.class)
+-injars examples(*.class)
-outjars out
-libraryjars <java.home>/lib/rt.jar
diff --git a/examples/annotations/lib/annotations.jar b/examples/annotations/lib/annotations.jar
index 967d604..f43f24e 100644
--- a/examples/annotations/lib/annotations.jar
+++ b/examples/annotations/lib/annotations.jar
Binary files differ
diff --git a/examples/ant/applets.xml b/examples/ant/applets.xml
index a55b1c3..4d0cb38 100644
--- a/examples/ant/applets.xml
+++ b/examples/ant/applets.xml
@@ -7,7 +7,9 @@
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
- <proguard printseeds="on">
+ <proguard printseeds="on"
+ printmapping="out.map"
+ renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
@@ -16,14 +18,19 @@
<libraryjar file="${java.home}/lib/rt.jar" />
- <!-- Preserve all public applets. -->
-
- <keep access="public" extends="java.applet.Applet" />
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
<!-- Preserve all annotations. -->
<keepattribute name="*Annotation*" />
+ <!-- Preserve all public applets. -->
+
+ <keep access="public" extends="java.applet.Applet" />
+
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames>
diff --git a/examples/ant/applications1.xml b/examples/ant/applications1.xml
index 7a3d473..6df5789 100644
--- a/examples/ant/applications1.xml
+++ b/examples/ant/applications1.xml
@@ -1,6 +1,6 @@
<!-- This Ant build file illustrates how to process applications,
by including a ProGuard-style configuration file.
- Usage: ant -f applications.xml -->
+ Usage: ant -f applications1.xml -->
<project name="Applications" default="obfuscate" basedir="../..">
diff --git a/examples/ant/applications2.xml b/examples/ant/applications2.xml
index 2e28f01..681a894 100644
--- a/examples/ant/applications2.xml
+++ b/examples/ant/applications2.xml
@@ -1,6 +1,6 @@
<!-- This Ant build file illustrates how to process applications,
by including ProGuard-style configuration options.
- Usage: ant -f applications.xml -->
+ Usage: ant -f applications2.xml -->
<project name="Applications" default="obfuscate" basedir="../..">
@@ -21,16 +21,22 @@
<!-- -libraryjars jai_core.jar -->
<!-- ... -->
- <!-- Preserve all public applications. -->
+ <!-- Save the obfuscation mapping to a file, and preserve line numbers. -->
- -keepclasseswithmembers public class * {
- public static void main(java.lang.String[]);
- }
+ -printmapping out.map
+ -renamesourcefileattribute SourceFile
+ -keepattributes SourceFile,LineNumberTable
<!-- Preserve all annotations. -->
-keepattributes *Annotation*
+ <!-- Preserve all public applications. -->
+
+ -keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+ }
+
<!-- Preserve all native method names and the names of their classes. -->
-keepclasseswithmembernames class * {
diff --git a/examples/ant/applications3.xml b/examples/ant/applications3.xml
index d5501e0..e42eb39 100644
--- a/examples/ant/applications3.xml
+++ b/examples/ant/applications3.xml
@@ -1,6 +1,6 @@
<!-- This Ant build file illustrates how to process applications,
using a full-blown XML configuration.
- Usage: ant -f applications.xml -->
+ Usage: ant -f applications3.xml -->
<project name="Applications" default="obfuscate" basedir="../..">
@@ -8,7 +8,9 @@
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
- <proguard printseeds="on">
+ <proguard printseeds="on"
+ printmapping="out.map"
+ renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
@@ -21,6 +23,14 @@
<!-- libraryjar file="jai_core.jar" / -->
<!-- ... / -->
+ <!-- Preserve line numbers in the obfuscated stack traces. -->
+
+ <keepattribute name="LineNumberTable" />
+ <keepattribute name="SourceFile" />
+
+ <!-- Preserve all annotations. -->
+
+ <keepattribute name="*Annotation*" />
<!-- Preserve all public applications. -->
@@ -31,10 +41,6 @@
parameters="java.lang.String[]" />
</keepclasseswithmembers>
- <!-- Preserve all annotations. -->
-
- <keepattribute name="*Annotation*" />
-
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames>
diff --git a/examples/ant/midlets.xml b/examples/ant/midlets.xml
index b17d036..223d0da 100644
--- a/examples/ant/midlets.xml
+++ b/examples/ant/midlets.xml
@@ -8,13 +8,15 @@
classpath="lib/proguard.jar" />
<proguard microedition="on"
+ printseeds="on"
+ printmapping="out.map"
overloadaggressively="on"
repackageclasses=""
allowaccessmodification="on"
- printseeds="on">
+ renamesourcefileattribute="SourceFile">
<!-- On Windows, you can't use mixed case class names,
- for the sake of the preverify tool.
+ should you still want to use the preverify tool.
usemixedcaseclassnames="false">
-->
@@ -23,8 +25,13 @@
<injar file="in.jar" />
<outjar file="out.jar" />
- <libraryjar file="/usr/local/java/wtk2.1/lib/midpapi20.jar" />
- <libraryjar file="/usr/local/java/wtk2.1/lib/cldcapi11.jar" />
+ <libraryjar file="/usr/local/java/wtk2.5.2/lib/midpapi20.jar" />
+ <libraryjar file="/usr/local/java/wtk2.5.2/lib/cldcapi11.jar" />
+
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
<!-- Preserve all public midlets. -->
diff --git a/examples/ant/proguard.xml b/examples/ant/proguard.xml
index 315e628..1911a90 100644
--- a/examples/ant/proguard.xml
+++ b/examples/ant/proguard.xml
@@ -9,10 +9,10 @@
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
- <proguard skipnonpubliclibraryclasses="off"
- printmapping="proguard.map"
+ <proguard printmapping="proguard.map"
overloadaggressively="on"
- repackageclasses="">
+ repackageclasses=""
+ renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
@@ -23,8 +23,12 @@
<outjar file="examples/ant/proguard_out.jar" />
<libraryjar file="${java.home}/lib/rt.jar" />
- <libraryjar file="/usr/local/java/ant1.7.0/lib/ant.jar" />
- <libraryjar file="/usr/local/java/wtk2.1/wtklib/kenv.zip" />
+ <libraryjar file="/usr/local/java/ant/lib/ant.jar" />
+ <libraryjar file="/usr/local/java/gradle-1.3/lib/plugins/gradle-plugins-1.3.jar" />
+ <libraryjar file="/usr/local/java/gradle-1.3/lib/gradle-base-services-1.3.jar" />
+ <libraryjar file="/usr/local/java/gradle-1.3/lib/gradle-core-1.3.jar" />
+ <libraryjar file="/usr/local/java/gradle-1.3/lib/groovy-all-1.8.6.jar" />
+ <libraryjar file="/usr/local/java/wtk2.5.2/wtklib/kenv.zip" />
<!-- Adapt the resource file names, based on the corresponding obfuscated
class names. -->
@@ -32,6 +36,11 @@
<adaptresourcefilenames filter="**.properties,**.gif,**.jpg" />
<adaptresourcefilecontents filter="proguard/ant/task.properties" />
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
+
<!-- The main seeds: ProGuard and its companion tool ReTrace. -->
<keep access="public" name="proguard.ProGuard">
@@ -63,6 +72,12 @@
<method access="public" type="void" name="add*" parameters="***" />
</keepclassmembers>
+ <!-- If we have the Gradle jars, we can properly process the Gradle task. -->
+
+ <keep access="public" name="proguard.gradle.*">
+ <method access="public" />
+ </keep>
+
<!-- If we have kenv.zip, we can process the J2ME WTK plugin. -->
<keep access="public" name="proguard.wtk.ProGuardObfuscator" />
diff --git a/examples/ant/servlets.xml b/examples/ant/servlets.xml
index 83af0f2..51bcaad 100644
--- a/examples/ant/servlets.xml
+++ b/examples/ant/servlets.xml
@@ -7,7 +7,9 @@
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
- <proguard printseeds="on">
+ <proguard printseeds="on"
+ printmapping="proguard.map"
+ renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
@@ -16,14 +18,19 @@
<libraryjar file="${java.home}/lib/rt.jar" />
- <!-- Keep all public servlets. -->
-
- <keep access="public" implements="javax.servlet.Servlet" />
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
<!-- Preserve all annotations. -->
<keepattribute name="*Annotation*" />
+ <!-- Keep all public servlets. -->
+
+ <keep access="public" implements="javax.servlet.Servlet" />
+
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames>
diff --git a/examples/applets.pro b/examples/applets.pro
index ee90db0..c5affc1 100644
--- a/examples/applets.pro
+++ b/examples/applets.pro
@@ -11,18 +11,27 @@
-libraryjars <java.home>/lib/rt.jar
-# Preserve all public applets.
-
--keep public class * extends java.applet.Applet
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
-# Print out a list of what we're preserving.
-
--printseeds
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
# Preserve all annotations.
-keepattributes *Annotation*
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public applets.
+
+-keep public class * extends java.applet.Applet
+
# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
diff --git a/examples/applications.pro b/examples/applications.pro
index 29d8e43..f718088 100644
--- a/examples/applications.pro
+++ b/examples/applications.pro
@@ -15,20 +15,29 @@
#-libraryjars jai_core.jar
#...
-# Preserve all public applications.
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
--keepclasseswithmembers public class * {
- public static void main(java.lang.String[]);
-}
-
-# Print out a list of what we're preserving.
-
--printseeds
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
# Preserve all annotations.
-keepattributes *Annotation*
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public applications.
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
diff --git a/examples/dictionaries/shakespeare.txt b/examples/dictionaries/shakespeare.txt
index 28b1cd8..28b1cd8 100755..100644
--- a/examples/dictionaries/shakespeare.txt
+++ b/examples/dictionaries/shakespeare.txt
diff --git a/examples/gradle/android.gradle b/examples/gradle/android.gradle
new file mode 100644
index 0000000..4e950d5
--- /dev/null
+++ b/examples/gradle/android.gradle
@@ -0,0 +1,195 @@
+//
+// This Gradle build file illustrates how to process Android
+// applications.
+// Usage:
+// gradle -b android.gradle proguard
+//
+// If you're using the Android SDK, the Ant release build and Eclipse export
+// already take care of the proper settings. You only need to enable ProGuard
+// by commenting in the corresponding line in project.properties. You can still
+// add project-specific configuration in proguard-project.txt.
+//
+// This configuration file is for custom, stand-alone builds.
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // Note that ProGuard works with Java bytecode (.class),
+ // before the dex compiler converts it into Dalvik code (.dex).
+
+ injars 'bin/classes'
+ injars 'libs'
+ outjars 'bin/classes-processed.jar'
+
+ libraryjars '/usr/local/android-sdk/platforms/android-9/android.jar'
+ //libraryjars '/usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar'
+ // ...
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on.
+
+ printmapping 'bin/classes-processed.map'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'bin/classes-processed.seeds'
+
+ // Preverification is irrelevant for the dex compiler and the Dalvik VM.
+
+ dontpreverify
+
+ // Reduce the size of the output some more.
+
+ repackageclasses ''
+ allowaccessmodification
+
+ // Switch off some optimizations that trip older versions of the Dalvik VM.
+
+ optimizations '!code/simplification/arithmetic'
+
+ // Keep a fixed source file attribute and all line number tables to get line
+ // numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // RemoteViews might need annotations.
+
+ keepattributes '*Annotation*'
+
+ // Preserve all fundamental application classes.
+
+ keep 'public class * extends android.app.Activity'
+ keep 'public class * extends android.app.Application'
+ keep 'public class * extends android.app.Service'
+ keep 'public class * extends android.content.BroadcastReceiver'
+ keep 'public class * extends android.content.ContentProvider'
+
+ // Preserve all View implementations, their special context constructors, and
+ // their setters.
+
+ keep 'public class * extends android.view.View { \
+ public <init>(android.content.Context); \
+ public <init>(android.content.Context, android.util.AttributeSet); \
+ public <init>(android.content.Context, android.util.AttributeSet, int); \
+ public void set*(...); \
+ }'
+
+ // Preserve all classes that have special context constructors, and the
+ // constructors themselves.
+
+ keepclasseswithmembers 'class * { \
+ public <init>(android.content.Context, android.util.AttributeSet); \
+ }'
+
+ // Preserve all classes that have special context constructors, and the
+ // constructors themselves.
+
+ keepclasseswithmembers 'class * { \
+ public <init>(android.content.Context, android.util.AttributeSet, int); \
+ }'
+
+ // Preserve all possible onClick handlers.
+
+ keepclassmembers 'class * extends android.content.Context { \
+ public void *(android.view.View); \
+ public void *(android.view.MenuItem); \
+ }'
+
+ // Preserve the special fields of all Parcelable implementations.
+
+ keepclassmembers 'class * implements android.os.Parcelable { \
+ static android.os.Parcelable$Creator CREATOR; \
+ }'
+
+ // Preserve static fields of inner classes of R classes that might be accessed
+ // through introspection.
+
+ keepclassmembers 'class **.R$* { \
+ public static <fields>; \
+ }'
+
+ // Preserve annotated Javascript interface methods.
+
+ keepclassmembers 'class * { \
+ @android.webkit.JavascriptInterface <methods>; \
+ }'
+
+ // Preserve the required interface from the License Verification Library
+ // (but don't nag the developer if the library is not used at all).
+
+ keep 'public interface com.android.vending.licensing.ILicensingService'
+
+ dontnote 'com.android.vending.licensing.ILicensingService'
+
+ // The Android Compatibility library references some classes that may not be
+ // present in all versions of the API, but we know that's ok.
+
+ dontwarn 'android.support.**'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers 'class * extends java.lang.Enum { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your application doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ //keep 'public class mypackage.MyClass'
+ //keep 'public interface mypackage.MyInterface'
+ //keep 'public class * implements mypackage.MyInterface'
+
+ // If you wish, you can let the optimization step remove Android logging
+ // calls.
+ //assumenosideeffects class android.util.Log {
+ // public static boolean isLoggable(java.lang.String, int);
+ // public static int v(...);
+ // public static int i(...);
+ // public static int w(...);
+ // public static int d(...);
+ // public static int e(...);
+ //}
+}
diff --git a/examples/gradle/applets.gradle b/examples/gradle/applets.gradle
new file mode 100644
index 0000000..29c8559
--- /dev/null
+++ b/examples/gradle/applets.gradle
@@ -0,0 +1,90 @@
+//
+// This Gradle build file illustrates how to process applets.
+// Usage:
+// gradle -b applets.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public applets.
+
+ keep 'public class * extends java.applet.Applet'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers 'class * extends java.lang.Enum { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your library doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/examples/gradle/applications.gradle b/examples/gradle/applications.gradle
new file mode 100644
index 0000000..73dfdf0
--- /dev/null
+++ b/examples/gradle/applications.gradle
@@ -0,0 +1,96 @@
+//
+// This Gradle build file illustrates how to process applications.
+// Usage:
+// gradle -b applications.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ //libraryjars 'junit.jar'
+ //libraryjars 'servlet.jar'
+ //libraryjars 'jai_core.jar'
+ //...
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public applications.
+
+ keepclasseswithmembers 'public class * { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers 'class * extends java.lang.Enum { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your application doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/examples/gradle/library.gradle b/examples/gradle/library.gradle
new file mode 100644
index 0000000..2f68962
--- /dev/null
+++ b/examples/gradle/library.gradle
@@ -0,0 +1,99 @@
+//
+// This Gradle build file illustrates how to process a program
+// library, such that it remains usable as a library.
+// Usage:
+// gradle -b library.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // In this case, the input jar is the program library that we want to process.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // Save the obfuscation mapping to a file, so we can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ keepparameternames
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,EnclosingMethod'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // Preserve all public classes, and their public and protected fields and
+ // methods.
+
+ keep 'public class * { \
+ public protected *; \
+ }'
+
+ // Preserve all .class method names.
+
+ keepclassmembernames 'class * { \
+ java.lang.Class class$(java.lang.String); \
+ java.lang.Class class$(java.lang.String, boolean); \
+ }'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers 'class * extends java.lang.Enum { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your library doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your library may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/examples/gradle/midlets.gradle b/examples/gradle/midlets.gradle
new file mode 100644
index 0000000..dffb2c3
--- /dev/null
+++ b/examples/gradle/midlets.gradle
@@ -0,0 +1,88 @@
+//
+// This Gradle build file illustrates how to process J2ME midlets.
+// Usage:
+// gradle -b midlets.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars '/usr/local/java/wtk2.5.2/lib/midpapi20.jar'
+ libraryjars '/usr/local/java/wtk2.5.2/lib/cldcapi11.jar'
+
+ // Preverify the code suitably for Java Micro Edition.
+
+ microedition
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Allow classes and class members to be made public.
+
+ allowaccessmodification
+
+ // On Windows, you can't use mixed case class names,
+ // should you still want to use the preverify tool.
+ //
+ // dontusemixedcaseclassnames
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on.
+
+ printmapping 'out.map'
+
+ // You can keep a fixed source file attribute and all line number tables to
+ // get stack traces with line numbers.
+
+ //renamesourcefileattribute 'SourceFile'
+ //keepattributes 'SourceFile,LineNumberTable'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public midlets.
+
+ keep 'public class * extends javax.microedition.midlet.MIDlet'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames 'class * { \
+ native <methods>; \
+ }'
+
+ // Your midlet may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/examples/gradle/proguard.gradle b/examples/gradle/proguard.gradle
new file mode 100644
index 0000000..8974f93
--- /dev/null
+++ b/examples/gradle/proguard.gradle
@@ -0,0 +1,91 @@
+//
+// This Gradle build file illustrates how to process ProGuard itself.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b proguard.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+ // everything else.
+
+ injars '../../lib/proguard.jar', filter: '!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**'
+ outjars 'proguard_out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // Write out an obfuscation mapping file, for de-obfuscating any stack traces
+ // later on, or for incremental obfuscation of extensions.
+
+ printmapping 'proguard.map'
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Allow classes and class members to be made public.
+
+ allowaccessmodification
+
+ // The entry point: ProGuard and its main method.
+
+ keep 'public class proguard.ProGuard { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // If you want to preserve the Ant task as well, you'll have to specify the
+ // main ant.jar.
+
+ //libraryjars '/usr/local/java/ant/lib/ant.jar'
+ //adaptresourcefilecontents 'proguard/ant/task.properties'
+ //
+ //keep allowobfuscation: true, 'class proguard.ant.*'
+ //keepclassmembers 'public class proguard.ant.* { \
+ // <init>(org.apache.tools.ant.Project); \
+ // public void set*(***); \
+ // public void add*(***); \
+ //}'
+
+ // If you want to preserve the Gradle task, you'll have to specify the Gradle
+ // jars.
+
+ //libraryjars '/usr/local/java/gradle-1.3/lib/plugins/gradle-plugins-1.3.jar'
+ //libraryjars '/usr/local/java/gradle-1.3/lib/gradle-base-services-1.3.jar'
+ //libraryjars '/usr/local/java/gradle-1.3/lib/gradle-core-1.3.jar'
+ //libraryjars '/usr/local/java/gradle-1.3/lib/groovy-all-1.8.6.jar'
+
+ //keep 'public class proguard.gradle.* { \
+ // public *; \
+ //}'
+
+ // If you want to preserve the WTK obfuscation plug-in, you'll have to specify
+ // the kenv.zip file.
+
+ //libraryjars '/usr/local/java/wtk2.5.2/wtklib/kenv.zip'
+ //keep 'public class proguard.wtk.ProGuardObfuscator'
+}
diff --git a/examples/gradle/proguardall.gradle b/examples/gradle/proguardall.gradle
new file mode 100644
index 0000000..561a455
--- /dev/null
+++ b/examples/gradle/proguardall.gradle
@@ -0,0 +1,93 @@
+//
+// This Gradle build file illustrates how to process ProGuard
+// (including its main application, its GUI, its Ant task, and its WTK plugin),
+// and the ReTrace tool, all in one go.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b proguardall.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // We'll read all jars from the lib directory, process them, and write the
+ // processed jars to a new out directory.
+
+ injars '../../lib'
+ outjars 'out'
+
+ // You may have to adapt the paths below.
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ libraryjars '/usr/local/java/ant/lib/ant.jar'
+ libraryjars '/usr/local/java/gradle-1.3/lib/plugins/gradle-plugins-1.3.jar'
+ libraryjars '/usr/local/java/gradle-1.3/lib/gradle-base-services-1.3.jar'
+ libraryjars '/usr/local/java/gradle-1.3/lib/gradle-core-1.3.jar'
+ libraryjars '/usr/local/java/gradle-1.3/lib/groovy-all-1.8.6.jar'
+ libraryjars '/usr/local/java/wtk2.5.2/wtklib/kenv.zip'
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Adapt the names and contents of the resource files.
+
+ adaptresourcefilenames '**.properties,**.gif,**.jpg'
+ adaptresourcefilecontents 'proguard/ant/task.properties'
+
+ // The main entry points.
+
+ keep 'public class proguard.ProGuard { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ keep 'public class proguard.gui.ProGuardGUI { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ keep 'public class proguard.retrace.ReTrace { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // If we have ant.jar, we can properly process the Ant task.
+
+ keep allowobfuscation: true, 'class proguard.ant.*'
+ keepclassmembers 'public class proguard.ant.* { \
+ <init>(org.apache.tools.ant.Project); \
+ public void set*(***); \
+ public void add*(***); \
+ }'
+
+ // If we have the Gradle jars, we can properly process the Gradle task.
+
+ keep 'public class proguard.gradle.* { \
+ public *; \
+ }'
+
+ // If we have kenv.zip, we can process the J2ME WTK plugin.
+
+ keep 'public class proguard.wtk.ProGuardObfuscator'
+}
diff --git a/examples/gradle/proguardgui.gradle b/examples/gradle/proguardgui.gradle
new file mode 100644
index 0000000..7bfebd9
--- /dev/null
+++ b/examples/gradle/proguardgui.gradle
@@ -0,0 +1,72 @@
+//
+// This Gradle build file illustrates how to process the ProGuard GUI.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b proguardgui.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // The input jars will be merged in a single output jar.
+ // We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+ // everything else.
+
+ injars '../../lib/proguardgui.jar'
+ injars '../../lib/proguard.jar', filter: '!META-INF/**,!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**'
+ injars '../../lib/retrace.jar', filter: '!META-INF/**'
+ outjars 'proguardgui_out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // If we wanted to reuse the previously obfuscated proguard_out.jar, we could
+ // perform incremental obfuscation based on its mapping file, and only keep the
+ // additional GUI files instead of all files.
+
+ //applymapping 'proguard.map'
+ //injars '../../lib/proguardgui.jar'
+ //outjars 'proguardgui_out.jar'
+ //libraryjars '../../lib/proguard.jar', filter: '!proguard/ant/**,!proguard/wtk/**'
+ //libraryjars '../../lib/retrace.jar'
+ //libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Adapt the names of resource files, based on the corresponding obfuscated
+ // class names. Notably, in this case, the GUI resource properties file will
+ // have to be renamed.
+
+ adaptresourcefilenames '**.properties,**.gif,**.jpg'
+
+ // The entry point: ProGuardGUI and its main method.
+
+ keep 'public class proguard.gui.ProGuardGUI { \
+ public static void main(java.lang.String[]); \
+ }'
+}
diff --git a/examples/gradle/retrace.gradle b/examples/gradle/retrace.gradle
new file mode 100644
index 0000000..7fe2c7e
--- /dev/null
+++ b/examples/gradle/retrace.gradle
@@ -0,0 +1,64 @@
+//
+// This Gradle build file illustrates how to process the ReTrace tool.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b retrace.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // The input jars will be merged in a single output jar.
+ // We'll filter out the Ant and WTK classes.
+
+ injars '../../lib/retrace.jar'
+ injars '../../lib/proguard.jar(!META-INF/MANIFEST.MF,'
+ !proguard/ant/**,!proguard/wtk/**)
+ outjars 'retrace_out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // If we wanted to reuse the previously obfuscated proguard_out.jar, we could
+ // perform incremental obfuscation based on its mapping file, and only keep the
+ // additional ReTrace files instead of all files.
+
+ //applymapping 'proguard.map'
+ //outjars 'retrace_out.jar', filter: 'proguard/retrace/**'
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Allow classes and class members to be made public.
+
+ allowaccessmodification
+
+ // The entry point: ReTrace and its main method.
+
+ keep 'public class proguard.retrace.ReTrace { \
+ public static void main(java.lang.String[]); \
+ }'
+}
diff --git a/examples/gradle/scala.gradle b/examples/gradle/scala.gradle
new file mode 100644
index 0000000..286e5e9
--- /dev/null
+++ b/examples/gradle/scala.gradle
@@ -0,0 +1,153 @@
+//
+// This Gradle build file illustrates how to process Scala
+// applications, including the Scala runtime.
+// Usage:
+// gradle -b scala.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ injars '/usr/local/java/scala-2.9.1/lib/scala-library.jar'
+ //injars '/usr/local/java/scala-2.9.1/lib/scala-compiler.jar', filter: '!META-INF/MANIFEST.MF'
+ //injars '/usr/local/java/scala-2.9.1/lib/jline.jar', filter: '!META-INF/MANIFEST.MF'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ //libraryjars '/usr/local/java/ant/lib/ant.jar'
+ //...
+
+ // Ignore some compiler artefacts.
+
+ dontwarn 'scala.**'
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public applications.
+
+ keepclasseswithmembers 'public class * { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // Preserve some classes and class members that are accessed by means of
+ // introspection.
+
+ keep 'class * implements org.xml.sax.EntityResolver'
+
+ keepclassmembers 'class * { \
+ ** MODULE$; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.ForkJoinPool { \
+ long eventCount; \
+ int workerCounts; \
+ int runControl; \
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack; \
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.ForkJoinWorkerThread { \
+ int base; \
+ int sp; \
+ int runState; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.ForkJoinTask { \
+ int status; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.LinkedTransferQueue { \
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head; \
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail; \
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe; \
+ }'
+
+ // Preserve some classes and class members that are accessed by means of
+ // introspection in the Scala compiler library, if it is processed as well.
+
+ //keep 'class * implements jline.Completor'
+ //keep 'class * implements jline.Terminal'
+
+ //keep 'class scala.tools.nsc.Global'
+
+ //keepclasseswithmembers 'class * { \
+ // <init>(scala.tools.nsc.Global); \
+ //}'
+
+ //keepclassmembers 'class * { \
+ // *** scala_repl_value(); \
+ // *** scala_repl_result(); \
+ //}'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers 'class * extends java.lang.Enum { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your application doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+
+}
diff --git a/examples/gradle/servlets.gradle b/examples/gradle/servlets.gradle
new file mode 100644
index 0000000..c91ed6a
--- /dev/null
+++ b/examples/gradle/servlets.gradle
@@ -0,0 +1,91 @@
+//
+// This Gradle build file illustrates how to process servlets.
+// Usage:
+// gradle -b servlets.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ libraryjars '/usr/local/java/servlet/servlet.jar'
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public servlets.
+
+ keep 'public class * implements javax.servlet.Servlet'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers 'class * extends java.lang.Enum { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your library doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/examples/library.pro b/examples/library.pro
index 37be47e..b812082 100644
--- a/examples/library.pro
+++ b/examples/library.pro
@@ -15,10 +15,11 @@
# Save the obfuscation mapping to a file, so we can de-obfuscate any stack
# traces later on. Keep a fixed source file attribute and all line number
-# tables to actually get these stack traces.
+# tables to get line numbers in the stack traces.
# You can comment this out if you're not interested in stack traces.
-printmapping out.map
+-keepparameternames
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
SourceFile,LineNumberTable,EnclosingMethod
diff --git a/examples/midlets.pro b/examples/midlets.pro
index bffc38e..1383980 100644
--- a/examples/midlets.pro
+++ b/examples/midlets.pro
@@ -9,8 +9,8 @@
-injars in.jar
-outjars out.jar
--libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
--libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
# Preverify the code suitably for Java Micro Edition.
@@ -34,13 +34,24 @@
#
# -dontusemixedcaseclassnames
-# Preserve all public midlets.
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on.
--keep public class * extends javax.microedition.midlet.MIDlet
+-printmapping out.map
+
+# You can keep a fixed source file attribute and all line number tables to
+# get stack traces with line numbers.
+
+#-renamesourcefileattribute SourceFile
+#-keepattributes SourceFile,LineNumberTable
-# Print out a list of what we're preserving.
+# You can print out the seeds that are matching the keep options below.
--printseeds
+#-printseeds out.seeds
+
+# Preserve all public midlets.
+
+-keep public class * extends javax.microedition.midlet.MIDlet
# Preserve all native method names and the names of their classes.
diff --git a/examples/proguard.pro b/examples/proguard.pro
index c48b87e..9cdd0a9 100644
--- a/examples/proguard.pro
+++ b/examples/proguard.pro
@@ -6,9 +6,10 @@
#
# Specify the input jars, output jars, and library jars.
-# We'll filter out the Ant and WTK classes, keeping everything else.
+# We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+# everything else.
--injars ../lib/proguard.jar(!proguard/ant/**,!proguard/wtk/**)
+-injars ../lib/proguard.jar(!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**)
-outjars proguard_out.jar
-libraryjars <java.home>/lib/rt.jar
@@ -50,8 +51,20 @@
# public void add*(***);
#}
+# If you want to preserve the Gradle task, you'll have to specify the Gradle
+# jars.
+
+#-libraryjars /usr/local/java/gradle-1.3/lib/plugins/gradle-plugins-1.3.jar
+#-libraryjars /usr/local/java/gradle-1.3/lib/gradle-base-services-1.3.jar
+#-libraryjars /usr/local/java/gradle-1.3/lib/gradle-core-1.3.jar
+#-libraryjars /usr/local/java/gradle-1.3/lib/groovy-all-1.8.6.jar
+
+#-keep public class proguard.gradle.* {
+# public *;
+#}
+
# If you want to preserve the WTK obfuscation plug-in, you'll have to specify
# the kenv.zip file.
-#-libraryjars /usr/local/java/wtk2.1/wtklib/kenv.zip
+#-libraryjars /usr/local/java/wtk2.5.2/wtklib/kenv.zip
#-keep public class proguard.wtk.ProGuardObfuscator
diff --git a/examples/proguardall.pro b/examples/proguardall.pro
index 8dc042e..b96da6c 100644
--- a/examples/proguardall.pro
+++ b/examples/proguardall.pro
@@ -17,8 +17,12 @@
# You may have to adapt the paths below.
-libraryjars <java.home>/lib/rt.jar
--libraryjars /usr/local/java/ant1.5.0/lib/ant.jar
--libraryjars /usr/local/java/wtk2.1/wtklib/kenv.zip
+-libraryjars /usr/local/java/ant/lib/ant.jar
+-libraryjars /usr/local/java/gradle-1.3/lib/plugins/gradle-plugins-1.3.jar
+-libraryjars /usr/local/java/gradle-1.3/lib/gradle-base-services-1.3.jar
+-libraryjars /usr/local/java/gradle-1.3/lib/gradle-core-1.3.jar
+-libraryjars /usr/local/java/gradle-1.3/lib/groovy-all-1.8.6.jar
+-libraryjars /usr/local/java/wtk2.5.2/wtklib/kenv.zip
# Allow methods with the same signature, except for the return type,
# to get the same obfuscation name.
@@ -57,6 +61,12 @@
public void add*(***);
}
+# If we have the Gradle jars, we can properly process the Gradle task.
+
+-keep public class proguard.gradle.* {
+ public *;
+}
+
# If we have kenv.zip, we can process the J2ME WTK plugin.
-keep public class proguard.wtk.ProGuardObfuscator
diff --git a/examples/proguardgui.pro b/examples/proguardgui.pro
index 2cb83ed..78f67db 100644
--- a/examples/proguardgui.pro
+++ b/examples/proguardgui.pro
@@ -7,20 +7,16 @@
# Specify the input jars, output jars, and library jars.
# The input jars will be merged in a single output jar.
-# We'll filter out the Ant and WTK classes.
+# We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+# everything else.
-injars ../lib/proguardgui.jar
--injars ../lib/proguard.jar(!META-INF/**,!proguard/ant/**,!proguard/wtk/**)
+-injars ../lib/proguard.jar(!META-INF/**,!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**)
-injars ../lib/retrace.jar (!META-INF/**)
-outjars proguardgui_out.jar
-libraryjars <java.home>/lib/rt.jar
-# In recent JREs, some public Swing classes depend on package visible classes,
-# so don't skip these package visible classes while parsing the library jar.
-
--dontskipnonpubliclibraryclasses
-
# If we wanted to reuse the previously obfuscated proguard_out.jar, we could
# perform incremental obfuscation based on its mapping file, and only keep the
# additional GUI files instead of all files.
diff --git a/examples/scala.pro b/examples/scala.pro
new file mode 100644
index 0000000..658fc77
--- /dev/null
+++ b/examples/scala.pro
@@ -0,0 +1,132 @@
+#
+# This ProGuard configuration file illustrates how to process Scala
+# applications, including the Scala runtime.
+# Usage:
+# java -jar proguard.jar @scala.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+
+-injars in.jar
+-injars /usr/local/java/scala-2.9.1/lib/scala-library.jar
+#-injars /usr/local/java/scala-2.9.1/lib/scala-compiler.jar(!META-INF/MANIFEST.MF)
+#-injars /usr/local/java/scala-2.9.1/lib/jline.jar(!META-INF/MANIFEST.MF)
+-outjars out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+#-libraryjars /usr/local/java/ant/lib/ant.jar
+#...
+
+# Ignore some compiler artefacts.
+
+-dontwarn scala.**
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+# Preserve all annotations.
+
+-keepattributes *Annotation*
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public applications.
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+# Preserve some classes and class members that are accessed by means of
+# introspection.
+
+-keep class * implements org.xml.sax.EntityResolver
+
+-keepclassmembers class * {
+ ** MODULE$;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool {
+ long eventCount;
+ int workerCounts;
+ int runControl;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread {
+ int base;
+ int sp;
+ int runState;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask {
+ int status;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue {
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe;
+}
+
+# Preserve some classes and class members that are accessed by means of
+# introspection in the Scala compiler library, if it is processed as well.
+
+#-keep class * implements jline.Completor
+#-keep class * implements jline.Terminal
+
+#-keep class scala.tools.nsc.Global
+
+#-keepclasseswithmembers class * {
+# <init>(scala.tools.nsc.Global);
+#}
+
+#-keepclassmembers class * {
+# *** scala_repl_value();
+# *** scala_repl_result();
+#}
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers class * extends java.lang.Enum {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your application doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your application may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
+
diff --git a/examples/servlets.pro b/examples/servlets.pro
index fdc36b0..b42b2e4 100644
--- a/examples/servlets.pro
+++ b/examples/servlets.pro
@@ -12,18 +12,27 @@
-libraryjars <java.home>/lib/rt.jar
-libraryjars /usr/local/java/servlet/servlet.jar
-# Preserve all public servlets.
-
--keep public class * implements javax.servlet.Servlet
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
-# Print out a list of what we're preserving.
-
--printseeds
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
# Preserve all annotations.
-keepattributes *Annotation*
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public servlets.
+
+-keep public class * implements javax.servlet.Servlet
+
# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
diff --git a/lib/proguard.jar b/lib/proguard.jar
index 3a9aebc..dfb7f29 100644
--- a/lib/proguard.jar
+++ b/lib/proguard.jar
Binary files differ
diff --git a/lib/proguardgui.jar b/lib/proguardgui.jar
index 5866856..03a5eb5 100644
--- a/lib/proguardgui.jar
+++ b/lib/proguardgui.jar
Binary files differ
diff --git a/lib/retrace.jar b/lib/retrace.jar
index ea5998b..30fa081 100644
--- a/lib/retrace.jar
+++ b/lib/retrace.jar
Binary files differ
diff --git a/src/proguard/ArgumentWordReader.java b/src/proguard/ArgumentWordReader.java
index 89f3824..efe8e6e 100644
--- a/src/proguard/ArgumentWordReader.java
+++ b/src/proguard/ArgumentWordReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -32,7 +32,8 @@ import java.io.*;
public class ArgumentWordReader extends WordReader
{
private final String[] arguments;
- private int index = 0;
+
+ private int index = 0;
// /**
@@ -86,7 +87,7 @@ public class ArgumentWordReader extends WordReader
{
while (true)
{
- String word = reader.nextWord();
+ String word = reader.nextWord(false);
if (word == null)
System.exit(-1);
diff --git a/src/proguard/ClassPath.java b/src/proguard/ClassPath.java
index f4eeaad..3d7d119 100644
--- a/src/proguard/ClassPath.java
+++ b/src/proguard/ClassPath.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassPathEntry.java b/src/proguard/ClassPathEntry.java
index 28483be..7051955 100644
--- a/src/proguard/ClassPathEntry.java
+++ b/src/proguard/ClassPathEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,6 +20,8 @@
*/
package proguard;
+import proguard.util.ListUtil;
+
import java.io.*;
import java.util.List;
@@ -44,7 +46,7 @@ public class ClassPathEntry
/**
- * Creates a new ClassPathEntry with the given name and type.
+ * Creates a new ClassPathEntry with the given file and output flag.
*/
public ClassPathEntry(File file, boolean isOutput)
{
@@ -69,81 +71,212 @@ public class ClassPathEntry
}
+ /**
+ * Returns the file.
+ */
public File getFile()
{
return file;
}
+ /**
+ * Sets the file.
+ */
public void setFile(File file)
{
this.file = file;
}
+ /**
+ * Returns whether this data entry is an output entry.
+ */
public boolean isOutput()
{
return output;
}
+ /**
+ * Specifies whether this data entry is an output entry.
+ */
public void setOutput(boolean output)
{
this.output = output;
}
+ /**
+ * Returns whether this data entry is a jar file.
+ */
+ public boolean isJar()
+ {
+ return hasExtension(".jar");
+ }
+
+
+ /**
+ * Returns whether this data entry is a war file.
+ */
+ public boolean isWar()
+ {
+ return hasExtension(".war");
+ }
+
+
+ /**
+ * Returns whether this data entry is a ear file.
+ */
+ public boolean isEar()
+ {
+ return hasExtension(".ear");
+ }
+
+
+ /**
+ * Returns whether this data entry is a zip file.
+ */
+ public boolean isZip()
+ {
+ return hasExtension(".zip");
+ }
+
+
+ /**
+ * Returns whether this data entry has the given extension.
+ */
+ private boolean hasExtension(String extension)
+ {
+ return endsWithIgnoreCase(file.getPath(), extension);
+ }
+
+
+ /**
+ * Returns whether the given string ends with the given suffix, ignoring
+ * its case.
+ */
+ private static boolean endsWithIgnoreCase(String string, String suffix)
+ {
+ int stringLength = string.length();
+ int suffixLength = suffix.length();
+
+ return string.regionMatches(true, stringLength -
+ suffixLength, suffix, 0, suffixLength);
+ }
+
+
+ /**
+ * Returns the name filter that is applied to bottom-level files in this entry.
+ */
public List getFilter()
{
return filter;
}
+ /**
+ * Sets the name filter that is applied to bottom-level files in this entry.
+ */
public void setFilter(List filter)
{
this.filter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to jar files in this entry, if any.
+ */
public List getJarFilter()
{
return jarFilter;
}
+ /**
+ * Sets the name filter that is applied to jar files in this entry, if any.
+ */
public void setJarFilter(List filter)
{
this.jarFilter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to war files in this entry, if any.
+ */
public List getWarFilter()
{
return warFilter;
}
+ /**
+ * Sets the name filter that is applied to war files in this entry, if any.
+ */
public void setWarFilter(List filter)
{
this.warFilter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to ear files in this entry, if any.
+ */
public List getEarFilter()
{
return earFilter;
}
+ /**
+ * Sets the name filter that is applied to ear files in this entry, if any.
+ */
public void setEarFilter(List filter)
{
this.earFilter = filter == null || filter.size() == 0 ? null : filter;
}
+ /**
+ * Returns the name filter that is applied to zip files in this entry, if any.
+ */
public List getZipFilter()
{
return zipFilter;
}
+ /**
+ * Sets the name filter that is applied to zip files in this entry, if any.
+ */
public void setZipFilter(List filter)
{
this.zipFilter = filter == null || filter.size() == 0 ? null : filter;
}
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ String string = getName();
+
+ if (filter != null ||
+ jarFilter != null ||
+ warFilter != null ||
+ earFilter != null ||
+ zipFilter != null)
+ {
+ string +=
+ ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
+ (zipFilter != null ? ListUtil.commaSeparatedString(zipFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (earFilter != null ? ListUtil.commaSeparatedString(earFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (warFilter != null ? ListUtil.commaSeparatedString(warFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (jarFilter != null ? ListUtil.commaSeparatedString(jarFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (filter != null ? ListUtil.commaSeparatedString(filter, true) : "") +
+ ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD;
+ }
+
+ return string;
+ }
}
diff --git a/src/proguard/ClassSpecification.java b/src/proguard/ClassSpecification.java
index a84e0c8..485c0b0 100644
--- a/src/proguard/ClassSpecification.java
+++ b/src/proguard/ClassSpecification.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassSpecificationVisitorFactory.java b/src/proguard/ClassSpecificationVisitorFactory.java
index c99ab2c..dc5d71f 100644
--- a/src/proguard/ClassSpecificationVisitorFactory.java
+++ b/src/proguard/ClassSpecificationVisitorFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -493,7 +493,8 @@ public class ClassSpecificationVisitorFactory
private static boolean containsWildCards(String string)
{
return string != null &&
- (string.indexOf('*') >= 0 ||
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
string.indexOf('?') >= 0 ||
string.indexOf('%') >= 0 ||
string.indexOf(',') >= 0 ||
diff --git a/src/proguard/Configuration.java b/src/proguard/Configuration.java
index d513e2c..4711260 100644
--- a/src/proguard/Configuration.java
+++ b/src/proguard/Configuration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -32,6 +32,9 @@ import java.util.List;
*/
public class Configuration
{
+ public static final File STD_OUT = new File("");
+
+
///////////////////////////////////////////////////////////////////////////
// Input and output options.
///////////////////////////////////////////////////////////////////////////
@@ -50,7 +53,7 @@ public class Configuration
* Specifies whether to skip non-public library classes while reading
* library jars.
*/
- public boolean skipNonPublicLibraryClasses = true;
+ public boolean skipNonPublicLibraryClasses = false;
/**
* Specifies whether to skip non-public library class members while reading
@@ -237,12 +240,19 @@ public class Configuration
public List keepAttributes;
/**
+ * Specifies whether method parameter names and types should be kept for
+ * methods that are not obfuscated. This is achieved by keeping partial
+ * "LocalVariableTable" and "LocalVariableTypeTable" attributes.
+ */
+ public boolean keepParameterNames = false;
+
+ /**
* An optional replacement for all SourceFile attributes.
*/
public String newSourceFileAttribute;
/**
- * A list of <code>String</code>s specifying a filter for clases whose
+ * A list of <code>String</code>s specifying a filter for classes whose
* string constants are to be adapted, based on corresponding obfuscated
* class names.
*/
diff --git a/src/proguard/ConfigurationConstants.java b/src/proguard/ConfigurationConstants.java
index 694e006..14c5654 100644
--- a/src/proguard/ConfigurationConstants.java
+++ b/src/proguard/ConfigurationConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -73,6 +73,7 @@ class ConfigurationConstants
public static final String REPACKAGE_CLASSES_OPTION = "-repackageclasses";
public static final String DEFAULT_PACKAGE_OPTION = "-defaultpackage";
public static final String KEEP_ATTRIBUTES_OPTION = "-keepattributes";
+ public static final String KEEP_PARAMETER_NAMES_OPTION = "-keepparameternames";
public static final String RENAME_SOURCE_FILE_ATTRIBUTE_OPTION = "-renamesourcefileattribute";
public static final String ADAPT_CLASS_STRINGS_OPTION = "-adaptclassstrings";
public static final String ADAPT_RESOURCE_FILE_NAMES_OPTION = "-adaptresourcefilenames";
@@ -87,6 +88,7 @@ class ConfigurationConstants
public static final String IGNORE_WARNINGS_OPTION = "-ignorewarnings";
public static final String PRINT_CONFIGURATION_OPTION = "-printconfiguration";
public static final String DUMP_OPTION = "-dump";
+ public static final String SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION = "-skipnonpubliclibraryclasses";
public static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION = "-dontskipnonpubliclibraryclasses";
public static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION = "-dontskipnonpubliclibraryclassmembers";
public static final String TARGET_OPTION = "-target";
diff --git a/src/proguard/ConfigurationParser.java b/src/proguard/ConfigurationParser.java
index e01809e..a38e9ed 100644
--- a/src/proguard/ConfigurationParser.java
+++ b/src/proguard/ConfigurationParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,56 +31,101 @@ import java.util.*;
/**
* This class parses ProGuard configurations. Configurations can be read from an
- * array of arguments or from a configuration file or URL.
+ * array of arguments or from a configuration file or URL. External references
+ * in file names ('<...>') can be resolved against a given set of properties.
*
* @author Eric Lafortune
*/
public class ConfigurationParser
{
- private WordReader reader;
+ private final WordReader reader;
+ private final Properties properties;
+
private String nextWord;
private String lastComments;
/**
- * Creates a new ConfigurationParser for the given String arguments.
+ * Creates a new ConfigurationParser for the given String arguments and
+ * the given Properties.
*/
- public ConfigurationParser(String[] args) throws IOException
+ public ConfigurationParser(String[] args,
+ Properties properties) throws IOException
{
- this(args, null);
+ this(args, null, properties);
}
/**
* Creates a new ConfigurationParser for the given String arguments,
- * with the given base directory.
+ * with the given base directory and the given Properties.
*/
- public ConfigurationParser(String[] args,
- File baseDir) throws IOException
+ public ConfigurationParser(String[] args,
+ File baseDir,
+ Properties properties) throws IOException
{
- reader = new ArgumentWordReader(args, baseDir);
+ this(new ArgumentWordReader(args, baseDir), properties);
+ }
- readNextWord();
+
+ /**
+ * Creates a new ConfigurationParser for the given lines,
+ * with the given base directory and the given Properties.
+ */
+ public ConfigurationParser(String lines,
+ String description,
+ File baseDir,
+ Properties properties) throws IOException
+ {
+ this(new LineWordReader(new LineNumberReader(new StringReader(lines)),
+ description,
+ baseDir),
+ properties);
}
/**
- * Creates a new ConfigurationParser for the given file.
+ * Creates a new ConfigurationParser for the given file, with the system
+ * Properties.
+ * @deprecated Temporary code for backward compatibility in Obclipse.
*/
public ConfigurationParser(File file) throws IOException
{
- reader = new FileWordReader(file);
+ this(file, System.getProperties());
+ }
- readNextWord();
+
+ /**
+ * Creates a new ConfigurationParser for the given file and the given
+ * Properties.
+ */
+ public ConfigurationParser(File file,
+ Properties properties) throws IOException
+ {
+ this(new FileWordReader(file), properties);
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given URL and the given
+ * Properties.
+ */
+ public ConfigurationParser(URL url,
+ Properties properties) throws IOException
+ {
+ this(new FileWordReader(url), properties);
}
/**
- * Creates a new ConfigurationParser for the given URL.
+ * Creates a new ConfigurationParser for the given word reader and the
+ * given Properties.
*/
- public ConfigurationParser(URL url) throws IOException
+ public ConfigurationParser(WordReader reader,
+ Properties properties) throws IOException
{
- reader = new FileWordReader(url);
+ this.reader = reader;
+ this.properties = properties;
readNextWord();
}
@@ -110,6 +155,7 @@ public class ConfigurationParser
else if (ConfigurationConstants.OUTJARS_OPTION .startsWith(nextWord)) configuration.programJars = parseClassPathArgument(configuration.programJars, true);
else if (ConfigurationConstants.LIBRARYJARS_OPTION .startsWith(nextWord)) configuration.libraryJars = parseClassPathArgument(configuration.libraryJars, false);
else if (ConfigurationConstants.RESOURCEJARS_OPTION .startsWith(nextWord)) throw new ParseException("The '-resourcejars' option is no longer supported. Please use the '-injars' option for all input");
+ else if (ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(true);
else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(false);
else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION.startsWith(nextWord)) configuration.skipNonPublicLibraryClassMembers = parseNoArgument(false);
else if (ConfigurationConstants.TARGET_OPTION .startsWith(nextWord)) configuration.targetClassVersion = parseClassVersion();
@@ -124,7 +170,7 @@ public class ConfigurationParser
else if (ConfigurationConstants.PRINT_SEEDS_OPTION .startsWith(nextWord)) configuration.printSeeds = parseOptionalFile();
// After '-keep'.
- else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION .startsWith(nextWord)) configuration.keepDirectories = parseCommaSeparatedList("directory name", true, true, false, false, true, false, false, configuration.keepDirectories);
+ else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION .startsWith(nextWord)) configuration.keepDirectories = parseCommaSeparatedList("directory name", true, true, false, true, false, true, false, false, configuration.keepDirectories);
else if (ConfigurationConstants.DONT_SHRINK_OPTION .startsWith(nextWord)) configuration.shrink = parseNoArgument(false);
else if (ConfigurationConstants.PRINT_USAGE_OPTION .startsWith(nextWord)) configuration.printUsage = parseOptionalFile();
@@ -132,7 +178,7 @@ public class ConfigurationParser
else if (ConfigurationConstants.DONT_OPTIMIZE_OPTION .startsWith(nextWord)) configuration.optimize = parseNoArgument(false);
else if (ConfigurationConstants.OPTIMIZATION_PASSES .startsWith(nextWord)) configuration.optimizationPasses = parseIntegerArgument();
- else if (ConfigurationConstants.OPTIMIZATIONS .startsWith(nextWord)) configuration.optimizations = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, configuration.optimizations);
+ else if (ConfigurationConstants.OPTIMIZATIONS .startsWith(nextWord)) configuration.optimizations = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, false, configuration.optimizations);
else if (ConfigurationConstants.ASSUME_NO_SIDE_EFFECTS_OPTION .startsWith(nextWord)) configuration.assumeNoSideEffects = parseClassSpecificationArguments(configuration.assumeNoSideEffects);
else if (ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION .startsWith(nextWord)) configuration.allowAccessModification = parseNoArgument(true);
else if (ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.mergeInterfacesAggressively = parseNoArgument(true);
@@ -146,22 +192,23 @@ public class ConfigurationParser
else if (ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.overloadAggressively = parseNoArgument(true);
else if (ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.useUniqueClassMemberNames = parseNoArgument(true);
else if (ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION .startsWith(nextWord)) configuration.useMixedCaseClassNames = parseNoArgument(false);
- else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION .startsWith(nextWord)) configuration.keepPackageNames = parseCommaSeparatedList("package name", true, true, false, true, false, true, false, configuration.keepPackageNames);
+ else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION .startsWith(nextWord)) configuration.keepPackageNames = parseCommaSeparatedList("package name", true, true, false, false, true, false, true, false, configuration.keepPackageNames);
else if (ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION .startsWith(nextWord)) configuration.flattenPackageHierarchy = ClassUtil.internalClassName(parseOptionalArgument());
else if (ConfigurationConstants.REPACKAGE_CLASSES_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument());
else if (ConfigurationConstants.DEFAULT_PACKAGE_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument());
- else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION .startsWith(nextWord)) configuration.keepAttributes = parseCommaSeparatedList("attribute name", true, true, false, true, false, false, false, configuration.keepAttributes);
+ else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION .startsWith(nextWord)) configuration.keepAttributes = parseCommaSeparatedList("attribute name", true, true, false, false, true, false, false, false, configuration.keepAttributes);
+ else if (ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION .startsWith(nextWord)) configuration.keepParameterNames = parseNoArgument(true);
else if (ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION .startsWith(nextWord)) configuration.newSourceFileAttribute = parseOptionalArgument();
- else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION .startsWith(nextWord)) configuration.adaptClassStrings = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.adaptClassStrings);
- else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, false, false, false, false, false, configuration.adaptResourceFileNames);
- else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION .startsWith(nextWord)) configuration.adaptResourceFileContents = parseCommaSeparatedList("resource file name", true, true, false, false, false, false, false, configuration.adaptResourceFileContents);
+ else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION .startsWith(nextWord)) configuration.adaptClassStrings = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.adaptClassStrings);
+ else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileNames);
+ else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION .startsWith(nextWord)) configuration.adaptResourceFileContents = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileContents);
else if (ConfigurationConstants.DONT_PREVERIFY_OPTION .startsWith(nextWord)) configuration.preverify = parseNoArgument(false);
else if (ConfigurationConstants.MICRO_EDITION_OPTION .startsWith(nextWord)) configuration.microEdition = parseNoArgument(true);
else if (ConfigurationConstants.VERBOSE_OPTION .startsWith(nextWord)) configuration.verbose = parseNoArgument(true);
- else if (ConfigurationConstants.DONT_NOTE_OPTION .startsWith(nextWord)) configuration.note = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.note);
- else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.warn);
+ else if (ConfigurationConstants.DONT_NOTE_OPTION .startsWith(nextWord)) configuration.note = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.note);
+ else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.warn);
else if (ConfigurationConstants.IGNORE_WARNINGS_OPTION .startsWith(nextWord)) configuration.ignoreWarnings = parseNoArgument(true);
else if (ConfigurationConstants.PRINT_CONFIGURATION_OPTION .startsWith(nextWord)) configuration.printConfiguration = parseOptionalFile();
else if (ConfigurationConstants.DUMP_OPTION .startsWith(nextWord)) configuration.dump = parseOptionalFile();
@@ -190,7 +237,7 @@ public class ConfigurationParser
private long parseIncludeArgument(long lastModified) throws ParseException, IOException
{
// Read the configuation file name.
- readNextWord("configuration file name");
+ readNextWord("configuration file name", true, false);
File file = file(nextWord);
reader.includeWordReader(new FileWordReader(file));
@@ -204,7 +251,7 @@ public class ConfigurationParser
private void parseBaseDirectoryArgument() throws ParseException, IOException
{
// Read the base directory name.
- readNextWord("base directory name");
+ readNextWord("base directory name", true, false);
reader.setBaseDir(file(nextWord));
@@ -225,7 +272,7 @@ public class ConfigurationParser
while (true)
{
// Read the next jar name.
- readNextWord("jar or directory name");
+ readNextWord("jar or directory name", true, false);
// Create a new class path entry.
ClassPathEntry entry = new ClassPathEntry(file(nextWord), isOutput);
@@ -245,7 +292,7 @@ public class ConfigurationParser
{
// Read the filter.
filters[counter++] =
- parseCommaSeparatedList("filter", true, false, true, false, true, false, false, null);
+ parseCommaSeparatedList("filter", true, true, true, true, false, true, false, false, null);
}
while (counter < filters.length &&
ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord));
@@ -343,7 +390,7 @@ public class ConfigurationParser
throws ParseException, IOException
{
// Read the obligatory file name.
- readNextWord("file name");
+ readNextWord("file name", true, false);
// Make sure the file is properly resolved.
File file = file(nextWord);
@@ -358,12 +405,12 @@ public class ConfigurationParser
throws ParseException, IOException
{
// Read the optional file name.
- readNextWord();
+ readNextWord(true);
// Didn't the user specify a file name?
if (configurationEnd())
{
- return new File("");
+ return Configuration.STD_OUT;
}
// Make sure the file is properly resolved.
@@ -386,11 +433,11 @@ public class ConfigurationParser
return "";
}
- String fileName = nextWord;
+ String argument = nextWord;
readNextWord();
- return fileName;
+ return argument;
}
@@ -431,7 +478,8 @@ public class ConfigurationParser
{
readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
"', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
- "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
+ "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'",
+ false, true);
if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
{
@@ -491,7 +539,8 @@ public class ConfigurationParser
// Read and add the class configuration.
readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
"', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
- "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
+ "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'",
+ false, true);
classSpecifications.add(parseClassSpecificationArguments());
@@ -499,7 +548,13 @@ public class ConfigurationParser
}
- private ClassSpecification parseClassSpecificationArguments()
+ /**
+ * Parses and returns a class specification.
+ * @throws ParseException if the class specification contains a syntax error.
+ * @throws IOException if an IO error occurs while reading the class
+ * specification.
+ */
+ public ClassSpecification parseClassSpecificationArguments()
throws ParseException, IOException
{
// Clear the annotation type.
@@ -512,30 +567,21 @@ public class ConfigurationParser
// Parse the class annotations and access modifiers until the class keyword.
while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord))
{
- // Parse the annotation type, if any.
-// if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
-// {
-// annotationType =
-// ClassUtil.internalType(
-// ListUtil.commaSeparatedString(
-// parseCommaSeparatedList("annotation type",
-// true, false, false, true, false, null)));
-//
-// continue;
-// }
-
// Strip the negating sign, if any.
- String strippedWord = nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD) ?
+ boolean negated =
+ nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD);
+
+ String strippedWord = negated ?
nextWord.substring(1) :
nextWord;
// Parse the class access modifiers.
- // TODO: Distinguish annotation from annotation modifier.
int accessFlag =
strippedWord.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ENUM) ? ClassConstants.INTERNAL_ACC_ENUM :
unknownAccessFlag();
@@ -543,9 +589,11 @@ public class ConfigurationParser
// Is it an annotation modifier?
if (accessFlag == ClassConstants.INTERNAL_ACC_ANNOTATTION)
{
- // Is the next word actually an annotation type?
- readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", false);
+ // Already read the next word.
+ readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'",
+ false, false);
+ // Is the next word actually an annotation type?
if (!nextWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) &&
!nextWord.equals(ClassConstants.EXTERNAL_ACC_ENUM) &&
!nextWord.equals(ConfigurationConstants.CLASS_KEYWORD))
@@ -554,13 +602,17 @@ public class ConfigurationParser
annotationType =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- false, false, false, true, false, false, true, null));
+ false, false, false, false, true, false, false, true, null), false);
+ // Continue parsing the access modifier that we just read
+ // in the next cycle.
continue;
}
+
+ // Otherwise just handle the annotation modifier.
}
- if (strippedWord.equals(nextWord))
+ if (!negated)
{
requiredSetClassAccessFlags |= accessFlag;
}
@@ -569,7 +621,6 @@ public class ConfigurationParser
requiredUnsetClassAccessFlags |= accessFlag;
}
-
if ((requiredSetClassAccessFlags &
requiredUnsetClassAccessFlags) != 0)
{
@@ -585,16 +636,21 @@ public class ConfigurationParser
break;
}
- readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
- "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
- "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
+ // Should we read the next word?
+ if (accessFlag != ClassConstants.INTERNAL_ACC_ANNOTATTION)
+ {
+ readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
+ "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE +
+ "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'",
+ false, true);
+ }
}
// Parse the class name part.
String externalClassName =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("class name or interface name",
- true, false, false, true, false, false, false, null));
+ true, false, false, false, true, false, false, false, null), false);
// For backward compatibility, allow a single "*" wildcard to match any
// class.
@@ -612,7 +668,7 @@ public class ConfigurationParser
if (ConfigurationConstants.IMPLEMENTS_KEYWORD.equals(nextWord) ||
ConfigurationConstants.EXTENDS_KEYWORD.equals(nextWord))
{
- readNextWord("class name or interface name", true);
+ readNextWord("class name or interface name", false, true);
// Parse the annotation type, if any.
if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
@@ -620,13 +676,13 @@ public class ConfigurationParser
extendsAnnotationType =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- true, false, false, true, false, false, true, null));
+ true, false, false, false, true, false, false, true, null), false);
}
String externalExtendsClassName =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("class name or interface name",
- false, false, false, true, false, false, false, null));
+ false, false, false, false, true, false, false, false, null), false);
extendsClassName = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalExtendsClassName) ?
null :
@@ -659,7 +715,8 @@ public class ConfigurationParser
while (true)
{
readNextWord("class member description" +
- " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'", true);
+ " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'",
+ false, true);
if (nextWord.equals(ConfigurationConstants.CLOSE_KEYWORD))
{
@@ -697,8 +754,7 @@ public class ConfigurationParser
annotationType =
ListUtil.commaSeparatedString(
parseCommaSeparatedList("annotation type",
- true, false, false, true, false, false, true, null));
-
+ true, false, false, false, true, false, false, true, null), false);
continue;
}
@@ -716,9 +772,12 @@ public class ConfigurationParser
strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
strippedWord.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT :
+ strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
0;
if (accessFlag == 0)
{
@@ -875,7 +934,7 @@ public class ConfigurationParser
// Parse the method arguments.
String descriptor =
ClassUtil.internalMethodDescriptor(type,
- parseCommaSeparatedList("argument", true, true, true, true, false, false, false, null));
+ parseCommaSeparatedList("argument", true, true, true, false, true, false, false, false, null));
if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord))
{
@@ -913,14 +972,30 @@ public class ConfigurationParser
/**
- * Reads a comma-separated list of java identifiers or of file names. If an
- * empty list is allowed, the reading will end after a closing parenthesis
- * or semi-colon.
+ * Reads a comma-separated list of java identifiers or of file names.
+ * Examples of invocation arguments:
+ * ("directory n", true, true, false, true, false, true, false, false, ...)
+ * ("optimizatio", true, false, false, false, false, false, false, false, ...)
+ * ("package nam", true, true, false, false, true, false, true, false, ...)
+ * ("attribute n", true, true, false, false, true, false, false, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("resource fi", true, true, false, true, false, false, false, false, ...)
+ * ("resource fi", true, true, false, true, false, false, false, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("filter", true, true, true, true, false, true, false, false, ...)
+ * ("annotation ", false, false, false, false, true, false, false, true, ...)
+ * ("class name ", true, false, false, false, true, false, false, false, ...)
+ * ("annotation ", true, false, false, false, true, false, false, true, ...)
+ * ("class name ", false, false, false, false, true, false, false, false, ...)
+ * ("annotation ", true, false, false, false, true, false, false, true, ...)
+ * ("argument", true, true, true, false, true, false, false, false, ...)
*/
private List parseCommaSeparatedList(String expectedDescription,
boolean readFirstWord,
boolean allowEmptyList,
boolean expectClosingParenthesis,
+ boolean isFileName,
boolean checkJavaIdentifiers,
boolean replaceSystemProperties,
boolean replaceExternalClassNames,
@@ -935,19 +1010,38 @@ public class ConfigurationParser
if (readFirstWord)
{
- if (expectClosingParenthesis || !allowEmptyList)
+ if (!allowEmptyList)
{
// Read the first list entry.
- readNextWord(expectedDescription);
+ readNextWord(expectedDescription, isFileName, false);
+ }
+ else if (expectClosingParenthesis)
+ {
+ // Read the first list entry.
+ readNextWord(expectedDescription, isFileName, false);
+
+ // Return if the entry is actually empty (an empty file name or
+ // a closing parenthesis).
+ if (nextWord.length() == 0)
+ {
+ // Read the closing parenthesis
+ readNextWord("closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
+ "'");
+
+ return list;
+ }
+ else if (nextWord.equals(ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD))
+ {
+ return list;
+ }
}
else
{
// Read the first list entry, if there is any.
- readNextWord();
+ readNextWord(isFileName);
// Check if the list is empty.
- if (configurationEnd() ||
- nextWord.equals(ConfigurationConstants.ANY_ATTRIBUTE_KEYWORD))
+ if (configurationEnd())
{
return list;
}
@@ -956,14 +1050,6 @@ public class ConfigurationParser
while (true)
{
- if (expectClosingParenthesis &&
- list.size() == 0 &&
- (ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord) ||
- ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord)))
- {
- break;
- }
-
if (checkJavaIdentifiers)
{
checkJavaIdentifier("java type");
@@ -1001,14 +1087,12 @@ public class ConfigurationParser
if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
{
- break;
+ return list;
}
// Read the next list entry.
- readNextWord(expectedDescription);
+ readNextWord(expectedDescription, isFileName, false);
}
-
- return list;
}
@@ -1035,23 +1119,13 @@ public class ConfigurationParser
file = new File(reader.getBaseDir(), fileName);
}
- // Try to get a canonical representation.
- try
- {
- file = file.getCanonicalFile();
- }
- catch (IOException ex)
- {
- // Just keep the original representation.
- }
-
return file;
}
/**
- * Replaces any system properties in the given word by their values
- * (e.g. the substring "<java.home>" is replaced by its value).
+ * Replaces any properties in the given word by their values.
+ * For instance, the substring "<java.home>" is replaced by its value.
*/
private String replaceSystemProperties(String word) throws ParseException
{
@@ -1073,7 +1147,7 @@ public class ConfigurationParser
}
String propertyName = word.substring(fromIndex+1, toIndex);
- String propertyValue = System.getProperty(propertyName);
+ String propertyValue = properties.getProperty(propertyName);
if (propertyValue == null)
{
throw new ParseException("Value of system property '" + propertyName +
@@ -1096,7 +1170,7 @@ public class ConfigurationParser
private void readNextWord(String expectedDescription)
throws ParseException, IOException
{
- readNextWord(expectedDescription, false);
+ readNextWord(expectedDescription, false, false);
}
@@ -1105,10 +1179,11 @@ public class ConfigurationParser
* throwing an exception if there is no next word.
*/
private void readNextWord(String expectedDescription,
+ boolean isFileName,
boolean expectingAtCharacter)
throws ParseException, IOException
{
- readNextWord();
+ readNextWord(isFileName);
if (configurationEnd(expectingAtCharacter))
{
throw new ParseException("Expecting " + expectedDescription +
@@ -1122,7 +1197,16 @@ public class ConfigurationParser
*/
private void readNextWord() throws IOException
{
- nextWord = reader.nextWord();
+ readNextWord(false);
+ }
+
+
+ /**
+ * Reads the next word of the configuration in the 'nextWord' field.
+ */
+ private void readNextWord(boolean isFileName) throws IOException
+ {
+ nextWord = reader.nextWord(isFileName);
}
@@ -1168,6 +1252,11 @@ public class ConfigurationParser
*/
private boolean isJavaIdentifier(String aWord)
{
+ if (aWord.length() == 0)
+ {
+ return false;
+ }
+
for (int index = 0; index < aWord.length(); index++)
{
char c = aWord.charAt(index);
@@ -1234,7 +1323,8 @@ public class ConfigurationParser
{
try
{
- ConfigurationParser parser = new ConfigurationParser(args);
+ ConfigurationParser parser =
+ new ConfigurationParser(args, System.getProperties());
try
{
diff --git a/src/proguard/ConfigurationWriter.java b/src/proguard/ConfigurationWriter.java
index 5d112d6..00dfa9e 100644
--- a/src/proguard/ConfigurationWriter.java
+++ b/src/proguard/ConfigurationWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,7 +25,7 @@ import proguard.classfile.util.ClassUtil;
import proguard.util.ListUtil;
import java.io.*;
-import java.util.List;
+import java.util.*;
/**
@@ -44,7 +44,7 @@ public class ConfigurationWriter
private final PrintWriter writer;
- private File baseDir;
+ private File baseDir;
/**
@@ -105,7 +105,7 @@ public class ConfigurationWriter
writer.println();
// Write the other options.
- writeOption(ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION, !configuration.skipNonPublicLibraryClasses);
+ writeOption(ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION, configuration.skipNonPublicLibraryClasses);
writeOption(ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION, !configuration.skipNonPublicLibraryClassMembers);
writeOption(ConfigurationConstants.KEEP_DIRECTORIES_OPTION, configuration.keepDirectories);
writeOption(ConfigurationConstants.TARGET_OPTION, ClassUtil.externalClassVersion(configuration.targetClassVersion));
@@ -115,7 +115,7 @@ public class ConfigurationWriter
writeOption(ConfigurationConstants.PRINT_USAGE_OPTION, configuration.printUsage);
writeOption(ConfigurationConstants.DONT_OPTIMIZE_OPTION, !configuration.optimize);
- writeOption(ConfigurationConstants.OPTIMIZATIONS, configuration.optimize ? ListUtil.commaSeparatedString(configuration.optimizations) : null);
+ writeOption(ConfigurationConstants.OPTIMIZATIONS, configuration.optimizations);
writeOption(ConfigurationConstants.OPTIMIZATION_PASSES, configuration.optimizationPasses);
writeOption(ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION, configuration.allowAccessModification);
writeOption(ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION, configuration.mergeInterfacesAggressively);
@@ -133,6 +133,7 @@ public class ConfigurationWriter
writeOption(ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION, configuration.flattenPackageHierarchy, true);
writeOption(ConfigurationConstants.REPACKAGE_CLASSES_OPTION, configuration.repackageClasses, true);
writeOption(ConfigurationConstants.KEEP_ATTRIBUTES_OPTION, configuration.keepAttributes);
+ writeOption(ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION, configuration.keepParameterNames);
writeOption(ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION, configuration.newSourceFileAttribute);
writeOption(ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION, configuration.adaptClassStrings, true);
writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION, configuration.adaptResourceFileNames);
@@ -218,15 +219,7 @@ public class ConfigurationWriter
writer.print(ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD);
}
- for (int index = 0; index < filter.size(); index++)
- {
- if (index > 0)
- {
- writer.print(ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD);
- }
-
- writer.print(quotedString((String)filter.get(index)));
- }
+ writer.print(ListUtil.commaSeparatedString(filter, true));
filtered = true;
}
@@ -273,16 +266,14 @@ public class ConfigurationWriter
}
else
{
- String argumentString = ListUtil.commaSeparatedString(arguments);
-
if (replaceInternalClassNames)
{
- argumentString = ClassUtil.externalClassName(argumentString);
+ arguments = externalClassNames(arguments);
}
writer.print(optionName);
writer.print(' ');
- writer.println(quotedString(argumentString));
+ writer.println(ListUtil.commaSeparatedString(arguments, true));
}
}
}
@@ -585,6 +576,23 @@ public class ConfigurationWriter
/**
+ * Returns a list with external versions of the given list of internal
+ * class names.
+ */
+ private List externalClassNames(List internalClassNames)
+ {
+ List externalClassNames = new ArrayList(internalClassNames.size());
+
+ for (int index = 0; index < internalClassNames.size(); index++)
+ {
+ externalClassNames.add(ClassUtil.externalClassName((String)internalClassNames.get(index)));
+ }
+
+ return externalClassNames;
+ }
+
+
+ /**
* Returns a relative file name of the given file, if possible.
* The file name is also quoted, if necessary.
*/
diff --git a/src/proguard/DataEntryReaderFactory.java b/src/proguard/DataEntryReaderFactory.java
index a9724b5..3bf6f56 100644
--- a/src/proguard/DataEntryReaderFactory.java
+++ b/src/proguard/DataEntryReaderFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -48,11 +48,10 @@ public class DataEntryReaderFactory
ClassPathEntry classPathEntry,
DataEntryReader reader)
{
- String entryName = classPathEntry.getName();
- boolean isJar = endsWithIgnoreCase(entryName, ".jar");
- boolean isWar = endsWithIgnoreCase(entryName, ".war");
- boolean isEar = endsWithIgnoreCase(entryName, ".ear");
- boolean isZip = endsWithIgnoreCase(entryName, ".zip");
+ boolean isJar = classPathEntry.isJar();
+ boolean isWar = classPathEntry.isWar();
+ boolean isEar = classPathEntry.isEar();
+ boolean isZip = classPathEntry.isZip();
List filter = classPathEntry.getFilter();
List jarFilter = classPathEntry.getJarFilter();
@@ -139,17 +138,4 @@ public class DataEntryReaderFactory
reader);
}
}
-
-
- /**
- * Returns whether the given string ends with the given suffix, ignoring its
- * case.
- */
- private static boolean endsWithIgnoreCase(String string, String suffix)
- {
- int stringLength = string.length();
- int suffixLength = suffix.length();
-
- return string.regionMatches(true, stringLength - suffixLength, suffix, 0, suffixLength);
- }
}
diff --git a/src/proguard/DataEntryWriterFactory.java b/src/proguard/DataEntryWriterFactory.java
index 9fbc6d0..ca33a35 100644
--- a/src/proguard/DataEntryWriterFactory.java
+++ b/src/proguard/DataEntryWriterFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -65,11 +65,10 @@ public class DataEntryWriterFactory
private static DataEntryWriter createClassPathEntryWriter(ClassPathEntry classPathEntry,
DataEntryWriter alternativeWriter)
{
- String entryName = classPathEntry.getName();
- boolean isJar = endsWithIgnoreCase(entryName, ".jar");
- boolean isWar = endsWithIgnoreCase(entryName, ".war");
- boolean isEar = endsWithIgnoreCase(entryName, ".ear");
- boolean isZip = endsWithIgnoreCase(entryName, ".zip");
+ boolean isJar = classPathEntry.isJar();
+ boolean isWar = classPathEntry.isWar();
+ boolean isEar = classPathEntry.isEar();
+ boolean isZip = classPathEntry.isZip();
List filter = classPathEntry.getFilter();
List jarFilter = classPathEntry.getJarFilter();
@@ -83,7 +82,7 @@ public class DataEntryWriterFactory
isEar ? "ear" :
isZip ? "zip" :
"directory") +
- " [" + entryName + "]" +
+ " [" + classPathEntry.getName() + "]" +
(filter != null ||
jarFilter != null ||
warFilter != null ||
@@ -148,17 +147,4 @@ public class DataEntryWriterFactory
filteredJarWriter,
isJar ? jarWriter : writer);
}
-
-
- /**
- * Returns whether the given string ends with the given suffix, ignoring its
- * case.
- */
- private static boolean endsWithIgnoreCase(String string, String suffix)
- {
- int stringLength = string.length();
- int suffixLength = suffix.length();
-
- return string.regionMatches(true, stringLength - suffixLength, suffix, 0, suffixLength);
- }
}
diff --git a/src/proguard/DescriptorKeepChecker.java b/src/proguard/DescriptorKeepChecker.java
index 1dfaf1a..fcd80b2 100644
--- a/src/proguard/DescriptorKeepChecker.java
+++ b/src/proguard/DescriptorKeepChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,7 @@ package proguard;
import proguard.classfile.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
-import proguard.optimize.KeepMarker;
+import proguard.optimize.*;
import java.util.List;
@@ -64,7 +64,7 @@ implements MemberVisitor,
/**
* Checks the classes mentioned in the given keep specifications, printing
- * notes if necessary. Returns the number of notes printed.
+ * notes if necessary.
*/
public void checkClassSpecifications(List keepSpecifications)
{
@@ -85,8 +85,11 @@ implements MemberVisitor,
programClassPool.accept(classPoolvisitor);
libraryClassPool.accept(classPoolvisitor);
- // Print out notes about argument types that are not being kept.
- programClassPool.classesAccept(new AllMemberVisitor(this));
+ // Print out notes about argument types that are not being kept in
+ // class members that are being kept.
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new KeptMemberFilter(this)));
}
@@ -94,39 +97,42 @@ implements MemberVisitor,
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- if (KeepMarker.isKept(programField))
- {
- referencingClass = programClass;
- referencingMember = programField;
- isField = true;
-
- // Don't check the type, because it is not required for introspection.
- //programField.referencedClassesAccept(this);
- }
+ //referencingClass = programClass;
+ //referencingMember = programField;
+ //isField = true;
+ //
+ // Don't check the type, because it is not required for introspection.
+ //programField.referencedClassesAccept(this);
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- if (KeepMarker.isKept(programMethod))
+ referencingClass = programClass;
+ referencingMember = programMethod;
+ isField = false;
+
+ // Don't check the return type, because it is not required for
+ // introspection (e.g. the return type of the special Enum methods).
+ //programMethod.referencedClassesAccept(this);
+
+ Clazz[] referencedClasses = programMethod.referencedClasses;
+ if (referencedClasses != null)
{
- referencingClass = programClass;
- referencingMember = programMethod;
- isField = false;
+ int count = referencedClasses.length;
- // Don't check the return type, because it is not required for
- // introspection (e.g. the return type of the special Enum methods).
- //programMethod.referencedClassesAccept(this);
+ // Adapt the count if the return type is a class type (not so
+ // pretty; assuming test just checks for final ';').
+ if (ClassUtil.isInternalClassType(programMethod.getDescriptor(programClass)))
+ {
+ count--;
+ }
- Clazz[] referencedClasses = programMethod.referencedClasses;
- if (referencedClasses != null)
+ for (int index = 0; index < count; index++)
{
- for (int index = 0; index < referencedClasses.length-1; index++)
+ if (referencedClasses[index] != null)
{
- if (referencedClasses[index] != null)
- {
- referencedClasses[index].accept(this);
- }
+ referencedClasses[index].accept(this);
}
}
}
diff --git a/src/proguard/DuplicateClassPrinter.java b/src/proguard/DuplicateClassPrinter.java
index 21b6aa0..7a071ce 100644
--- a/src/proguard/DuplicateClassPrinter.java
+++ b/src/proguard/DuplicateClassPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/FileWordReader.java b/src/proguard/FileWordReader.java
index fb9fa50..7309843 100644
--- a/src/proguard/FileWordReader.java
+++ b/src/proguard/FileWordReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,23 +29,17 @@ import java.net.URL;
*
* @author Eric Lafortune
*/
-public class FileWordReader extends WordReader
+public class FileWordReader extends LineWordReader
{
- private final String name;
- private LineNumberReader reader;
-
-
/**
* Creates a new FileWordReader for the given file.
*/
public FileWordReader(File file) throws IOException
{
- super(file.getParentFile());
-
- this.name = file.getPath();
- this.reader = new LineNumberReader(
- new BufferedReader(
- new FileReader(file)));
+ super(new LineNumberReader(new BufferedReader(new FileReader(file))),
+ "file '" + file.getPath() + "'",
+ file.getParentFile()
+ );
}
@@ -54,36 +48,8 @@ public class FileWordReader extends WordReader
*/
public FileWordReader(URL url) throws IOException
{
- super(null);
-
- this.name = url.toString();
- this.reader = new LineNumberReader(
- new BufferedReader(
- new InputStreamReader(url.openStream())));
- }
-
-
- // Implementations for WordReader.
-
- protected String nextLine() throws IOException
- {
- return reader.readLine();
- }
-
-
- protected String lineLocationDescription()
- {
- return "line " + reader.getLineNumber() + " of file '" + name + "'";
- }
-
-
- public void close() throws IOException
- {
- super.close();
-
- if (reader != null)
- {
- reader.close();
- }
+ super(new LineNumberReader(new BufferedReader(new InputStreamReader(url.openStream()))),
+ "file '" + url.toString() + "'",
+ null);
}
}
diff --git a/src/proguard/FullyQualifiedClassNameChecker.java b/src/proguard/FullyQualifiedClassNameChecker.java
index 06949b5..eb1865a 100644
--- a/src/proguard/FullyQualifiedClassNameChecker.java
+++ b/src/proguard/FullyQualifiedClassNameChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -42,7 +42,7 @@ implements ClassVisitor
/**
- * Creates a new DescriptorKeepChecker.
+ * Creates a new FullyQualifiedClassNameChecker.
*/
public FullyQualifiedClassNameChecker(ClassPool programClassPool,
ClassPool libraryClassPool,
@@ -56,7 +56,7 @@ implements ClassVisitor
/**
* Checks the classes mentioned in the given class specifications, printing
- * notes if necessary. Returns the number of notes printed.
+ * notes if necessary.
*/
public void checkClassSpecifications(List classSpecifications)
{
@@ -173,7 +173,8 @@ implements ClassVisitor
private static boolean containsWildCards(String string)
{
return string != null &&
- (string.indexOf('*') >= 0 ||
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
string.indexOf('?') >= 0 ||
string.indexOf(',') >= 0 ||
string.indexOf("///") >= 0);
diff --git a/src/proguard/GPL.java b/src/proguard/GPL.java
index 272a837..51220b8 100644
--- a/src/proguard/GPL.java
+++ b/src/proguard/GPL.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -48,9 +48,10 @@ public class GPL
{
String uniquePackageNames = uniquePackageNames(unknownPackageNames);
- System.out.println("ProGuard is released under the GNU General Public License. The authors of all");
- System.out.println("programs or plugins that link to it ("+uniquePackageNames+"...) therefore");
- System.out.println("must ensure that these programs carry the GNU General Public License as well.");
+ System.out.println("ProGuard is released under the GNU General Public License. You therefore");
+ System.out.println("must ensure that programs that link to it ("+uniquePackageNames+"...)");
+ System.out.println("carry the GNU General Public License as well. Alternatively, you can");
+ System.out.println("apply for an exception with the author of ProGuard.");
}
}
@@ -163,11 +164,20 @@ public class GPL
packageName.startsWith("proguard") ||
packageName.startsWith("org.apache.tools.ant") ||
packageName.startsWith("org.apache.tools.maven") ||
+ packageName.startsWith("org.gradle") ||
+ packageName.startsWith("org.codehaus.groovy") ||
packageName.startsWith("org.eclipse") ||
packageName.startsWith("org.netbeans") ||
+ packageName.startsWith("com.android") ||
packageName.startsWith("com.sun.kvem") ||
+ packageName.startsWith("com.intel") ||
packageName.startsWith("net.certiv.proguarddt") ||
+ packageName.startsWith("groovy") ||
+ packageName.startsWith("scala") ||
+ packageName.startsWith("sbt") ||
+ packageName.startsWith("xsbt") ||
packageName.startsWith("eclipseme") ||
+ packageName.startsWith("com.neomades") ||
packageName.startsWith("jg.j2me") ||
packageName.startsWith("jg.common") ||
packageName.startsWith("jg.buildengine");
diff --git a/src/proguard/Initializer.java b/src/proguard/Initializer.java
index 41cf971..405c06d 100644
--- a/src/proguard/Initializer.java
+++ b/src/proguard/Initializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,7 @@
package proguard;
import proguard.classfile.ClassPool;
+import proguard.classfile.attribute.annotation.visitor.*;
import proguard.classfile.attribute.visitor.AllAttributeVisitor;
import proguard.classfile.constant.visitor.*;
import proguard.classfile.instruction.visitor.AllInstructionVisitor;
@@ -60,6 +61,16 @@ public class Initializer
{
int originalLibraryClassPoolSize = libraryClassPool.size();
+ // Perform basic checks on the configuration.
+ WarningPrinter fullyQualifiedClassNameNotePrinter = new WarningPrinter(System.out, configuration.note);
+ WarningPrinter keepClassMemberNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ new FullyQualifiedClassNameChecker(programClassPool,
+ libraryClassPool,
+ fullyQualifiedClassNameNotePrinter).checkClassSpecifications(configuration.keep);
+
+ new KeepClassMemberChecker(keepClassMemberNotePrinter).checkClassSpecifications(configuration.keep);
+
// Construct a reduced library class pool with only those library
// classes whose hierarchies are referenced by the program classes.
// We can't do this if we later have to come up with the obfuscated
@@ -88,13 +99,15 @@ public class Initializer
// Initialize the class references of program class members and
// attributes. Note that all superclass hierarchies have to be
// initialized for this purpose.
- WarningPrinter memberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter programMemberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter libraryMemberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
programClassPool.classesAccept(
new ClassReferenceInitializer(programClassPool,
libraryClassPool,
classReferenceWarningPrinter,
- memberReferenceWarningPrinter,
+ programMemberReferenceWarningPrinter,
+ libraryMemberReferenceWarningPrinter,
null));
if (reducedLibraryClassPool != null)
@@ -115,7 +128,13 @@ public class Initializer
null));
}
- // Initialize the Class.forName references.
+ // Initialize the enum annotation references.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(true,
+ new AllElementValueVisitor(true,
+ new EnumFieldReferenceInitializer())));
+
+ // Initialize the Class.forName references.
WarningPrinter dynamicClassReferenceNotePrinter = new WarningPrinter(System.out, configuration.note);
WarningPrinter classForNameNotePrinter = new WarningPrinter(System.out, configuration.note);
@@ -153,13 +172,8 @@ public class Initializer
libraryClassPool))));
}
- // Print various notes, if specified.
- WarningPrinter fullyQualifiedClassNameNotePrinter = new WarningPrinter(System.out, configuration.note);
- WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note);
-
- new FullyQualifiedClassNameChecker(programClassPool,
- libraryClassPool,
- fullyQualifiedClassNameNotePrinter).checkClassSpecifications(configuration.keep);
+ // Check for unkept descriptor classes of kept class members.
+ WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note);
new DescriptorKeepChecker(programClassPool,
libraryClassPool,
@@ -184,6 +198,7 @@ public class Initializer
libraryClassPool,
null,
null,
+ null,
dependencyWarningPrinter));
// Reset the library class pool.
@@ -214,6 +229,7 @@ public class Initializer
libraryClassPool,
null,
null,
+ null,
dependencyWarningPrinter));
}
@@ -232,6 +248,18 @@ public class Initializer
System.out.println("Note: there were " + fullyQualifiedNoteCount +
" references to unknown classes.");
System.out.println(" You should check your configuration for typos.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unknownclass)");
+ }
+
+ // Print out a summary of the notes, if necessary.
+ int keepClassMemberNoteCount = keepClassMemberNotePrinter.getWarningCount();
+ if (keepClassMemberNoteCount > 0)
+ {
+ System.out.println("Note: there were " + keepClassMemberNoteCount +
+ " '-keepclassmembers' options that didn't specify class");
+ System.out.println(" members. You should specify at least some class members or consider");
+ System.out.println(" if you just need '-keep'.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#classmembers)");
}
int descriptorNoteCount = descriptorKeepNotePrinter.getWarningCount();
@@ -241,6 +269,7 @@ public class Initializer
" unkept descriptor classes in kept class members.");
System.out.println(" You should consider explicitly keeping the mentioned classes");
System.out.println(" (using '-keep').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#descriptorclass)");
}
int dynamicClassReferenceNoteCount = dynamicClassReferenceNotePrinter.getWarningCount();
@@ -248,7 +277,8 @@ public class Initializer
{
System.out.println("Note: there were " + dynamicClassReferenceNoteCount +
" unresolved dynamic references to classes or interfaces.");
- System.err.println(" You should check if you need to specify additional program jars.");
+ System.out.println(" You should check if you need to specify additional program jars.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclass)");
}
int classForNameNoteCount = classForNameNotePrinter.getWarningCount();
@@ -258,6 +288,7 @@ public class Initializer
" class casts of dynamically created class instances.");
System.out.println(" You might consider explicitly keeping the mentioned classes and/or");
System.out.println(" their implementations (using '-keep').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclasscast)");
}
int getmemberNoteCount = getMemberNotePrinter.getWarningCount();
@@ -267,6 +298,7 @@ public class Initializer
" accesses to class members by means of introspection.");
System.out.println(" You should consider explicitly keeping the mentioned class members");
System.out.println(" (using '-keep' or '-keepclassmembers').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclassmember)");
}
// Print out a summary of the warnings, if necessary.
@@ -275,8 +307,16 @@ public class Initializer
{
System.err.println("Warning: there were " + classReferenceWarningCount +
" unresolved references to classes or interfaces.");
- System.err.println(" You may need to specify additional library jars (using '-libraryjars'),");
- System.err.println(" or perhaps the '-dontskipnonpubliclibraryclasses' option.");
+ System.err.println(" You may need to add missing library jars or update their versions.");
+ System.err.println(" If your code works fine without the missing classes, you can suppress");
+ System.err.println(" the warnings with '-dontwarn' options.");
+
+ if (configuration.skipNonPublicLibraryClasses)
+ {
+ System.err.println(" You may also have to remove the option '-skipnonpubliclibraryclasses'.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)");
}
int dependencyWarningCount = dependencyWarningPrinter.getWarningCount();
@@ -286,23 +326,44 @@ public class Initializer
" instances of library classes depending on program classes.");
System.err.println(" You must avoid such dependencies, since the program classes will");
System.err.println(" be processed, while the library classes will remain unchanged.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dependency)");
}
- int memberReferenceWarningCount = memberReferenceWarningPrinter.getWarningCount();
- if (memberReferenceWarningCount > 0)
+ int programMemberReferenceWarningCount = programMemberReferenceWarningPrinter.getWarningCount();
+ if (programMemberReferenceWarningCount > 0)
{
- System.err.println("Warning: there were " + memberReferenceWarningCount +
+ System.err.println("Warning: there were " + programMemberReferenceWarningCount +
" unresolved references to program class members.");
System.err.println(" Your input classes appear to be inconsistent.");
- System.err.println(" You may need to recompile them and try again.");
- System.err.println(" Alternatively, you may have to specify the options ");
- System.err.println(" '-dontskipnonpubliclibraryclasses' and/or");
- System.err.println(" '-dontskipnonpubliclibraryclassmembers'.");
+ System.err.println(" You may need to recompile the code.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)");
+ }
+
+ int libraryMemberReferenceWarningCount = libraryMemberReferenceWarningPrinter.getWarningCount();
+ if (libraryMemberReferenceWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + libraryMemberReferenceWarningCount +
+ " unresolved references to library class members.");
+ System.err.println(" You probably need to update the library versions.");
+
+ if (!configuration.skipNonPublicLibraryClassMembers)
+ {
+ System.err.println(" Alternatively, you may have to specify the option ");
+ System.err.println(" '-dontskipnonpubliclibraryclassmembers'.");
+ }
+
+ if (configuration.skipNonPublicLibraryClasses)
+ {
+ System.err.println(" You may also have to remove the option '-skipnonpubliclibraryclasses'.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)");
}
- if ((classReferenceWarningCount > 0 ||
- dependencyWarningCount > 0 ||
- memberReferenceWarningCount > 0) &&
+ if ((classReferenceWarningCount > 0 ||
+ dependencyWarningCount > 0 ||
+ programMemberReferenceWarningCount > 0 ||
+ libraryMemberReferenceWarningCount > 0) &&
!configuration.ignoreWarnings)
{
throw new IOException("Please correct the above warnings first.");
diff --git a/src/proguard/InputReader.java b/src/proguard/InputReader.java
index c088324..707774e 100644
--- a/src/proguard/InputReader.java
+++ b/src/proguard/InputReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -115,6 +115,7 @@ public class InputReader
{
System.err.println("Note: there were " + noteCount +
" duplicate class definitions.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#duplicateclass)");
}
// Print out a summary of the warnings, if necessary.
@@ -125,6 +126,7 @@ public class InputReader
" classes in incorrectly named files.");
System.err.println(" You should make sure all file names correspond to their class names.");
System.err.println(" The directory hierarchies must correspond to the package hierarchies.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unexpectedclass)");
if (!configuration.ignoreWarnings)
{
@@ -227,7 +229,7 @@ public class InputReader
}
catch (IOException ex)
{
- throw new IOException("Can't read [" + classPathEntry + "] (" + ex.getMessage() + ")");
+ throw (IOException)new IOException("Can't read [" + classPathEntry + "] (" + ex.getMessage() + ")").initCause(ex);
}
}
}
diff --git a/src/proguard/KeepClassMemberChecker.java b/src/proguard/KeepClassMemberChecker.java
new file mode 100644
index 0000000..3ea518e
--- /dev/null
+++ b/src/proguard/KeepClassMemberChecker.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.List;
+
+/**
+ * This class checks if the user has forgotten to specify class members in
+ * some keep options in the configuration.
+ *
+ * @author Eric Lafortune
+ */
+public class KeepClassMemberChecker
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new KeepClassMemberChecker.
+ */
+ public KeepClassMemberChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks if the given class specifications try to keep class members
+ * without actually specifying any, printing notes if necessary. Returns
+ * the number of notes printed.
+ */
+ public void checkClassSpecifications(List keepClassSpecifications)
+ {
+ if (keepClassSpecifications != null)
+ {
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepClassSpecifications.get(index);
+
+ if (!keepClassSpecification.markClasses &&
+ (keepClassSpecification.fieldSpecifications == null ||
+ keepClassSpecification.fieldSpecifications.size() == 0) &&
+ (keepClassSpecification.methodSpecifications == null ||
+ keepClassSpecification.methodSpecifications.size() == 0))
+ {
+ String className = keepClassSpecification.className;
+ if (className == null)
+ {
+ className = keepClassSpecification.extendsClassName;
+ }
+
+ if (notePrinter.accepts(className))
+ {
+ notePrinter.print(className,
+ "Note: the configuration doesn't specify which class members to keep for class '" +
+ (className == null ?
+ ConfigurationConstants.ANY_CLASS_KEYWORD :
+ ClassUtil.externalClassName(className)) + "'");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/proguard/KeepClassSpecification.java b/src/proguard/KeepClassSpecification.java
index 29c0d3c..a6215c5 100644
--- a/src/proguard/KeepClassSpecification.java
+++ b/src/proguard/KeepClassSpecification.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/LineWordReader.java b/src/proguard/LineWordReader.java
new file mode 100644
index 0000000..64a228c
--- /dev/null
+++ b/src/proguard/LineWordReader.java
@@ -0,0 +1,74 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+
+
+/**
+ * A <code>WordReader</code> that returns words from a line number reader.
+ *
+ * @author Eric Lafortune
+ */
+public class LineWordReader extends WordReader
+{
+ private final LineNumberReader reader;
+ private final String description;
+
+
+ /**
+ * Creates a new LineWordReader for the given input.
+ */
+ public LineWordReader(LineNumberReader lineNumberReader,
+ String description,
+ File baseDir) throws IOException
+ {
+ super(baseDir);
+
+ this.reader = lineNumberReader;
+ this.description = description;
+ }
+
+
+ // Implementations for WordReader.
+
+ protected String nextLine() throws IOException
+ {
+ return reader.readLine();
+ }
+
+
+ protected String lineLocationDescription()
+ {
+ return "line " + reader.getLineNumber() + " of " + description;
+ }
+
+
+ public void close() throws IOException
+ {
+ super.close();
+
+ if (reader != null)
+ {
+ reader.close();
+ }
+ }
+}
diff --git a/src/proguard/MemberSpecification.java b/src/proguard/MemberSpecification.java
index 1cfa962..e771fde 100644
--- a/src/proguard/MemberSpecification.java
+++ b/src/proguard/MemberSpecification.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/OutputWriter.java b/src/proguard/OutputWriter.java
index 10c18fb..c4467cf 100644
--- a/src/proguard/OutputWriter.java
+++ b/src/proguard/OutputWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,13 +63,12 @@ public class OutputWriter
"] must be specified after an input jar, or it will be empty.");
}
- // Perform some checks on the output jars.
+ // Check if the first of two subsequent the output jars has a filter.
for (int index = 0; index < programJars.size() - 1; index++)
{
ClassPathEntry entry = programJars.get(index);
if (entry.isOutput())
{
- // Check if all but the last output jars have filters.
if (entry.getFilter() == null &&
entry.getJarFilter() == null &&
entry.getWarFilter() == null &&
@@ -78,10 +77,17 @@ public class OutputWriter
programJars.get(index + 1).isOutput())
{
throw new IOException("The output jar [" + entry.getName() +
- "] must have a filter, or all subsequent jars will be empty.");
+ "] must have a filter, or all subsequent output jars will be empty.");
}
+ }
+ }
- // Check if the output jar name is different from the input jar names.
+ // Check if the output jar names are different from the input jar names.
+ for (int outIndex = 0; outIndex < programJars.size() - 1; outIndex++)
+ {
+ ClassPathEntry entry = programJars.get(outIndex);
+ if (entry.isOutput())
+ {
for (int inIndex = 0; inIndex < programJars.size(); inIndex++)
{
ClassPathEntry otherEntry = programJars.get(inIndex);
@@ -96,6 +102,40 @@ public class OutputWriter
}
}
+ // Check for potential problems with mixed-case class names on
+ // case-insensitive file systems.
+ if (configuration.obfuscate &&
+ configuration.useMixedCaseClassNames &&
+ configuration.classObfuscationDictionary == null &&
+ (configuration.note == null ||
+ !configuration.note.isEmpty()))
+ {
+ String os = System.getProperty("os.name").toLowerCase();
+ if (os.startsWith("windows") ||
+ os.startsWith("mac os"))
+ {
+ // Go over all program class path entries.
+ for (int index = 0; index < programJars.size(); index++)
+ {
+ // Is it an output directory?
+ ClassPathEntry entry = programJars.get(index);
+ if (entry.isOutput() &&
+ !entry.isJar() &&
+ !entry.isWar() &&
+ !entry.isEar() &&
+ !entry.isZip())
+ {
+ System.out.println("Note: you're writing the processed class files to a directory [" + entry.getName() +"].");
+ System.out.println(" This will likely cause problems with obfuscated mixed-case class names.");
+ System.out.println(" You should consider writing the output to a jar file, or otherwise");
+ System.out.println(" specify '-dontusemixedcaseclassnames'.");
+
+ break;
+ }
+ }
+ }
+ }
+
int firstInputIndex = 0;
int lastInputIndex = 0;
@@ -166,7 +206,7 @@ public class OutputWriter
{
resourceRewriter =
new NameFilter(configuration.adaptResourceFileContents,
- new NameFilter("META-INF/**",
+ new NameFilter("META-INF/MANIFEST.MF,META-INF/*.SF",
new ManifestRewriter(programClassPool, writer),
new DataEntryRewriter(programClassPool, writer)),
resourceRewriter);
@@ -221,7 +261,7 @@ public class OutputWriter
}
catch (IOException ex)
{
- throw new IOException("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")");
+ throw (IOException)new IOException("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")").initCause(ex);
}
}
@@ -232,25 +272,25 @@ public class OutputWriter
*/
private static Map createPackagePrefixMap(ClassPool classPool)
{
- Map PackagePrefixMap = new HashMap();
+ Map packagePrefixMap = new HashMap();
Iterator iterator = classPool.classNames();
while (iterator.hasNext())
{
String className = (String)iterator.next();
- String PackagePrefix = ClassUtil.internalPackagePrefix(className);
+ String packagePrefix = ClassUtil.internalPackagePrefix(className);
- String mappedNewPackagePrefix = (String)PackagePrefixMap.get(PackagePrefix);
+ String mappedNewPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
if (mappedNewPackagePrefix == null ||
- !mappedNewPackagePrefix.equals(PackagePrefix))
+ !mappedNewPackagePrefix.equals(packagePrefix))
{
String newClassName = classPool.getClass(className).getName();
String newPackagePrefix = ClassUtil.internalPackagePrefix(newClassName);
- PackagePrefixMap.put(PackagePrefix, newPackagePrefix);
+ packagePrefixMap.put(packagePrefix, newPackagePrefix);
}
}
- return PackagePrefixMap;
+ return packagePrefixMap;
}
}
diff --git a/src/proguard/ParseException.java b/src/proguard/ParseException.java
index 9294200..b4af6c2 100644
--- a/src/proguard/ParseException.java
+++ b/src/proguard/ParseException.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ProGuard.java b/src/proguard/ProGuard.java
index 8c30e10..f9dbf54 100644
--- a/src/proguard/ProGuard.java
+++ b/src/proguard/ProGuard.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,11 +24,12 @@ import proguard.classfile.ClassPool;
import proguard.classfile.editor.ClassElementSorter;
import proguard.classfile.visitor.*;
import proguard.obfuscate.Obfuscator;
-import proguard.optimize.Optimizer;
+import proguard.optimize.*;
import proguard.preverify.*;
import proguard.shrink.Shrinker;
import java.io.*;
+import java.util.Properties;
/**
* Tool for shrinking, optimizing, obfuscating, and preverifying Java classes.
@@ -37,7 +38,7 @@ import java.io.*;
*/
public class ProGuard
{
- public static final String VERSION = "ProGuard, version 4.4";
+ public static final String VERSION = "ProGuard, version 4.10";
private final Configuration configuration;
private ClassPool programClassPool = new ClassPool();
@@ -77,7 +78,8 @@ public class ProGuard
readInput();
- if (configuration.shrink ||
+ if (configuration.printSeeds != null ||
+ configuration.shrink ||
configuration.optimize ||
configuration.obfuscate ||
configuration.preverify)
@@ -236,30 +238,10 @@ public class ProGuard
System.out.println("Printing kept classes, fields, and methods...");
}
- // Check if we have at least some keep commands.
- if (configuration.keep == null)
- {
- throw new IOException("You have to specify '-keep' options for the shrinking step.");
- }
-
PrintStream ps = createPrintStream(configuration.printSeeds);
try
{
- // Create a visitor for printing out the seeds. We're printing out
- // the program elements that are preserved against shrinking,
- // optimization, or obfuscation.
- SimpleClassPrinter printer = new SimpleClassPrinter(false, ps);
- ClassPoolVisitor classPoolvisitor =
- ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
- new ProgramClassFilter(printer),
- new ProgramMemberFilter(printer),
- true,
- true,
- true);
-
- // Print out the seeds.
- programClassPool.accept(classPoolvisitor);
- libraryClassPool.accept(classPoolvisitor);
+ new SeedPrinter(ps).write(configuration, programClassPool, libraryClassPool);
}
finally
{
@@ -421,9 +403,10 @@ public class ProGuard
private PrintStream createPrintStream(File file)
throws FileNotFoundException
{
- return isFile(file) ?
- new PrintStream(new BufferedOutputStream(new FileOutputStream(file))) :
- System.out;
+ return file == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(file)));
}
@@ -445,24 +428,26 @@ public class ProGuard
/**
- * Returns the absolute file name for the given file, or the standard output
+ * Returns the canonical file name for the given file, or "standard output"
* if the file name is empty.
*/
private String fileName(File file)
{
- return isFile(file) ?
- file.getAbsolutePath() :
- "standard output";
- }
-
-
- /**
- * Returns whether the given file is actually a file, or just a placeholder
- * for the standard output.
- */
- private boolean isFile(File file)
- {
- return file.getPath().length() > 0;
+ if (file == Configuration.STD_OUT)
+ {
+ return "standard output";
+ }
+ else
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
}
@@ -484,8 +469,8 @@ public class ProGuard
try
{
// Parse the options specified in the command line arguments.
- ConfigurationParser parser = new ConfigurationParser(args);
-
+ ConfigurationParser parser = new ConfigurationParser(args,
+ System.getProperties());
try
{
parser.parse(configuration);
diff --git a/src/proguard/SeedPrinter.java b/src/proguard/SeedPrinter.java
new file mode 100644
index 0000000..8ed74b6
--- /dev/null
+++ b/src/proguard/SeedPrinter.java
@@ -0,0 +1,97 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassPool;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.constant.visitor.AllConstantVisitor;
+import proguard.classfile.instruction.visitor.AllInstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.*;
+import proguard.util.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class prints out the seeds specified by keep options.
+ *
+ * @author Eric Lafortune
+ */
+public class SeedPrinter
+{
+ private final PrintStream ps;
+
+
+ /**
+ * Creates a new ConfigurationWriter for the given PrintStream.
+ */
+ public SeedPrinter(PrintStream ps) throws IOException
+ {
+ this.ps = ps;
+ }
+
+
+ /**
+ * Prints out the seeds for the classes in the given program class pool.
+ * @param configuration the configuration containing the keep options.
+ * @throws IOException if an IO error occurs while writing the configuration.
+ */
+ public void write(Configuration configuration,
+ ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ // Check if we have at least some keep commands.
+ if (configuration.keep == null)
+ {
+ throw new IOException("You have to specify '-keep' options for the shrinking step.");
+ }
+
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+ libraryClassPool.classesAccept(new ClassCleaner());
+
+ // Create a visitor for printing out the seeds. We're printing out
+ // the program elements that are preserved against shrinking,
+ // optimization, or obfuscation.
+ KeepMarker keepMarker = new KeepMarker();
+ ClassPoolVisitor classPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
+ keepMarker,
+ keepMarker,
+ true,
+ true,
+ true);
+ // Mark the seeds.
+ programClassPool.accept(classPoolvisitor);
+ libraryClassPool.accept(classPoolvisitor);
+
+ // Print out the seeds.
+ SimpleClassPrinter printer = new SimpleClassPrinter(false, ps);
+ programClassPool.classesAcceptAlphabetically(new MultiClassVisitor(
+ new ClassVisitor[]
+ {
+ new KeptClassFilter(printer),
+ new AllMemberVisitor(new KeptMemberFilter(printer))
+ }));
+ }
+} \ No newline at end of file
diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/SubclassedClassFilter.java
index 27cac11..1b9c1fe 100644
--- a/src/proguard/SubclassedClassFilter.java
+++ b/src/proguard/SubclassedClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/Targeter.java b/src/proguard/Targeter.java
index 5067205..675f0df 100644
--- a/src/proguard/Targeter.java
+++ b/src/proguard/Targeter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/UpToDateChecker.java b/src/proguard/UpToDateChecker.java
index 9fa5d16..7f5e7a6 100644
--- a/src/proguard/UpToDateChecker.java
+++ b/src/proguard/UpToDateChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -47,107 +47,186 @@ public class UpToDateChecker
*/
public boolean check()
{
- long inputLastModified = configuration.lastModified;
- long outputLastModified = Long.MAX_VALUE;
+ try
+ {
+ ModificationTimeChecker checker = new ModificationTimeChecker();
- ClassPath programJars = configuration.programJars;
- ClassPath libraryJars = configuration.libraryJars;
+ checker.updateInputModificationTime(configuration.lastModified);
- // Check the dates of the program jars, if any.
- if (programJars != null)
- {
- for (int index = 0; index < programJars.size(); index++)
+ ClassPath programJars = configuration.programJars;
+ ClassPath libraryJars = configuration.libraryJars;
+
+ // Check the dates of the program jars, if any.
+ if (programJars != null)
{
- // Break early, if possible.
- if (inputLastModified >= outputLastModified)
+ for (int index = 0; index < programJars.size(); index++)
{
- break;
- }
+ // Update the input and output modification times.
+ ClassPathEntry classPathEntry = programJars.get(index);
- // Update the input and output modification times.
- ClassPathEntry classPathEntry = programJars.get(index);
- if (classPathEntry.isOutput())
- {
- long lastModified = lastModified(classPathEntry.getFile(), true);
- if (outputLastModified > lastModified)
- {
- outputLastModified = lastModified;
- }
- }
- else
- {
- long lastModified = lastModified(classPathEntry.getFile(), false);
- if (inputLastModified < lastModified)
- {
- inputLastModified = lastModified;
- }
+ checker.updateModificationTime(classPathEntry.getFile(),
+ classPathEntry.isOutput());
}
}
- }
- // Check the dates of the library jars, if any.
- if (libraryJars != null)
- {
- for (int index = 0; index < libraryJars.size(); index++)
+ // Check the dates of the library jars, if any.
+ if (libraryJars != null)
{
- // Break early, if possible.
- if (inputLastModified >= outputLastModified)
+ for (int index = 0; index < libraryJars.size(); index++)
{
- break;
- }
+ // Update the input modification time.
+ ClassPathEntry classPathEntry = libraryJars.get(index);
- // Update the input modification time.
- ClassPathEntry classPathEntry = libraryJars.get(index);
- long lastModified = lastModified(classPathEntry.getFile(), false);
- if (inputLastModified < lastModified)
- {
- inputLastModified = lastModified;
+ checker.updateModificationTime(classPathEntry.getFile(),
+ false);
}
}
- }
- boolean outputUpToDate = inputLastModified < outputLastModified;
- if (outputUpToDate)
+ // Check the dates of the auxiliary input files.
+ checker.updateInputModificationTime(configuration.applyMapping);
+ checker.updateInputModificationTime(configuration.obfuscationDictionary);
+ checker.updateInputModificationTime(configuration.classObfuscationDictionary);
+ checker.updateInputModificationTime(configuration.packageObfuscationDictionary);
+
+ // Check the dates of the auxiliary output files.
+ checker.updateOutputModificationTime(configuration.printSeeds);
+ checker.updateOutputModificationTime(configuration.printUsage);
+ checker.updateOutputModificationTime(configuration.printMapping);
+ checker.updateOutputModificationTime(configuration.printConfiguration);
+ checker.updateOutputModificationTime(configuration.dump);
+ }
+ catch (IllegalStateException e)
{
- System.out.println("The output is up to date");
+ // The output is outdated.
+ return false;
}
- return outputUpToDate;
+ System.out.println("The output seems up to date");
+
+ return true;
}
/**
- * Returns the minimum or maximum modification time of the given file or
- * of the files in the given directory (recursively).
+ * This class maintains the modification times of input and output.
+ * The methods throw an IllegalStateException if the output appears
+ * outdated.
*/
- private long lastModified(File file, boolean minimum)
- {
- // Is it a directory?
- if (file.isDirectory())
+ private static class ModificationTimeChecker {
+
+ private long inputModificationTime = Long.MIN_VALUE;
+ private long outputModificationTime = Long.MAX_VALUE;
+
+
+ /**
+ * Updates the input modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateInputModificationTime(File file)
{
- // Ignore the directory's modification time; just recurse on its files.
- File[] files = file.listFiles();
+ if (file != null)
+ {
+ updateModificationTime(file, false);
+ }
+ }
- // Still, an empty output directory is probably a sign that it is
- // not up to date.
- long lastModified = files.length != 0 && minimum ?
- Long.MAX_VALUE : 0L;
- for (int index = 0; index < files.length; index++)
+ /**
+ * Updates the input modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateOutputModificationTime(File file)
+ {
+ if (file != null && file.getName().length() > 0)
{
- long fileLastModified = lastModified(files[index], minimum);
- if ((lastModified < fileLastModified) ^ minimum)
+ updateModificationTime(file, true);
+ }
+ }
+
+
+ /**
+ * Updates the specified modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateModificationTime(File file, boolean isOutput)
+ {
+ // Is it a directory?
+ if (file.isDirectory())
+ {
+ // Ignore the directory's modification time; just recurse on
+ // its files.
+ File[] files = file.listFiles();
+
+ // Still, an empty output directory is probably a sign that it
+ // is not up to date.
+ if (files.length == 0 && isOutput)
{
- lastModified = fileLastModified;
+ updateOutputModificationTime(Long.MIN_VALUE);
}
+
+ for (int index = 0; index < files.length; index++)
+ {
+ updateModificationTime(files[index], isOutput);
+ }
+ }
+ else
+ {
+ // Update with the file's modification time.
+ updateModificationTime(file.lastModified(), isOutput);
}
+ }
+
- return lastModified;
+ /**
+ * Updates the specified modification time.
+ */
+ public void updateModificationTime(long time, boolean isOutput)
+ {
+ if (isOutput)
+ {
+ updateOutputModificationTime(time);
+ }
+ else
+ {
+ updateInputModificationTime(time);
+ }
}
- else
+
+
+ /**
+ * Updates the input modification time.
+ */
+ public void updateInputModificationTime(long time)
{
- // Return the file's modification time.
- return file.lastModified();
+ if (inputModificationTime < time)
+ {
+ inputModificationTime = time;
+
+ checkModificationTimes();
+ }
+ }
+
+
+ /**
+ * Updates the output modification time.
+ */
+ public void updateOutputModificationTime(long time)
+ {
+ if (outputModificationTime > time)
+ {
+ outputModificationTime = time;
+
+ checkModificationTimes();
+ }
+ }
+
+
+ private void checkModificationTimes()
+ {
+ if (inputModificationTime > outputModificationTime)
+ {
+ throw new IllegalStateException("The output is outdated");
+ }
}
}
}
diff --git a/src/proguard/WordReader.java b/src/proguard/WordReader.java
index d73505a..110fce3 100644
--- a/src/proguard/WordReader.java
+++ b/src/proguard/WordReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -105,9 +105,11 @@ public abstract class WordReader
* Reads a word from this WordReader, or from one of its active included
* WordReader objects.
*
+ * @param isFileName return a complete line (or argument), if the word
+ * isn't an option (it doesn't start with '-').
* @return the read word.
*/
- public String nextWord() throws IOException
+ public String nextWord(boolean isFileName) throws IOException
{
currentWord = null;
@@ -115,7 +117,7 @@ public abstract class WordReader
if (includeWordReader != null)
{
// Does the included word reader still produce a word?
- currentWord = includeWordReader.nextWord();
+ currentWord = includeWordReader.nextWord(isFileName);
if (currentWord != null)
{
// Return it if so.
@@ -129,12 +131,22 @@ public abstract class WordReader
// Get a word from this reader.
- // Skip leading whitespace.
- while (currentLine != null &&
- currentIndex < currentLineLength &&
- Character.isWhitespace(currentLine.charAt(currentIndex)))
+ // Skip any whitespace and comments left on the current line.
+ if (currentLine != null)
{
- currentIndex++;
+ // Skip any leading whitespace.
+ while (currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
+ {
+ currentIndex++;
+ }
+
+ // Skip any comments.
+ if (currentIndex < currentLineLength &&
+ isComment(currentLine.charAt(currentIndex)))
+ {
+ currentIndex = currentLineLength;
+ }
}
// Make sure we have a non-blank line.
@@ -146,29 +158,28 @@ public abstract class WordReader
return null;
}
- // Trim off any comments.
- int comments_start = currentLine.indexOf(COMMENT_CHARACTER);
- if (comments_start >= 0)
+ currentLineLength = currentLine.length();
+
+ // Skip any leading whitespace.
+ currentIndex = 0;
+ while (currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
{
- currentLineLength = comments_start;
+ currentIndex++;
+ }
+ // Remember any leading comments.
+ if (currentIndex < currentLineLength &&
+ isComment(currentLine.charAt(currentIndex)))
+ {
// Remember the comments.
- String comment = currentLine.substring(comments_start + 1);
+ String comment = currentLine.substring(currentIndex + 1);
currentComments = currentComments == null ?
comment :
currentComments + '\n' + comment;
- }
- else
- {
- currentLineLength = currentLine.length();
- }
- // Skip leading whitespace.
- currentIndex = 0;
- while (currentIndex < currentLineLength &&
- Character.isWhitespace(currentLine.charAt(currentIndex)))
- {
- currentIndex++;
+ // Skip the comments.
+ currentIndex = currentLineLength;
}
}
@@ -178,12 +189,7 @@ public abstract class WordReader
char startChar = currentLine.charAt(startIndex);
- if (isDelimiter(startChar))
- {
- // The next word is a single delimiting character.
- endIndex = ++currentIndex;
- }
- else if (isQuote(startChar))
+ if (isQuote(startChar))
{
// The next word is starting with a quote character.
// Skip the opening quote.
@@ -205,6 +211,39 @@ public abstract class WordReader
endIndex = currentIndex++;
}
+ else if (isFileName &&
+ !isOption(startChar))
+ {
+ // The next word is a (possibly optional) file name.
+ // Find the end of the line, the first path separator, the first
+ // option, or the first comment.
+ while (currentIndex < currentLineLength)
+ {
+ char currentCharacter = currentLine.charAt(currentIndex);
+ if (isFileDelimiter(currentCharacter) ||
+ ((isOption(currentCharacter) ||
+ isComment(currentCharacter)) &&
+ Character.isWhitespace(currentLine.charAt(currentIndex-1)))) {
+ break;
+ }
+
+ currentIndex++;
+ }
+
+ endIndex = currentIndex;
+
+ // Trim any trailing whitespace.
+ while (endIndex > startIndex &&
+ Character.isWhitespace(currentLine.charAt(endIndex-1)))
+ {
+ endIndex--;
+ }
+ }
+ else if (isDelimiter(startChar))
+ {
+ // The next word is a single delimiting character.
+ endIndex = ++currentIndex;
+ }
else
{
// The next word is a simple character string.
@@ -213,9 +252,9 @@ public abstract class WordReader
while (currentIndex < currentLineLength)
{
char currentCharacter = currentLine.charAt(currentIndex);
- if (isDelimiter(currentCharacter) ||
- Character.isWhitespace(currentCharacter))
- {
+ if (isDelimiter(currentCharacter) ||
+ Character.isWhitespace(currentCharacter) ||
+ isComment(currentCharacter)) {
break;
}
@@ -305,6 +344,18 @@ public abstract class WordReader
// Small utility methods.
+ private boolean isOption(char character)
+ {
+ return character == '-';
+ }
+
+
+ private boolean isComment(char character)
+ {
+ return character == COMMENT_CHARACTER;
+ }
+
+
private boolean isDelimiter(char character)
{
return character == '@' ||
@@ -318,6 +369,16 @@ public abstract class WordReader
}
+ private boolean isFileDelimiter(char character)
+ {
+ return character == '(' ||
+ character == ')' ||
+ character == ',' ||
+ character == ';' ||
+ character == File.pathSeparatorChar;
+ }
+
+
private boolean isQuote(char character)
{
return character == '\'' ||
diff --git a/src/proguard/ant/ClassPathElement.java b/src/proguard/ant/ClassPathElement.java
index b5c2df4..b496123 100644
--- a/src/proguard/ant/ClassPathElement.java
+++ b/src/proguard/ant/ClassPathElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/ClassSpecificationElement.java b/src/proguard/ant/ClassSpecificationElement.java
index f4ea2ff..c07e101 100644
--- a/src/proguard/ant/ClassSpecificationElement.java
+++ b/src/proguard/ant/ClassSpecificationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -222,6 +222,7 @@ public class ClassSpecificationElement extends DataType
strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
0;
diff --git a/src/proguard/ant/ConfigurationElement.java b/src/proguard/ant/ConfigurationElement.java
index 76e9418..d184aef 100644
--- a/src/proguard/ant/ConfigurationElement.java
+++ b/src/proguard/ant/ConfigurationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,34 +20,105 @@
*/
package proguard.ant;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.DataType;
-import proguard.Configuration;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.*;
+import proguard.*;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.Properties;
/**
- * This DataType represents a reference to a ProGuard configuration in Ant.
+ * This DataType represents a reference to an XML-style ProGuard configuration
+ * in Ant, or a file set of ProGuard-style configuration files.
*
* @author Eric Lafortune
*/
-public class ConfigurationElement extends DataType
+public class ConfigurationElement extends FileSet
{
/**
- * Adds the contents of this configuration task to the given configuration.
+ * Adds the contents of this configuration element to the given
+ * configuration.
* @param configuration the configuration to be extended.
*/
public void appendTo(Configuration configuration)
{
- // Get the referenced element.
- if (!isReference())
+ File baseDir;
+ String[] fileNames;
+
+ if (isReference())
{
- throw new BuildException("Nested element <configuration> must have a refid attribute");
+ // Get the referenced path or file set.
+ Object referencedObject = getCheckedRef(Object.class,
+ Object.class.getName());
+
+ if (referencedObject instanceof ConfigurationTask)
+ {
+ // The reference doesn't point to a file set, but to a
+ // configuration task.
+ ConfigurationTask configurationTask =
+ (ConfigurationTask)referencedObject;
+
+ // Append the contents of the referenced configuration to the
+ // current configuration.
+ configurationTask.appendTo(configuration);
+
+ return;
+ }
+ else if (referencedObject instanceof AbstractFileSet)
+ {
+ AbstractFileSet fileSet = (AbstractFileSet)referencedObject;
+
+ // Get the names of the existing input files in the referenced file set.
+ DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
+ baseDir = scanner.getBasedir();
+ fileNames = scanner.getIncludedFiles();
+ }
+ else
+ {
+ throw new BuildException("The refid attribute doesn't point to a <proguardconfiguration> element or a <fileset> element");
+ }
}
+ else
+ {
+ // Get the names of the existing input files in the referenced file set.
+ DirectoryScanner scanner = getDirectoryScanner(getProject());
+ baseDir = scanner.getBasedir();
+ fileNames = scanner.getIncludedFiles();
+ }
+
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(getProject().getProperties());
- ConfigurationTask configurationTask =
- (ConfigurationTask)getCheckedRef(ConfigurationTask.class,
- ConfigurationTask.class.getName());
+ try
+ {
+ // Append the contents of the configuration files to the current
+ // configuration.
+ for (int index = 0; index < fileNames.length; index++)
+ {
+ File configurationFile = new File(baseDir, fileNames[index]);
- // Append the referenced configuration entries to the given configuration.
- configurationTask.appendTo(configuration);
+ ConfigurationParser parser =
+ new ConfigurationParser(configurationFile, properties);
+ try
+ {
+ parser.parse(configuration);
+ }
+ catch (ParseException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
}
}
diff --git a/src/proguard/ant/ConfigurationTask.java b/src/proguard/ant/ConfigurationTask.java
index 0d2f04f..376a1a1 100644
--- a/src/proguard/ant/ConfigurationTask.java
+++ b/src/proguard/ant/ConfigurationTask.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -291,10 +291,20 @@ public class ConfigurationTask extends Task
{
try
{
- String arg = getProject().replaceProperties(text);
+ Project project = getProject();
- ConfigurationParser parser = new ConfigurationParser(new String[] { arg },
- getProject().getBaseDir());
+ // Replace Ant-style properties ('${...}').
+ String arg = project.replaceProperties(text);
+
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(project.getProperties());
+
+ ConfigurationParser parser = new ConfigurationParser(arg,
+ "embedded configuration",
+ project.getBaseDir(),
+ properties);
try
{
diff --git a/src/proguard/ant/FilterElement.java b/src/proguard/ant/FilterElement.java
index d792c5d..ab3364a 100644
--- a/src/proguard/ant/FilterElement.java
+++ b/src/proguard/ant/FilterElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/KeepSpecificationElement.java b/src/proguard/ant/KeepSpecificationElement.java
index e36b744..feabc18 100644
--- a/src/proguard/ant/KeepSpecificationElement.java
+++ b/src/proguard/ant/KeepSpecificationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,9 +39,9 @@ public class KeepSpecificationElement extends ClassSpecificationElement
/**
* Adds the contents of this class specification element to the given list.
* @param keepSpecifications the class specifications to be extended.
- * @param markClasses specifies whether to mark the classes.
- * @param markConditionally specifies whether to mark the classes
- * and class members conditionally.
+ * @param markClasses specifies whether to mark the classes.
+ * @param markConditionally specifies whether to mark the classes
+ * and class members conditionally.
*/
public void appendTo(List keepSpecifications,
boolean markClasses,
@@ -50,16 +50,16 @@ public class KeepSpecificationElement extends ClassSpecificationElement
// Get the referenced file set, or else this one.
KeepSpecificationElement keepSpecificationElement = isReference() ?
(KeepSpecificationElement)getCheckedRef(this.getClass(),
- this.getClass().getName()) :
+ this.getClass().getName()) :
this;
KeepClassSpecification keepClassSpecification =
new KeepClassSpecification(markClasses,
- markConditionally,
- allowShrinking,
- allowOptimization,
- allowObfuscation,
- createClassSpecification(keepSpecificationElement));
+ markConditionally,
+ allowShrinking,
+ allowOptimization,
+ allowObfuscation,
+ createClassSpecification(keepSpecificationElement));
// Add it to the list.
keepSpecifications.add(keepClassSpecification);
diff --git a/src/proguard/ant/MemberSpecificationElement.java b/src/proguard/ant/MemberSpecificationElement.java
index d4bb4a9..9762009 100644
--- a/src/proguard/ant/MemberSpecificationElement.java
+++ b/src/proguard/ant/MemberSpecificationElement.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,7 +63,7 @@ public class MemberSpecificationElement extends DataType
this.getClass().getName()) :
this;
- // Create a new class specification.
+ // Create a new class member specification.
String access = memberSpecificationElement.access;
String type = memberSpecificationElement.type;
String annotation = memberSpecificationElement.annotation;
@@ -195,9 +195,12 @@ public class MemberSpecificationElement extends DataType
strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
strippedToken.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
0;
if (accessFlag == 0)
diff --git a/src/proguard/ant/ProGuardTask.java b/src/proguard/ant/ProGuardTask.java
index b7fc361..7ab1cdf 100644
--- a/src/proguard/ant/ProGuardTask.java
+++ b/src/proguard/ant/ProGuardTask.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,7 +25,7 @@ import proguard.*;
import proguard.classfile.util.ClassUtil;
import java.io.*;
-import java.util.ArrayList;
+import java.util.*;
/**
* This Task allows to configure and run ProGuard from Ant.
@@ -40,8 +40,13 @@ public class ProGuardTask extends ConfigurationTask
{
try
{
- ConfigurationParser parser = new ConfigurationParser(configurationFile);
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(getProject().getProperties());
+ ConfigurationParser parser = new ConfigurationParser(configurationFile,
+ properties);
try
{
parser.parse(configuration);
@@ -215,6 +220,12 @@ public class ProGuardTask extends ConfigurationTask
}
+ public void setKeepparameternames(boolean keepParameterNames)
+ {
+ configuration.keepParameterNames = keepParameterNames;
+ }
+
+
public void setRenamesourcefileattribute(String newSourceFileAttribute)
{
configuration.newSourceFileAttribute = newSourceFileAttribute;
@@ -241,13 +252,39 @@ public class ProGuardTask extends ConfigurationTask
public void setNote(boolean note)
{
- configuration.note = note ? null : new ArrayList();
+ if (note)
+ {
+ // Switch on notes if they were completely disabled.
+ if (configuration.note != null &&
+ configuration.note.isEmpty())
+ {
+ configuration.note = null;
+ }
+ }
+ else
+ {
+ // Switch off notes.
+ configuration.note = new ArrayList();
+ }
}
public void setWarn(boolean warn)
{
- configuration.warn = warn ? null : new ArrayList();
+ if (warn)
+ {
+ // Switch on warnings if they were completely disabled.
+ if (configuration.warn != null &&
+ configuration.warn.isEmpty())
+ {
+ configuration.warn = null;
+ }
+ }
+ else
+ {
+ // Switch off warnings.
+ configuration.warn = new ArrayList();
+ }
}
@@ -302,7 +339,7 @@ public class ProGuardTask extends ConfigurationTask
fileName.equalsIgnoreCase("off") ? null :
fileName.equalsIgnoreCase("true") ||
fileName.equalsIgnoreCase("yes") ||
- fileName.equalsIgnoreCase("on") ? new File("") :
+ fileName.equalsIgnoreCase("on") ? Configuration.STD_OUT :
resolvedFile(file);
}
diff --git a/src/proguard/ant/task.properties b/src/proguard/ant/task.properties
index b676db7..82d0f3f 100644
--- a/src/proguard/ant/task.properties
+++ b/src/proguard/ant/task.properties
@@ -1,2 +1,2 @@
-proguard = proguard.ant.ProGuardTask
-proguardconfiguration = proguard.ant.ConfigurationTask
+proguard = proguard.ant.ProGuardTask
+proguardconfiguration = proguard.ant.ConfigurationTask
diff --git a/src/proguard/classfile/ClassConstants.java b/src/proguard/classfile/ClassConstants.java
index 3b243e0..59580c5 100644
--- a/src/proguard/classfile/ClassConstants.java
+++ b/src/proguard/classfile/ClassConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -43,6 +43,8 @@ public interface ClassConstants
public static final int INTERNAL_CLASS_VERSION_1_5_MINOR = 0;
public static final int INTERNAL_CLASS_VERSION_1_6_MAJOR = 50;
public static final int INTERNAL_CLASS_VERSION_1_6_MINOR = 0;
+ public static final int INTERNAL_CLASS_VERSION_1_7_MAJOR = 51;
+ public static final int INTERNAL_CLASS_VERSION_1_7_MINOR = 0;
public static final int INTERNAL_CLASS_VERSION_1_0 = (INTERNAL_CLASS_VERSION_1_0_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_0_MINOR;
public static final int INTERNAL_CLASS_VERSION_1_2 = (INTERNAL_CLASS_VERSION_1_2_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_2_MINOR;
@@ -50,6 +52,7 @@ public interface ClassConstants
public static final int INTERNAL_CLASS_VERSION_1_4 = (INTERNAL_CLASS_VERSION_1_4_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_4_MINOR;
public static final int INTERNAL_CLASS_VERSION_1_5 = (INTERNAL_CLASS_VERSION_1_5_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_5_MINOR;
public static final int INTERNAL_CLASS_VERSION_1_6 = (INTERNAL_CLASS_VERSION_1_6_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_6_MINOR;
+ public static final int INTERNAL_CLASS_VERSION_1_7 = (INTERNAL_CLASS_VERSION_1_7_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_7_MINOR;
public static final String EXTERNAL_CLASS_VERSION_1_0 = "1.0";
public static final String EXTERNAL_CLASS_VERSION_1_1 = "1.1";
@@ -58,8 +61,10 @@ public interface ClassConstants
public static final String EXTERNAL_CLASS_VERSION_1_4 = "1.4";
public static final String EXTERNAL_CLASS_VERSION_1_5 = "1.5";
public static final String EXTERNAL_CLASS_VERSION_1_6 = "1.6";
+ public static final String EXTERNAL_CLASS_VERSION_1_7 = "1.7";
public static final String EXTERNAL_CLASS_VERSION_1_5_ALIAS = "5";
public static final String EXTERNAL_CLASS_VERSION_1_6_ALIAS = "6";
+ public static final String EXTERNAL_CLASS_VERSION_1_7_ALIAS = "7";
public static final int INTERNAL_ACC_PUBLIC = 0x0001;
public static final int INTERNAL_ACC_PRIVATE = 0x0002;
@@ -119,10 +124,13 @@ public interface ClassConstants
public static final String EXTERNAL_ACC_SYNCHRONIZED = "synchronized";
public static final String EXTERNAL_ACC_VOLATILE = "volatile";
public static final String EXTERNAL_ACC_TRANSIENT = "transient";
+ public static final String EXTERNAL_ACC_BRIDGE = "bridge";
+ public static final String EXTERNAL_ACC_VARARGS = "varargs";
public static final String EXTERNAL_ACC_NATIVE = "native";
public static final String EXTERNAL_ACC_INTERFACE = "interface";
public static final String EXTERNAL_ACC_ABSTRACT = "abstract";
public static final String EXTERNAL_ACC_STRICT = "strictfp";
+ public static final String EXTERNAL_ACC_SYNTHETIC = "synthetic";
public static final String EXTERNAL_ACC_ANNOTATION = "@";
public static final String EXTERNAL_ACC_ENUM = "enum";
@@ -137,7 +145,21 @@ public interface ClassConstants
public static final int CONSTANT_Methodref = 10;
public static final int CONSTANT_InterfaceMethodref = 11;
public static final int CONSTANT_NameAndType = 12;
+ public static final int CONSTANT_MethodHandle = 15;
+ public static final int CONSTANT_MethodType = 16;
+ public static final int CONSTANT_InvokeDynamic = 18;
+ public static final int REF_getField = 1;
+ public static final int REF_getStatic = 2;
+ public static final int REF_putField = 3;
+ public static final int REF_putStatic = 4;
+ public static final int REF_invokeVirtual = 5;
+ public static final int REF_invokeStatic = 6;
+ public static final int REF_invokeSpecial = 7;
+ public static final int REF_newInvokeSpecial = 8;
+ public static final int REF_invokeInterface = 9;
+
+ public static final String ATTR_BootstrapMethods = "BootstrapMethods";
public static final String ATTR_SourceFile = "SourceFile";
public static final String ATTR_SourceDir = "SourceDir";
public static final String ATTR_InnerClasses = "InnerClasses";
@@ -159,11 +181,11 @@ public interface ClassConstants
public static final String ATTR_RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations";
public static final String ATTR_AnnotationDefault = "AnnotationDefault";
- public static final int ELEMENT_VALUE_STRING_CONSTANT = 's';
- public static final int ELEMENT_VALUE_ENUM_CONSTANT = 'e';
- public static final int ELEMENT_VALUE_CLASS = 'c';
- public static final int ELEMENT_VALUE_ANNOTATION = '@';
- public static final int ELEMENT_VALUE_ARRAY = '[';
+ public static final char ELEMENT_VALUE_STRING_CONSTANT = 's';
+ public static final char ELEMENT_VALUE_ENUM_CONSTANT = 'e';
+ public static final char ELEMENT_VALUE_CLASS = 'c';
+ public static final char ELEMENT_VALUE_ANNOTATION = '@';
+ public static final char ELEMENT_VALUE_ARRAY = '[';
public static final char EXTERNAL_PACKAGE_SEPARATOR = '.';
public static final char EXTERNAL_INNER_CLASS_SEPARATOR = '.';
@@ -179,41 +201,93 @@ public interface ClassConstants
public static final char INTERNAL_METHOD_ARGUMENTS_OPEN = '(';
public static final char INTERNAL_METHOD_ARGUMENTS_CLOSE = ')';
- public static final String INTERNAL_PACKAGE_JAVA_LANG = "java/lang/";
- public static final String INTERNAL_NAME_JAVA_LANG_OBJECT = "java/lang/Object";
- public static final String INTERNAL_TYPE_JAVA_LANG_OBJECT = "Ljava/lang/Object;";
- public static final String INTERNAL_NAME_JAVA_LANG_CLONEABLE = "java/lang/Cloneable";
- public static final String INTERNAL_NAME_JAVA_LANG_THROWABLE = "java/lang/Throwable";
- public static final String INTERNAL_NAME_JAVA_LANG_CLASS = "java/lang/Class";
- public static final String INTERNAL_NAME_JAVA_LANG_STRING = "java/lang/String";
- public static final String INTERNAL_NAME_JAVA_IO_SERIALIZABLE = "java/io/Serializable";
+ public static final String INTERNAL_PACKAGE_JAVA_LANG = "java/lang/";
+ public static final String INTERNAL_NAME_JAVA_LANG_OBJECT = "java/lang/Object";
+ public static final String INTERNAL_TYPE_JAVA_LANG_OBJECT = "Ljava/lang/Object;";
+ public static final String INTERNAL_NAME_JAVA_LANG_CLONEABLE = "java/lang/Cloneable";
+ public static final String INTERNAL_NAME_JAVA_LANG_THROWABLE = "java/lang/Throwable";
+ public static final String INTERNAL_NAME_JAVA_LANG_CLASS = "java/lang/Class";
+ public static final String INTERNAL_NAME_JAVA_LANG_STRING = "java/lang/String";
+ public static final String INTERNAL_NAME_JAVA_LANG_STRING_BUFFER = "java/lang/StringBuffer";
+ public static final String INTERNAL_NAME_JAVA_LANG_STRING_BUILDER = "java/lang/StringBuilder";
+ public static final String INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE = "java/lang/invoke/MethodHandle";
+ public static final String INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE = "java/lang/invoke/MethodType";
+ public static final String INTERNAL_NAME_JAVA_IO_SERIALIZABLE = "java/io/Serializable";
+
+ public static final String INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicIntegerFieldUpdater";
+ public static final String INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicLongFieldUpdater";
+ public static final String INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicReferenceFieldUpdater";
public static final String INTERNAL_METHOD_NAME_INIT = "<init>";
public static final String INTERNAL_METHOD_TYPE_INIT = "()V";
public static final String INTERNAL_METHOD_NAME_CLINIT = "<clinit>";
public static final String INTERNAL_METHOD_TYPE_CLINIT = "()V";
- public static final String INTERNAL_METHOD_NAME_CLASS_FOR_NAME = "forName";
- public static final String INTERNAL_METHOD_TYPE_CLASS_FOR_NAME = "(Ljava/lang/String;)Ljava/lang/Class;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_COMPONENT_TYPE = "getComponentType";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_COMPONENT_TYPE = "()Ljava/lang/Class;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_FIELD = "getField";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_FIELD = "getDeclaredField";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_METHOD = "getMethod";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
- public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_METHOD = "getDeclaredMethod";
- public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_FOR_NAME = "forName";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_FOR_NAME = "(Ljava/lang/String;)Ljava/lang/Class;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_COMPONENT_TYPE = "getComponentType";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_COMPONENT_TYPE = "()Ljava/lang/Class;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_FIELD = "getField";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_FIELD = "getDeclaredField";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
+ public static final String INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR = "getConstructor";
+ public static final String INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;";
+ public static final String INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR = "getDeclaredConstructor";
+ public static final String INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_METHOD = "getMethod";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_METHOD = "getDeclaredMethod";
+ public static final String INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String INTERNAL_METHOD_NAME_NEW_UPDATER = "newUpdater";
+ public static final String INTERNAL_METHOD_TYPE_NEW_INTEGER_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;";
+ public static final String INTERNAL_METHOD_TYPE_NEW_LONG_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicLongFieldUpdater;";
+ public static final String INTERNAL_METHOD_TYPE_NEW_REFERENCE_UPDATER = "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;";
public static final String INTERNAL_METHOD_NAME_DOT_CLASS_JAVAC = "class$";
public static final String INTERNAL_METHOD_TYPE_DOT_CLASS_JAVAC = "(Ljava/lang/String;)Ljava/lang/Class;";
public static final String INTERNAL_METHOD_NAME_DOT_CLASS_JIKES = "class";
public static final String INTERNAL_METHOD_TYPE_DOT_CLASS_JIKES = "(Ljava/lang/String;Z)Ljava/lang/Class;";
+ public static final String INTERNAL_METHOD_TYPE_INIT_ENUM = "(Ljava/lang/String;I)V";
+
public static final String INTERNAL_METHOD_NAME_NEW_INSTANCE = "newInstance";
public static final String INTERNAL_METHOD_TYPE_NEW_INSTANCE = "()Ljava/lang/Object;";
+ public static final String INTERNAL_METHOD_NAME_EQUALS = "equals";
+ public static final String INTERNAL_METHOD_TYPE_EQUALS = "(Ljava/lang/Object;)Z";
+ public static final String INTERNAL_METHOD_NAME_LENGTH = "length";
+ public static final String INTERNAL_METHOD_NAME_VALUEOF = "valueOf";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_BOOLEAN = "(Z)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_CHAR = "(C)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_INT = "(I)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_LONG = "(J)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_FLOAT = "(F)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_DOUBLE = "(D)Ljava/lang/String;";
+ public static final String INTERNAL_METHOD_TYPE_VALUEOF_OBJECT = "(Ljava/lang/Object;)Ljava/lang/String;";
+
+ public static final String INTERNAL_METHOD_TYPE_LENGTH = "()I";
+ public static final String INTERNAL_METHOD_NAME_APPEND = "append";
+ public static final String INTERNAL_METHOD_TYPE_STRING_VOID = "(Ljava/lang/String;)V";
+ public static final String INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUFFER = "(Z)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_CHAR_STRING_BUFFER = "(C)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_INT_STRING_BUFFER = "(I)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_LONG_STRING_BUFFER = "(J)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_FLOAT_STRING_BUFFER = "(F)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUFFER = "(D)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_STRING_STRING_BUFFER = "(Ljava/lang/String;)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_OBJECT_STRING_BUFFER = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;";
+ public static final String INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUILDER = "(Z)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_CHAR_STRING_BUILDER = "(C)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_INT_STRING_BUILDER = "(I)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_LONG_STRING_BUILDER = "(J)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_FLOAT_STRING_BUILDER = "(F)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUILDER = "(D)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_STRING_STRING_BUILDER = "(Ljava/lang/String;)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_TYPE_OBJECT_STRING_BUILDER = "(Ljava/lang/Object;)Ljava/lang/StringBuilder;";
+ public static final String INTERNAL_METHOD_NAME_TOSTRING = "toString";
+ public static final String INTERNAL_METHOD_TYPE_TOSTRING = "()Ljava/lang/String;";
+
public static final char INTERNAL_TYPE_VOID = 'V';
public static final char INTERNAL_TYPE_BOOLEAN = 'Z';
public static final char INTERNAL_TYPE_BYTE = 'B';
diff --git a/src/proguard/classfile/ClassPool.java b/src/proguard/classfile/ClassPool.java
index 57728a5..5439c6f 100644
--- a/src/proguard/classfile/ClassPool.java
+++ b/src/proguard/classfile/ClassPool.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,14 +26,16 @@ import proguard.classfile.visitor.*;
import java.util.*;
/**
- * This is a set of representations of classes. They can be enumerated or
+ * This is a set of representations of classes. They can be enumerated or
* retrieved by name. They can also be accessed by means of class visitors.
*
* @author Eric Lafortune
*/
public class ClassPool
{
- private final Map classes = new HashMap();
+ // We're using a sorted tree map instead of a hash map to store the classes,
+ // in order to make the processing more deterministic.
+ private final Map classes = new TreeMap();
/**
@@ -59,18 +61,27 @@ public class ClassPool
*/
public void removeClass(Clazz clazz)
{
- classes.remove(clazz.getName());
+ removeClass(clazz.getName());
+ }
+
+
+ /**
+ * Removes the specified Clazz from the class pool.
+ */
+ public void removeClass(String className)
+ {
+ classes.remove(className);
}
/**
* Returns a Clazz from the class pool based on its name. Returns
* <code>null</code> if the class with the given name is not in the class
- * pool. Returns the base class if the class name is an array type.
+ * pool.
*/
public Clazz getClass(String className)
{
- return (Clazz)classes.get(ClassUtil.internalClassNameFromClassType(className));
+ return (Clazz)classes.get(className);
}
@@ -122,8 +133,11 @@ public class ClassPool
*/
public void classesAcceptAlphabetically(ClassVisitor classVisitor)
{
- TreeMap sortedClasses = new TreeMap(classes);
- Iterator iterator = sortedClasses.values().iterator();
+ // We're already using a tree map.
+ //TreeMap sortedClasses = new TreeMap(classes);
+ //Iterator iterator = sortedClasses.values().iterator();
+
+ Iterator iterator = classes.values().iterator();
while (iterator.hasNext())
{
Clazz clazz = (Clazz)iterator.next();
diff --git a/src/proguard/classfile/Clazz.java b/src/proguard/classfile/Clazz.java
index da37d9a..35f8a1c 100644
--- a/src/proguard/classfile/Clazz.java
+++ b/src/proguard/classfile/Clazz.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -90,6 +90,16 @@ public interface Clazz extends VisitorAccepter
*/
public String getType(int constantIndex);
+ /**
+ * Returns the name of the RefConstant at the specified index.
+ */
+ public String getRefName(int constantIndex);
+
+ /**
+ * Returns the type of the RefConstant at the specified index.
+ */
+ public String getRefType(int constantIndex);
+
// Methods pertaining to related classes.
@@ -116,12 +126,26 @@ public interface Clazz extends VisitorAccepter
public boolean extends_(Clazz clazz);
/**
+ * Returns whether this class extends the specified class.
+ * A class is always considered to extend itself.
+ * Interfaces are considered to only extend the root Object class.
+ */
+ public boolean extends_(String className);
+
+ /**
* Returns whether this class implements the given class.
* A class is always considered to implement itself.
* Interfaces are considered to implement all their superinterfaces.
*/
public boolean extendsOrImplements(Clazz clazz);
+ /**
+ * Returns whether this class implements the specified class.
+ * A class is always considered to implement itself.
+ * Interfaces are considered to implement all their superinterfaces.
+ */
+ public boolean extendsOrImplements(String className);
+
// Methods for getting specific class members.
@@ -229,4 +253,9 @@ public interface Clazz extends VisitorAccepter
* Lets the given attribute info visitor visit all attributes of this class.
*/
public void attributesAccept(AttributeVisitor attributeVisitor);
+
+ /**
+ * Lets the given attribute info visitor visit the specified attribute.
+ */
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor);
}
diff --git a/src/proguard/classfile/Field.java b/src/proguard/classfile/Field.java
index ba1315a..61bf2da 100644
--- a/src/proguard/classfile/Field.java
+++ b/src/proguard/classfile/Field.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/LibraryClass.java b/src/proguard/classfile/LibraryClass.java
index 0a27593..151a32a 100644
--- a/src/proguard/classfile/LibraryClass.java
+++ b/src/proguard/classfile/LibraryClass.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -137,6 +137,17 @@ public class LibraryClass implements Clazz
}
+ public String getRefName(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getRefType(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+
public void addSubClass(Clazz clazz)
{
if (subClasses == null)
@@ -179,6 +190,18 @@ public class LibraryClass implements Clazz
}
+ public boolean extends_(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ return superClass != null &&
+ superClass.extends_(className);
+ }
+
+
public boolean extendsOrImplements(Clazz clazz)
{
if (this.equals(clazz))
@@ -209,6 +232,36 @@ public class LibraryClass implements Clazz
}
+ public boolean extendsOrImplements(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ if (superClass != null &&
+ superClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+
+ if (interfaceClasses != null)
+ {
+ for (int index = 0; index < interfaceClasses.length; index++)
+ {
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null &&
+ interfaceClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
public Field findField(String name, String descriptor)
{
for (int index = 0; index < fields.length; index++)
@@ -467,6 +520,12 @@ public class LibraryClass implements Clazz
}
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store attributes");
+ }
+
+
// Implementations for VisitorAccepter.
public Object getVisitorInfo()
diff --git a/src/proguard/classfile/LibraryField.java b/src/proguard/classfile/LibraryField.java
index 2908c37..1c1c427 100644
--- a/src/proguard/classfile/LibraryField.java
+++ b/src/proguard/classfile/LibraryField.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/LibraryMember.java b/src/proguard/classfile/LibraryMember.java
index 41ccb60..8d8d00e 100644
--- a/src/proguard/classfile/LibraryMember.java
+++ b/src/proguard/classfile/LibraryMember.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/LibraryMethod.java b/src/proguard/classfile/LibraryMethod.java
index a49a5f1..ac07857 100644
--- a/src/proguard/classfile/LibraryMethod.java
+++ b/src/proguard/classfile/LibraryMethod.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/Member.java b/src/proguard/classfile/Member.java
index 1400b9c..ee2cf19 100644
--- a/src/proguard/classfile/Member.java
+++ b/src/proguard/classfile/Member.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/Method.java b/src/proguard/classfile/Method.java
index ebcae2b..64ff50a 100644
--- a/src/proguard/classfile/Method.java
+++ b/src/proguard/classfile/Method.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/ProgramClass.java b/src/proguard/classfile/ProgramClass.java
index 9d0fc0c..54bb8b1 100644
--- a/src/proguard/classfile/ProgramClass.java
+++ b/src/proguard/classfile/ProgramClass.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -117,8 +117,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- new ClassPrinter().visitProgramClass(this);
- throw new ClassCastException("Expected Utf8Constant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected Utf8Constant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -130,7 +129,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected StringConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected StringConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -142,7 +141,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected ClassConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected ClassConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -154,7 +153,7 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -166,7 +165,32 @@ public class ProgramClass implements Clazz
}
catch (ClassCastException ex)
{
- throw new ClassCastException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
+ throw ((IllegalStateException)new IllegalStateException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+
+ public String getRefName(int constantIndex)
+ {
+ try
+ {
+ return ((RefConstant)constantPool[constantIndex]).getName(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+ public String getRefType(int constantIndex)
+ {
+ try
+ {
+ return ((RefConstant)constantPool[constantIndex]).getType(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
}
}
@@ -216,6 +240,19 @@ public class ProgramClass implements Clazz
}
+ public boolean extends_(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ return superClass != null &&
+ superClass.extends_(className);
+ }
+
+
public boolean extendsOrImplements(Clazz clazz)
{
if (this.equals(clazz))
@@ -244,6 +281,34 @@ public class ProgramClass implements Clazz
}
+ public boolean extendsOrImplements(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ if (superClass != null &&
+ superClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+
+ for (int index = 0; index < u2interfacesCount; index++)
+ {
+ Clazz interfaceClass = getInterface(index);
+ if (interfaceClass != null &&
+ interfaceClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
public Field findField(String name, String descriptor)
{
for (int index = 0; index < u2fieldsCount; index++)
@@ -472,6 +537,19 @@ public class ProgramClass implements Clazz
}
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+ if (attribute.getAttributeName(this).equals(name))
+ {
+ attribute.accept(this, attributeVisitor);
+ }
+ }
+ }
+
+
// Implementations for VisitorAccepter.
public Object getVisitorInfo()
diff --git a/src/proguard/classfile/ProgramField.java b/src/proguard/classfile/ProgramField.java
index 5991b00..3bdfd85 100644
--- a/src/proguard/classfile/ProgramField.java
+++ b/src/proguard/classfile/ProgramField.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/ProgramMember.java b/src/proguard/classfile/ProgramMember.java
index ea6f46d..240d344 100644
--- a/src/proguard/classfile/ProgramMember.java
+++ b/src/proguard/classfile/ProgramMember.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -53,7 +53,7 @@ public abstract class ProgramMember implements Member
/**
- * Creates an initialized ProgramMember.
+ * Creates an initialized ProgramMember.
*/
protected ProgramMember(int u2accessFlags,
int u2nameIndex,
@@ -70,34 +70,6 @@ public abstract class ProgramMember implements Member
/**
- * Returns the line number range of the given class member as "m:n",
- * if it can find it, or <code>null</code> otherwise.
- */
- public String getLineNumberRange(Clazz clazz)
- {
- CodeAttribute codeAttribute =
- (CodeAttribute)getAttribute(clazz, ClassConstants.ATTR_Code);
- if (codeAttribute == null)
- {
- return null;
- }
-
- LineNumberTableAttribute lineNumberTableAttribute =
- (LineNumberTableAttribute)codeAttribute.getAttribute(clazz,
- ClassConstants.ATTR_LineNumberTable);
- if (lineNumberTableAttribute == null)
- {
- return null;
- }
-
- return "" +
- lineNumberTableAttribute.getLineNumber(0) +
- ":" +
- lineNumberTableAttribute.getLineNumber(Integer.MAX_VALUE);
- }
-
-
- /**
* Returns the (first) attribute with the given name.
*/
private Attribute getAttribute(Clazz clazz, String name)
diff --git a/src/proguard/classfile/ProgramMethod.java b/src/proguard/classfile/ProgramMethod.java
index 943c3d6..26f793f 100644
--- a/src/proguard/classfile/ProgramMethod.java
+++ b/src/proguard/classfile/ProgramMethod.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/VisitorAccepter.java b/src/proguard/classfile/VisitorAccepter.java
index e38f888..9c7a062 100644
--- a/src/proguard/classfile/VisitorAccepter.java
+++ b/src/proguard/classfile/VisitorAccepter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/Attribute.java b/src/proguard/classfile/attribute/Attribute.java
index 2e16e22..f34a0ee 100644
--- a/src/proguard/classfile/attribute/Attribute.java
+++ b/src/proguard/classfile/attribute/Attribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/BootstrapMethodInfo.java b/src/proguard/classfile/attribute/BootstrapMethodInfo.java
new file mode 100755
index 0000000..f246766
--- /dev/null
+++ b/src/proguard/classfile/attribute/BootstrapMethodInfo.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * Representation of a bootstrap method.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodInfo implements VisitorAccepter
+{
+ public int u2methodHandleIndex;
+ public int u2methodArgumentCount;
+ public int[] u2methodArguments;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized BootstrapMethodInfo.
+ */
+ public BootstrapMethodInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized BootstrapMethodInfo.
+ */
+ public BootstrapMethodInfo(int u2methodHandleIndex,
+ int u2methodArgumentCount,
+ int[] u2methodArguments)
+ {
+ this.u2methodHandleIndex = u2methodHandleIndex;
+ this.u2methodArgumentCount = u2methodArgumentCount;
+ this.u2methodArguments = u2methodArguments;
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the argument constants of the
+ * bootstrap method.
+ */
+ public void methodArgumentsAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ for (int index = 0; index < u2methodArgumentCount; index++)
+ {
+ clazz.constantPoolEntryAccept(u2methodArguments[index],
+ constantVisitor);
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java b/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java
new file mode 100755
index 0000000..4471a75
--- /dev/null
+++ b/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java
@@ -0,0 +1,95 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Attribute represents a bootstrap methods attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodsAttribute extends Attribute
+{
+ public int u2bootstrapMethodsCount;
+ public BootstrapMethodInfo[] bootstrapMethods;
+
+
+ /**
+ * Creates an uninitialized BootstrapMethodsAttribute.
+ */
+ public BootstrapMethodsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized BootstrapMethodsAttribute.
+ */
+ public BootstrapMethodsAttribute(int u2attributeNameIndex,
+ int u2bootstrapMethodsCount,
+ BootstrapMethodInfo[] bootstrapMethods)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2bootstrapMethodsCount = u2bootstrapMethodsCount;
+ this.bootstrapMethods = bootstrapMethods;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, this);
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to all bootstrap method info
+ * entries.
+ */
+ public void bootstrapMethodEntriesAccept(Clazz clazz, BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ for (int index = 0; index < u2bootstrapMethodsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of BootstrapMethodInfo.
+ bootstrapMethodInfoVisitor.visitBootstrapMethodInfo(clazz, bootstrapMethods[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the specified bootstrap method
+ * info entry.
+ */
+ public void bootstrapMethodEntryAccept(Clazz clazz,
+ int bootstrapMethodIndex,
+ BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of BootstrapMethodInfo.
+ bootstrapMethodInfoVisitor.visitBootstrapMethodInfo(clazz, bootstrapMethods[bootstrapMethodIndex]);
+ }
+}
diff --git a/src/proguard/classfile/attribute/CodeAttribute.java b/src/proguard/classfile/attribute/CodeAttribute.java
index 92ff9ea..b3d4f4c 100644
--- a/src/proguard/classfile/attribute/CodeAttribute.java
+++ b/src/proguard/classfile/attribute/CodeAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/ConstantValueAttribute.java b/src/proguard/classfile/attribute/ConstantValueAttribute.java
index 3ae991e..056e377 100644
--- a/src/proguard/classfile/attribute/ConstantValueAttribute.java
+++ b/src/proguard/classfile/attribute/ConstantValueAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/DeprecatedAttribute.java b/src/proguard/classfile/attribute/DeprecatedAttribute.java
index 4180950..f668063 100644
--- a/src/proguard/classfile/attribute/DeprecatedAttribute.java
+++ b/src/proguard/classfile/attribute/DeprecatedAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/EnclosingMethodAttribute.java b/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
index 9275b3a..1c2ecc4 100644
--- a/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
+++ b/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/ExceptionInfo.java b/src/proguard/classfile/attribute/ExceptionInfo.java
index 082efab..31512e5 100644
--- a/src/proguard/classfile/attribute/ExceptionInfo.java
+++ b/src/proguard/classfile/attribute/ExceptionInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/ExceptionsAttribute.java b/src/proguard/classfile/attribute/ExceptionsAttribute.java
index d22c4a6..ff7b84a 100644
--- a/src/proguard/classfile/attribute/ExceptionsAttribute.java
+++ b/src/proguard/classfile/attribute/ExceptionsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -69,12 +69,12 @@ public class ExceptionsAttribute extends Attribute
* Applies the given constant pool visitor to all exception class pool info
* entries.
*/
- public void exceptionEntriesAccept(ProgramClass programClass, ConstantVisitor constantVisitor)
+ public void exceptionEntriesAccept(Clazz clazz, ConstantVisitor constantVisitor)
{
for (int index = 0; index < u2exceptionIndexTableLength; index++)
{
- programClass.constantPoolEntryAccept(u2exceptionIndexTable[index],
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2exceptionIndexTable[index],
+ constantVisitor);
}
}
}
diff --git a/src/proguard/classfile/attribute/InnerClassesAttribute.java b/src/proguard/classfile/attribute/InnerClassesAttribute.java
index 2f7e310..b08d104 100644
--- a/src/proguard/classfile/attribute/InnerClassesAttribute.java
+++ b/src/proguard/classfile/attribute/InnerClassesAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/InnerClassesInfo.java b/src/proguard/classfile/attribute/InnerClassesInfo.java
index 1bdd6c3..87b9de4 100644
--- a/src/proguard/classfile/attribute/InnerClassesInfo.java
+++ b/src/proguard/classfile/attribute/InnerClassesInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -74,8 +74,7 @@ public class InnerClassesInfo implements VisitorAccepter
{
if (u2innerClassIndex != 0)
{
- clazz.constantPoolEntryAccept(u2innerClassIndex,
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2innerClassIndex, constantVisitor);
}
}
@@ -88,8 +87,7 @@ public class InnerClassesInfo implements VisitorAccepter
{
if (u2outerClassIndex != 0)
{
- clazz.constantPoolEntryAccept(u2outerClassIndex,
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2outerClassIndex, constantVisitor);
}
}
@@ -102,8 +100,7 @@ public class InnerClassesInfo implements VisitorAccepter
{
if (u2innerNameIndex != 0)
{
- clazz.constantPoolEntryAccept(u2innerNameIndex,
- constantVisitor);
+ clazz.constantPoolEntryAccept(u2innerNameIndex, constantVisitor);
}
}
diff --git a/src/proguard/classfile/attribute/LineNumberInfo.java b/src/proguard/classfile/attribute/LineNumberInfo.java
index f58083a..1bcacef 100644
--- a/src/proguard/classfile/attribute/LineNumberInfo.java
+++ b/src/proguard/classfile/attribute/LineNumberInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/LineNumberTableAttribute.java b/src/proguard/classfile/attribute/LineNumberTableAttribute.java
index 4d507d9..c217119 100644
--- a/src/proguard/classfile/attribute/LineNumberTableAttribute.java
+++ b/src/proguard/classfile/attribute/LineNumberTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -77,6 +77,56 @@ public class LineNumberTableAttribute extends Attribute
}
+ /**
+ * Returns the lowest line number, or 0 if there aren't any line numbers.
+ */
+ public int getLowestLineNumber()
+ {
+ if (u2lineNumberTableLength == 0)
+ {
+ return 0;
+ }
+
+ int lowestLineNumber = Integer.MAX_VALUE;
+
+ for (int index = 0; index < u2lineNumberTableLength; index++)
+ {
+ int lineNumber = lineNumberTable[index].u2lineNumber;
+ if (lineNumber < lowestLineNumber)
+ {
+ lowestLineNumber = lineNumber;
+ }
+ }
+
+ return lowestLineNumber;
+ }
+
+
+ /**
+ * Returns the highest line number, or 0 if there aren't any line numbers.
+ */
+ public int getHighestLineNumber()
+ {
+ if (u2lineNumberTableLength == 0)
+ {
+ return 0;
+ }
+
+ int highestLineNumber = Integer.MIN_VALUE;
+
+ for (int index = 0; index < u2lineNumberTableLength; index++)
+ {
+ int lineNumber = lineNumberTable[index].u2lineNumber;
+ if (lineNumber > highestLineNumber)
+ {
+ highestLineNumber = lineNumber;
+ }
+ }
+
+ return highestLineNumber;
+ }
+
+
// Implementations for Attribute.
public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
diff --git a/src/proguard/classfile/attribute/LocalVariableInfo.java b/src/proguard/classfile/attribute/LocalVariableInfo.java
index 4e54c22..00bbd50 100644
--- a/src/proguard/classfile/attribute/LocalVariableInfo.java
+++ b/src/proguard/classfile/attribute/LocalVariableInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,7 +20,7 @@
*/
package proguard.classfile.attribute;
-import proguard.classfile.Clazz;
+import proguard.classfile.*;
import proguard.classfile.visitor.ClassVisitor;
/**
@@ -28,7 +28,7 @@ import proguard.classfile.visitor.ClassVisitor;
*
* @author Eric Lafortune
*/
-public class LocalVariableInfo
+public class LocalVariableInfo implements VisitorAccepter, Comparable
{
public int u2startPC;
public int u2length;
@@ -44,6 +44,11 @@ public class LocalVariableInfo
*/
public Clazz referencedClass;
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
/**
* Creates an uninitialized LocalVariableInfo.
@@ -80,4 +85,33 @@ public class LocalVariableInfo
referencedClass.accept(classVisitor);
}
}
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Comparable.
+
+ public int compareTo(Object object)
+ {
+ LocalVariableInfo other = (LocalVariableInfo)object;
+
+ return
+ this.u2startPC < other.u2startPC ? -1 : this.u2startPC > other.u2startPC ? 1 :
+ this.u2index < other.u2index ? -1 : this.u2index > other.u2index ? 1 :
+ this.u2length < other.u2length ? -1 : this.u2length > other.u2length ? 1 :
+ this.u2descriptorIndex < other.u2descriptorIndex ? -1 : this.u2descriptorIndex > other.u2descriptorIndex ? 1 :
+ this.u2nameIndex < other.u2nameIndex ? -1 : this.u2nameIndex > other.u2nameIndex ? 1 :
+ 0;
+ }
}
diff --git a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
index 9c3f115..9e081c0 100644
--- a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
+++ b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/LocalVariableTypeInfo.java b/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
index 1b71f35..15b9d24 100644
--- a/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
+++ b/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,7 +20,7 @@
*/
package proguard.classfile.attribute;
-import proguard.classfile.Clazz;
+import proguard.classfile.*;
import proguard.classfile.visitor.ClassVisitor;
/**
@@ -28,7 +28,7 @@ import proguard.classfile.visitor.ClassVisitor;
*
* @author Eric Lafortune
*/
-public class LocalVariableTypeInfo
+public class LocalVariableTypeInfo implements VisitorAccepter, Comparable
{
public int u2startPC;
public int u2length;
@@ -45,6 +45,11 @@ public class LocalVariableTypeInfo
*/
public Clazz[] referencedClasses;
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
/**
* Creates an uninitialized LocalVariableTypeInfo.
@@ -88,4 +93,33 @@ public class LocalVariableTypeInfo
}
}
}
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Comparable.
+
+ public int compareTo(Object object)
+ {
+ LocalVariableTypeInfo other = (LocalVariableTypeInfo)object;
+
+ return
+ this.u2startPC < other.u2startPC ? -1 : this.u2startPC > other.u2startPC ? 1 :
+ this.u2length < other.u2length ? -1 : this.u2length > other.u2length ? 1 :
+ this.u2index < other.u2index ? -1 : this.u2index > other.u2index ? 1 :
+ this.u2signatureIndex < other.u2signatureIndex ? -1 : this.u2signatureIndex > other.u2signatureIndex ? 1 :
+ this.u2nameIndex < other.u2nameIndex ? -1 : this.u2nameIndex > other.u2nameIndex ? 1 :
+ 0;
+ }
}
diff --git a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
index fd856fe..dda24fb 100644
--- a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
+++ b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SignatureAttribute.java b/src/proguard/classfile/attribute/SignatureAttribute.java
index c7585fe..86f95b8 100644
--- a/src/proguard/classfile/attribute/SignatureAttribute.java
+++ b/src/proguard/classfile/attribute/SignatureAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SourceDirAttribute.java b/src/proguard/classfile/attribute/SourceDirAttribute.java
index a26e8b1..faa1c79 100644
--- a/src/proguard/classfile/attribute/SourceDirAttribute.java
+++ b/src/proguard/classfile/attribute/SourceDirAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SourceFileAttribute.java b/src/proguard/classfile/attribute/SourceFileAttribute.java
index 24269b7..4abac17 100644
--- a/src/proguard/classfile/attribute/SourceFileAttribute.java
+++ b/src/proguard/classfile/attribute/SourceFileAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/SyntheticAttribute.java b/src/proguard/classfile/attribute/SyntheticAttribute.java
index 6ccb1b5..0135330 100644
--- a/src/proguard/classfile/attribute/SyntheticAttribute.java
+++ b/src/proguard/classfile/attribute/SyntheticAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/UnknownAttribute.java b/src/proguard/classfile/attribute/UnknownAttribute.java
index 2f138bd..182a9e8 100644
--- a/src/proguard/classfile/attribute/UnknownAttribute.java
+++ b/src/proguard/classfile/attribute/UnknownAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/Annotation.java b/src/proguard/classfile/attribute/annotation/Annotation.java
index 41bb8e3..b2f18d5 100644
--- a/src/proguard/classfile/attribute/annotation/Annotation.java
+++ b/src/proguard/classfile/attribute/annotation/Annotation.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
index b378cd2..b8f29cc 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java b/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
index 29129d0..8354f5d 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,7 +64,7 @@ public class AnnotationElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_ANNOTATION;
}
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
index 8117077..a936ff4 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/ArrayElementValue.java b/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
index 25b8b9f..0aab49b 100644
--- a/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -58,7 +58,7 @@ public class ArrayElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_ARRAY;
}
diff --git a/src/proguard/classfile/attribute/annotation/ClassElementValue.java b/src/proguard/classfile/attribute/annotation/ClassElementValue.java
index ba51641..ffeaf71 100644
--- a/src/proguard/classfile/attribute/annotation/ClassElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ClassElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -83,7 +83,7 @@ public class ClassElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_CLASS;
}
diff --git a/src/proguard/classfile/attribute/annotation/ConstantElementValue.java b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
index 3ebe5e5..8be4329 100644
--- a/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -30,14 +30,14 @@ import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
*/
public class ConstantElementValue extends ElementValue
{
- public final int u1tag;
- public int u2constantValueIndex;
+ public final char u1tag;
+ public int u2constantValueIndex;
/**
* Creates an uninitialized ConstantElementValue.
*/
- public ConstantElementValue(int u1tag)
+ public ConstantElementValue(char u1tag)
{
this.u1tag = u1tag;
}
@@ -46,9 +46,9 @@ public class ConstantElementValue extends ElementValue
/**
* Creates an initialized ConstantElementValue.
*/
- public ConstantElementValue(int u1tag,
- int u2elementNameIndex,
- int u2constantValueIndex)
+ public ConstantElementValue(char u1tag,
+ int u2elementNameIndex,
+ int u2constantValueIndex)
{
super(u2elementNameIndex);
@@ -59,7 +59,7 @@ public class ConstantElementValue extends ElementValue
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return u1tag;
}
diff --git a/src/proguard/classfile/attribute/annotation/ElementValue.java b/src/proguard/classfile/attribute/annotation/ElementValue.java
index 39f8953..19a7198 100644
--- a/src/proguard/classfile/attribute/annotation/ElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -90,7 +90,7 @@ public abstract class ElementValue implements VisitorAccepter
/**
* Returns the tag of this element value.
*/
- public abstract int getTag();
+ public abstract char getTag();
/**
diff --git a/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
index d46bb7f..cd0f2f9 100644
--- a/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,7 +22,7 @@ package proguard.classfile.attribute.annotation;
import proguard.classfile.*;
import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
-import proguard.classfile.visitor.ClassVisitor;
+import proguard.classfile.visitor.*;
/**
* This ElementValue represents an enumeration constant element value.
@@ -43,6 +43,14 @@ public class EnumConstantElementValue extends ElementValue
*/
public Clazz[] referencedClasses;
+ /**
+ * An extra field optionally pointing to the referenced enum Field object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Field referencedField;
+
/**
* Creates an uninitialized EnumConstantElementValue.
@@ -67,6 +75,24 @@ public class EnumConstantElementValue extends ElementValue
/**
+ * Returns the enumeration type name.
+ */
+ public String getTypeName(Clazz clazz)
+ {
+ return clazz.getString(u2typeNameIndex);
+ }
+
+
+ /**
+ * Returns the constant name.
+ */
+ public String getConstantName(Clazz clazz)
+ {
+ return clazz.getString(u2constantNameIndex);
+ }
+
+
+ /**
* Applies the given visitor to all referenced classes.
*/
public void referencedClassesAccept(ClassVisitor classVisitor)
@@ -85,9 +111,22 @@ public class EnumConstantElementValue extends ElementValue
}
+ /**
+ * Applies the given visitor to the referenced field.
+ */
+ public void referencedFieldAccept(MemberVisitor memberVisitor)
+ {
+ if (referencedField != null)
+ {
+ referencedField.accept(referencedClasses[0],
+ memberVisitor);
+ }
+ }
+
+
// Implementations for ElementValue.
- public int getTag()
+ public char getTag()
{
return ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT;
}
diff --git a/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
index 3c700c8..ddaa3a6 100644
--- a/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
index 9c8180c..deda8a5 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
index 7e41656..2fcae88 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
index 380c52e..da94f0c 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
index 626fbda..caa6830 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
index bce7170..0aadfe3 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,6 +39,11 @@ implements AttributeVisitor
private final AnnotationVisitor annotationVisitor;
+ /**
+ * Creates a new AllAnnotationVisitor.
+ * @param annotationVisitor the AnnotationVisitor to which visits will be
+ * delegated.
+ */
public AllAnnotationVisitor(AnnotationVisitor annotationVisitor)
{
this.annotationVisitor = annotationVisitor;
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java
new file mode 100644
index 0000000..b728b8b
--- /dev/null
+++ b/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java
@@ -0,0 +1,201 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.util.*;
+
+/**
+ * This AttributeVisitor and AnnotationVisitor lets a given ElementValueVisitor
+ * visit all ElementValue objects of the attributes or annotations that it
+ * visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllElementValueVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private final boolean deep;
+ private final ElementValueVisitor elementValueVisitor;
+
+
+ /**
+ * Creates a new AllElementValueVisitor.
+ * @param elementValueVisitor the AllElementValueVisitor to which visits
+ * will be delegated.
+ */
+ public AllElementValueVisitor(ElementValueVisitor elementValueVisitor)
+ {
+ this(false, elementValueVisitor);
+ }
+
+
+ /**
+ * Creates a new AllElementValueVisitor.
+ * @param deep specifies whether the element values
+ * further down the hierarchy should be
+ * visited too.
+ * @param elementValueVisitor the AllElementValueVisitor to which visits
+ * will be delegated.
+ */
+ public AllElementValueVisitor(boolean deep,
+ ElementValueVisitor elementValueVisitor)
+ {
+ this.deep = deep;
+ this.elementValueVisitor = elementValueVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, field, this);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, field, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Visit the default element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Field field, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ elementValueVisitor.visitConstantElementValue(clazz, annotation, constantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ elementValueVisitor.visitEnumConstantElementValue(clazz, annotation, enumConstantElementValue);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ elementValueVisitor.visitClassElementValue(clazz, annotation, classElementValue);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ elementValueVisitor.visitAnnotationElementValue(clazz, annotation, annotationElementValue);
+
+ if (deep)
+ {
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ elementValueVisitor.visitArrayElementValue(clazz, annotation, arrayElementValue);
+
+ if (deep)
+ {
+ arrayElementValue.elementValuesAccept(clazz, annotation, elementValueVisitor);
+ }
+ }
+}
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
index 7a1d7c6..305928e 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
index c206c16..7833f7e 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
index d869fd2..d6ec3ca 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -33,7 +33,6 @@ import proguard.util.*;
* @author Eric Lafortune
*/
public class AnnotationTypeFilter
-extends SimplifiedVisitor
implements AnnotationVisitor
{
private final StringMatcher regularExpressionMatcher;
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
index 16b2a56..8d207af 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
index 112084a..2d3a20d 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/DoubleType.java b/src/proguard/classfile/attribute/preverification/DoubleType.java
index d574dcb..1bc3e5d 100644
--- a/src/proguard/classfile/attribute/preverification/DoubleType.java
+++ b/src/proguard/classfile/attribute/preverification/DoubleType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/FloatType.java b/src/proguard/classfile/attribute/preverification/FloatType.java
index 2f24720..c58cd0a 100644
--- a/src/proguard/classfile/attribute/preverification/FloatType.java
+++ b/src/proguard/classfile/attribute/preverification/FloatType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/FullFrame.java b/src/proguard/classfile/attribute/preverification/FullFrame.java
index adf5684..4f0d72e 100644
--- a/src/proguard/classfile/attribute/preverification/FullFrame.java
+++ b/src/proguard/classfile/attribute/preverification/FullFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/IntegerType.java b/src/proguard/classfile/attribute/preverification/IntegerType.java
index 55e3abe..9c43cae 100644
--- a/src/proguard/classfile/attribute/preverification/IntegerType.java
+++ b/src/proguard/classfile/attribute/preverification/IntegerType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/LessZeroFrame.java b/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
index fcc8e0a..f722d73 100644
--- a/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/LongType.java b/src/proguard/classfile/attribute/preverification/LongType.java
index 9b14dd6..c986165 100644
--- a/src/proguard/classfile/attribute/preverification/LongType.java
+++ b/src/proguard/classfile/attribute/preverification/LongType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java b/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
index 881f188..be74df0 100644
--- a/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/NullType.java b/src/proguard/classfile/attribute/preverification/NullType.java
index f35cefd..fe0d85f 100644
--- a/src/proguard/classfile/attribute/preverification/NullType.java
+++ b/src/proguard/classfile/attribute/preverification/NullType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/ObjectType.java b/src/proguard/classfile/attribute/preverification/ObjectType.java
index fbdeec7..4ea370a 100644
--- a/src/proguard/classfile/attribute/preverification/ObjectType.java
+++ b/src/proguard/classfile/attribute/preverification/ObjectType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/SameOneFrame.java b/src/proguard/classfile/attribute/preverification/SameOneFrame.java
index db6747b..4384aae 100644
--- a/src/proguard/classfile/attribute/preverification/SameOneFrame.java
+++ b/src/proguard/classfile/attribute/preverification/SameOneFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/SameZeroFrame.java b/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
index 64b17f5..a3bd824 100644
--- a/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/StackMapAttribute.java b/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
index db53ff1..51e69fb 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/StackMapFrame.java b/src/proguard/classfile/attribute/preverification/StackMapFrame.java
index aa3e1f2..01890f3 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapFrame.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapFrame.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java b/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
index 0cddf70..3de059f 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/TopType.java b/src/proguard/classfile/attribute/preverification/TopType.java
index bde8dda..02dd1a2 100644
--- a/src/proguard/classfile/attribute/preverification/TopType.java
+++ b/src/proguard/classfile/attribute/preverification/TopType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/UninitializedThisType.java b/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
index dc4654f..7b2bfa9 100644
--- a/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
+++ b/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/UninitializedType.java b/src/proguard/classfile/attribute/preverification/UninitializedType.java
index a495f1f..7e4a0fd 100644
--- a/src/proguard/classfile/attribute/preverification/UninitializedType.java
+++ b/src/proguard/classfile/attribute/preverification/UninitializedType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/VerificationType.java b/src/proguard/classfile/attribute/preverification/VerificationType.java
index f33d511..02c3872 100644
--- a/src/proguard/classfile/attribute/preverification/VerificationType.java
+++ b/src/proguard/classfile/attribute/preverification/VerificationType.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java b/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
index f8ef7e0..ada9ce8 100644
--- a/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
+++ b/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java b/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
index 7db246c..5e4cf88 100644
--- a/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
+++ b/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java b/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
index e9931f8..2a3e9e7 100644
--- a/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
+++ b/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
index 61b0f1a..9d8801c 100644
--- a/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java b/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java
new file mode 100644
index 0000000..d70803c
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given BootstrapMethodInfoVisitor visit all
+ * bootstrap method objects of the BootstrapMethodsAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllBootstrapMethodInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor;
+
+
+ public AllBootstrapMethodInfoVisitor(BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ this.bootstrapMethodInfoVisitor = bootstrapMethodInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, bootstrapMethodInfoVisitor);
+ }
+}
diff --git a/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
index 839e104..927bfd9 100644
--- a/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java b/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java
new file mode 100644
index 0000000..2422218
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given InnerClassesInfoVisitor visit all
+ * InnerClassessInfo objects of the InnerClassesAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllInnerClassesInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final InnerClassesInfoVisitor innerClassesInfoVisitor;
+
+
+ public AllInnerClassesInfoVisitor(InnerClassesInfoVisitor innerClassesInfoVisitor)
+ {
+ this.innerClassesInfoVisitor = innerClassesInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ innerClassesAttribute.innerClassEntriesAccept(clazz, innerClassesInfoVisitor);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
index aa81ce0..0db77d5 100644
--- a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
+++ b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,34 +24,66 @@ import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
import proguard.classfile.attribute.preverification.*;
-import proguard.util.StringMatcher;
+import proguard.util.*;
+
+import java.util.List;
/**
* This AttributeVisitor delegates its visits another AttributeVisitor, but
- * only when the visited attribute has a name that passes a given string
- * matcher.
+ * only when the visited attribute has a name that that matches a given regular
+ * expression.
*
* @author Eric Lafortune
*/
public class AttributeNameFilter
implements AttributeVisitor
{
- private final StringMatcher stringMatcher;
+ private final StringMatcher regularExpressionMatcher;
private final AttributeVisitor attributeVisitor;
/**
* Creates a new AttributeNameFilter.
- * @param stringMatcher the string matcher that will check the attribute
- * names.
- * @param attributeVisitor the <code>AttributeVisitor</code> to which
- * visits will be delegated.
+ * @param regularExpression the regular expression against which attribute
+ * names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
+ */
+ public AttributeNameFilter(String regularExpression,
+ AttributeVisitor attributeVisitor)
+ {
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ attributeVisitor);
+ }
+
+
+ /**
+ * Creates a new AttributeNameFilter.
+ * @param regularExpression the regular expression against which attribute
+ * names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
*/
- public AttributeNameFilter(StringMatcher stringMatcher,
+ public AttributeNameFilter(List regularExpression,
AttributeVisitor attributeVisitor)
{
- this.stringMatcher = stringMatcher;
- this.attributeVisitor = attributeVisitor;
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ attributeVisitor);
+ }
+
+
+ /**
+ * Creates a new AttributeNameFilter.
+ * @param regularExpressionMatcher the string matcher against which
+ * attribute names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to
+ * which visits will be delegated.
+ */
+ public AttributeNameFilter(StringMatcher regularExpressionMatcher,
+ AttributeVisitor attributeVisitor)
+ {
+ this.regularExpressionMatcher = regularExpressionMatcher;
+ this.attributeVisitor = attributeVisitor;
}
@@ -66,6 +98,15 @@ implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (accepted(clazz, bootstrapMethodsAttribute))
+ {
+ bootstrapMethodsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
if (accepted(clazz, sourceFileAttribute))
@@ -340,6 +381,6 @@ implements AttributeVisitor
private boolean accepted(Clazz clazz, Attribute attribute)
{
- return stringMatcher.matches(attribute.getAttributeName(clazz));
+ return regularExpressionMatcher.matches(attribute.getAttributeName(clazz));
}
}
diff --git a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
index e8f226b..76c1ab9 100644
--- a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -35,11 +35,12 @@ public interface AttributeVisitor
{
// Attributes that are attached to classes.
- public void visitUnknownAttribute( Clazz clazz, UnknownAttribute unknownAttribute);
- public void visitSourceFileAttribute( Clazz clazz, SourceFileAttribute sourceFileAttribute);
- public void visitSourceDirAttribute( Clazz clazz, SourceDirAttribute sourceDirAttribute);
- public void visitInnerClassesAttribute( Clazz clazz, InnerClassesAttribute innerClassesAttribute);
- public void visitEnclosingMethodAttribute( Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute);
+ public void visitUnknownAttribute( Clazz clazz, UnknownAttribute unknownAttribute);
+ public void visitBootstrapMethodsAttribute( Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute);
+ public void visitSourceFileAttribute( Clazz clazz, SourceFileAttribute sourceFileAttribute);
+ public void visitSourceDirAttribute( Clazz clazz, SourceDirAttribute sourceDirAttribute);
+ public void visitInnerClassesAttribute( Clazz clazz, InnerClassesAttribute innerClassesAttribute);
+ public void visitEnclosingMethodAttribute( Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute);
// Attributes that are attached to classes, fields, and methods.
diff --git a/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java b/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java
new file mode 100755
index 0000000..9aab92e
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java
@@ -0,0 +1,40 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+import java.beans.MethodDescriptor;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>BootstrapMethodInfo</code> objects. Note that there is only a single
+ * implementation of <code>BootstrapMethodInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface BootstrapMethodInfoVisitor
+{
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo);
+}
diff --git a/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
index 7c85e53..4a765f2 100644
--- a/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java b/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
index 91267b0..b373493 100644
--- a/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
index e59ed7b..189b3d0 100644
--- a/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
index 8647cb3..c888d63 100644
--- a/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
index 9ad38e0..f992e6d 100644
--- a/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java b/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
index 870ba94..37c0639 100644
--- a/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -85,6 +85,15 @@ public class MultiAttributeVisitor implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
for (int index = 0; index < attributeVisitors.length; index++)
diff --git a/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java b/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java
new file mode 100644
index 0000000..2ccc09c
--- /dev/null
+++ b/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java
@@ -0,0 +1,293 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.util.StringMatcher;
+
+/**
+ * This AttributeVisitor delegates its visits another AttributeVisitor, but
+ * only when the visited attribute is not empty. For instance, a local variable
+ * table without variables is empty.
+ *
+ * @author Eric Lafortune
+ */
+public class NonEmptyAttributeFilter
+implements AttributeVisitor
+{
+ private final AttributeVisitor attributeVisitor;
+
+
+ /**
+ * Creates a new NonEmptyAttributeFilter.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
+ */
+ public NonEmptyAttributeFilter(AttributeVisitor attributeVisitor)
+ {
+ this.attributeVisitor = attributeVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ unknownAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (bootstrapMethodsAttribute.u2bootstrapMethodsCount > 0)
+ {
+ bootstrapMethodsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ sourceFileAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ sourceDirAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ if (innerClassesAttribute.u2classesCount > 0)
+ {
+ innerClassesAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ enclosingMethodAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ deprecatedAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ deprecatedAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ deprecatedAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ syntheticAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ syntheticAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ syntheticAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.accept(clazz, attributeVisitor);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ constantValueAttribute.accept(clazz, field, attributeVisitor);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ if (exceptionsAttribute.u2exceptionIndexTableLength > 0)
+ {
+ exceptionsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.accept(clazz, method, attributeVisitor);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ if (stackMapAttribute.u2stackMapFramesCount > 0)
+ {
+ stackMapAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ if (stackMapTableAttribute.u2stackMapFramesCount > 0)
+ {
+ stackMapTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ if (lineNumberTableAttribute.u2lineNumberTableLength > 0)
+ {
+ lineNumberTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (localVariableTableAttribute.u2localVariableTableLength > 0)
+ {
+ localVariableTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (localVariableTypeTableAttribute.u2localVariableTypeTableLength > 0)
+ {
+ localVariableTypeTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeVisibleAnnotationsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeVisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeVisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeInvisibleAnnotationsAttribute.accept(clazz, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeInvisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ runtimeInvisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ if (runtimeVisibleParameterAnnotationsAttribute.u2parametersCount > 0)
+ {
+ runtimeVisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ if (runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount > 0)
+ {
+ runtimeInvisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor);
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ annotationDefaultAttribute.accept(clazz, method, attributeVisitor);
+ }
+}
diff --git a/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
index 92099f9..58e4e40 100644
--- a/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
+++ b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,6 +31,8 @@ import proguard.obfuscate.AttributeShrinker;
* AttributeVisitor instances, depending on whether the visited attribute
* is strictly required or not.
*
+ * Stack map attributes and stack map table attributes are treated as optional.
+ *
* @see AttributeShrinker
*
* @author Eric Lafortune
@@ -80,6 +82,15 @@ implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (requiredAttributeVisitor != null)
+ {
+ bootstrapMethodsAttribute.accept(clazz, requiredAttributeVisitor);
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
if (optionalAttributeVisitor != null)
@@ -235,9 +246,9 @@ implements AttributeVisitor
public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
{
- if (requiredAttributeVisitor != null)
+ if (optionalAttributeVisitor != null)
{
- stackMapTableAttribute.accept(clazz, method, codeAttribute, requiredAttributeVisitor);
+ stackMapTableAttribute.accept(clazz, method, codeAttribute, optionalAttributeVisitor);
}
}
diff --git a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
index 401f188..b5e02e2 100644
--- a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
+++ b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor computes the stack sizes at all instruction offsets
* of the code attributes that it visits.
@@ -140,10 +142,7 @@ implements AttributeVisitor,
}
else
{
- for (int index = 0; index < codeLength; index++)
- {
- evaluated[index] = false;
- }
+ Arrays.fill(evaluated, 0, codeLength, false);
}
// The initial stack is always empty.
diff --git a/src/proguard/classfile/constant/ClassConstant.java b/src/proguard/classfile/constant/ClassConstant.java
index d217bf6..bbd9b31 100644
--- a/src/proguard/classfile/constant/ClassConstant.java
+++ b/src/proguard/classfile/constant/ClassConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/Constant.java b/src/proguard/classfile/constant/Constant.java
index 30ce5df..b4168ce 100644
--- a/src/proguard/classfile/constant/Constant.java
+++ b/src/proguard/classfile/constant/Constant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/DoubleConstant.java b/src/proguard/classfile/constant/DoubleConstant.java
index 61779b5..a4c64cf 100644
--- a/src/proguard/classfile/constant/DoubleConstant.java
+++ b/src/proguard/classfile/constant/DoubleConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/FieldrefConstant.java b/src/proguard/classfile/constant/FieldrefConstant.java
index d4afce5..d552d47 100644
--- a/src/proguard/classfile/constant/FieldrefConstant.java
+++ b/src/proguard/classfile/constant/FieldrefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/FloatConstant.java b/src/proguard/classfile/constant/FloatConstant.java
index 578f567..1709fcb 100644
--- a/src/proguard/classfile/constant/FloatConstant.java
+++ b/src/proguard/classfile/constant/FloatConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/IntegerConstant.java b/src/proguard/classfile/constant/IntegerConstant.java
index 8a476c6..5f0d7f9 100644
--- a/src/proguard/classfile/constant/IntegerConstant.java
+++ b/src/proguard/classfile/constant/IntegerConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/InterfaceMethodrefConstant.java b/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
index ddee42f..52f1852 100644
--- a/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
+++ b/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/InvokeDynamicConstant.java b/src/proguard/classfile/constant/InvokeDynamicConstant.java
new file mode 100755
index 0000000..57474aa
--- /dev/null
+++ b/src/proguard/classfile/constant/InvokeDynamicConstant.java
@@ -0,0 +1,148 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This Constant represents an invoke dynamic constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class InvokeDynamicConstant extends Constant
+{
+ public int u2bootstrapMethodAttributeIndex;
+ public int u2nameAndTypeIndex;
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * descriptor string. This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized InvokeDynamicConstant.
+ */
+ public InvokeDynamicConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new InvokeDynamicConstant with the given bootstrap method
+ * and name-and-type indices.
+ * @param u2bootstrapMethodAttributeIndex the index of the bootstrap method
+ * entry in the bootstrap methods
+ * attribute.
+ * @param u2nameAndTypeIndex the index of the name and type
+ * entry in the constant pool.
+ * @param referencedClasses the classes referenced by the
+ * type.
+ */
+ public InvokeDynamicConstant(int u2bootstrapMethodAttributeIndex,
+ int u2nameAndTypeIndex,
+ Clazz[] referencedClasses)
+ {
+ this.u2bootstrapMethodAttributeIndex = u2bootstrapMethodAttributeIndex;
+ this.u2nameAndTypeIndex = u2nameAndTypeIndex;
+ this.referencedClasses = referencedClasses;
+ }
+
+
+ /**
+ * Returns the index of the bootstrap method in the bootstrap methods
+ * attribute of the class.
+ */
+ public int getBootstrapMethodAttributeIndex()
+ {
+ return u2bootstrapMethodAttributeIndex;
+ }
+
+ /**
+ * Returns the name-and-type index.
+ */
+ public int getNameAndTypeIndex()
+ {
+ return u2nameAndTypeIndex;
+ }
+
+ /**
+ * Returns the method name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getName(u2nameAndTypeIndex);
+ }
+
+ /**
+ * Returns the method type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getType(u2nameAndTypeIndex);
+ }
+
+
+ /**
+ * Lets the Clazz objects referenced in the descriptor string
+ * accept the given visitor.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Lets the bootstrap method handle constant accept the given visitor.
+ */
+ public void bootstrapMethodHandleAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ new BootstrapMethodHandleTraveler(constantVisitor).visitInvokeDynamicConstant(clazz, this);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_InvokeDynamic;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitInvokeDynamicConstant(clazz, this);
+ }
+}
diff --git a/src/proguard/classfile/constant/LongConstant.java b/src/proguard/classfile/constant/LongConstant.java
index ea66e07..2416f01 100644
--- a/src/proguard/classfile/constant/LongConstant.java
+++ b/src/proguard/classfile/constant/LongConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/MethodHandleConstant.java b/src/proguard/classfile/constant/MethodHandleConstant.java
new file mode 100755
index 0000000..6cffd9a
--- /dev/null
+++ b/src/proguard/classfile/constant/MethodHandleConstant.java
@@ -0,0 +1,124 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a method handle constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodHandleConstant extends Constant
+{
+ public int u1referenceKind;
+ public int u2referenceIndex;
+
+
+ /**
+ * An extra field pointing to the java.lang.invoke.MethodHandle Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>..
+ */
+ public Clazz javaLangInvokeMethodHandleClass;
+
+
+ /**
+ * Creates an uninitialized MethodHandleConstant.
+ */
+ public MethodHandleConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new MethodHandleConstant with the given type and method ref
+ * index.
+ * @param u1referenceKind the reference kind.
+ * @param u2referenceIndex the index of the field ref constant, interface
+ * method ref constant, or method ref constant in
+ * the constant pool.
+ */
+ public MethodHandleConstant(int u1referenceKind, int u2referenceIndex)
+ {
+ this.u1referenceKind = u1referenceKind;
+ this.u2referenceIndex = u2referenceIndex;
+ }
+
+
+ /**
+ * Returns the kind of reference to which this constant is pointing.
+ * @return One of
+ * {@link ClassConstants#REF_getField },
+ * {@link ClassConstants#REF_getStatic },
+ * {@link ClassConstants#REF_putField },
+ * {@link ClassConstants#REF_putStatic },
+ * {@link ClassConstants#REF_invokeVirtual },
+ * {@link ClassConstants#REF_invokeStatic },
+ * {@link ClassConstants#REF_invokeSpecial },
+ * {@link ClassConstants#REF_newInvokeSpecial}, or
+ * {@link ClassConstants#REF_invokeInterface }.
+ */
+ public int getReferenceKind()
+ {
+ return u1referenceKind;
+ }
+
+ /**
+ * Returns the field ref, interface method ref, or method ref index.
+ */
+ public int getReferenceIndex()
+ {
+ return u2referenceIndex;
+ }
+
+
+ /**
+ * Returns the method/field name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getRefName(u2referenceIndex);
+ }
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getRefType(u2referenceIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_MethodHandle;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitMethodHandleConstant(clazz, this);
+ }
+}
diff --git a/src/proguard/classfile/constant/MethodTypeConstant.java b/src/proguard/classfile/constant/MethodTypeConstant.java
new file mode 100644
index 0000000..96c136f
--- /dev/null
+++ b/src/proguard/classfile/constant/MethodTypeConstant.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a method handle constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodTypeConstant extends Constant
+{
+ public int u2descriptorIndex;
+
+
+ /**
+ * An extra field pointing to the java.lang.invoke.MethodType Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>..
+ */
+ public Clazz javaLangInvokeMethodTypeClass;
+
+
+ /**
+ * Creates an uninitialized MethodTypeConstant.
+ */
+ public MethodTypeConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new MethodTypeConstant with the given descriptor index.
+ * @param u2descriptorIndex the index of the descriptor in the constant
+ * pool.
+ */
+ public MethodTypeConstant(int u2descriptorIndex)
+ {
+ this.u2descriptorIndex = u2descriptorIndex;
+ }
+
+
+ /**
+ * Returns the descriptor index.
+ */
+ public int getDescriptorIndex()
+ {
+ return u2descriptorIndex;
+ }
+
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getString(u2descriptorIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_MethodType;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitMethodTypeConstant(clazz, this);
+ }
+}
diff --git a/src/proguard/classfile/constant/MethodrefConstant.java b/src/proguard/classfile/constant/MethodrefConstant.java
index 858eec9..1ffa236 100644
--- a/src/proguard/classfile/constant/MethodrefConstant.java
+++ b/src/proguard/classfile/constant/MethodrefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/NameAndTypeConstant.java b/src/proguard/classfile/constant/NameAndTypeConstant.java
index e83d2f1..2a4dd66 100644
--- a/src/proguard/classfile/constant/NameAndTypeConstant.java
+++ b/src/proguard/classfile/constant/NameAndTypeConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/RefConstant.java b/src/proguard/classfile/constant/RefConstant.java
index 4e4d019..0a8fb78 100644
--- a/src/proguard/classfile/constant/RefConstant.java
+++ b/src/proguard/classfile/constant/RefConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/StringConstant.java b/src/proguard/classfile/constant/StringConstant.java
index 9a8d453..9b83745 100644
--- a/src/proguard/classfile/constant/StringConstant.java
+++ b/src/proguard/classfile/constant/StringConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/Utf8Constant.java b/src/proguard/classfile/constant/Utf8Constant.java
index ae419c9..3707ba9 100644
--- a/src/proguard/classfile/constant/Utf8Constant.java
+++ b/src/proguard/classfile/constant/Utf8Constant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java b/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
index d2d3c2c..3c36609 100644
--- a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
+++ b/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java b/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java
new file mode 100644
index 0000000..6dce6c5
--- /dev/null
+++ b/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java
@@ -0,0 +1,100 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+import proguard.optimize.info.MethodOptimizationInfo;
+
+/**
+ * This ConstantVisitor and BootstrapMethodInfoVisitor travels from any invoke
+ * dynamic constants or bootstrap method info entries that it visits to their
+ * bootstrap method handle constants, and applies a given constant visitor.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodHandleTraveler
+extends SimplifiedVisitor
+implements ConstantVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor
+{
+ private ConstantVisitor bootstrapMethodHandleVisitor;
+
+ // Field serving as a method argument.
+ int bootstrapMethodAttributeIndex;
+
+
+ /**
+ * Creates a new BootstrapMethodHandleVisitor that will delegate to the
+ * given constant visitor.
+ */
+ public BootstrapMethodHandleTraveler(ConstantVisitor bootstrapMethodHandleVisitor)
+ {
+ this.bootstrapMethodHandleVisitor = bootstrapMethodHandleVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Pass the method index.
+ bootstrapMethodAttributeIndex =
+ invokeDynamicConstant.u2bootstrapMethodAttributeIndex;
+
+ // Delegate to the bootstrap method.
+ clazz.attributesAccept(this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Check bootstrap methods.
+ bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
+ bootstrapMethodAttributeIndex,
+ this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Check bootstrap method.
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex,
+ bootstrapMethodHandleVisitor);
+ }
+}
diff --git a/src/proguard/classfile/constant/visitor/ConstantTagFilter.java b/src/proguard/classfile/constant/visitor/ConstantTagFilter.java
new file mode 100644
index 0000000..a3fcc8a
--- /dev/null
+++ b/src/proguard/classfile/constant/visitor/ConstantTagFilter.java
@@ -0,0 +1,86 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>ConstantVisitor</code> delegates its visits to one or more
+ * specified types of constants.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantTagFilter
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final int constantTagMask;
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new ConstantTagFilter.
+ * @param constantTag the type of constants for which visits will be
+ * delegated.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ConstantTagFilter(int constantTag,
+ ConstantVisitor constantVisitor)
+ {
+ this.constantTagMask = 1 << constantTag;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ /**
+ * Creates a new ConstantTagFilter.
+ * @param constantTags the types of constants for which visits will be
+ * delegated.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ConstantTagFilter(int[] constantTags,
+ ConstantVisitor constantVisitor)
+ {
+ int constantTagMask = 0;
+ for (int index = 0; index < constantTags.length; index++)
+ {
+ constantTagMask |= 1 << constantTags[index];
+ }
+
+ this.constantTagMask = constantTagMask;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ if (((1 << constant.getTag()) & constantTagMask) != 0)
+ {
+ constant.accept(clazz, constantVisitor);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/constant/visitor/ConstantVisitor.java b/src/proguard/classfile/constant/visitor/ConstantVisitor.java
index 6cae352..362d54d 100644
--- a/src/proguard/classfile/constant/visitor/ConstantVisitor.java
+++ b/src/proguard/classfile/constant/visitor/ConstantVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -38,9 +38,12 @@ public interface ConstantVisitor
public void visitDoubleConstant( Clazz clazz, DoubleConstant doubleConstant);
public void visitStringConstant( Clazz clazz, StringConstant stringConstant);
public void visitUtf8Constant( Clazz clazz, Utf8Constant utf8Constant);
+ public void visitInvokeDynamicConstant( Clazz clazz, InvokeDynamicConstant invokeDynamicConstant);
+ public void visitMethodHandleConstant( Clazz clazz, MethodHandleConstant methodHandleConstant);
public void visitFieldrefConstant( Clazz clazz, FieldrefConstant fieldrefConstant);
public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant);
public void visitMethodrefConstant( Clazz clazz, MethodrefConstant methodrefConstant);
public void visitClassConstant( Clazz clazz, ClassConstant classConstant);
+ public void visitMethodTypeConstant( Clazz clazz, MethodTypeConstant methodTypeConstant);
public void visitNameAndTypeConstant( Clazz clazz, NameAndTypeConstant nameAndTypeConstant);
}
diff --git a/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
index fbb3e52..bff4d1e 100644
--- a/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
+++ b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -44,16 +44,16 @@ implements ConstantVisitor
/**
- * Creates a new ClassNameFilter.
+ * Creates a new ExceptClassConstantFilter.
* @param exceptClassName the name of the class that will not be visited.
* @param constantVisitor the <code>ConstantVisitor</code> to which visits
* will be delegated.
*/
- public ExceptClassConstantFilter(String exceptClassName,
- ConstantVisitor constantVisitor)
+ public ExceptClassConstantFilter(String exceptClassName,
+ ConstantVisitor constantVisitor)
{
- this.exceptClassName = exceptClassName;
- this.constantVisitor = constantVisitor;
+ this.exceptClassName = exceptClassName;
+ this.constantVisitor = constantVisitor;
}
diff --git a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java b/src/proguard/classfile/constant/visitor/MethodrefTraveler.java
index ee028f8..acd1bc8 100644
--- a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java
+++ b/src/proguard/classfile/constant/visitor/MethodrefTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,38 +18,32 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package proguard.classfile.visitor;
+package proguard.classfile.constant.visitor;
import proguard.classfile.Clazz;
+import proguard.classfile.attribute.*;
import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.SimplifiedVisitor;
-
/**
- * This ConstantVisitor lets a given <code>ClassVisitor</code> visit all
- * constant classes involved in any <code>Class.forName</code> constructs that
- * it visits.
- *
- * @see DotClassClassVisitor
+ * This ConstantVisitor travels from any method handle constants that it visits
+ * to their methodref constants, and applies a given constant visitor.
*
* @author Eric Lafortune
*/
-public class ClassForNameClassVisitor
+public class MethodrefTraveler
extends SimplifiedVisitor
implements ConstantVisitor
{
- private final ClassVisitor classVisitor;
+ private ConstantVisitor methodrefConstantVisitor;
/**
- * Creates a new ClassHierarchyTraveler.
- * @param classVisitor the <code>ClassVisitor</code> to which visits will
- * be delegated.
+ * Creates a new v that will delegate to the given constant visitor.
*/
- public ClassForNameClassVisitor(ClassVisitor classVisitor)
+ public MethodrefTraveler(ConstantVisitor methodrefConstantVisitor)
{
- this.classVisitor = classVisitor;
+ this.methodrefConstantVisitor = methodrefConstantVisitor;
}
@@ -58,9 +52,9 @@ implements ConstantVisitor
public void visitAnyConstant(Clazz clazz, Constant constant) {}
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
{
- // Visit the referenced class from the Class.forName construct, if any.
- stringConstant.referencedClassAccept(classVisitor);
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex,
+ methodrefConstantVisitor);
}
}
diff --git a/src/proguard/classfile/editor/AccessFixer.java b/src/proguard/classfile/editor/AccessFixer.java
index 7d6274e..d770531 100644
--- a/src/proguard/classfile/editor/AccessFixer.java
+++ b/src/proguard/classfile/editor/AccessFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,8 @@
package proguard.classfile.editor;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.*;
@@ -61,12 +63,26 @@ implements ConstantVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Check the bootstrap method.
+ invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the method reference.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
referencingClass = clazz;
// Remember the specified class, since it might be different from
- // the referenced class that acutally contains the class member.
+ // the referenced class that actually contains the class member.
clazz.constantPoolEntryAccept(refConstant.u2classIndex, referencedClassFinder);
// Make sure the access flags of the referenced class member are
@@ -91,8 +107,8 @@ implements ConstantVisitor,
public void visitProgramClass(ProgramClass programClass)
{
- int currentAccessFlags = programClass.getAccessFlags();
- int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
+ int currentAccessFlags = programClass.getAccessFlags();
+ int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
// Compute the required access level.
Clazz referencingClass = this.referencingClass;
@@ -117,8 +133,8 @@ implements ConstantVisitor,
public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
{
- int currentAccessFlags = programMember.getAccessFlags();
- int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
+ int currentAccessFlags = programMember.getAccessFlags();
+ int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
// Compute the required access level.
int requiredAccessLevel =
diff --git a/src/proguard/classfile/editor/AnnotationAdder.java b/src/proguard/classfile/editor/AnnotationAdder.java
index 359164a..0389ab1 100644
--- a/src/proguard/classfile/editor/AnnotationAdder.java
+++ b/src/proguard/classfile/editor/AnnotationAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
index bf8852c..a175c33 100644
--- a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
+++ b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/AttributeAdder.java b/src/proguard/classfile/editor/AttributeAdder.java
index 2b610b7..ad4ecc0 100644
--- a/src/proguard/classfile/editor/AttributeAdder.java
+++ b/src/proguard/classfile/editor/AttributeAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -138,16 +138,14 @@ implements AttributeVisitor
public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
{
- // TODO: Implement method.
- // Note that the attribute may already be present.
-// // Create a copy of the attribute.
-// InnerClassesAttribute newInnerClassesAttribute =
-// new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex),
-// 0,
-// null);
-//
-// // Add it to the target class.
-// attributesEditor.addClassAttribute(newInnerClassesAttribute);
+ // Create a copy of the attribute.
+ InnerClassesAttribute newInnerClassesAttribute =
+ new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex),
+ 0,
+ null);
+
+ // Add it to the target class.
+ attributesEditor.addAttribute(newInnerClassesAttribute);
}
@@ -256,7 +254,7 @@ implements AttributeVisitor
CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength + 32);
// Add the instructions.
codeAttribute.instructionsAccept(clazz,
diff --git a/src/proguard/classfile/editor/AttributeSorter.java b/src/proguard/classfile/editor/AttributeSorter.java
index d8e3367..23fe027 100644
--- a/src/proguard/classfile/editor/AttributeSorter.java
+++ b/src/proguard/classfile/editor/AttributeSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/AttributesEditor.java b/src/proguard/classfile/editor/AttributesEditor.java
index 10846cc..f50b8f1 100644
--- a/src/proguard/classfile/editor/AttributesEditor.java
+++ b/src/proguard/classfile/editor/AttributesEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/BridgeMethodFixer.java b/src/proguard/classfile/editor/BridgeMethodFixer.java
new file mode 100644
index 0000000..2f1120d
--- /dev/null
+++ b/src/proguard/classfile/editor/BridgeMethodFixer.java
@@ -0,0 +1,117 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This MemberVisitor fixes all inappropriate bridge access flags of the
+ * program methods that it visits, checking whether the methods to which they
+ * bridge have the same name. Some compilers, like in Eclipse and in later
+ * versions of JDK 1.6, complain if they can't find the method with the same
+ * name.
+ *
+ * @author Eric Lafortune
+ */
+public class BridgeMethodFixer
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ // Return values for the visitor methods.
+ private String bridgedMethodName;
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_BRIDGE) != 0)
+ {
+ programMethod.attributesAccept(programClass, this);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Go over the instructions of the bridge method.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ // Get the name of the bridged method.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+
+ // Check if the name is different.
+ if (!method.getName(clazz).equals(bridgedMethodName))
+ {
+ if (DEBUG)
+ {
+ System.out.println("BridgeMethodFixer: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] does not bridge to ["+bridgedMethodName+"]");
+ }
+
+ // Clear the bridge flag.
+ ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.INTERNAL_ACC_BRIDGE;
+ }
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ bridgedMethodName = refConstant.getName(clazz);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/editor/ClassEditor.java b/src/proguard/classfile/editor/ClassEditor.java
index e503ea3..7703c9d 100644
--- a/src/proguard/classfile/editor/ClassEditor.java
+++ b/src/proguard/classfile/editor/ClassEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ClassElementSorter.java b/src/proguard/classfile/editor/ClassElementSorter.java
index 3256c88..9875a29 100644
--- a/src/proguard/classfile/editor/ClassElementSorter.java
+++ b/src/proguard/classfile/editor/ClassElementSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ClassMemberSorter.java b/src/proguard/classfile/editor/ClassMemberSorter.java
index f31fcd0..ed0b5b1 100644
--- a/src/proguard/classfile/editor/ClassMemberSorter.java
+++ b/src/proguard/classfile/editor/ClassMemberSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ClassReferenceFixer.java b/src/proguard/classfile/editor/ClassReferenceFixer.java
index 9857903..1f8b396 100644
--- a/src/proguard/classfile/editor/ClassReferenceFixer.java
+++ b/src/proguard/classfile/editor/ClassReferenceFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/CodeAttributeComposer.java b/src/proguard/classfile/editor/CodeAttributeComposer.java
index e783203..c59b712 100644
--- a/src/proguard/classfile/editor/CodeAttributeComposer.java
+++ b/src/proguard/classfile/editor/CodeAttributeComposer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,6 +28,9 @@ import proguard.classfile.attribute.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import proguard.util.ArrayUtil;
+
+import java.util.Arrays;
/**
* This AttributeVisitor accumulates instructions and exceptions, and then
@@ -49,7 +52,7 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- public static boolean DEBUG = true;
+ public static boolean DEBUG = false;
//*/
@@ -57,7 +60,8 @@ implements AttributeVisitor,
private static final int INVALID = -1;
- private boolean allowExternalExceptionHandlers;
+ private final boolean allowExternalExceptionHandlers;
+ private final boolean shrinkInstructions;
private int maximumCodeLength;
private int codeLength;
@@ -77,26 +81,34 @@ implements AttributeVisitor,
private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater();
private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();
-// private final InstructionWriter instructionWriter = new InstructionWriter();
+ private final InstructionWriter instructionWriter = new InstructionWriter();
/**
* Creates a new CodeAttributeComposer that doesn't allow external exception
- * handlers.
+ * handlers and that automatically shrinks instructions.
*/
public CodeAttributeComposer()
{
- this(false);
+ this(false, true);
}
/**
- * Creates a new CodeAttributeComposer that optionally allows external
- * exception handlers.
+ * Creates a new CodeAttributeComposer.
+ * @param allowExternalExceptionHandlers specifies whether exception
+ * handlers can lie outside the code
+ * fragment in which exceptions are
+ * defined.
+ * @param shrinkInstructions specifies whether instructions
+ * should automatically be shrunk
+ * before being written.
*/
- public CodeAttributeComposer(boolean allowExternalExceptionHandlers)
+ public CodeAttributeComposer(boolean allowExternalExceptionHandlers,
+ boolean shrinkInstructions)
{
this.allowExternalExceptionHandlers = allowExternalExceptionHandlers;
+ this.shrinkInstructions = shrinkInstructions;
}
@@ -109,6 +121,8 @@ implements AttributeVisitor,
codeLength = 0;
exceptionTableLength = 0;
level = -1;
+
+ instructionWriter.reset(ClassConstants.TYPICAL_CODE_LENGTH);
}
@@ -116,7 +130,10 @@ implements AttributeVisitor,
* Starts a new code fragment. Branch instructions that are added are
* assumed to be relative within such code fragments.
* @param maximumCodeFragmentLength the maximum length of the code that will
- * be added as part of this fragment.
+ * be added as part of this fragment (more
+ * precisely, the maximum old instruction
+ * offset or label that is specified, plus
+ * one).
*/
public void beginCodeFragment(int maximumCodeFragmentLength)
{
@@ -127,14 +144,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Maximum number of code fragment levels exceeded ["+level+"]");
}
-// // TODO: Figure out some length.
-// if (level == 0)
-// {
-// // Prepare for possible widening of instructions.
-// instructionWriter.reset(2 * maximumCodeFragmentLength);
-// }
-
// Make sure there is sufficient space for adding the code fragment.
+ // It's only a rough initial estimate for the code length, not even
+ // necessarily a length expressed in bytes.
maximumCodeLength += maximumCodeFragmentLength;
ensureCodeLength(maximumCodeLength);
@@ -159,6 +171,8 @@ implements AttributeVisitor,
/**
* Appends the given instruction with the given old offset.
+ * Branch instructions must fit, for instance by enabling automatic
+ * shrinking of instructions.
* @param oldInstructionOffset the old offset of the instruction, to which
* branches and other references in the current
* code fragment are pointing.
@@ -167,12 +181,17 @@ implements AttributeVisitor,
public void appendInstruction(int oldInstructionOffset,
Instruction instruction)
{
+ if (shrinkInstructions)
+ {
+ instruction = instruction.shrink();
+ }
+
if (DEBUG)
{
println("["+codeLength+"] <- ", instruction.toString(oldInstructionOffset));
}
- // Make sure the code array is large enough.
+ // Make sure the code and offset arrays are large enough.
int newCodeLength = codeLength + instruction.length(codeLength);
ensureCodeLength(newCodeLength);
@@ -180,17 +199,18 @@ implements AttributeVisitor,
// Remember the old offset of the appended instruction.
oldInstructionOffsets[codeLength] = oldInstructionOffset;
- // Write the instruction.
-// instruction.accept(null,
-// null,
-// new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
-// codeLength,
-// instructionWriter);
- instruction.write(code, codeLength);
-
// Fill out the new offset of the appended instruction.
instructionOffsetMap[level][oldInstructionOffset] = codeLength;
+ // Write the instruction. The instruction writer may widen it later on,
+ // if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ codeLength,
+ instructionWriter);
+ //instruction.write(code, codeLength);
+
// Continue appending at the next instruction offset.
codeLength = newCodeLength;
}
@@ -209,12 +229,70 @@ implements AttributeVisitor,
println("["+codeLength+"] <- ", "[" + oldInstructionOffset + "] (label)");
}
- // Fill out the new offset of the appended instruction.
+ // Make sure the code and offset arrays are large enough.
+ ensureCodeLength(codeLength + 1);
+
+ // Remember the old offset of the following instruction.
+ oldInstructionOffsets[codeLength] = oldInstructionOffset;
+
+ // Fill out the new offset of the following instruction.
instructionOffsetMap[level][oldInstructionOffset] = codeLength;
}
/**
+ * Appends the given instruction without defined offsets.
+ * @param instructions the instructions to be appended.
+ */
+ public void appendInstructions(Instruction[] instructions)
+ {
+ for (int index = 0; index < instructions.length; index++)
+ {
+ appendInstruction(instructions[index]);
+ }
+ }
+
+
+ /**
+ * Appends the given instruction without a defined offset.
+ * Branch instructions should have a label, to allow computing the
+ * new relative offset.
+ * Branch instructions must fit, for instance by enabling automatic
+ * shrinking of instructions.
+ * @param instruction the instruction to be appended.
+ */
+ public void appendInstruction(Instruction instruction)
+ {
+ if (shrinkInstructions)
+ {
+ instruction = instruction.shrink();
+ }
+
+ if (DEBUG)
+ {
+ println("["+codeLength+"] <- ", instruction.toString());
+ }
+
+ // Make sure the code array is large enough.
+ int newCodeLength = codeLength + instruction.length(codeLength);
+
+ ensureCodeLength(newCodeLength);
+
+ // Write the instruction. The instruction writer may widen it later on,
+ // if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ codeLength,
+ instructionWriter);
+ //instruction.write(code, codeLength);
+
+ // Continue appending at the next instruction offset.
+ codeLength = newCodeLength;
+ }
+
+
+ /**
* Appends the given exception to the exception table.
* @param exceptionInfo the exception to be appended.
*/
@@ -244,16 +322,11 @@ implements AttributeVisitor,
return;
}
- // Make sure there is sufficient space in the exception table.
- if (exceptionTable.length <= exceptionTableLength)
- {
- ExceptionInfo[] newExceptionTable = new ExceptionInfo[exceptionTableLength+1];
- System.arraycopy(exceptionTable, 0, newExceptionTable, 0, exceptionTableLength);
- exceptionTable = newExceptionTable;
- }
-
// Add the exception.
- exceptionTable[exceptionTableLength++] = exceptionInfo;
+ exceptionTable =
+ (ExceptionInfo[])ArrayUtil.add(exceptionTable,
+ exceptionTableLength++,
+ exceptionInfo);
}
@@ -281,13 +354,14 @@ implements AttributeVisitor,
// Adapt the instruction for its new offset.
instruction.accept(null, null, null, instructionOffset, this);
- // Write the instruction back.
-// instruction.accept(null,
-// null,
-// new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
-// instructionOffset,
-// instructionWriter);
- instruction.write(code, instructionOffset);
+ // Write the instruction back. The instruction writer may still
+ // widen it later on, if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ instructionOffset,
+ instructionWriter);
+ //instruction.write(code, codeLength);
// Don't remap this instruction again.
oldInstructionOffsets[instructionOffset] = -1;
@@ -313,9 +387,9 @@ implements AttributeVisitor,
int handlerPC = -exceptionInfo.u2handlerPC;
if (handlerPC > 0)
{
- if (remappableInstructionOffset(handlerPC))
+ if (remappableExceptionHandler(handlerPC))
{
- exceptionInfo.u2handlerPC = remapInstructionOffset(handlerPC);
+ exceptionInfo.u2handlerPC = newInstructionOffset(handlerPC);
}
else if (level == 0)
{
@@ -381,7 +455,7 @@ implements AttributeVisitor,
// Remap the line number table and the local variable table.
codeAttribute.attributesAccept(clazz, method, this);
- // Remap the exception table.
+ // Remap the exception table (done before).
//codeAttribute.exceptionsAccept(clazz, method, this);
// Remove exceptions with empty code blocks (done before).
@@ -389,8 +463,8 @@ implements AttributeVisitor,
// removeEmptyExceptions(codeAttribute.exceptionTable,
// codeAttribute.u2exceptionTableLength);
-// // Make sure instructions are widened if necessary.
-// instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
+ // Make sure instructions are widened if necessary.
+ instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
level--;
}
@@ -459,20 +533,20 @@ implements AttributeVisitor,
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
{
// Adjust the branch offset.
- branchInstruction.branchOffset = remapBranchOffset(offset,
- branchInstruction.branchOffset);
+ branchInstruction.branchOffset = newBranchOffset(offset,
+ branchInstruction.branchOffset);
}
public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
{
// Adjust the default jump offset.
- switchInstruction.defaultOffset = remapBranchOffset(offset,
- switchInstruction.defaultOffset);
+ switchInstruction.defaultOffset = newBranchOffset(offset,
+ switchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
- switchInstruction.jumpOffsets);
+ updateJumpOffsets(offset,
+ switchInstruction.jumpOffsets);
}
@@ -482,16 +556,16 @@ implements AttributeVisitor,
{
// Remap the code offsets. Note that the instruction offset map also has
// an entry for the first offset after the code, for u2endPC.
- exceptionInfo.u2startPC = remapInstructionOffset(exceptionInfo.u2startPC);
- exceptionInfo.u2endPC = remapInstructionOffset(exceptionInfo.u2endPC);
+ exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC);
+ exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC);
// See if we can remap the handler right away. Unmapped exception
// handlers are negated, in order to mark them as external.
int handlerPC = exceptionInfo.u2handlerPC;
exceptionInfo.u2handlerPC =
!allowExternalExceptionHandlers ||
- remappableInstructionOffset(handlerPC) ?
- remapInstructionOffset(handlerPC) :
+ remappableExceptionHandler(handlerPC) ?
+ newInstructionOffset(handlerPC) :
-handlerPC;
}
@@ -501,7 +575,7 @@ implements AttributeVisitor,
public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
{
// Remap the stack map frame offset.
- int stackMapFrameOffset = remapInstructionOffset(offset);
+ int stackMapFrameOffset = newInstructionOffset(offset);
int offsetDelta = stackMapFrameOffset;
@@ -557,7 +631,7 @@ implements AttributeVisitor,
public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
{
// Remap the offset of the 'new' instruction.
- uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset);
+ uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset);
}
@@ -566,7 +640,7 @@ implements AttributeVisitor,
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
{
// Remap the code offset.
- lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC);
+ lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC);
}
@@ -576,8 +650,9 @@ implements AttributeVisitor,
{
// Remap the code offset and length.
// TODO: The local variable frame might not be strictly preserved.
- int startPC = remapInstructionOffset(localVariableInfo.u2startPC);
- int endPC = remapInstructionOffset(localVariableInfo.u2startPC + localVariableInfo.u2length);
+ int startPC = newInstructionOffset(localVariableInfo.u2startPC);
+ int endPC = newInstructionOffset(localVariableInfo.u2startPC +
+ localVariableInfo.u2length);
localVariableInfo.u2startPC = startPC;
localVariableInfo.u2length = endPC - startPC;
@@ -589,8 +664,9 @@ implements AttributeVisitor,
{
// Remap the code offset and length.
// TODO: The local variable frame might not be strictly preserved.
- int startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC);
- int endPC = remapInstructionOffset(localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length);
+ int startPC = newInstructionOffset(localVariableTypeInfo.u2startPC);
+ int endPC = newInstructionOffset(localVariableTypeInfo.u2startPC +
+ localVariableTypeInfo.u2length);
localVariableTypeInfo.u2startPC = startPC;
localVariableTypeInfo.u2length = endPC - startPC;
@@ -609,13 +685,10 @@ implements AttributeVisitor,
// Add 20% to avoid extending the arrays too often.
newCodeLength = newCodeLength * 6 / 5;
- byte[] newCode = new byte[newCodeLength];
- System.arraycopy(code, 0, newCode, 0, codeLength);
- code = newCode;
+ code = ArrayUtil.extendArray(code, newCodeLength);
+ oldInstructionOffsets = ArrayUtil.extendArray(oldInstructionOffsets, newCodeLength);
- int[] newOldInstructionOffsets = new int[newCodeLength];
- System.arraycopy(oldInstructionOffsets, 0, newOldInstructionOffsets, 0, codeLength);
- oldInstructionOffsets = newOldInstructionOffsets;
+ instructionWriter.extend(newCodeLength);
}
}
@@ -623,11 +696,11 @@ implements AttributeVisitor,
/**
* Adjusts the given jump offsets for the instruction at the given offset.
*/
- private void remapJumpOffsets(int offset, int[] jumpOffsets)
+ private void updateJumpOffsets(int offset, int[] jumpOffsets)
{
for (int index = 0; index < jumpOffsets.length; index++)
{
- jumpOffsets[index] = remapBranchOffset(offset, jumpOffsets[index]);
+ jumpOffsets[index] = newBranchOffset(offset, jumpOffsets[index]);
}
}
@@ -636,7 +709,7 @@ implements AttributeVisitor,
* Computes the new branch offset for the instruction at the given new offset
* with the given old branch offset.
*/
- private int remapBranchOffset(int newInstructionOffset, int branchOffset)
+ private int newBranchOffset(int newInstructionOffset, int oldBranchOffset)
{
if (newInstructionOffset < 0 ||
newInstructionOffset > codeLength)
@@ -646,8 +719,8 @@ implements AttributeVisitor,
int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset];
- return remapInstructionOffset(oldInstructionOffset + branchOffset) -
- remapInstructionOffset(oldInstructionOffset);
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) -
+ newInstructionOffset(oldInstructionOffset);
}
@@ -655,7 +728,7 @@ implements AttributeVisitor,
* Computes the new instruction offset for the instruction at the given old
* offset.
*/
- private int remapInstructionOffset(int oldInstructionOffset)
+ private int newInstructionOffset(int oldInstructionOffset)
{
if (oldInstructionOffset < 0 ||
oldInstructionOffset > codeFragmentLengths[level])
@@ -674,13 +747,25 @@ implements AttributeVisitor,
/**
- * Returns whether the given old instruction offset can be remapped at the
+ * Returns whether the given old exception handler can be remapped in the
+ * current code fragment.
*/
- private boolean remappableInstructionOffset(int oldInstructionOffset)
+ private boolean remappableExceptionHandler(int oldInstructionOffset)
{
- return
- oldInstructionOffset <= codeFragmentLengths[level] &&
- instructionOffsetMap[level][oldInstructionOffset] > INVALID;
+ // Can we index in the array?
+ if (oldInstructionOffset > codeFragmentLengths[level])
+ {
+ return false;
+ }
+
+ // Do we have a valid new instruction offset, but not yet right after
+ // the code? That offset is only labeled for mapping try blocks, not
+ // for mapping handlers.
+ int newInstructionOffset =
+ instructionOffsetMap[level][oldInstructionOffset];
+
+ return newInstructionOffset > INVALID &&
+ newInstructionOffset < codeLength;
}
@@ -703,10 +788,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < exceptionInfoCount; index++)
- {
- exceptionInfos[index] = null;
- }
+ Arrays.fill(exceptionInfos, newIndex, exceptionInfoCount, null);
return newIndex;
}
@@ -734,10 +816,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < lineNumberInfoCount; index++)
- {
- lineNumberInfos[index] = null;
- }
+ Arrays.fill(lineNumberInfos, newIndex, lineNumberInfoCount, null);
return newIndex;
}
@@ -764,10 +843,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < localVariableInfoCount; index++)
- {
- localVariableInfos[index] = null;
- }
+ Arrays.fill(localVariableInfos, newIndex, localVariableInfoCount, null);
return newIndex;
}
@@ -794,10 +870,7 @@ implements AttributeVisitor,
}
// Clear the unused array entries.
- for (int index = newIndex; index < localVariableTypeInfoCount; index++)
- {
- localVariableTypeInfos[index] = null;
- }
+ Arrays.fill(localVariableTypeInfos, newIndex, localVariableTypeInfoCount, null);
return newIndex;
}
diff --git a/src/proguard/classfile/editor/CodeAttributeEditor.java b/src/proguard/classfile/editor/CodeAttributeEditor.java
index 9658c98..337e0d4 100644
--- a/src/proguard/classfile/editor/CodeAttributeEditor.java
+++ b/src/proguard/classfile/editor/CodeAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,9 @@ import proguard.classfile.attribute.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.ClassPrinter;
+import proguard.util.ArrayUtil;
+
+import java.util.Arrays;
/**
* This AttributeVisitor accumulates specified changes to code, and then applies
@@ -50,10 +52,12 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ public static boolean DEBUG = false;
//*/
- private boolean updateFrameSizes;
+
+ private final boolean updateFrameSizes;
+ private final boolean shrinkInstructions;
private int codeLength;
private boolean modified;
@@ -64,7 +68,7 @@ implements AttributeVisitor,
/*private*/public Instruction[] postInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];
/*private*/public boolean[] deleted = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
- private int[] instructionOffsetMap = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] newInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int newOffset;
private boolean lengthIncreased;
@@ -75,15 +79,28 @@ implements AttributeVisitor,
private final InstructionWriter instructionWriter = new InstructionWriter();
+ /**
+ * Creates a new CodeAttributeEditor that automatically updates frame
+ * sizes and shrinks instructions.
+ */
public CodeAttributeEditor()
{
- this(true);
+ this(true, true);
}
- public CodeAttributeEditor(boolean updateFrameSizes)
+ /**
+ * Creates a new CodeAttributeEditor.
+ * @param updateFrameSizes specifies whether frame sizes of edited code
+ * should be updated.
+ * @param shrinkInstructions specifies whether added instructions should
+ * automatically be shrunk before being written.
+ */
+ public CodeAttributeEditor(boolean updateFrameSizes,
+ boolean shrinkInstructions)
{
- this.updateFrameSizes = updateFrameSizes;
+ this.updateFrameSizes = updateFrameSizes;
+ this.shrinkInstructions = shrinkInstructions;
}
@@ -93,8 +110,6 @@ implements AttributeVisitor,
*/
public void reset(int codeLength)
{
- this.codeLength = codeLength;
-
// Try to reuse the previous arrays.
if (preInsertions.length < codeLength)
{
@@ -105,18 +120,42 @@ implements AttributeVisitor,
}
else
{
- for (int index = 0; index < codeLength; index++)
- {
- preInsertions[index] = null;
- replacements[index] = null;
- postInsertions[index] = null;
- deleted[index] = false;
- }
+ Arrays.fill(preInsertions, 0, codeLength, null);
+ Arrays.fill(replacements, 0, codeLength, null);
+ Arrays.fill(postInsertions, 0, codeLength, null);
+ Arrays.fill(deleted, 0, codeLength, false);
}
+ this.codeLength = codeLength;
+
modified = false;
simple = true;
+ }
+
+
+ /**
+ * Extends the size of the accumulated code changes.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void extend(int codeLength)
+ {
+ // Try to reuse the previous arrays.
+ if (preInsertions.length < codeLength)
+ {
+ preInsertions = (Instruction[])ArrayUtil.extendArray(preInsertions, codeLength);
+ replacements = (Instruction[])ArrayUtil.extendArray(replacements, codeLength);
+ postInsertions = (Instruction[])ArrayUtil.extendArray(postInsertions, codeLength);
+ deleted = ArrayUtil.extendArray(deleted, codeLength);
+ }
+ else
+ {
+ Arrays.fill(preInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(replacements, this.codeLength, codeLength, null);
+ Arrays.fill(postInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(deleted, this.codeLength, codeLength, false);
+ }
+ this.codeLength = codeLength;
}
@@ -134,7 +173,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- preInsertions[instructionOffset] = instruction;
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -156,7 +197,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- preInsertions[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -178,7 +224,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- replacements[instructionOffset] = instruction;
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
}
@@ -198,7 +246,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- replacements[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
}
@@ -218,7 +271,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- postInsertions[instructionOffset] = instruction;
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -239,7 +294,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- postInsertions[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -282,6 +342,34 @@ implements AttributeVisitor,
/**
+ * Clears all modifications of the instruction at the given offset.
+ * @param instructionOffset the offset of the instruction to be deleted.
+ */
+ public void clearModifications(int instructionOffset)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ preInsertions[instructionOffset] = null;
+ replacements[instructionOffset] = null;
+ postInsertions[instructionOffset] = null;
+ deleted[instructionOffset] = false;
+ }
+
+
+ /**
+ * Returns whether the code has been modified in any way.
+ */
+ public boolean isModified()
+ {
+ return modified;
+ }
+
+
+ /**
* Returns whether the instruction at the given offset has been modified
* in any way.
*/
@@ -326,54 +414,53 @@ implements AttributeVisitor,
public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
- if (DEBUG)
- {
- System.out.println("CodeAttributeEditor: ["+clazz.getName()+"."+method.getName(clazz)+"]");
- }
-
- // Avoid doing any work if nothing is changing anyway.
- if (!modified)
+ // Do we have to update the code?
+ if (modified)
{
- return;
- }
+ if (DEBUG)
+ {
+ System.out.println("CodeAttributeEditor: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
- // Check if we can perform a faster simple replacement of instructions.
- if (canPerformSimpleReplacements(codeAttribute))
- {
- // Simply overwrite the instructions.
- performSimpleReplacements(codeAttribute);
+ // Can we perform a faster simple replacement of instructions?
+ if (canPerformSimpleReplacements(codeAttribute))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Simple editing");
+ }
- // Update the maximum stack size and local variable frame size.
- updateFrameSizes(clazz, method, codeAttribute);
- }
- else
- {
- // Move and remap the instructions.
- codeAttribute.u4codeLength =
- updateInstructions(clazz, method, codeAttribute);
+ // Simply overwrite the instructions.
+ performSimpleReplacements(codeAttribute);
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Full editing");
+ }
- // Remap the exception table.
- codeAttribute.exceptionsAccept(clazz, method, this);
+ // Move and remap the instructions.
+ codeAttribute.u4codeLength =
+ updateInstructions(clazz, method, codeAttribute);
- // Remove exceptions with empty code blocks.
- codeAttribute.u2exceptionTableLength =
- removeEmptyExceptions(codeAttribute.exceptionTable,
- codeAttribute.u2exceptionTableLength);
+ // Update the exception table.
+ codeAttribute.exceptionsAccept(clazz, method, this);
- // Update the maximum stack size and local variable frame size.
- updateFrameSizes(clazz, method, codeAttribute);
+ // Remove exceptions with empty code blocks.
+ codeAttribute.u2exceptionTableLength =
+ removeEmptyExceptions(codeAttribute.exceptionTable,
+ codeAttribute.u2exceptionTableLength);
- // Remap the line number table and the local variable table.
- codeAttribute.attributesAccept(clazz, method, this);
+ // Update the line number table and the local variable tables.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
// Make sure instructions are widened if necessary.
instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
}
- }
-
- private void updateFrameSizes(Clazz clazz, Method method, CodeAttribute codeAttribute)
- {
+ // Update the maximum stack size and local variable frame size.
if (updateFrameSizes)
{
stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
@@ -384,7 +471,7 @@ implements AttributeVisitor,
public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
{
- // Remap all stack map entries.
+ // Update all stack map entries.
expectedStackMapFrameOffset = -1;
stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
}
@@ -392,7 +479,7 @@ implements AttributeVisitor,
public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
{
- // Remap all stack map table entries.
+ // Update all stack map table entries.
expectedStackMapFrameOffset = 0;
stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
}
@@ -400,7 +487,7 @@ implements AttributeVisitor,
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
- // Remap all line number table entries.
+ // Update all line number table entries.
lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
// Remove line numbers with empty code blocks.
@@ -413,27 +500,15 @@ implements AttributeVisitor,
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
{
- // Remap all local variable table entries.
+ // Update all local variable table entries.
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables with empty code blocks.
- localVariableTableAttribute.u2localVariableTableLength =
- removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
- localVariableTableAttribute.u2localVariableTableLength,
- codeAttribute.u2maxLocals);
}
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
{
- // Remap all local variable table entries.
+ // Update all local variable table entries.
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables with empty code blocks.
- localVariableTypeTableAttribute.u2localVariableTypeTableLength =
- removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
- localVariableTypeTableAttribute.u2localVariableTypeTableLength,
- codeAttribute.u2maxLocals);
}
@@ -491,7 +566,7 @@ implements AttributeVisitor,
if (DEBUG)
{
- System.out.println(" Replaced "+replacementInstruction.toString(newOffset));
+ System.out.println(" Replaced "+replacementInstruction.toString(offset));
}
}
}
@@ -513,9 +588,9 @@ implements AttributeVisitor,
int oldLength = codeAttribute.u4codeLength;
// Make sure there is a sufficiently large instruction offset map.
- if (instructionOffsetMap.length < oldLength + 1)
+ if (newInstructionOffsets.length < oldLength + 1)
{
- instructionOffsetMap = new int[oldLength + 1];
+ newInstructionOffsets = new int[oldLength + 1];
}
// Fill out the instruction offset map.
@@ -574,7 +649,7 @@ implements AttributeVisitor,
while (oldOffset < oldLength);
// Also add an entry for the first offset after the code.
- instructionOffsetMap[oldOffset] = newOffset;
+ newInstructionOffsets[oldOffset] = newOffset;
return newOffset;
}
@@ -588,7 +663,7 @@ implements AttributeVisitor,
private void mapInstruction(int oldOffset,
Instruction instruction)
{
- instructionOffsetMap[oldOffset] = newOffset;
+ newInstructionOffsets[oldOffset] = newOffset;
// Account for the pre-inserted instruction, if any.
Instruction preInstruction = preInsertions[oldOffset];
@@ -670,52 +745,53 @@ implements AttributeVisitor,
int oldOffset,
Instruction instruction)
{
- // Remap and insert the pre-inserted instruction, if any.
+ // Update and insert the pre-inserted instruction, if any.
Instruction preInstruction = preInsertions[oldOffset];
if (preInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Pre-inserted "+preInstruction.toString(newOffset));
+ System.out.println(" Pre-inserted ["+oldOffset+"] -> "+preInstruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
preInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
- // Remap and insert the replacement instruction, or the current
+ // Update and insert the replacement instruction, or the current
// instruction, if it shouldn't be deleted.
Instruction replacementInstruction = replacements[oldOffset];
if (replacementInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Replaced "+replacementInstruction.toString(newOffset));
+ System.out.println(" Replaced ["+oldOffset+"] -> "+replacementInstruction.toString(newOffset));
}
- // Remap the instruction.
+
+ // Update the instruction.
replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
else if (!deleted[oldOffset])
{
if (DEBUG)
{
- System.out.println(" Copied "+instruction.toString(newOffset));
+ System.out.println(" Copied ["+oldOffset+"] -> "+instruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
instruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
- // Remap and insert the post-inserted instruction, if any.
+ // Update and insert the post-inserted instruction, if any.
Instruction postInstruction = postInsertions[oldOffset];
if (postInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Post-inserted "+postInstruction.toString(newOffset));
+ System.out.println(" Post-inserted ["+oldOffset+"] -> "+postInstruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
postInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
}
@@ -765,8 +841,8 @@ implements AttributeVisitor,
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
{
// Adjust the branch offset.
- branchInstruction.branchOffset = remapBranchOffset(offset,
- branchInstruction.branchOffset);
+ branchInstruction.branchOffset = newBranchOffset(offset,
+ branchInstruction.branchOffset);
// Write out the instruction.
instructionWriter.visitBranchInstruction(clazz,
@@ -782,11 +858,11 @@ implements AttributeVisitor,
public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
{
// Adjust the default jump offset.
- tableSwitchInstruction.defaultOffset = remapBranchOffset(offset,
- tableSwitchInstruction.defaultOffset);
+ tableSwitchInstruction.defaultOffset = newBranchOffset(offset,
+ tableSwitchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
+ newJumpOffsets(offset,
tableSwitchInstruction.jumpOffsets);
// Write out the instruction.
@@ -803,11 +879,11 @@ implements AttributeVisitor,
public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
{
// Adjust the default jump offset.
- lookUpSwitchInstruction.defaultOffset = remapBranchOffset(offset,
- lookUpSwitchInstruction.defaultOffset);
+ lookUpSwitchInstruction.defaultOffset = newBranchOffset(offset,
+ lookUpSwitchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
+ newJumpOffsets(offset,
lookUpSwitchInstruction.jumpOffsets);
// Write out the instruction.
@@ -825,11 +901,11 @@ implements AttributeVisitor,
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- // Remap the code offsets. Note that the instruction offset map also has
+ // Update the code offsets. Note that the instruction offset map also has
// an entry for the first offset after the code, for u2endPC.
- exceptionInfo.u2startPC = remapInstructionOffset(exceptionInfo.u2startPC);
- exceptionInfo.u2endPC = remapInstructionOffset(exceptionInfo.u2endPC);
- exceptionInfo.u2handlerPC = remapInstructionOffset(exceptionInfo.u2handlerPC);
+ exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC);
+ exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC);
+ exceptionInfo.u2handlerPC = newInstructionOffset(exceptionInfo.u2handlerPC);
}
@@ -837,8 +913,8 @@ implements AttributeVisitor,
public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
{
- // Remap the stack map frame offset.
- int stackMapFrameOffset = remapInstructionOffset(offset);
+ // Update the stack map frame offset.
+ int stackMapFrameOffset = newInstructionOffset(offset);
int offsetDelta = stackMapFrameOffset;
@@ -857,30 +933,30 @@ implements AttributeVisitor,
public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame);
- // Remap the verification type offset.
+ // Update the verification type offset.
sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
}
public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame);
- // Remap the verification type offsets.
+ // Update the verification type offsets.
moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
}
public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame);
- // Remap the verification type offsets.
+ // Update the verification type offsets.
fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
}
@@ -893,8 +969,8 @@ implements AttributeVisitor,
public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
{
- // Remap the offset of the 'new' instruction.
- uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset);
+ // Update the offset of the 'new' instruction.
+ uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset);
}
@@ -902,8 +978,8 @@ implements AttributeVisitor,
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
{
- // Remap the code offset.
- lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC);
+ // Update the code offset.
+ lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC);
}
@@ -911,11 +987,13 @@ implements AttributeVisitor,
public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
{
- // Remap the code offset and length.
- // TODO: The local variable frame might not be strictly preserved.
- localVariableInfo.u2length = remapBranchOffset(localVariableInfo.u2startPC,
- localVariableInfo.u2length);
- localVariableInfo.u2startPC = remapInstructionOffset(localVariableInfo.u2startPC);
+ // Update the code offset and length.
+ int newStartPC = newInstructionOffset(localVariableInfo.u2startPC);
+ int newEndPC = newInstructionOffset(localVariableInfo.u2startPC +
+ localVariableInfo.u2length);
+
+ localVariableInfo.u2length = newEndPC - newStartPC;
+ localVariableInfo.u2startPC = newStartPC;
}
@@ -923,11 +1001,13 @@ implements AttributeVisitor,
public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
{
- // Remap the code offset and length.
- // TODO: The local variable frame might not be strictly preserved.
- localVariableTypeInfo.u2length = remapBranchOffset(localVariableTypeInfo.u2startPC,
- localVariableTypeInfo.u2length);
- localVariableTypeInfo.u2startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC);
+ // Update the code offset and length.
+ int newStartPC = newInstructionOffset(localVariableTypeInfo.u2startPC);
+ int newEndPC = newInstructionOffset(localVariableTypeInfo.u2startPC +
+ localVariableTypeInfo.u2length);
+
+ localVariableTypeInfo.u2length = newEndPC - newStartPC;
+ localVariableTypeInfo.u2startPC = newStartPC;
}
@@ -936,11 +1016,11 @@ implements AttributeVisitor,
/**
* Adjusts the given jump offsets for the instruction at the given offset.
*/
- private void remapJumpOffsets(int offset, int[] jumpOffsets)
+ private void newJumpOffsets(int oldInstructionOffset, int[] oldJumpOffsets)
{
- for (int index = 0; index < jumpOffsets.length; index++)
+ for (int index = 0; index < oldJumpOffsets.length; index++)
{
- jumpOffsets[index] = remapBranchOffset(offset, jumpOffsets[index]);
+ oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, oldJumpOffsets[index]);
}
}
@@ -949,24 +1029,24 @@ implements AttributeVisitor,
* Computes the new branch offset for the instruction at the given offset
* with the given branch offset.
*/
- private int remapBranchOffset(int offset, int branchOffset)
+ private int newBranchOffset(int oldInstructionOffset, int oldBranchOffset)
{
- return remapInstructionOffset(offset + branchOffset) - newOffset;
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - newOffset;
}
/**
* Computes the new instruction offset for the instruction at the given offset.
*/
- private int remapInstructionOffset(int offset)
+ private int newInstructionOffset(int oldInstructionOffset)
{
- if (offset < 0 ||
- offset > codeLength)
+ if (oldInstructionOffset < 0 ||
+ oldInstructionOffset > codeLength)
{
- throw new IllegalArgumentException("Invalid instruction offset ["+offset+"] in code with length ["+codeLength+"]");
+ throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset+"] in code with length ["+codeLength+"]");
}
- return instructionOffsetMap[offset];
+ return newInstructionOffsets[oldInstructionOffset];
}
@@ -1018,53 +1098,9 @@ implements AttributeVisitor,
/**
- * Returns the given list of local variables, without the ones that have empty
- * code blocks or that exceed the actual number of local variables.
+ * This instruction is a composite of other instructions, for local use
+ * inside the editor class only.
*/
- private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
- int localVariableInfoCount,
- int maxLocals)
- {
- // Overwrite all empty local variable entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableInfoCount; index++)
- {
- LocalVariableInfo localVariableInfo = localVariableInfos[index];
- if (localVariableInfo.u2length > 0 &&
- localVariableInfo.u2index < maxLocals)
- {
- localVariableInfos[newIndex++] = localVariableInfo;
- }
- }
-
- return newIndex;
- }
-
-
- /**
- * Returns the given list of local variable types, without the ones that
- * have empty code blocks or that exceed the actual number of local variables.
- */
- private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
- int localVariableTypeInfoCount,
- int maxLocals)
- {
- // Overwrite all empty local variable type entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableTypeInfoCount; index++)
- {
- LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
- if (localVariableTypeInfo.u2length > 0 &&
- localVariableTypeInfo.u2index < maxLocals)
- {
- localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
- }
- }
-
- return newIndex;
- }
-
-
private class CompositeInstruction
extends Instruction
{
diff --git a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
index 9962ea5..8f767c7 100644
--- a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
+++ b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ComparableConstant.java b/src/proguard/classfile/editor/ComparableConstant.java
index bb81221..476edd6 100644
--- a/src/proguard/classfile/editor/ComparableConstant.java
+++ b/src/proguard/classfile/editor/ComparableConstant.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,7 +39,7 @@ class ComparableConstant
extends SimplifiedVisitor
implements Comparable, ConstantVisitor
{
- private static final int[] PRIORITIES = new int[13];
+ private static final int[] PRIORITIES = new int[19];
static
{
PRIORITIES[ClassConstants.CONSTANT_Integer] = 0; // Possibly byte index (ldc).
@@ -47,12 +47,15 @@ implements Comparable, ConstantVisitor
PRIORITIES[ClassConstants.CONSTANT_String] = 2;
PRIORITIES[ClassConstants.CONSTANT_Class] = 3;
PRIORITIES[ClassConstants.CONSTANT_Long] = 4; // Always wide index (ldc2_w).
- PRIORITIES[ClassConstants.CONSTANT_Double] = 5;
- PRIORITIES[ClassConstants.CONSTANT_Fieldref] = 6; // Always wide index.
- PRIORITIES[ClassConstants.CONSTANT_Methodref] = 7;
- PRIORITIES[ClassConstants.CONSTANT_InterfaceMethodref] = 8;
- PRIORITIES[ClassConstants.CONSTANT_NameAndType] = 9;
- PRIORITIES[ClassConstants.CONSTANT_Utf8] = 10;
+ PRIORITIES[ClassConstants.CONSTANT_Double] = 5; // Always wide index (ldc2_w).
+ PRIORITIES[ClassConstants.CONSTANT_Fieldref] = 6; // Always wide index (getfield,...).
+ PRIORITIES[ClassConstants.CONSTANT_Methodref] = 7; // Always wide index (invokespecial,...).
+ PRIORITIES[ClassConstants.CONSTANT_InterfaceMethodref] = 8; // Always wide index (invokeinterface).
+ PRIORITIES[ClassConstants.CONSTANT_InvokeDynamic] = 9; // Always wide index (invokedynamic).
+ PRIORITIES[ClassConstants.CONSTANT_MethodHandle] = 10;
+ PRIORITIES[ClassConstants.CONSTANT_NameAndType] = 11;
+ PRIORITIES[ClassConstants.CONSTANT_MethodType] = 12;
+ PRIORITIES[ClassConstants.CONSTANT_Utf8] = 13;
}
private final Clazz clazz;
@@ -122,26 +125,32 @@ implements Comparable, ConstantVisitor
public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
{
- // In JDK 1.4, we can use Integer.compare(a,b).
- result = new Integer(integerConstant.getValue()).compareTo(new Integer(((IntegerConstant)otherConstant).getValue()));
+ int value = integerConstant.getValue();
+ int otherValue = ((IntegerConstant)otherConstant).getValue();
+ result = value < otherValue ? -1 :
+ value == otherValue ? 0 :
+ 1;
}
public void visitLongConstant(Clazz clazz, LongConstant longConstant)
{
- // In JDK 1.4, we can use Long.compare(a,b).
- result = new Long(longConstant.getValue()).compareTo(new Long(((LongConstant)otherConstant).getValue()));
+ long value = longConstant.getValue();
+ long otherValue = ((LongConstant)otherConstant).getValue();
+ result = value < otherValue ? -1 :
+ value == otherValue ? 0 :
+ 1;
}
public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
{
- // In JDK 1.4, we can use Float.compare(a,b).
- result = new Float(floatConstant.getValue()).compareTo(new Float(((FloatConstant)otherConstant).getValue()));
+ result = Float.compare(floatConstant.getValue(),
+ ((FloatConstant)otherConstant).getValue());
}
public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
- {
- // In JDK 1.4, we can use Double.compare(a,b).
- result = new Double(doubleConstant.getValue()).compareTo(new Double(((DoubleConstant)otherConstant).getValue()));
+ {
+ result = Double.compare(doubleConstant.getValue(),
+ ((DoubleConstant)otherConstant).getValue());
}
public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
@@ -154,6 +163,38 @@ implements Comparable, ConstantVisitor
result = utf8Constant.getString().compareTo(((Utf8Constant)otherConstant).getString());
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ InvokeDynamicConstant otherInvokeDynamicConstant = (InvokeDynamicConstant)otherConstant;
+
+ int index = invokeDynamicConstant.getBootstrapMethodAttributeIndex();
+ int otherIndex = otherInvokeDynamicConstant.getBootstrapMethodAttributeIndex();
+
+ result = index < otherIndex ? -1 :
+ index > otherIndex ? 1 :
+ (invokeDynamicConstant.getName(clazz) + ' ' +
+ invokeDynamicConstant.getType(clazz))
+ .compareTo
+ (otherInvokeDynamicConstant.getName(clazz) + ' ' +
+ otherInvokeDynamicConstant.getType(clazz));
+ }
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ MethodHandleConstant otherMethodHandleConstant = (MethodHandleConstant)otherConstant;
+
+ int kind = methodHandleConstant.getReferenceKind();
+ int otherKind = methodHandleConstant.getReferenceKind();
+
+ result = kind < otherKind ? -1 :
+ kind > otherKind ? 1 :
+ (methodHandleConstant.getName(clazz) + ' ' +
+ methodHandleConstant.getType(clazz))
+ .compareTo
+ (otherMethodHandleConstant.getName(clazz) + ' ' +
+ otherMethodHandleConstant.getType(clazz));
+ }
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
RefConstant otherRefConstant = (RefConstant)otherConstant;
@@ -171,6 +212,14 @@ implements Comparable, ConstantVisitor
result = classConstant.getName(clazz).compareTo(((ClassConstant)otherConstant).getName(clazz));
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant MethodTypeConstant)
+ {
+ MethodTypeConstant otherMethodTypeConstant = (MethodTypeConstant)otherConstant;
+ result = MethodTypeConstant.getType(clazz)
+ .compareTo
+ (otherMethodTypeConstant.getType(clazz));
+ }
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
NameAndTypeConstant otherNameAndTypeConstant = (NameAndTypeConstant)otherConstant;
diff --git a/src/proguard/classfile/editor/ConstantAdder.java b/src/proguard/classfile/editor/ConstantAdder.java
index 2b74f5f..9d20199 100644
--- a/src/proguard/classfile/editor/ConstantAdder.java
+++ b/src/proguard/classfile/editor/ConstantAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,6 +23,7 @@ package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.util.ListUtil;
/**
* This ConstantVisitor adds all constants that it visits to the constant pool
@@ -128,6 +129,43 @@ implements ConstantVisitor
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // First add the name and type constant.
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+
+ // Copy the referenced classes.
+ Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses;
+ Clazz[] referencedClassesCopy = null;
+ if (referencedClasses != null)
+ {
+ referencedClassesCopy = new Clazz[referencedClasses.length];
+ System.arraycopy(referencedClasses, 0,
+ referencedClassesCopy, 0,
+ referencedClasses.length);
+ }
+
+ // Then add the actual invoke dynamic constant.
+ constantIndex =
+ constantPoolEditor.addInvokeDynamicConstant(invokeDynamicConstant.getBootstrapMethodAttributeIndex(),
+ constantIndex,
+ referencedClassesCopy);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // First add the field ref, interface method ref, or method ref
+ // constant.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+
+ // Then add the actual method handle constant.
+ constantIndex =
+ constantPoolEditor.addMethodHandleConstant(methodHandleConstant.getReferenceKind(),
+ constantIndex);
+ }
+
+
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
// First add the referenced class constant, with its own referenced class.
@@ -185,6 +223,13 @@ implements ConstantVisitor
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addMethodTypeConstant(methodTypeConstant.getType(clazz));
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
constantIndex =
diff --git a/src/proguard/classfile/editor/ConstantPoolEditor.java b/src/proguard/classfile/editor/ConstantPoolEditor.java
index 8663dee..7adbc44 100644
--- a/src/proguard/classfile/editor/ConstantPoolEditor.java
+++ b/src/proguard/classfile/editor/ConstantPoolEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -199,6 +199,93 @@ public class ConstantPoolEditor
/**
+ * Finds or creates a InvokeDynamicConstant constant pool entry with the
+ * given bootstrap method constant pool entry index, method name, and
+ * descriptor.
+ * @return the constant pool index of the InvokeDynamicConstant.
+ */
+ public int addInvokeDynamicConstant(int bootstrapMethodIndex,
+ String name,
+ String descriptor,
+ Clazz[] referencedClasses)
+ {
+ return addInvokeDynamicConstant(bootstrapMethodIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClasses);
+ }
+
+
+ /**
+ * Finds or creates a InvokeDynamicConstant constant pool entry with the given
+ * class constant pool entry index and name and type constant pool entry
+ * index.
+ * @return the constant pool index of the InvokeDynamicConstant.
+ */
+ public int addInvokeDynamicConstant(int bootstrapMethodIndex,
+ int nameAndTypeIndex,
+ Clazz[] referencedClasses)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_InvokeDynamic)
+ {
+ InvokeDynamicConstant invokeDynamicConstant = (InvokeDynamicConstant)constant;
+ if (invokeDynamicConstant.u2bootstrapMethodAttributeIndex == bootstrapMethodIndex &&
+ invokeDynamicConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new InvokeDynamicConstant(bootstrapMethodIndex,
+ nameAndTypeIndex,
+ referencedClasses));
+ }
+
+
+ /**
+ * Finds or creates a MethodHandleConstant constant pool entry of the
+ * specified kind and with the given field ref, interface method ref,
+ * or method ref constant pool entry index.
+ * @return the constant pool index of the MethodHandleConstant.
+ */
+ public int addMethodHandleConstant(int referenceKind,
+ int referenceIndex)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_MethodHandle)
+ {
+ MethodHandleConstant methodHandleConstant = (MethodHandleConstant)constant;
+ if (methodHandleConstant.u1referenceKind == referenceKind &&
+ methodHandleConstant.u2referenceIndex == referenceIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodHandleConstant(referenceKind,
+ referenceIndex));
+ }
+
+
+ /**
* Finds or creates a FieldrefConstant constant pool entry for the given
* class and field.
* @return the constant pool index of the FieldrefConstant.
@@ -563,6 +650,36 @@ public class ConstantPoolEditor
/**
+ * Finds or creates a MethodTypeConstant constant pool entry with the given
+ * type.
+ * @return the constant pool index of the MethodTypeConstant.
+ */
+ public int addMethodTypeConstant(String type)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_MethodType)
+ {
+ MethodTypeConstant methodTypeConstant = (MethodTypeConstant)constant;
+ if (methodTypeConstant.getType(targetClass).equals(type))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodTypeConstant(addUtf8Constant(type)));
+ }
+
+
+ /**
* Finds or creates a NameAndTypeConstant constant pool entry with the given
* name and type.
* @return the constant pool index of the NameAndTypeConstant.
diff --git a/src/proguard/classfile/editor/ConstantPoolRemapper.java b/src/proguard/classfile/editor/ConstantPoolRemapper.java
index 7430d3d..eaf7653 100644
--- a/src/proguard/classfile/editor/ConstantPoolRemapper.java
+++ b/src/proguard/classfile/editor/ConstantPoolRemapper.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -47,9 +47,10 @@ implements ClassVisitor,
ConstantVisitor,
MemberVisitor,
AttributeVisitor,
- InstructionVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
ExceptionInfoVisitor,
+ InstructionVisitor,
StackMapFrameVisitor,
VerificationTypeVisitor,
LocalVariableInfoVisitor,
@@ -57,7 +58,7 @@ implements ClassVisitor,
AnnotationVisitor,
ElementValueVisitor
{
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true);
private int[] constantIndexMap;
@@ -100,40 +101,66 @@ implements ClassVisitor,
// Implementations for ConstantVisitor.
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
{
- classConstant.u2nameIndex =
- remapConstantIndex(classConstant.u2nameIndex);
+ // Nothing to do.
}
- public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
{
// Nothing to do.
}
- public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
{
- fieldrefConstant.u2classIndex =
- remapConstantIndex(fieldrefConstant.u2classIndex);
- fieldrefConstant.u2nameAndTypeIndex =
- remapConstantIndex(fieldrefConstant.u2nameAndTypeIndex);
+ // Nothing to do.
}
- public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
{
// Nothing to do.
}
- public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ stringConstant.u2stringIndex =
+ remapConstantIndex(stringConstant.u2stringIndex);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
{
// Nothing to do.
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.u2nameAndTypeIndex =
+ remapConstantIndex(invokeDynamicConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ methodHandleConstant.u2referenceIndex =
+ remapConstantIndex(methodHandleConstant.u2referenceIndex);
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ fieldrefConstant.u2classIndex =
+ remapConstantIndex(fieldrefConstant.u2classIndex);
+ fieldrefConstant.u2nameAndTypeIndex =
+ remapConstantIndex(fieldrefConstant.u2nameAndTypeIndex);
+ }
+
+
public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
{
interfaceMethodrefConstant.u2classIndex =
@@ -143,12 +170,6 @@ implements ClassVisitor,
}
- public void visitLongConstant(Clazz clazz, LongConstant longConstant)
- {
- // Nothing to do.
- }
-
-
public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
{
methodrefConstant.u2classIndex =
@@ -158,25 +179,26 @@ implements ClassVisitor,
}
- public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
- nameAndTypeConstant.u2nameIndex =
- remapConstantIndex(nameAndTypeConstant.u2nameIndex);
- nameAndTypeConstant.u2descriptorIndex =
- remapConstantIndex(nameAndTypeConstant.u2descriptorIndex);
+ classConstant.u2nameIndex =
+ remapConstantIndex(classConstant.u2nameIndex);
}
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
{
- stringConstant.u2stringIndex =
- remapConstantIndex(stringConstant.u2stringIndex);
+ methodTypeConstant.u2descriptorIndex =
+ remapConstantIndex(methodTypeConstant.u2descriptorIndex);
}
- public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
- // Nothing to do.
+ nameAndTypeConstant.u2nameIndex =
+ remapConstantIndex(nameAndTypeConstant.u2nameIndex);
+ nameAndTypeConstant.u2descriptorIndex =
+ remapConstantIndex(nameAndTypeConstant.u2descriptorIndex);
}
@@ -230,6 +252,16 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ bootstrapMethodsAttribute.u2attributeNameIndex =
+ remapConstantIndex(bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the bootstrap method entries.
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
sourceFileAttribute.u2attributeNameIndex =
@@ -410,6 +442,19 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ bootstrapMethodInfo.u2methodHandleIndex =
+ remapConstantIndex(bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Remap the constant pool references of the bootstrap methods..
+ remapConstantIndexArray(bootstrapMethodInfo.u2methodArguments,
+ bootstrapMethodInfo.u2methodArgumentCount);
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
@@ -461,7 +506,7 @@ implements ClassVisitor,
Instruction replacementInstruction =
new ConstantInstruction(constantInstruction.opcode,
newConstantIndex,
- constantInstruction.constant).shrink();
+ constantInstruction.constant);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
}
diff --git a/src/proguard/classfile/editor/ConstantPoolShrinker.java b/src/proguard/classfile/editor/ConstantPoolShrinker.java
new file mode 100644
index 0000000..ee309a0
--- /dev/null
+++ b/src/proguard/classfile/editor/ConstantPoolShrinker.java
@@ -0,0 +1,578 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor removes all unused entries from the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantPoolShrinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor,
+ InstructionVisitor
+{
+ // A visitor info flag to indicate the constant is being used.
+ private static final Object USED = new Object();
+
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Mark this class's name.
+ markConstant(programClass, programClass.u2thisClass);
+
+ // Mark the superclass class constant.
+ programClass.superClassConstantAccept(this);
+
+ // Mark the interface class constants.
+ programClass.interfaceConstantsAccept(this);
+
+ // Mark the constants referenced by the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Mark the attributes.
+ programClass.attributesAccept(this);
+
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Mark the name and descriptor.
+ markConstant(programClass, programMember.u2nameIndex);
+ markConstant(programClass, programMember.u2descriptorIndex);
+
+ // Mark the attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ markAsUsed(constant);
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ markAsUsed(stringConstant);
+
+ markConstant(clazz, stringConstant.u2stringIndex);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ markAsUsed(invokeDynamicConstant);
+
+ markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
+
+ // Mark the bootstrap methods attribute.
+ clazz.attributesAccept(this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ markAsUsed(methodHandleConstant);
+
+ markConstant(clazz, methodHandleConstant.u2referenceIndex);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ markAsUsed(refConstant);
+
+ markConstant(clazz, refConstant.u2classIndex);
+ markConstant(clazz, refConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ markAsUsed(classConstant);
+
+ markConstant(clazz, classConstant.u2nameIndex);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ markAsUsed(methodTypeConstant);
+
+ markConstant(clazz, methodTypeConstant.u2descriptorIndex);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ markAsUsed(nameAndTypeConstant);
+
+ markConstant(clazz, nameAndTypeConstant.u2nameIndex);
+ markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ markConstant(clazz, attribute.u2attributeNameIndex);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ // Mark the bootstrap method entries.
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ markConstant(clazz, innerClassesAttribute.u2attributeNameIndex);
+
+ // Mark the outer class entries.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
+ markConstant(clazz, enclosingMethodAttribute.u2classIndex);
+
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ markConstant(clazz, signatureAttribute.u2signatureIndex);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
+ markConstant(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the exceptions.
+ exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ markConstant(clazz, codeAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the instructions,
+ // by the exceptions, and by the attributes.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ markConstant(clazz, stackMapAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Mark the constant pool entries referenced by the arguments.
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+ innerClassesInfo.outerClassConstantAccept(clazz, this);
+ innerClassesInfo.innerNameConstantAccept(clazz, this);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (exceptionInfo.u2catchType != 0)
+ {
+ markConstant(clazz, exceptionInfo.u2catchType);
+ }
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ markConstant(clazz, objectType.u2classIndex);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ markConstant(clazz, localVariableInfo.u2nameIndex);
+ markConstant(clazz, localVariableInfo.u2descriptorIndex);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ markConstant(clazz, localVariableTypeInfo.u2nameIndex);
+ markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ markConstant(clazz, annotation.u2typeIndex);
+
+ // Mark the constant pool entries referenced by the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ if (constantElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, constantElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, constantElementValue.u2constantValueIndex);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ if (enumConstantElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
+ markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ if (classElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, classElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, classElementValue.u2classInfoIndex);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ if (annotationElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, annotationElementValue.u2elementNameIndex);
+ }
+
+ // Mark the constant pool entries referenced by the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ if (arrayElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, arrayElementValue.u2elementNameIndex);
+ }
+
+ // Mark the constant pool entries referenced by the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ markConstant(clazz, constantInstruction.constantIndex);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class. This includes
+ * visiting any referenced objects.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+
+
+ /**
+ * Marks the given visitor accepter as being used.
+ */
+ private void markAsUsed(Constant constant)
+ {
+ constant.setVisitorInfo(USED);
+ }
+
+
+ /**
+ * Returns whether the given visitor accepter has been marked as being used.
+ */
+ private boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == USED;
+ }
+
+
+ /**
+ * Removes all constants that are not marked as being used from the given
+ * constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ constantIndexMap[index] = counter;
+
+ Constant constant = constantPool[index];
+
+ // Don't update the flag if this is the second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ constantPool[counter++] = constant;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
+}
diff --git a/src/proguard/classfile/editor/ConstantPoolSorter.java b/src/proguard/classfile/editor/ConstantPoolSorter.java
index faae318..b578624 100644
--- a/src/proguard/classfile/editor/ConstantPoolSorter.java
+++ b/src/proguard/classfile/editor/ConstantPoolSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -112,10 +112,7 @@ implements ClassVisitor
System.arraycopy(newConstantPool, 0, programClass.constantPool, 0, newLength);
// Clear any remaining entries.
- for (int index = newLength; index < constantPoolCount; index++)
- {
- programClass.constantPool[index] = null;
- }
+ Arrays.fill(programClass.constantPool, newLength, constantPoolCount, null);
programClass.u2constantPoolCount = newLength;
diff --git a/src/proguard/classfile/editor/ElementValueAdder.java b/src/proguard/classfile/editor/ElementValueAdder.java
index 8cbd11d..9c8b3f9 100644
--- a/src/proguard/classfile/editor/ElementValueAdder.java
+++ b/src/proguard/classfile/editor/ElementValueAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ElementValuesEditor.java b/src/proguard/classfile/editor/ElementValuesEditor.java
index bfc4e9f..57671e6 100644
--- a/src/proguard/classfile/editor/ElementValuesEditor.java
+++ b/src/proguard/classfile/editor/ElementValuesEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/editor/ExceptionAdder.java
index 1ccb1a6..152a065 100644
--- a/src/proguard/classfile/editor/ExceptionAdder.java
+++ b/src/proguard/classfile/editor/ExceptionAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ExceptionInfoAdder.java b/src/proguard/classfile/editor/ExceptionInfoAdder.java
index e0cc9c5..c1c20fa 100644
--- a/src/proguard/classfile/editor/ExceptionInfoAdder.java
+++ b/src/proguard/classfile/editor/ExceptionInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ExceptionsAttributeEditor.java b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
index 4509a9a..98bb79e 100644
--- a/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
+++ b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/InnerClassesAccessFixer.java b/src/proguard/classfile/editor/InnerClassesAccessFixer.java
new file mode 100644
index 0000000..5a5e8a5
--- /dev/null
+++ b/src/proguard/classfile/editor/InnerClassesAccessFixer.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.InnerClassesInfoVisitor;
+import proguard.classfile.attribute.InnerClassesInfo;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This InnerClassesInfoVisitor fixes the inner class access flags of the
+ * inner classes information that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InnerClassesAccessFixer
+extends SimplifiedVisitor
+implements InnerClassesInfoVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ private int innerClassAccessFlags;
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // The current access flags are the default.
+ innerClassAccessFlags = innerClassesInfo.u2innerClassAccessFlags;
+
+ // See if we can find new access flags.
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+
+ // Update the access flags.
+ innerClassesInfo.u2innerClassAccessFlags = innerClassAccessFlags;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ innerClassAccessFlags =
+ AccessUtil.replaceAccessFlags(innerClassAccessFlags,
+ programClass.u2accessFlags);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/editor/InstructionAdder.java b/src/proguard/classfile/editor/InstructionAdder.java
index 60fde6d..422a348 100644
--- a/src/proguard/classfile/editor/InstructionAdder.java
+++ b/src/proguard/classfile/editor/InstructionAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -68,7 +68,7 @@ implements InstructionVisitor
Instruction newConstantInstruction =
new ConstantInstruction(constantInstruction.opcode,
constantAdder.addConstant(clazz, constantInstruction.constantIndex),
- constantInstruction.constant).shrink();
+ constantInstruction.constant);
// Add the instruction.
codeAttributeComposer.appendInstruction(offset, newConstantInstruction);
diff --git a/src/proguard/classfile/editor/InstructionWriter.java b/src/proguard/classfile/editor/InstructionWriter.java
index d842358..c4a9b09 100644
--- a/src/proguard/classfile/editor/InstructionWriter.java
+++ b/src/proguard/classfile/editor/InstructionWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,7 +31,7 @@ import proguard.classfile.util.SimplifiedVisitor;
* This InstructionVisitor writes out the instructions that it visits,
* collecting instructions that have to be widened. As an AttributeVisitor,
* it then applies the collected changes. The process will be repeated
- * recursively, if necessary.
+ * recursively, if necessary. The caller still has to update the frame sizes.
*
* @author Eric Lafortune
*/
@@ -40,20 +40,26 @@ extends SimplifiedVisitor
implements InstructionVisitor,
AttributeVisitor
{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = false;
+ //*/
+
+
private int codeLength;
private CodeAttributeEditor codeAttributeEditor;
/**
- * Resets the accumulated code changes.
+ * Resets the accumulated code.
* @param codeLength the length of the code that will be edited next.
*/
public void reset(int codeLength)
{
this.codeLength = codeLength;
- // The code attribute editor has to be created lazily.
if (codeAttributeEditor != null)
{
codeAttributeEditor.reset(codeLength);
@@ -61,6 +67,21 @@ implements InstructionVisitor,
}
+ /**
+ * Extends the size of the accumulated code.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void extend(int codeLength)
+ {
+ this.codeLength = codeLength;
+
+ if (codeAttributeEditor != null)
+ {
+ codeAttributeEditor.extend(codeLength);
+ }
+ }
+
+
// Implementations for InstructionVisitor.
public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
@@ -84,7 +105,12 @@ implements InstructionVisitor,
Instruction replacementInstruction =
new ConstantInstruction(constantInstruction.opcode,
constantInstruction.constantIndex,
- constantInstruction.constant).shrink();
+ constantInstruction.constant);
+
+ if (DEBUG)
+ {
+ System.out.println(" "+constantInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
replaceInstruction(offset, replacementInstruction);
@@ -109,10 +135,15 @@ implements InstructionVisitor,
Instruction replacementInstruction =
new VariableInstruction(variableInstruction.opcode,
variableInstruction.variableIndex,
- variableInstruction.constant).shrink();
+ variableInstruction.constant);
replaceInstruction(offset, replacementInstruction);
+ if (DEBUG)
+ {
+ System.out.println(" "+variableInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
+
// Write out a dummy variable instruction for now.
variableInstruction.variableIndex = 0;
variableInstruction.constant = 0;
@@ -143,7 +174,7 @@ implements InstructionVisitor,
// Create a new branch instruction that will fit.
replacementInstruction =
new BranchInstruction(branchInstruction.opcode,
- branchInstruction.branchOffset).shrink();
+ branchInstruction.branchOffset);
break;
}
@@ -190,6 +221,11 @@ implements InstructionVisitor,
}
}
+ if (DEBUG)
+ {
+ System.out.println(" "+branchInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
+
replaceInstruction(offset, replacementInstruction);
// Write out a dummy branch instruction for now.
@@ -214,10 +250,16 @@ implements InstructionVisitor,
// Avoid doing any work if nothing is changing anyway.
if (codeAttributeEditor != null)
{
+ if (DEBUG)
+ {
+ System.out.println("InstructionWriter: widening instructions in "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
// Apply the collected expansions.
codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
- // Clear the modifications for the next run.
+ // Don't keep the editor around. We're assuming it won't be needed
+ // very often, so we don't want to be resetting it all the time.
codeAttributeEditor = null;
}
}
@@ -271,7 +313,7 @@ implements InstructionVisitor,
{
if (codeAttributeEditor == null)
{
- codeAttributeEditor = new CodeAttributeEditor();
+ codeAttributeEditor = new CodeAttributeEditor(false, true);
codeAttributeEditor.reset(codeLength);
}
}
diff --git a/src/proguard/classfile/editor/InterfaceAdder.java b/src/proguard/classfile/editor/InterfaceAdder.java
index e095af6..1ad67dc 100644
--- a/src/proguard/classfile/editor/InterfaceAdder.java
+++ b/src/proguard/classfile/editor/InterfaceAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/InterfaceSorter.java b/src/proguard/classfile/editor/InterfaceSorter.java
index 6521369..0d1f28c 100644
--- a/src/proguard/classfile/editor/InterfaceSorter.java
+++ b/src/proguard/classfile/editor/InterfaceSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,10 +21,14 @@
package proguard.classfile.editor;
import proguard.classfile.*;
-import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.ClassVisitor;
-import java.util.Arrays;
+import java.util.*;
/**
* This ClassVisitor sorts the interfaces of the program classes that it visits.
@@ -33,7 +37,8 @@ import java.util.Arrays;
*/
public class InterfaceSorter
extends SimplifiedVisitor
-implements ClassVisitor
+implements ClassVisitor,
+ AttributeVisitor
{
// Implementations for ClassVisitor.
@@ -42,26 +47,106 @@ implements ClassVisitor
int[] interfaces = programClass.u2interfaces;
int interfacesCount = programClass.u2interfacesCount;
- // Sort the interfaces.
- Arrays.sort(interfaces, 0, interfacesCount);
+ if (interfacesCount > 1)
+ {
+ // Sort the interfaces.
+ Arrays.sort(interfaces, 0, interfacesCount);
+
+ // Remove any duplicate entries.
+ int newInterfacesCount = 0;
+ int previousInterfaceIndex = 0;
+ for (int index = 0; index < interfacesCount; index++)
+ {
+ int interfaceIndex = interfaces[index];
+
+ // Isn't this a duplicate of the previous interface?
+ if (interfaceIndex != previousInterfaceIndex)
+ {
+ interfaces[newInterfacesCount++] = interfaceIndex;
+
+ // Remember the interface.
+ previousInterfaceIndex = interfaceIndex;
+ }
+ }
+
+ programClass.u2interfacesCount = newInterfacesCount;
+
+ // Update the signature, if any
+ programClass.attributesAccept(this);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Process the generic definitions, superclass, and implemented
+ // interfaces.
+ String signature = clazz.getString(signatureAttribute.u2signatureIndex);
+
+ // Count the signature types.
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(signature);
- // Remove any duplicate entries.
- int newInterfacesCount = 0;
- int previousInterfaceIndex = 0;
- for (int index = 0; index < interfacesCount; index++)
+ int count = 0;
+ int interfacesCount = -1;
+ while (internalTypeEnumeration.hasMoreTypes())
{
- int interfaceIndex = interfaces[index];
+ String internalType = internalTypeEnumeration.nextType();
- // Isn't this a duplicate of the previous interface?
- if (interfaceIndex != previousInterfaceIndex)
+ count++;
+
+ if (ClassUtil.isInternalClassType(internalType))
{
- interfaces[newInterfacesCount++] = interfaceIndex;
+ interfacesCount++;
+ }
+ }
+
+ // Put the signature types in an array.
+ internalTypeEnumeration =
+ new InternalTypeEnumeration(signature);
+
+ String[] internalTypes = new String[count];
+
+ for (int index = 0; index < count; index++)
+ {
+ String internalType = internalTypeEnumeration.nextType();
+
+ internalTypes[index] = internalType;
+ }
- // Remember the interface.
- previousInterfaceIndex = interfaceIndex;
+ // Sort the interface types in the array.
+ Arrays.sort(internalTypes, count - interfacesCount, count);
+
+ // Recompose the signature types in a string.
+ StringBuffer newSignatureBuffer = new StringBuffer();
+
+ for (int index = 0; index < count; index++)
+ {
+ // Is this not an interface type, or an interface type that isn't
+ // a duplicate of the previous interface type?
+ if (index < count - interfacesCount ||
+ !internalTypes[index].equals(internalTypes[index-1]))
+ {
+ newSignatureBuffer.append(internalTypes[index]);
}
}
- programClass.u2interfacesCount = newInterfacesCount;
+ String newSignature = newSignatureBuffer.toString();
+
+ // Did the signature change?
+ if (!newSignature.equals(signature))
+ {
+ // Update the signature.
+ ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString());
+
+ // Clear the referenced classes.
+ // TODO: Properly update the referenced classes.
+ signatureAttribute.referencedClasses = null;
+ }
}
}
diff --git a/src/proguard/classfile/editor/InterfacesEditor.java b/src/proguard/classfile/editor/InterfacesEditor.java
index d3170e1..8765e36 100644
--- a/src/proguard/classfile/editor/InterfacesEditor.java
+++ b/src/proguard/classfile/editor/InterfacesEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LineNumberInfoAdder.java b/src/proguard/classfile/editor/LineNumberInfoAdder.java
index aa8c0c4..e1bd14a 100644
--- a/src/proguard/classfile/editor/LineNumberInfoAdder.java
+++ b/src/proguard/classfile/editor/LineNumberInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
index ab96b38..f712d46 100644
--- a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
+++ b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableInfoAdder.java b/src/proguard/classfile/editor/LocalVariableInfoAdder.java
index f285e4f..a270fcf 100644
--- a/src/proguard/classfile/editor/LocalVariableInfoAdder.java
+++ b/src/proguard/classfile/editor/LocalVariableInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
index 053b628..b9e601f 100644
--- a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
+++ b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
index ca50f3f..bed1366 100644
--- a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
+++ b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
index fe5a64d..00f7ef3 100644
--- a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
+++ b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java
index 5f939bb..811acae 100644
--- a/src/proguard/classfile/editor/MemberAdder.java
+++ b/src/proguard/classfile/editor/MemberAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,8 +26,9 @@ import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.MemberVisitor;
/**
- * This ConstantVisitor adds all class members that it visits to the given
- * target class.
+ * This MemberVisitor copies all class members that it visits to the given
+ * target class. Their visitor info is set to the class members from which they
+ * were copied.
*
* @author Eric Lafortune
*/
@@ -45,8 +46,9 @@ implements MemberVisitor
private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0];
- private final ProgramClass targetClass;
-// private final boolean addFields;
+ private final ProgramClass targetClass;
+// private final boolean addFields;
+ private final MemberVisitor extraMemberVisitor;
private final ConstantAdder constantAdder;
private final ClassEditor classEditor;
@@ -59,13 +61,30 @@ implements MemberVisitor
* @param targetClass the class to which all visited class members will be
* added.
*/
+ public MemberAdder(ProgramClass targetClass)
+ {
+ this(targetClass, null);
+ }
+
+
+ /**
+ * Creates a new MemberAdder that will copy methods into the given target
+ * class.
+ * @param targetClass the class to which all visited class members
+ * will be added.
+ * @param extraMemberVisitor an optional member visitor that visits each
+ * new member right after it has been added. This
+ * allows changing the visitor info, for instance.
+ */
// * @param addFields specifies whether fields should be added, or fused
// * with the present fields.
- public MemberAdder(ProgramClass targetClass)//),
-// boolean addFields)
+ public MemberAdder(ProgramClass targetClass,
+// boolean addFields,
+ MemberVisitor extraMemberVisitor)
{
- this.targetClass = targetClass;
-// this.addFields = addFields;
+ this.targetClass = targetClass;
+// this.addFields = addFields;
+ this.extraMemberVisitor = extraMemberVisitor;
constantAdder = new ConstantAdder(targetClass);
classEditor = new ClassEditor(targetClass);
@@ -77,51 +96,54 @@ implements MemberVisitor
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- String name = programField.getName(programClass);
- String descriptor = programField.getDescriptor(programClass);
+ //String name = programField.getName(programClass);
+ //String descriptor = programField.getDescriptor(programClass);
int accessFlags = programField.getAccessFlags();
- // Does the target class already have such a field?
- ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
- if (targetField != null)
- {
- // Is the field private or static?
- int targetAccessFlags = targetField.getAccessFlags();
- if ((targetAccessFlags &
- (ClassConstants.INTERNAL_ACC_PRIVATE |
- ClassConstants.INTERNAL_ACC_STATIC)) != 0)
- {
- if (DEBUG)
- {
- System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]");
- }
-
- // Rename the private or static field.
- targetField.u2nameIndex =
- constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName()));
- }
-// else
-// {
-// // Keep the non-private and non-static field, but update its
-// // contents, in order to keep any references to it valid.
-// if (DEBUG)
-// {
-// System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
-// }
-//
-// // Combine the access flags.
-// targetField.u2accessFlags = accessFlags | targetAccessFlags;
-//
-// // Add and replace any attributes.
-// programField.attributesAccept(programClass,
-// new AttributeAdder(targetClass,
-// targetField,
-// true));
-//
-// // Don't add a new field.
-// return;
-// }
- }
+ // TODO: Handle field with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical field
+ // still causes confused field references.
+ //// Does the target class already have such a field?
+ //ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
+ //if (targetField != null)
+ //{
+ // // Is the field private or static?
+ // int targetAccessFlags = targetField.getAccessFlags();
+ // if ((targetAccessFlags &
+ // (ClassConstants.INTERNAL_ACC_PRIVATE |
+ // ClassConstants.INTERNAL_ACC_STATIC)) != 0)
+ // {
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]");
+ // }
+ //
+ // // Rename the private or static field.
+ // targetField.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName()));
+ // }
+ // else
+ // {
+ // // Keep the non-private and non-static field, but update its
+ // // contents, in order to keep any references to it valid.
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ // }
+ //
+ // // Combine the access flags.
+ // targetField.u2accessFlags = accessFlags | targetAccessFlags;
+ //
+ // // Add and replace any attributes.
+ // programField.attributesAccept(programClass,
+ // new AttributeAdder(targetClass,
+ // targetField,
+ // true));
+ //
+ // // Don't add a new field.
+ // return;
+ // }
+ //}
if (DEBUG)
{
@@ -150,6 +172,12 @@ implements MemberVisitor
// Add the completed field.
classEditor.addField(newProgramField);
+
+ // Visit the newly added field, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramField(targetClass, newProgramField);
+ }
}
@@ -206,9 +234,12 @@ implements MemberVisitor
System.out.println("MemberAdder: renaming method ["+targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
}
- // Rename the private (non-abstract) or static method.
- targetMethod.u2nameIndex =
- constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
+ // TODO: Handle non-abstract method with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical method
+ // still causes confused method references.
+ //// Rename the private (non-abstract) or static method.
+ //targetMethod.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
}
if (DEBUG)
@@ -240,6 +271,12 @@ implements MemberVisitor
// Add the completed method.
classEditor.addMethod(newProgramMethod);
+
+ // Visit the newly added method, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramMethod(targetClass, newProgramMethod);
+ }
}
diff --git a/src/proguard/classfile/editor/MemberReferenceFixer.java b/src/proguard/classfile/editor/MemberReferenceFixer.java
index 4bd8af5..b623047 100644
--- a/src/proguard/classfile/editor/MemberReferenceFixer.java
+++ b/src/proguard/classfile/editor/MemberReferenceFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -298,22 +298,17 @@ implements ClassVisitor,
{
Clazz referencedClass = enclosingMethodAttribute.referencedClass;
- // Does it have a new class?
- if (!enclosingMethodAttribute.getClassName(clazz).equals(referencedClass.getName()))
- {
- // Update the class index.
- enclosingMethodAttribute.u2classIndex =
- new ConstantPoolEditor((ProgramClass)clazz).addClassConstant(referencedClass);
- }
-
// Does it have a new name or type?
- if (!enclosingMethodAttribute.getName(clazz).equals(referencedMember.getName(referencedClass)) ||
- !enclosingMethodAttribute.getType(clazz).equals(referencedMember.getDescriptor(referencedClass)))
+ String newName = referencedMember.getName(referencedClass);
+ String newType = referencedMember.getDescriptor(referencedClass);
+
+ if (!enclosingMethodAttribute.getName(clazz).equals(newName) ||
+ !enclosingMethodAttribute.getType(clazz).equals(newType))
{
// Update the name and type index.
enclosingMethodAttribute.u2nameAndTypeIndex =
- new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(referencedMember.getName(referencedClass),
- referencedMember.getDescriptor(referencedClass));
+ new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName,
+ newType);
}
}
}
@@ -324,7 +319,7 @@ implements ClassVisitor,
// Recompute the maximum stack size if necessary.
if (stackSizesMayHaveChanged)
{
- stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+ stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
}
// Fix the nested attributes.
@@ -433,10 +428,9 @@ implements ClassVisitor,
Member referencedMember)
{
System.out.println("MemberReferenceFixer:");
- System.out.println(" Class file = "+clazz.getName());
- System.out.println(" Ref class = "+referencedClass.getName());
- System.out.println(" Ref member name = "+stringConstant.getString(clazz));
- System.out.println(" -> "+referencedMember.getName(referencedClass));
+ System.out.println(" ["+clazz.getName()+"]: String ["+
+ stringConstant.getString(clazz)+"] -> ["+
+ referencedClass.getName()+"."+referencedMember.getName(referencedClass)+" "+referencedMember.getDescriptor(referencedClass)+"]");
}
@@ -446,11 +440,8 @@ implements ClassVisitor,
Member referencedMember)
{
System.out.println("MemberReferenceFixer:");
- System.out.println(" Class file = "+clazz.getName());
- System.out.println(" Ref class = "+referencedClass.getName());
- System.out.println(" Ref member name = "+refConstant.getName(clazz));
- System.out.println(" -> "+referencedMember.getName(referencedClass));
- System.out.println(" Ref descriptor = "+refConstant.getType(clazz));
- System.out.println(" -> "+referencedMember.getDescriptor(referencedClass));
+ System.out.println(" ["+clazz.getName()+"]: ["+
+ refConstant.getClassName(clazz)+"."+refConstant.getName(clazz)+" "+refConstant.getType(clazz)+"] -> ["+
+ referencedClass.getName()+"."+referencedMember.getName(referencedClass)+" "+referencedMember.getDescriptor(referencedClass)+"]");
}
}
diff --git a/src/proguard/classfile/editor/MethodInvocationFixer.java b/src/proguard/classfile/editor/MethodInvocationFixer.java
index ef76012..e457e63 100644
--- a/src/proguard/classfile/editor/MethodInvocationFixer.java
+++ b/src/proguard/classfile/editor/MethodInvocationFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,6 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
-import proguard.classfile.visitor.*;
/**
* This AttributeVisitor fixes all inappropriate special/virtual/static/interface
@@ -40,9 +39,7 @@ public class MethodInvocationFixer
extends SimplifiedVisitor
implements AttributeVisitor,
InstructionVisitor,
- ConstantVisitor,
- ClassVisitor,
- MemberVisitor
+ ConstantVisitor
{
private static final boolean DEBUG = false;
@@ -88,7 +85,8 @@ implements AttributeVisitor,
clazz.constantPoolEntryAccept(constantIndex, this);
// Did we find the called class and method?
- if (referencedMethod != null)
+ if (referencedClass != null &&
+ referencedMethod != null)
{
// Do we need to update the opcode?
byte opcode = constantInstruction.opcode;
@@ -102,7 +100,7 @@ implements AttributeVisitor,
// Replace the invocation by an invokestatic instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
- constantIndex).shrink();
+ constantIndex);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -123,7 +121,7 @@ implements AttributeVisitor,
// Replace the invocation by an invokespecial instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL,
- constantIndex).shrink();
+ constantIndex);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -149,7 +147,7 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKEINTERFACE,
constantIndex,
- invokeinterfaceConstant).shrink();
+ invokeinterfaceConstant);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -168,12 +166,13 @@ implements AttributeVisitor,
// but not a super call)?
if (opcode != InstructionConstants.OP_INVOKEVIRTUAL &&
(opcode != InstructionConstants.OP_INVOKESPECIAL ||
+ clazz.equals(referencedClass) ||
!clazz.extends_(referencedClass)))
{
// Replace the invocation by an invokevirtual instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL,
- constantIndex).shrink();
+ constantIndex);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -194,40 +193,30 @@ implements AttributeVisitor,
public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
{
- // Check if this is an interface method. Note that we're interested in
- // the class of the method reference, not in the class in which the
- // method was actually found.
- //refConstant.referencedClassAccept(this);
- clazz.constantPoolEntryAccept(refConstant.u2classIndex, this);
-
- // Get the referenced access flags and names.
- refConstant.referencedMemberAccept(this);
- }
-
+ // Remember the referenced class. Note that we're interested in the
+ // class of the method reference, not in the class in which the
+ // method was actually found, unless it is an array type.
+ //
+ if (ClassUtil.isInternalArrayType(refConstant.getClassName(clazz)))
+ {
+ // For an array type, the class will be java.lang.Object.
+ referencedClass = refConstant.referencedClass;
+ }
+ else
+ {
+ clazz.constantPoolEntryAccept(refConstant.u2classIndex, this);
+ }
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
- {
- // Check if this is an interface class.
- classConstant.referencedClassAccept(this);
+ // Remember the referenced method.
+ referencedMethodClass = refConstant.referencedClass;
+ referencedMethod = refConstant.referencedMember;
}
- // Implementations for ClassVisitor.
-
- public void visitAnyClass(Clazz clazz)
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
// Remember the referenced class.
- referencedClass = clazz;
- }
-
-
- // Implementations for MemberVisitor.
-
- public void visitAnyMember(Clazz clazz, Member member)
- {
- // Remember the referenced method.
- referencedMethodClass = clazz;
- referencedMethod = member;
+ referencedClass = classConstant.referencedClass;
}
diff --git a/src/proguard/obfuscate/NameAndTypeUsageMarker.java b/src/proguard/classfile/editor/NameAndTypeShrinker.java
index cc779f0..650f9ba 100644
--- a/src/proguard/obfuscate/NameAndTypeUsageMarker.java
+++ b/src/proguard/classfile/editor/NameAndTypeShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,25 +18,27 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package proguard.obfuscate;
+package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.ConstantPoolRemapper;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
+import java.util.Arrays;
+
+
/**
- * This ClassVisitor marks all NameAndType constant pool entries that are
- * being used in the program classes it visits.
- *
- * @see NameAndTypeShrinker
+ * This ClassVisitor removes NameAndType constant pool entries that are not
+ * used.
*
* @author Eric Lafortune
*/
-public class NameAndTypeUsageMarker
+public class NameAndTypeShrinker
extends SimplifiedVisitor
implements ClassVisitor,
ConstantVisitor,
@@ -45,6 +47,9 @@ implements ClassVisitor,
// A visitor info flag to indicate the NameAndType constant pool entry is being used.
private static final Object USED = new Object();
+ private int[] constantIndexMap;
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
// Implementations for ClassVisitor.
@@ -57,33 +62,37 @@ implements ClassVisitor,
// Mark the NameAndType entries referenced by all EnclosingMethod
// attributes.
programClass.attributesAccept(this);
- }
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
- // Implementations for ConstantVisitor.
-
- public void visitAnyConstant(Clazz clazz, Constant constant) {}
-
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
- public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
- {
- visitRefConstant(clazz, fieldrefConstant);
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
}
- public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
- {
- visitRefConstant(clazz, interfaceMethodrefConstant);
- }
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
- public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
{
- visitRefConstant(clazz, methodrefConstant);
+ markNameAndTypeConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
}
- private void visitRefConstant(Clazz clazz, RefConstant refConstant)
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
markNameAndTypeConstant(clazz, refConstant.u2nameAndTypeIndex);
}
@@ -118,7 +127,7 @@ implements ClassVisitor,
* Marks the given VisitorAccepter as being used.
* In this context, the VisitorAccepter will be a NameAndTypeConstant object.
*/
- private static void markAsUsed(VisitorAccepter visitorAccepter)
+ private void markAsUsed(VisitorAccepter visitorAccepter)
{
visitorAccepter.setVisitorInfo(USED);
}
@@ -128,8 +137,52 @@ implements ClassVisitor,
* Returns whether the given VisitorAccepter has been marked as being used.
* In this context, the VisitorAccepter will be a NameAndTypeConstant object.
*/
- static boolean isUsed(VisitorAccepter visitorAccepter)
+ private boolean isUsed(VisitorAccepter visitorAccepter)
{
return visitorAccepter.getVisitorInfo() == USED;
}
+
+
+ /**
+ * Removes all NameAndType entries that are not marked as being used
+ * from the given constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap == null ||
+ constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ constantIndexMap[index] = counter;
+
+ Constant constant = constantPool[index];
+
+ // Don't update the flag if this is the second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType ||
+ isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ constantPool[counter++] = constant;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
}
diff --git a/src/proguard/classfile/editor/NamedAttributeDeleter.java b/src/proguard/classfile/editor/NamedAttributeDeleter.java
index 0c4d339..6aa5cdf 100644
--- a/src/proguard/classfile/editor/NamedAttributeDeleter.java
+++ b/src/proguard/classfile/editor/NamedAttributeDeleter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
index 4cad6b8..232747f 100644
--- a/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
+++ b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/StackSizeUpdater.java b/src/proguard/classfile/editor/StackSizeUpdater.java
index 94e0519..d90b3d0 100644
--- a/src/proguard/classfile/editor/StackSizeUpdater.java
+++ b/src/proguard/classfile/editor/StackSizeUpdater.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/SubclassAdder.java b/src/proguard/classfile/editor/SubclassAdder.java
index 6b9fd64..717bb1c 100644
--- a/src/proguard/classfile/editor/SubclassAdder.java
+++ b/src/proguard/classfile/editor/SubclassAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/SubclassToAdder.java b/src/proguard/classfile/editor/SubclassToAdder.java
index deb242f..109152b 100644
--- a/src/proguard/classfile/editor/SubclassToAdder.java
+++ b/src/proguard/classfile/editor/SubclassToAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Utf8UsageMarker.java b/src/proguard/classfile/editor/Utf8Shrinker.java
index c59ebb8..eda5826 100644
--- a/src/proguard/obfuscate/Utf8UsageMarker.java
+++ b/src/proguard/classfile/editor/Utf8Shrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,7 +18,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package proguard.obfuscate;
+package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
@@ -28,18 +28,19 @@ import proguard.classfile.attribute.preverification.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.ConstantPoolRemapper;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.*;
+import java.util.Arrays;
+
+
/**
- * This ClassVisitor marks all UTF-8 constant pool entries that are
- * being used in the program classes it visits.
- *
- * @see Utf8Shrinker
+ * This ClassVisitor removes UTF-8 constant pool entries that are not used.
*
* @author Eric Lafortune
*/
-public class Utf8UsageMarker
+public class Utf8Shrinker
extends SimplifiedVisitor
implements ClassVisitor,
MemberVisitor,
@@ -54,6 +55,9 @@ implements ClassVisitor,
// A visitor info flag to indicate the UTF-8 constant pool entry is being used.
private static final Object USED = new Object();
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
// Implementations for ClassVisitor.
@@ -68,6 +72,22 @@ implements ClassVisitor,
// Mark the UTF-8 entries referenced by the attributes.
programClass.attributesAccept(this);
+
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
}
@@ -375,7 +395,7 @@ implements ClassVisitor,
* Marks the given VisitorAccepter as being used.
* In this context, the VisitorAccepter will be a Utf8Constant object.
*/
- private static void markAsUsed(VisitorAccepter visitorAccepter)
+ private void markAsUsed(VisitorAccepter visitorAccepter)
{
visitorAccepter.setVisitorInfo(USED);
}
@@ -385,8 +405,51 @@ implements ClassVisitor,
* Returns whether the given VisitorAccepter has been marked as being used.
* In this context, the VisitorAccepter will be a Utf8Constant object.
*/
- static boolean isUsed(VisitorAccepter visitorAccepter)
+ private boolean isUsed(VisitorAccepter visitorAccepter)
{
return visitorAccepter.getVisitorInfo() == USED;
}
+
+
+ /**
+ * Removes all UTF-8 entries that are not marked as being used
+ * from the given constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ constantIndexMap[index] = counter;
+
+ Constant constant = constantPool[index];
+
+ // Don't update the flag if this is the second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 ||
+ isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ constantPool[counter++] = constant;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
}
diff --git a/src/proguard/classfile/editor/VariableCleaner.java b/src/proguard/classfile/editor/VariableCleaner.java
index 1e93c15..63b7d4a 100644
--- a/src/proguard/classfile/editor/VariableCleaner.java
+++ b/src/proguard/classfile/editor/VariableCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,15 +22,15 @@ package proguard.classfile.editor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
-import proguard.classfile.attribute.visitor.*;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.optimize.info.VariableUsageMarker;
+
+import java.util.Arrays;
/**
- * This AttributeVisitor cleans up unused variables in all attributes that it
- * visits.
+ * This AttributeVisitor cleans up variable tables in all code attributes that
+ * it visits. It trims overlapping local variables. It removes empty local
+ * variables and empty local variable tables.
*
* @author Eric Lafortune
*/
@@ -38,7 +38,8 @@ public class VariableCleaner
extends SimplifiedVisitor
implements AttributeVisitor
{
- private final VariableUsageMarker variableUsageMarker = new VariableUsageMarker();
+ private boolean deleteLocalVariableTableAttribute;
+ private boolean deleteLocalVariableTypeTableAttribute;
// Implementations for AttributeVisitor.
@@ -48,11 +49,35 @@ implements AttributeVisitor
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
- // Figure out the local variables that are used by the code.
- variableUsageMarker.visitCodeAttribute(clazz, method, codeAttribute);
+ deleteLocalVariableTableAttribute = false;
+ deleteLocalVariableTypeTableAttribute = false;
- // Clean up the variables of the attributes.
+ // Trim the local variable table and the local variable type table.
codeAttribute.attributesAccept(clazz, method, this);
+
+ // Delete the local variable table if it ended up empty.
+ if (deleteLocalVariableTableAttribute)
+ {
+ AttributesEditor editor =
+ new AttributesEditor((ProgramClass)clazz,
+ (ProgramMember)method,
+ codeAttribute,
+ true);
+
+ editor.deleteAttribute(ClassConstants.ATTR_LocalVariableTable);
+ }
+
+ // Delete the local variable type table if it ended up empty.
+ if (deleteLocalVariableTypeTableAttribute)
+ {
+ AttributesEditor editor =
+ new AttributesEditor((ProgramClass)clazz,
+ (ProgramMember)method,
+ codeAttribute,
+ true);
+
+ editor.deleteAttribute(ClassConstants.ATTR_LocalVariableTypeTable);
+ }
}
@@ -60,9 +85,20 @@ implements AttributeVisitor
{
// Clean up local variables that aren't used.
localVariableTableAttribute.u2localVariableTableLength =
- removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
- localVariableTableAttribute.u2localVariableTableLength,
- codeAttribute.u2maxLocals);
+ removeUnusedLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Trim the code blocks of the local variables.
+ trimLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Delete the attribute in a moment, if it is empty.
+ if (localVariableTableAttribute.u2localVariableTableLength == 0)
+ {
+ deleteLocalVariableTableAttribute = true;
+ }
}
@@ -70,9 +106,20 @@ implements AttributeVisitor
{
// Clean up local variables that aren't used.
localVariableTypeTableAttribute.u2localVariableTypeTableLength =
- removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
- localVariableTypeTableAttribute.u2localVariableTypeTableLength,
- codeAttribute.u2maxLocals);
+ removeUnusedLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Trim the code blocks of the local variables.
+ trimLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Delete the attribute in a moment, if it is empty.
+ if (localVariableTypeTableAttribute.u2localVariableTypeTableLength == 0)
+ {
+ deleteLocalVariableTypeTableAttribute = true;
+ }
}
@@ -80,27 +127,30 @@ implements AttributeVisitor
/**
* Returns the given list of local variables, without the ones that aren't
- * used
+ * used.
*/
- private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
- int localVariableInfoCount,
- int maxLocals)
+ private int removeUnusedLocalVariables(LocalVariableInfo[] localVariableInfos,
+ int localVariableInfoCount,
+ int maxLocals)
{
// Overwrite all empty local variable entries.
+ // Do keep parameter entries.
int newIndex = 0;
- for (int index = 0; index < localVariableInfoCount && index < maxLocals; index++)
+ for (int index = 0; index < localVariableInfoCount; index++)
{
- if (variableUsageMarker.isVariableUsed(index))
+ LocalVariableInfo localVariableInfo = localVariableInfos[index];
+
+ if (localVariableInfo.u2index >= 0 &&
+ localVariableInfo.u2index < maxLocals &&
+ (localVariableInfo.u2startPC == 0 ||
+ localVariableInfo.u2length > 0))
{
localVariableInfos[newIndex++] = localVariableInfos[index];
}
}
// Clean up any remaining array elements.
- for (int index = newIndex; index < localVariableInfoCount; index++)
- {
- localVariableInfos[index] = null;
- }
+ Arrays.fill(localVariableInfos, newIndex, localVariableInfoCount, null);
return newIndex;
}
@@ -108,28 +158,114 @@ implements AttributeVisitor
/**
* Returns the given list of local variable types, without the ones that
- * aren't used
+ * aren't used.
*/
- private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
- int localVariableTypeInfoCount,
- int maxLocals)
+ private int removeUnusedLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
+ int localVariableTypeInfoCount,
+ int maxLocals)
{
// Overwrite all empty local variable type entries.
+ // Do keep parameter entries.
int newIndex = 0;
- for (int index = 0; index < localVariableTypeInfoCount && index < maxLocals; index++)
+ for (int index = 0; index < localVariableTypeInfoCount; index++)
{
- if (variableUsageMarker.isVariableUsed(index))
+ LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
+
+ if (localVariableTypeInfo.u2index >= 0 &&
+ localVariableTypeInfo.u2index < maxLocals &&
+ (localVariableTypeInfo.u2startPC == 0 ||
+ localVariableTypeInfo.u2length > 0))
{
localVariableTypeInfos[newIndex++] = localVariableTypeInfos[index];
}
}
// Clean up any remaining array elements.
- for (int index = newIndex; index < localVariableTypeInfoCount; index++)
+ Arrays.fill(localVariableTypeInfos, newIndex, localVariableTypeInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ /**
+ * Sorts the given list of local variables and trims their code blocks
+ * when necessary. The block is trimmed at the end, which is a bit
+ * arbitrary.
+ */
+ private void trimLocalVariables(LocalVariableInfo[] localVariableInfos,
+ int localVariableInfoCount,
+ int maxLocals)
+ {
+ // Sort the local variable entries.
+ Arrays.sort(localVariableInfos, 0, localVariableInfoCount);
+
+ int[] startPCs = createMaxArray(maxLocals);
+
+ // Trim the local variable entries, starting at the last one.
+ for (int index = localVariableInfoCount-1; index >= 0; index--)
{
- localVariableTypeInfos[index] = null;
+ LocalVariableInfo localVariableInfo = localVariableInfos[index];
+
+ // Make sure the variable's code block doesn't overlap with the
+ // next one for the same variable.
+ int maxLength = startPCs[localVariableInfo.u2index] -
+ localVariableInfo.u2startPC;
+
+ if (localVariableInfo.u2length > maxLength)
+ {
+ localVariableInfo.u2length = maxLength;
+ }
+
+ startPCs[localVariableInfo.u2index] = localVariableInfo.u2startPC;
}
+ }
- return newIndex;
+
+ /**
+ * Sorts the given list of local variable types and trims their code blocks
+ * when necessary. The block is trimmed at the end, which is a bit
+ * arbitrary.
+ */
+ private void trimLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
+ int localVariableTypeInfoCount,
+ int maxLocals)
+ {
+ // Sort the local variable entries.
+ Arrays.sort(localVariableTypeInfos, 0, localVariableTypeInfoCount);
+
+ int[] startPCs = createMaxArray(maxLocals);
+
+ // Trim the local variable entries, starting at the last one.
+ for (int index = localVariableTypeInfoCount-1; index >= 0; index--)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
+
+ // Make sure the variable's code block doesn't overlap with the
+ // next one for the same variable.
+ int maxLength = startPCs[localVariableTypeInfo.u2index] -
+ localVariableTypeInfo.u2startPC;
+
+ if (localVariableTypeInfo.u2length > maxLength)
+ {
+ localVariableTypeInfo.u2length = maxLength;
+ }
+
+ startPCs[localVariableTypeInfo.u2index] = localVariableTypeInfo.u2startPC;
+ }
+ }
+
+
+ /**
+ * Creates an integer array of the given length, initialized with
+ * Integer.MAX_VALUE.
+ */
+ private int[] createMaxArray(int length)
+ {
+ int[] startPCs = new int[length];
+ for (int index = 0; index < length; index++)
+ {
+ startPCs[index] = Integer.MAX_VALUE;
+ }
+ return startPCs;
}
} \ No newline at end of file
diff --git a/src/proguard/classfile/editor/VariableEditor.java b/src/proguard/classfile/editor/VariableEditor.java
index a583b49..b5143b5 100644
--- a/src/proguard/classfile/editor/VariableEditor.java
+++ b/src/proguard/classfile/editor/VariableEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,6 +25,8 @@ import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor accumulates specified changes to local variables, and
* then applies these accumulated changes to the code attributes that it visits.
@@ -53,14 +55,13 @@ implements AttributeVisitor
// Try to reuse the previous array.
if (deleted.length < maxLocals)
{
+ // Create a new array.
deleted = new boolean[maxLocals];
}
else
{
- for (int index = 0; index < maxLocals; index++)
- {
- deleted[index] = false;
- }
+ // Reset the array.
+ Arrays.fill(deleted, 0, maxLocals, false);
}
modified = false;
diff --git a/src/proguard/classfile/editor/VariableRemapper.java b/src/proguard/classfile/editor/VariableRemapper.java
index 590cd4e..ca9d88a 100644
--- a/src/proguard/classfile/editor/VariableRemapper.java
+++ b/src/proguard/classfile/editor/VariableRemapper.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -40,6 +40,9 @@ implements AttributeVisitor,
LocalVariableInfoVisitor,
LocalVariableTypeInfoVisitor
{
+ private static final boolean DEBUG = false;
+
+
private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
private int[] variableMap;
@@ -62,6 +65,19 @@ implements AttributeVisitor,
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
+ if (DEBUG)
+ {
+ System.out.println("VariableRemapper: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ for (int index= 0; index < codeAttribute.u2maxLocals; index++)
+ {
+ System.out.println(" v"+index+" -> "+variableMap[index]);
+ }
+ }
+
+ // Remap the variables of the attributes, before editing the code and
+ // cleaning up its local variable frame.
+ codeAttribute.attributesAccept(clazz, method, this);
+
// Initially, the code attribute editor doesn't contain any changes.
codeAttributeEditor.reset(codeAttribute.u4codeLength);
@@ -70,9 +86,6 @@ implements AttributeVisitor,
// Apply the code atribute editor.
codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
-
- // Remap the variables of the attributes.
- codeAttribute.attributesAccept(clazz, method, this);
}
@@ -80,11 +93,6 @@ implements AttributeVisitor,
{
// Remap the variable references of the local variables.
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables that haven't been mapped.
- localVariableTableAttribute.u2localVariableTableLength =
- removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
- localVariableTableAttribute.u2localVariableTableLength);
}
@@ -92,11 +100,6 @@ implements AttributeVisitor,
{
// Remap the variable references of the local variables.
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables that haven't been mapped.
- localVariableTypeTableAttribute.u2localVariableTypeTableLength =
- removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
- localVariableTypeTableAttribute.u2localVariableTypeTableLength);
}
@@ -134,7 +137,7 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new VariableInstruction(variableInstruction.opcode,
newVariableIndex,
- variableInstruction.constant).shrink();
+ variableInstruction.constant);
codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
}
@@ -150,48 +153,4 @@ implements AttributeVisitor,
{
return variableMap[variableIndex];
}
-
-
- /**
- * Returns the given list of local variables, without the ones that have
- * been removed.
- */
- private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
- int localVariableInfoCount)
- {
- // Overwrite all empty local variable entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableInfoCount; index++)
- {
- LocalVariableInfo localVariableInfo = localVariableInfos[index];
- if (localVariableInfo.u2index >= 0)
- {
- localVariableInfos[newIndex++] = localVariableInfo;
- }
- }
-
- return newIndex;
- }
-
-
- /**
- * Returns the given list of local variable types, without the ones that
- * have been removed.
- */
- private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
- int localVariableTypeInfoCount)
- {
- // Overwrite all empty local variable type entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableTypeInfoCount; index++)
- {
- LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
- if (localVariableTypeInfo.u2index >= 0)
- {
- localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
- }
- }
-
- return newIndex;
- }
}
diff --git a/src/proguard/classfile/editor/VariableSizeUpdater.java b/src/proguard/classfile/editor/VariableSizeUpdater.java
index 18958c5..2feaa9d 100644
--- a/src/proguard/classfile/editor/VariableSizeUpdater.java
+++ b/src/proguard/classfile/editor/VariableSizeUpdater.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,7 +29,8 @@ import proguard.classfile.util.*;
/**
* This AttributeVisitor computes and updates the maximum local variable frame
- * size of the code attributes that it visits.
+ * size of the code attributes that it visits. It also cleans up the local
+ * variable tables.
*
* @author Eric Lafortune
*/
@@ -45,6 +46,9 @@ implements AttributeVisitor,
//*/
+ private VariableCleaner variableCleaner = new VariableCleaner();
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -69,6 +73,9 @@ implements AttributeVisitor,
// Go over all instructions.
codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Remove the unused variables of the attributes.
+ variableCleaner.visitCodeAttribute(clazz, method, codeAttribute);
}
@@ -91,7 +98,7 @@ implements AttributeVisitor,
if (DEBUG)
{
- System.out.println("Max locals: "+codeAttribute.u2maxLocals+" <- "+variableInstruction.toString(offset));
+ System.out.println(" Max locals: "+codeAttribute.u2maxLocals+" <- "+variableInstruction.toString(offset));
}
}
}
diff --git a/src/proguard/classfile/instruction/BranchInstruction.java b/src/proguard/classfile/instruction/BranchInstruction.java
index 2baa917..f3a7080 100644
--- a/src/proguard/classfile/instruction/BranchInstruction.java
+++ b/src/proguard/classfile/instruction/BranchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -174,7 +174,6 @@ public class BranchInstruction extends Instruction
*/
private int requiredBranchOffsetSize()
{
- return branchOffset << 16 >> 16 == branchOffset ? 2 :
- 4;
+ return (short)branchOffset == branchOffset ? 2 : 4;
}
}
diff --git a/src/proguard/classfile/instruction/ConstantInstruction.java b/src/proguard/classfile/instruction/ConstantInstruction.java
index 6c2d1a3..42d1523 100644
--- a/src/proguard/classfile/instruction/ConstantInstruction.java
+++ b/src/proguard/classfile/instruction/ConstantInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -93,13 +93,9 @@ implements ConstantVisitor
public byte canonicalOpcode()
{
// Remove the _w extension, if any.
- switch (opcode)
- {
- case InstructionConstants.OP_LDC_W:
- case InstructionConstants.OP_LDC2_W: return InstructionConstants.OP_LDC;
-
- default: return opcode;
- }
+ return
+ opcode == InstructionConstants.OP_LDC_W ? InstructionConstants.OP_LDC :
+ opcode;
}
public Instruction shrink()
@@ -185,7 +181,8 @@ implements ConstantVisitor
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
- // The some parameters may be popped from the stack.
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ // Some parameters may be popped from the stack.
clazz.constantPoolEntryAccept(constantIndex, this);
stackPopCount += parameterStackDelta;
break;
@@ -208,6 +205,7 @@ implements ConstantVisitor
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
// The field value or a return value may be pushed onto the stack.
clazz.constantPoolEntryAccept(constantIndex, this);
stackPushCount += typeStackDelta;
@@ -226,8 +224,9 @@ implements ConstantVisitor
public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) {}
public void visitStringConstant(Clazz clazz, StringConstant stringConstant) {}
public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) {}
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) {}
public void visitClassConstant(Clazz clazz, ClassConstant classConstant) {}
- public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) {}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) {}
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
@@ -238,21 +237,27 @@ implements ConstantVisitor
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+ }
+
+
public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
{
- visitRefConstant(clazz, interfaceMethodrefConstant);
+ clazz.constantPoolEntryAccept(interfaceMethodrefConstant.u2nameAndTypeIndex, this);
}
public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
{
- visitRefConstant(clazz, methodrefConstant);
+ clazz.constantPoolEntryAccept(methodrefConstant.u2nameAndTypeIndex, this);
}
- private void visitRefConstant(Clazz clazz, RefConstant methodrefConstant)
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
- String type = methodrefConstant.getType(clazz);
+ String type = nameAndTypeConstant.getType(clazz);
parameterStackDelta = ClassUtil.internalMethodParameterSize(type);
typeStackDelta = ClassUtil.internalTypeSize(ClassUtil.internalMethodReturnType(type));
@@ -263,7 +268,7 @@ implements ConstantVisitor
public String toString()
{
- return getName()+" #"+constantIndex;
+ return getName()+" #"+constantIndex+(constantSize() == 0 ? "" : ", "+constant);
}
@@ -285,6 +290,7 @@ implements ConstantVisitor
private int constantSize()
{
return opcode == InstructionConstants.OP_MULTIANEWARRAY ? 1 :
+ opcode == InstructionConstants.OP_INVOKEDYNAMIC ||
opcode == InstructionConstants.OP_INVOKEINTERFACE ? 2 :
0;
}
diff --git a/src/proguard/classfile/instruction/Instruction.java b/src/proguard/classfile/instruction/Instruction.java
index 8437495..33e705d 100644
--- a/src/proguard/classfile/instruction/Instruction.java
+++ b/src/proguard/classfile/instruction/Instruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -220,7 +220,7 @@ public abstract class Instruction
false, // invokespecial
false, // invokestatic
false, // invokeinterface
- false, // unused
+ false, // invokedynamic
false, // new
false, // newarray
false, // anewarray
@@ -429,7 +429,7 @@ public abstract class Instruction
1, // invokespecial
0, // invokestatic
1, // invokeinterface
- 0, // unused
+ 0, // invokedynamic
0, // new
1, // newarray
1, // anewarray
@@ -638,7 +638,7 @@ public abstract class Instruction
0, // invokespecial
0, // invokestatic
0, // invokeinterface
- 0, // unused
+ 0, // invokedynamic
1, // new
1, // newarray
1, // anewarray
@@ -887,7 +887,7 @@ public abstract class Instruction
protected static void writeSignedByte(byte[] code, int offset, int value)
{
- if (value << 24 >> 24 != value)
+ if ((byte)value != value)
{
throw new IllegalArgumentException("Signed byte value out of range ["+value+"]");
}
@@ -897,7 +897,7 @@ public abstract class Instruction
protected static void writeSignedShort(byte[] code, int offset, int value)
{
- if (value << 16 >> 16 != value)
+ if ((short)value != value)
{
throw new IllegalArgumentException("Signed short value out of range ["+value+"]");
}
diff --git a/src/proguard/classfile/instruction/InstructionConstants.java b/src/proguard/classfile/instruction/InstructionConstants.java
index 78730b3..d8cbd98 100644
--- a/src/proguard/classfile/instruction/InstructionConstants.java
+++ b/src/proguard/classfile/instruction/InstructionConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -213,22 +213,22 @@ public interface InstructionConstants
public static final byte OP_INVOKESPECIAL = -73;
public static final byte OP_INVOKESTATIC = -72;
public static final byte OP_INVOKEINTERFACE = -71;
-// public static final byte OP_UNUSED = -70;
- public static final byte OP_NEW = -69;
- public static final byte OP_NEWARRAY = -68;
- public static final byte OP_ANEWARRAY = -67;
- public static final byte OP_ARRAYLENGTH = -66;
- public static final byte OP_ATHROW = -65;
- public static final byte OP_CHECKCAST = -64;
- public static final byte OP_INSTANCEOF = -63;
- public static final byte OP_MONITORENTER = -62;
- public static final byte OP_MONITOREXIT = -61;
- public static final byte OP_WIDE = -60;
- public static final byte OP_MULTIANEWARRAY = -59;
- public static final byte OP_IFNULL = -58;
- public static final byte OP_IFNONNULL = -57;
- public static final byte OP_GOTO_W = -56;
- public static final byte OP_JSR_W = -55;
+ public static final byte OP_INVOKEDYNAMIC = -70;
+ public static final byte OP_NEW = -69;
+ public static final byte OP_NEWARRAY = -68;
+ public static final byte OP_ANEWARRAY = -67;
+ public static final byte OP_ARRAYLENGTH = -66;
+ public static final byte OP_ATHROW = -65;
+ public static final byte OP_CHECKCAST = -64;
+ public static final byte OP_INSTANCEOF = -63;
+ public static final byte OP_MONITORENTER = -62;
+ public static final byte OP_MONITOREXIT = -61;
+ public static final byte OP_WIDE = -60;
+ public static final byte OP_MULTIANEWARRAY = -59;
+ public static final byte OP_IFNULL = -58;
+ public static final byte OP_IFNONNULL = -57;
+ public static final byte OP_GOTO_W = -56;
+ public static final byte OP_JSR_W = -55;
public static final String[] NAMES =
@@ -419,7 +419,7 @@ public interface InstructionConstants
"invokespecial",
"invokestatic",
"invokeinterface",
- "unused",
+ "invokedynamic",
"new",
"newarray",
"anewarray",
diff --git a/src/proguard/classfile/instruction/InstructionFactory.java b/src/proguard/classfile/instruction/InstructionFactory.java
index f898471..89d498c 100644
--- a/src/proguard/classfile/instruction/InstructionFactory.java
+++ b/src/proguard/classfile/instruction/InstructionFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -182,6 +182,7 @@ public class InstructionFactory
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
case InstructionConstants.OP_NEW:
case InstructionConstants.OP_ANEWARRAY:
diff --git a/src/proguard/classfile/instruction/InstructionUtil.java b/src/proguard/classfile/instruction/InstructionUtil.java
index a3a328a..c6ae99b 100644
--- a/src/proguard/classfile/instruction/InstructionUtil.java
+++ b/src/proguard/classfile/instruction/InstructionUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/LookUpSwitchInstruction.java b/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
index 178cce5..807c0cc 100644
--- a/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
+++ b/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/SimpleInstruction.java b/src/proguard/classfile/instruction/SimpleInstruction.java
index 84e6344..c9a2957 100644
--- a/src/proguard/classfile/instruction/SimpleInstruction.java
+++ b/src/proguard/classfile/instruction/SimpleInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -248,8 +248,8 @@ public class SimpleInstruction extends Instruction
private int requiredConstantSize()
{
return constant >= -1 && constant <= 5 ? 0 :
- constant << 24 >> 24 == constant ? 1 :
- constant << 16 >> 16 == constant ? 2 :
+ (byte)constant == constant ? 1 :
+ (short)constant == constant ? 2 :
4;
}
}
diff --git a/src/proguard/classfile/instruction/SwitchInstruction.java b/src/proguard/classfile/instruction/SwitchInstruction.java
index b98c2fb..3706ba0 100644
--- a/src/proguard/classfile/instruction/SwitchInstruction.java
+++ b/src/proguard/classfile/instruction/SwitchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/TableSwitchInstruction.java b/src/proguard/classfile/instruction/TableSwitchInstruction.java
index ee81af5..45490e5 100644
--- a/src/proguard/classfile/instruction/TableSwitchInstruction.java
+++ b/src/proguard/classfile/instruction/TableSwitchInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/VariableInstruction.java b/src/proguard/classfile/instruction/VariableInstruction.java
index 309f802..6390e0a 100644
--- a/src/proguard/classfile/instruction/VariableInstruction.java
+++ b/src/proguard/classfile/instruction/VariableInstruction.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -365,8 +365,8 @@ public class VariableInstruction extends Instruction
private int requiredConstantSize()
{
return opcode != InstructionConstants.OP_IINC ? 0 :
- constant << 24 >> 24 == constant ? 1 :
- constant << 16 >> 16 == constant ? 2 :
+ (byte)constant == constant ? 1 :
+ (short)constant == constant ? 2 :
4;
}
}
diff --git a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
index 71b2cde..4d739c2 100644
--- a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java b/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java
new file mode 100644
index 0000000..6b24e98
--- /dev/null
+++ b/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given ConstantVisitor visit all constants
+ * of the instructions it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionConstantVisitor
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new InstructionConstantVisitor.
+ * @param constantVisitor the ConstantVisitor to which visits will be
+ * delegated.
+ */
+ public InstructionConstantVisitor(ConstantVisitor constantVisitor)
+ {
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ constantVisitor);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/instruction/visitor/InstructionCounter.java b/src/proguard/classfile/instruction/visitor/InstructionCounter.java
index 1d10980..5623498 100644
--- a/src/proguard/classfile/instruction/visitor/InstructionCounter.java
+++ b/src/proguard/classfile/instruction/visitor/InstructionCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/InstructionVisitor.java b/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
index 11af131..cffb15e 100644
--- a/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
index aada455..444fd57 100644
--- a/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/io/LibraryClassReader.java b/src/proguard/classfile/io/LibraryClassReader.java
index f14471c..d1eab3e 100644
--- a/src/proguard/classfile/io/LibraryClassReader.java
+++ b/src/proguard/classfile/io/LibraryClassReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -277,6 +277,18 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ dataInput.skipBytes(4);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ dataInput.skipBytes(3);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
dataInput.skipBytes(4);
@@ -289,6 +301,12 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ dataInput.skipBytes(2);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
dataInput.skipBytes(4);
@@ -325,16 +343,19 @@ implements ClassVisitor,
switch (u1tag)
{
- case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
case ClassConstants.CONSTANT_Integer: return new IntegerConstant();
case ClassConstants.CONSTANT_Float: return new FloatConstant();
case ClassConstants.CONSTANT_Long: return new LongConstant();
case ClassConstants.CONSTANT_Double: return new DoubleConstant();
case ClassConstants.CONSTANT_String: return new StringConstant();
+ case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
+ case ClassConstants.CONSTANT_InvokeDynamic: return new InvokeDynamicConstant();
+ case ClassConstants.CONSTANT_MethodHandle: return new MethodHandleConstant();
case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant();
case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant();
case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
case ClassConstants.CONSTANT_Class: return new ClassConstant();
+ case ClassConstants.CONSTANT_MethodType : return new MethodTypeConstant();
case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant();
default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool");
diff --git a/src/proguard/classfile/io/ProgramClassReader.java b/src/proguard/classfile/io/ProgramClassReader.java
index 476a346..80a38f7 100644
--- a/src/proguard/classfile/io/ProgramClassReader.java
+++ b/src/proguard/classfile/io/ProgramClassReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -46,6 +46,7 @@ implements ClassVisitor,
MemberVisitor,
ConstantVisitor,
AttributeVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
ExceptionInfoVisitor,
StackMapFrameVisitor,
@@ -250,6 +251,20 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.u2bootstrapMethodAttributeIndex = dataInput.readUnsignedShort();
+ invokeDynamicConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ methodHandleConstant.u1referenceKind = dataInput.readUnsignedByte();
+ methodHandleConstant.u2referenceIndex = dataInput.readUnsignedShort();
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
refConstant.u2classIndex = dataInput.readUnsignedShort();
@@ -263,6 +278,12 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ methodTypeConstant.u2descriptorIndex = dataInput.readUnsignedShort();
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
nameAndTypeConstant.u2nameIndex = dataInput.readUnsignedShort();
@@ -281,6 +302,21 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Read the bootstrap methods.
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount = dataInput.readUnsignedShort();
+
+ bootstrapMethodsAttribute.bootstrapMethods = new BootstrapMethodInfo[bootstrapMethodsAttribute.u2bootstrapMethodsCount];
+ for (int index = 0; index < bootstrapMethodsAttribute.u2bootstrapMethodsCount; index++)
+ {
+ BootstrapMethodInfo bootstrapMethodInfo = new BootstrapMethodInfo();
+ visitBootstrapMethodInfo(clazz, bootstrapMethodInfo);
+ bootstrapMethodsAttribute.bootstrapMethods[index] = bootstrapMethodInfo;
+ }
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
sourceFileAttribute.u2sourceFileIndex = dataInput.readUnsignedShort();
@@ -302,7 +338,7 @@ implements ClassVisitor,
for (int index = 0; index < innerClassesAttribute.u2classesCount; index++)
{
InnerClassesInfo innerClassesInfo = new InnerClassesInfo();
- this.visitInnerClassesInfo(clazz, innerClassesInfo);
+ visitInnerClassesInfo(clazz, innerClassesInfo);
innerClassesAttribute.classes[index] = innerClassesInfo;
}
}
@@ -372,7 +408,7 @@ implements ClassVisitor,
for (int index = 0; index < codeAttribute.u2exceptionTableLength; index++)
{
ExceptionInfo exceptionInfo = new ExceptionInfo();
- this.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
codeAttribute.exceptionTable[index] = exceptionInfo;
}
@@ -398,7 +434,7 @@ implements ClassVisitor,
for (int index = 0; index < stackMapAttribute.u2stackMapFramesCount; index++)
{
FullFrame stackMapFrame = new FullFrame();
- this.visitFullFrame(clazz, method, codeAttribute, index, stackMapFrame);
+ visitFullFrame(clazz, method, codeAttribute, index, stackMapFrame);
stackMapAttribute.stackMapFrames[index] = stackMapFrame;
}
}
@@ -428,7 +464,7 @@ implements ClassVisitor,
for (int index = 0; index < lineNumberTableAttribute.u2lineNumberTableLength; index++)
{
LineNumberInfo lineNumberInfo = new LineNumberInfo();
- this.visitLineNumberInfo(clazz, method, codeAttribute, lineNumberInfo);
+ visitLineNumberInfo(clazz, method, codeAttribute, lineNumberInfo);
lineNumberTableAttribute.lineNumberTable[index] = lineNumberInfo;
}
}
@@ -443,7 +479,7 @@ implements ClassVisitor,
for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++)
{
LocalVariableInfo localVariableInfo = new LocalVariableInfo();
- this.visitLocalVariableInfo(clazz, method, codeAttribute, localVariableInfo);
+ visitLocalVariableInfo(clazz, method, codeAttribute, localVariableInfo);
localVariableTableAttribute.localVariableTable[index] = localVariableInfo;
}
}
@@ -458,7 +494,7 @@ implements ClassVisitor,
for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++)
{
LocalVariableTypeInfo localVariableTypeInfo = new LocalVariableTypeInfo();
- this.visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeInfo);
+ visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeInfo);
localVariableTypeTableAttribute.localVariableTypeTable[index] = localVariableTypeInfo;
}
}
@@ -473,7 +509,7 @@ implements ClassVisitor,
for (int index = 0; index < annotationsAttribute.u2annotationsCount; index++)
{
Annotation annotation = new Annotation();
- this.visitAnnotation(clazz, annotation);
+ visitAnnotation(clazz, annotation);
annotationsAttribute.annotations[index] = annotation;
}
}
@@ -508,7 +544,7 @@ implements ClassVisitor,
for (int index = 0; index < u2annotationsCount; index++)
{
Annotation annotation = new Annotation();
- this.visitAnnotation(clazz, annotation);
+ visitAnnotation(clazz, annotation);
annotations[index] = annotation;
}
@@ -527,6 +563,22 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ bootstrapMethodInfo.u2methodHandleIndex = dataInput.readUnsignedShort();
+
+ // Read the bootstrap method arguments.
+ bootstrapMethodInfo.u2methodArgumentCount = dataInput.readUnsignedShort();
+ bootstrapMethodInfo.u2methodArguments = new int[bootstrapMethodInfo.u2methodArgumentCount];
+ for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++)
+ {
+ bootstrapMethodInfo.u2methodArguments[index] = dataInput.readUnsignedShort();
+ }
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
@@ -721,7 +773,7 @@ implements ClassVisitor,
{
// Read the annotation.
Annotation annotationValue = new Annotation();
- this.visitAnnotation(clazz, annotationValue);
+ visitAnnotation(clazz, annotationValue);
annotationElementValue.annotationValue = annotationValue;
}
@@ -749,16 +801,19 @@ implements ClassVisitor,
switch (u1tag)
{
- case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
case ClassConstants.CONSTANT_Integer: return new IntegerConstant();
case ClassConstants.CONSTANT_Float: return new FloatConstant();
case ClassConstants.CONSTANT_Long: return new LongConstant();
case ClassConstants.CONSTANT_Double: return new DoubleConstant();
case ClassConstants.CONSTANT_String: return new StringConstant();
+ case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
+ case ClassConstants.CONSTANT_InvokeDynamic: return new InvokeDynamicConstant();
+ case ClassConstants.CONSTANT_MethodHandle: return new MethodHandleConstant();
case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant();
case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant();
case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
case ClassConstants.CONSTANT_Class: return new ClassConstant();
+ case ClassConstants.CONSTANT_MethodType : return new MethodTypeConstant();
case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant();
default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool");
@@ -771,7 +826,9 @@ implements ClassVisitor,
int u2attributeNameIndex = dataInput.readUnsignedShort();
int u4attributeLength = dataInput.readInt();
String attributeName = clazz.getString(u2attributeNameIndex);
+
Attribute attribute =
+ attributeName.equals(ClassConstants.ATTR_BootstrapMethods) ? (Attribute)new BootstrapMethodsAttribute():
attributeName.equals(ClassConstants.ATTR_SourceFile) ? (Attribute)new SourceFileAttribute():
attributeName.equals(ClassConstants.ATTR_SourceDir) ? (Attribute)new SourceDirAttribute():
attributeName.equals(ClassConstants.ATTR_InnerClasses) ? (Attribute)new InnerClassesAttribute():
@@ -849,7 +906,7 @@ implements ClassVisitor,
case ClassConstants.INTERNAL_TYPE_FLOAT:
case ClassConstants.INTERNAL_TYPE_LONG:
case ClassConstants.INTERNAL_TYPE_DOUBLE:
- case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue(u1tag);
+ case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue((char)u1tag);
case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT: return new EnumConstantElementValue();
case ClassConstants.ELEMENT_VALUE_CLASS: return new ClassElementValue();
diff --git a/src/proguard/classfile/io/ProgramClassWriter.java b/src/proguard/classfile/io/ProgramClassWriter.java
index e56f08a..dbf1de3 100644
--- a/src/proguard/classfile/io/ProgramClassWriter.java
+++ b/src/proguard/classfile/io/ProgramClassWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -57,7 +57,7 @@ implements ClassVisitor,
/**
- * Creates a new ProgramClassWriter for reading from the given DataOutput.
+ * Creates a new ProgramClassWriter for writing to the given DataOutput.
*/
public ProgramClassWriter(DataOutput dataOutput)
{
@@ -208,6 +208,20 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ dataOutput.writeShort(invokeDynamicConstant.u2bootstrapMethodAttributeIndex);
+ dataOutput.writeShort(invokeDynamicConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ dataOutput.writeByte(methodHandleConstant.u1referenceKind);
+ dataOutput.writeShort(methodHandleConstant.u2referenceIndex);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
dataOutput.writeShort(refConstant.u2classIndex);
@@ -221,6 +235,12 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ dataOutput.writeShort(methodTypeConstant.u2descriptorIndex);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
dataOutput.writeShort(nameAndTypeConstant.u2nameIndex);
@@ -263,6 +283,7 @@ implements ClassVisitor,
private class AttributeBodyWriter
extends SimplifiedVisitor
implements AttributeVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
ExceptionInfoVisitor,
StackMapFrameVisitor,
@@ -282,6 +303,15 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Write the bootstrap methods.
+ dataOutput.writeShort(bootstrapMethodsAttribute.u2bootstrapMethodsCount);
+
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex);
@@ -438,8 +468,7 @@ implements ClassVisitor,
for (int index = 0; index < u2annotationsCount; index++)
{
- Annotation annotation = annotations[index];
- this.visitAnnotation(clazz, annotation);
+ visitAnnotation(clazz, annotations[index]);
}
}
@@ -453,6 +482,22 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ dataOutput.writeShort(bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Write the bootstrap method arguments.
+ dataOutput.writeShort(bootstrapMethodInfo.u2methodArgumentCount);
+
+ for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++)
+ {
+ dataOutput.writeShort(bootstrapMethodInfo.u2methodArguments[index]);
+ }
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
diff --git a/src/proguard/classfile/io/RuntimeDataInput.java b/src/proguard/classfile/io/RuntimeDataInput.java
index 104b7c9..ce2d1a5 100644
--- a/src/proguard/classfile/io/RuntimeDataInput.java
+++ b/src/proguard/classfile/io/RuntimeDataInput.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/io/RuntimeDataOutput.java b/src/proguard/classfile/io/RuntimeDataOutput.java
index ffde3af..44acc70 100644
--- a/src/proguard/classfile/io/RuntimeDataOutput.java
+++ b/src/proguard/classfile/io/RuntimeDataOutput.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/AccessUtil.java b/src/proguard/classfile/util/AccessUtil.java
index 3ad6961..d16f576 100644
--- a/src/proguard/classfile/util/AccessUtil.java
+++ b/src/proguard/classfile/util/AccessUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/ClassReferenceInitializer.java b/src/proguard/classfile/util/ClassReferenceInitializer.java
index b1f2c27..a5748ee 100644
--- a/src/proguard/classfile/util/ClassReferenceInitializer.java
+++ b/src/proguard/classfile/util/ClassReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,7 +64,8 @@ implements ClassVisitor,
private final ClassPool programClassPool;
private final ClassPool libraryClassPool;
private final WarningPrinter missingClassWarningPrinter;
- private final WarningPrinter missingMemberWarningPrinter;
+ private final WarningPrinter missingProgramMemberWarningPrinter;
+ private final WarningPrinter missingLibraryMemberWarningPrinter;
private final WarningPrinter dependencyWarningPrinter;
private final MemberFinder memberFinder = new MemberFinder();
@@ -78,14 +79,16 @@ implements ClassVisitor,
public ClassReferenceInitializer(ClassPool programClassPool,
ClassPool libraryClassPool,
WarningPrinter missingClassWarningPrinter,
- WarningPrinter missingMemberWarningPrinter,
+ WarningPrinter missingProgramMemberWarningPrinter,
+ WarningPrinter missingLibraryMemberWarningPrinter,
WarningPrinter dependencyWarningPrinter)
{
- this.programClassPool = programClassPool;
- this.libraryClassPool = libraryClassPool;
- this.missingClassWarningPrinter = missingClassWarningPrinter;
- this.missingMemberWarningPrinter = missingMemberWarningPrinter;
- this.dependencyWarningPrinter = dependencyWarningPrinter;
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.missingClassWarningPrinter = missingClassWarningPrinter;
+ this.missingProgramMemberWarningPrinter = missingProgramMemberWarningPrinter;
+ this.missingLibraryMemberWarningPrinter = missingLibraryMemberWarningPrinter;
+ this.dependencyWarningPrinter = dependencyWarningPrinter;
}
@@ -166,17 +169,30 @@ implements ClassVisitor,
}
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Fill out the MethodHandle class.
+ methodHandleConstant.javaLangInvokeMethodHandleClass =
+ findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
String className = refConstant.getClassName(clazz);
+ // Methods for array types should be found in the Object class.
+ if (ClassUtil.isInternalArrayType(className))
+ {
+ className = ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT;
+ }
+
// See if we can find the referenced class.
// Unresolved references are assumed to refer to library classes
// that will not change anyway.
Clazz referencedClass = findClass(clazz.getName(), className);
- if (referencedClass != null &&
- !ClassUtil.isInternalArrayType(className))
+ if (referencedClass != null)
{
String name = refConstant.getName(clazz);
String type = refConstant.getType(clazz);
@@ -194,7 +210,13 @@ implements ClassVisitor,
if (refConstant.referencedMember == null)
{
- // We've haven't found the class member anywhere in the hierarchy.
+ // We haven't found the class member anywhere in the hierarchy.
+ boolean isProgramClass = referencedClass instanceof ProgramClass;
+
+ WarningPrinter missingMemberWarningPrinter = isProgramClass ?
+ missingProgramMemberWarningPrinter :
+ missingLibraryMemberWarningPrinter;
+
missingMemberWarningPrinter.print(clazz.getName(),
className,
"Warning: " +
@@ -203,7 +225,11 @@ implements ClassVisitor,
(isFieldRef ?
"field '" + ClassUtil.externalFullFieldDescription(0, name, type) :
"method '" + ClassUtil.externalFullMethodDescription(className, 0, name, type)) +
- "' in class " +
+ "' in " +
+ (isProgramClass ?
+ "program" :
+ "library") +
+ " class " +
ClassUtil.externalClassName(className));
}
}
@@ -216,7 +242,7 @@ implements ClassVisitor,
// Fill out the referenced class.
classConstant.referencedClass =
- findClass(className, classConstant.getName(clazz));
+ findClass(className, ClassUtil.internalClassNameFromClassType(classConstant.getName(clazz)));
// Fill out the Class class.
classConstant.javaLangClassClass =
@@ -224,6 +250,14 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ // Fill out the MethodType class.
+ methodTypeConstant.javaLangInvokeMethodTypeClass =
+ findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE);
+ }
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -235,49 +269,36 @@ implements ClassVisitor,
String enclosingClassName = enclosingMethodAttribute.getClassName(clazz);
// See if we can find the referenced class.
- Clazz referencedClass = findClass(className, enclosingClassName);
+ enclosingMethodAttribute.referencedClass =
+ findClass(className, enclosingClassName);
- if (referencedClass == null)
+ if (enclosingMethodAttribute.referencedClass != null)
{
- // We couldn't find the enclosing class.
- missingClassWarningPrinter.print(className,
- enclosingClassName,
- "Warning: " +
- ClassUtil.externalClassName(className) +
- ": can't find enclosing class " +
- ClassUtil.externalClassName(enclosingClassName));
- return;
- }
-
- // Make sure there is actually an enclosed method.
- if (enclosingMethodAttribute.u2nameAndTypeIndex == 0)
- {
- return;
- }
-
- String name = enclosingMethodAttribute.getName(clazz);
- String type = enclosingMethodAttribute.getType(clazz);
+ // Is there an enclosing method? Otherwise it's just initialization
+ // code outside of the constructors.
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ String name = enclosingMethodAttribute.getName(clazz);
+ String type = enclosingMethodAttribute.getType(clazz);
- // See if we can find the method in the referenced class.
- Method referencedMethod = referencedClass.findMethod(name, type);
+ // See if we can find the method in the referenced class.
+ enclosingMethodAttribute.referencedMethod =
+ enclosingMethodAttribute.referencedClass.findMethod(name, type);
- if (referencedMethod == null)
- {
- // We couldn't find the enclosing method.
- missingMemberWarningPrinter.print(className,
- enclosingClassName,
- "Warning: " +
- ClassUtil.externalClassName(className) +
- ": can't find enclosing method '" +
- ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) +
- "' in class " +
- ClassUtil.externalClassName(enclosingClassName));
- return;
+ if (enclosingMethodAttribute.referencedMethod == null)
+ {
+ // We couldn't find the enclosing method.
+ missingProgramMemberWarningPrinter.print(className,
+ enclosingClassName,
+ "Warning: " +
+ ClassUtil.externalClassName(className) +
+ ": can't find enclosing method '" +
+ ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) +
+ "' in program class " +
+ ClassUtil.externalClassName(enclosingClassName));
+ }
+ }
}
-
- // Save the references.
- enclosingMethodAttribute.referencedClass = referencedClass;
- enclosingMethodAttribute.referencedMethod = referencedMethod;
}
@@ -501,11 +522,17 @@ implements ClassVisitor,
*/
private Clazz findClass(String referencingClassName, String name)
{
- // Ignore any primitive array types.
- if (ClassUtil.isInternalArrayType(name) &&
- !ClassUtil.isInternalClassType(name))
+ // Is it an array type?
+ if (ClassUtil.isInternalArrayType(name))
{
- return null;
+ // Ignore any primitive array types.
+ if (!ClassUtil.isInternalClassType(name))
+ {
+ return null;
+ }
+
+ // Strip the array part.
+ name = ClassUtil.internalClassNameFromClassType(name);
}
// First look for the class in the program class pool.
diff --git a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
index 30fd526..993a559 100644
--- a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
+++ b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
index af2a209..fb431b8 100644
--- a/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
+++ b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -106,11 +106,6 @@ implements ClassVisitor,
libraryClass.interfaceClasses = interfaceClasses;
}
-
- // Discard the name Strings. From now on, we'll use the object
- // references.
- libraryClass.superClassName = null;
- libraryClass.interfaceNames = null;
}
diff --git a/src/proguard/classfile/util/ClassUtil.java b/src/proguard/classfile/util/ClassUtil.java
index 5f25f01..fb38616 100644
--- a/src/proguard/classfile/util/ClassUtil.java
+++ b/src/proguard/classfile/util/ClassUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -100,6 +100,8 @@ public class ClassUtil
classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_5) ? ClassConstants.INTERNAL_CLASS_VERSION_1_5 :
classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6_ALIAS) ||
classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6) ? ClassConstants.INTERNAL_CLASS_VERSION_1_6 :
+ classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_7_ALIAS) ||
+ classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_7) ? ClassConstants.INTERNAL_CLASS_VERSION_1_7 :
0;
}
@@ -119,6 +121,7 @@ public class ClassUtil
case ClassConstants.INTERNAL_CLASS_VERSION_1_4: return ClassConstants.EXTERNAL_CLASS_VERSION_1_4;
case ClassConstants.INTERNAL_CLASS_VERSION_1_5: return ClassConstants.EXTERNAL_CLASS_VERSION_1_5;
case ClassConstants.INTERNAL_CLASS_VERSION_1_6: return ClassConstants.EXTERNAL_CLASS_VERSION_1_6;
+ case ClassConstants.INTERNAL_CLASS_VERSION_1_7: return ClassConstants.EXTERNAL_CLASS_VERSION_1_7;
default: return null;
}
}
@@ -132,11 +135,14 @@ public class ClassUtil
public static void checkVersionNumbers(int classVersion) throws UnsupportedOperationException
{
if (classVersion < ClassConstants.INTERNAL_CLASS_VERSION_1_0 ||
- classVersion > ClassConstants.INTERNAL_CLASS_VERSION_1_6)
+ classVersion > ClassConstants.INTERNAL_CLASS_VERSION_1_7)
{
- throw new UnsupportedOperationException("Unsupported version number ["+
+ throw new UnsupportedOperationException("Unsupported class version number ["+
internalMajorClassVersion(classVersion)+"."+
- internalMinorClassVersion(classVersion)+"] for class format");
+ internalMinorClassVersion(classVersion)+"] (maximum "+
+ ClassConstants.INTERNAL_CLASS_VERSION_1_7_MAJOR+"."+
+ ClassConstants.INTERNAL_CLASS_VERSION_1_7_MINOR+", Java "+
+ ClassConstants.EXTERNAL_CLASS_VERSION_1_7+")");
}
}
@@ -189,8 +195,25 @@ public class ClassUtil
/**
- * Converts an internal class name into an external short class name, without
- * package specification.
+ * Returns the external base type of an external array type, dropping any
+ * array brackets.
+ * @param externalArrayType the external array type,
+ * e.g. "<code>java.lang.Object[][]</code>"
+ * @return the external base type,
+ * e.g. "<code>java.lang.Object</code>".
+ */
+ public static String externalBaseType(String externalArrayType)
+ {
+ int index = externalArrayType.indexOf(ClassConstants.EXTERNAL_TYPE_ARRAY);
+ return index >= 0 ?
+ externalArrayType.substring(0, index) :
+ externalArrayType;
+ }
+
+
+ /**
+ * Returns the external short class name of an external class name, dropping
+ * the package specification.
* @param externalClassName the external class name,
* e.g. "<code>java.lang.Object</code>"
* @return the external short class name,
@@ -410,6 +433,21 @@ public class ClassUtil
/**
+ * Returns whether the given method name refers to a class initializer or
+ * an instance initializer.
+ * @param internalMethodName the internal method name,
+ * e.g. "<code>&ltclinit&gt;</code>".
+ * @return whether the method name refers to an initializer,
+ * e.g. <code>true</code>.
+ */
+ public static boolean isInitializer(String internalMethodName)
+ {
+ return internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ||
+ internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);
+ }
+
+
+ /**
* Returns the internal type of the given internal method descriptor.
* @param internalMethodDescriptor the internal method descriptor,
* e.g. "<code>(II)Z</code>".
@@ -869,6 +907,21 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(' ');
+ }
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(' ');
+ }
if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0)
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(' ');
@@ -889,6 +942,10 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(' ');
}
+ else if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' ');
+ }
return string.toString();
}
@@ -950,6 +1007,10 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_TRANSIENT).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' ');
+ }
return string.toString();
}
@@ -1007,6 +1068,14 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_BRIDGE) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_BRIDGE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_VARARGS) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_VARARGS).append(' ');
+ }
if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0)
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_NATIVE).append(' ');
@@ -1019,6 +1088,10 @@ public class ClassUtil
{
string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STRICT).append(' ');
}
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' ');
+ }
return string.toString();
}
diff --git a/src/proguard/classfile/util/DescriptorClassEnumeration.java b/src/proguard/classfile/util/DescriptorClassEnumeration.java
index 0bee2d5..81590fa 100644
--- a/src/proguard/classfile/util/DescriptorClassEnumeration.java
+++ b/src/proguard/classfile/util/DescriptorClassEnumeration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
index 09ffdd0..865e094 100644
--- a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
+++ b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -301,7 +301,8 @@ implements InstructionVisitor,
{
// Save a reference to the corresponding class.
String externalClassName = stringConstant.getString(clazz);
- String internalClassName = ClassUtil.internalClassName(externalClassName);
+ String internalClassName = ClassUtil.internalClassName(
+ ClassUtil.externalBaseType(externalClassName));
stringConstant.referencedClass = findClass(clazz.getName(), internalClassName);
}
@@ -350,7 +351,7 @@ implements InstructionVisitor,
return;
}
- String className = methodrefConstant.getClassName(clazz);
+ String className = methodrefConstant.getClassName(clazz);
// Note that we look for the class by name, since the referenced
// class has not been initialized yet.
@@ -434,11 +435,17 @@ implements InstructionVisitor,
*/
private Clazz findClass(String referencingClassName, String name)
{
- // Ignore any primitive array types.
- if (ClassUtil.isInternalArrayType(name) &&
- !ClassUtil.isInternalClassType(name))
+ // Is it an array type?
+ if (ClassUtil.isInternalArrayType(name))
{
- return null;
+ // Ignore any primitive array types.
+ if (!ClassUtil.isInternalClassType(name))
+ {
+ return null;
+ }
+
+ // Strip the array part.
+ name = ClassUtil.internalClassNameFromClassType(name);
}
// First look for the class in the program class pool.
diff --git a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
index 1f57708..23c8d40 100644
--- a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
+++ b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -52,17 +52,22 @@ public class DynamicMemberReferenceInitializer
extends SimplifiedVisitor
implements InstructionVisitor,
ConstantVisitor,
- AttributeVisitor,
MemberVisitor
{
- public static final int X = InstructionSequenceMatcher.X;
- public static final int Y = InstructionSequenceMatcher.Y;
- public static final int Z = InstructionSequenceMatcher.Z;
+ /*
+ private static boolean DEBUG = true;
+ /*/
+ private static final boolean DEBUG = false;
+ //*/
- public static final int A = InstructionSequenceMatcher.A;
- public static final int B = InstructionSequenceMatcher.B;
- public static final int C = InstructionSequenceMatcher.C;
- public static final int D = InstructionSequenceMatcher.D;
+ public static final int CLASS_INDEX = InstructionSequenceMatcher.X;
+ public static final int MEMBER_NAME_INDEX = InstructionSequenceMatcher.Y;
+ public static final int TYPE_CLASS_INDEX = InstructionSequenceMatcher.Z;
+
+ public static final int PARAMETER0_CLASS_INDEX = InstructionSequenceMatcher.A;
+ public static final int PARAMETER1_CLASS_INDEX = InstructionSequenceMatcher.B;
+ public static final int PARAMETER2_CLASS_INDEX = InstructionSequenceMatcher.C;
+ public static final int PARAMETER3_CLASS_INDEX = InstructionSequenceMatcher.D;
private final Constant[] GET_FIELD_CONSTANTS = new Constant[]
@@ -85,6 +90,26 @@ implements InstructionVisitor,
new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD),
};
+ private final Constant[] GET_CONSTRUCTOR_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR),
+ };
+
+ private final Constant[] GET_DECLARED_CONSTRUCTOR_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR),
+ new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR),
+ };
+
private final Constant[] GET_METHOD_CONSTANTS = new Constant[]
{
new MethodrefConstant(1, 2, null, null),
@@ -105,19 +130,88 @@ implements InstructionVisitor,
new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD),
};
+ private final Constant[] NEW_INTEGER_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_INTEGER_UPDATER),
+ };
+
+ private final Constant[] NEW_LONG_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_LONG_UPDATER),
+ };
+
+ private final Constant[] NEW_REFERENCE_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_REFERENCE_UPDATER),
+ };
+
// SomeClass.class.get[Declared]Field("someField").
private final Instruction[] CONSTANT_GET_FIELD_INSTRUCTIONS = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
+// // SomeClass.class.get[Declared]Constructor(new Class[] {}).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+//
+// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class }).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+//
+// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class, B.class }).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+
// SomeClass.class.get[Declared]Method("someMethod", new Class[] {}).
private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS0 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
@@ -126,13 +220,13 @@ implements InstructionVisitor,
// SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class }).
private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS1 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
@@ -140,32 +234,86 @@ implements InstructionVisitor,
// SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class, B.class }).
private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS2 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, X),
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_2),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
- new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
+ // AtomicIntegerFieldUpdater.newUpdater(A.class, "someField").
+ // AtomicLongFieldUpdater.newUpdater(A.class, "someField").
+ private final Instruction[] CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+ // AtomicReferenceFieldUpdater.newUpdater(A.class, B.class, "someField").
+ private final Instruction[] CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, TYPE_CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
// get[Declared]Field("someField").
private final Instruction[] GET_FIELD_INSTRUCTIONS = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+// // get[Declared]Constructor(new Class[] {}).
+// private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[]
+// {
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+
+ // get[Declared]Constructor(new Class[] { A.class }).
+ private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // get[Declared]Constructor(new Class[] { A.class, B.class }).
+ private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
// get[Declared]Method("someMethod", new Class[] {}).
private final Instruction[] GET_METHOD_INSTRUCTIONS0 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
@@ -174,12 +322,12 @@ implements InstructionVisitor,
// get[Declared]Method("someMethod", new Class[] { A.class }).
private final Instruction[] GET_METHOD_INSTRUCTIONS1 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
@@ -187,20 +335,29 @@ implements InstructionVisitor,
// get[Declared]Method("someMethod", new Class[] { A.class, B.class }).
private final Instruction[] GET_METHOD_INSTRUCTIONS2 = new Instruction[]
{
- new ConstantInstruction(InstructionConstants.OP_LDC, Y),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
new SimpleInstruction(InstructionConstants.OP_ICONST_2),
new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
- new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new SimpleInstruction(InstructionConstants.OP_DUP),
new SimpleInstruction(InstructionConstants.OP_ICONST_1),
- new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
new SimpleInstruction(InstructionConstants.OP_AASTORE),
new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
};
+ // AtomicIntegerFieldUpdater.newUpdater(..., "someField").
+ // AtomicLongFieldUpdater.newUpdater(..., "someField").
+ // AtomicReferenceFieldUpdater.newUpdater(..., "someField").
+ private final Instruction[] NEW_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
private final ClassPool programClassPool;
private final ClassPool libraryClassPool;
@@ -217,6 +374,30 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS,
CONSTANT_GET_FIELD_INSTRUCTIONS);
+// private final InstructionSequenceMatcher constantGetConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher constantGetConstructorMatcher1 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher1 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1);
+//
+// private final InstructionSequenceMatcher constantGetConstructorMatcher2 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher2 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2);
+
private final InstructionSequenceMatcher constantGetMethodMatcher0 =
new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
CONSTANT_GET_METHOD_INSTRUCTIONS0);
@@ -241,6 +422,18 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
CONSTANT_GET_METHOD_INSTRUCTIONS2);
+ private final InstructionSequenceMatcher constantGetIntegerUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS,
+ CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher constantGetLongUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS,
+ CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher constantGetReferenceUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS,
+ CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS);
+
private final InstructionSequenceMatcher getFieldMatcher =
new InstructionSequenceMatcher(GET_FIELD_CONSTANTS,
GET_FIELD_INSTRUCTIONS);
@@ -249,6 +442,30 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS,
GET_FIELD_INSTRUCTIONS);
+// private final InstructionSequenceMatcher getConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher getDeclaredConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// GET_CONSTRUCTOR_INSTRUCTIONS0);
+
+ private final InstructionSequenceMatcher getConstructorMatcher1 =
+ new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getDeclaredConstructorMatcher1 =
+ new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getConstructorMatcher2 =
+ new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher getDeclaredConstructorMatcher2 =
+ new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS2);
+
private final InstructionSequenceMatcher getMethodMatcher0 =
new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
GET_METHOD_INSTRUCTIONS0);
@@ -273,11 +490,24 @@ implements InstructionVisitor,
new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
GET_METHOD_INSTRUCTIONS2);
+ private final InstructionSequenceMatcher getIntegerUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getLongUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getReferenceUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
private final MemberFinder memberFinder = new MemberFinder();
// Fields acting as parameters for the visitors.
private Clazz referencedClass;
+ private String descriptor;
private boolean isDeclared;
private boolean isField;
@@ -307,48 +537,110 @@ implements InstructionVisitor,
// Try to match the SomeClass.class.getField("someField") construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetFieldMatcher,
- getFieldMatcher, true, false);
+ getFieldMatcher, true, false, null, null);
// Try to match the SomeClass.class.getDeclaredField("someField") construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredFieldMatcher,
- getDeclaredFieldMatcher, true, true);
+ getDeclaredFieldMatcher, true, true, null, null);
+
+// // Try to match the SomeClass.class.getConstructor(new Class[]
+// // {}) construct.
+// matchGetMember(clazz, method, codeAttribute, offset, instruction,
+// cnull, //onstantGetConstructorMatcher0,
+// getConstructorMatcher0, false, false,
+// ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+//
+// // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+// // {}) construct.
+// matchGetMember(clazz, method, codeAttribute, offset, instruction,
+// null, //constantGetDeclaredConstructorMatcher0,
+// getDeclaredConstructorMatcher0, false, true,
+// ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getConstructor(new Class[]
+ // { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetConstructorMatcher1,
+ getConstructorMatcher1, false, false,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+ // { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetDeclaredConstructorMatcher1,
+ getDeclaredConstructorMatcher1, false, true,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getConstructor(new Class[]
+ // { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetConstructorMatcher2,
+ getConstructorMatcher2, false, false,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+ // { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetDeclaredConstructorMatcher2,
+ getDeclaredConstructorMatcher2, false, true,
+ ClassConstants.INTERNAL_METHOD_NAME_INIT, null);
// Try to match the SomeClass.class.getMethod("someMethod", new Class[]
// {}) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetMethodMatcher0,
- getMethodMatcher0, false, false);
+ getMethodMatcher0, false, false, null, null);
// Try to match the SomeClass.class.getDeclaredMethod("someMethod",
- // new Class[] {}) construct.
+ // new Class[] {}) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredMethodMatcher0,
- getDeclaredMethodMatcher0, false, true);
+ getDeclaredMethodMatcher0, false, true, null, null);
// Try to match the SomeClass.class.getMethod("someMethod", new Class[]
// { A.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetMethodMatcher1,
- getMethodMatcher1, false, false);
+ getMethodMatcher1, false, false, null, null);
// Try to match the SomeClass.class.getDeclaredMethod("someMethod",
// new Class[] { A.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredMethodMatcher1,
- getDeclaredMethodMatcher1, false, true);
+ getDeclaredMethodMatcher1, false, true, null, null);
// Try to match the SomeClass.class.getMethod("someMethod", new Class[]
// { A.class, B.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetMethodMatcher2,
- getMethodMatcher2, false, false);
+ getMethodMatcher2, false, false, null, null);
// Try to match the SomeClass.class.getDeclaredMethod("someMethod",
- // new Class[] { A.class, B.class }) construct.
+ // new Class[] { A.class, B.class }) construct.
matchGetMember(clazz, method, codeAttribute, offset, instruction,
constantGetDeclaredMethodMatcher2,
- getDeclaredMethodMatcher2, false, true);
+ getDeclaredMethodMatcher2, false, true, null, null);
+
+ // Try to match the AtomicIntegerFieldUpdater.newUpdater(
+ // SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetIntegerUpdaterMatcher,
+ getIntegerUpdaterMatcher, true, false, null,
+ "" + ClassConstants.INTERNAL_TYPE_INT);
+
+ // Try to match the AtomicLongFieldUpdater.newUpdater(
+ // SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetLongUpdaterMatcher,
+ getLongUpdaterMatcher, true, false, null,
+ "" + ClassConstants.INTERNAL_TYPE_LONG);
+
+ // Try to match the AtomicReferenceFieldUpdater.newUpdater(
+ // SomeClass.class, SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetReferenceUpdaterMatcher,
+ getReferenceUpdaterMatcher, true, false, null, null);
}
@@ -364,26 +656,28 @@ implements InstructionVisitor,
InstructionSequenceMatcher constantSequenceMatcher,
InstructionSequenceMatcher variableSequenceMatcher,
boolean isField,
- boolean isDeclared)
+ boolean isDeclared,
+ String defaultName,
+ String defaultDescriptor)
{
- // Try to match the next instruction in the constant sequence.
- instruction.accept(clazz, method, codeAttribute, offset,
- constantSequenceMatcher);
-
- // Did we find a match to fill out the string constant?
- if (constantSequenceMatcher.isMatching())
+ if (constantSequenceMatcher != null)
{
- this.isField = isField;
- this.isDeclared = isDeclared;
-
- // Get the member's class.
- clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(X), this);
-
- // Fill out the matched string constant.
- clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(Y), this);
+ // Try to match the next instruction in the constant sequence.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ constantSequenceMatcher);
- // Don't look for the dynamic construct.
- variableSequenceMatcher.reset();
+ // Did we find a match to fill out the string constant?
+ if (constantSequenceMatcher.isMatching())
+ {
+ initializeStringReference(clazz,
+ constantSequenceMatcher,
+ isField,
+ isDeclared,
+ defaultDescriptor);
+
+ // Don't look for the dynamic construct.
+ variableSequenceMatcher.reset();
+ }
}
// Try to match the next instruction in the variable sequence.
@@ -397,11 +691,41 @@ implements InstructionVisitor,
printDynamicInvocationNote(clazz,
variableSequenceMatcher,
isField,
- isDeclared);
+ isDeclared,
+ defaultName,
+ defaultDescriptor);
}
}
+ /**
+ * Initializes the reference of the matched string constant to the
+ * referenced class member and its class.
+ */
+ private void initializeStringReference(Clazz clazz,
+ InstructionSequenceMatcher constantSequenceMatcher,
+ boolean isField,
+ boolean isDeclared,
+ String defaultDescriptor)
+ {
+ this.isField = isField;
+ this.isDeclared = isDeclared;
+
+ // Get the member's class.
+ int classIndex = constantSequenceMatcher.matchedConstantIndex(CLASS_INDEX);
+ clazz.constantPoolEntryAccept(classIndex, this);
+
+ // Get the field's reference type, if applicable.
+ int typeClassIndex = constantSequenceMatcher.matchedConstantIndex(TYPE_CLASS_INDEX);
+ descriptor = typeClassIndex <= 0 ? defaultDescriptor :
+ ClassUtil.internalTypeFromClassName(clazz.getClassName(typeClassIndex));
+
+ // Fill out the matched string constant.
+ int memberNameIndex = constantSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX);
+ clazz.constantPoolEntryAccept(memberNameIndex, this);
+ }
+
+
// Implementations for ConstantVisitor.
/**
@@ -409,6 +733,11 @@ implements InstructionVisitor,
*/
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
+ if (DEBUG)
+ {
+ System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched class ["+classConstant.getName(clazz)+"]");
+ }
+
// Remember the referenced class.
referencedClass = ClassUtil.isInternalArrayType(classConstant.getName(clazz)) ?
null :
@@ -425,15 +754,20 @@ implements InstructionVisitor,
{
String name = stringConstant.getString(clazz);
+ if (DEBUG)
+ {
+ System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched string ["+name+"]");
+ }
+
// See if we can find the referenced class member locally, or
// somewhere in the hierarchy.
Member referencedMember = isDeclared ? isField ?
- (Member)referencedClass.findField(name, null) :
- (Member)referencedClass.findMethod(name, null) :
+ (Member)referencedClass.findField(name, descriptor) :
+ (Member)referencedClass.findMethod(name, descriptor) :
(Member)memberFinder.findMember(clazz,
referencedClass,
name,
- null,
+ descriptor,
isField);
if (referencedMember != null)
{
@@ -454,7 +788,9 @@ implements InstructionVisitor,
private void printDynamicInvocationNote(Clazz clazz,
InstructionSequenceMatcher noteSequenceMatcher,
boolean isField,
- boolean isDeclared)
+ boolean isDeclared,
+ String defaultName,
+ String defaultDescriptor)
{
// Print out a note about the dynamic invocation.
if (notePrinter != null &&
@@ -465,8 +801,9 @@ implements InstructionVisitor,
noteFieldExceptionMatcher :
noteMethodExceptionMatcher;
- int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(Y);
- String memberName = clazz.getStringString(memberNameIndex);
+ int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX);
+ String memberName = memberNameIndex <= 0 ? defaultName :
+ clazz.getStringString(memberNameIndex);
if (noteExceptionMatcher == null ||
!noteExceptionMatcher.matches(memberName))
@@ -479,7 +816,8 @@ implements InstructionVisitor,
externalMemberDescription += '(';
for (int count = 0; count < 2; count++)
{
- int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(A + count);
+ int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(
+ PARAMETER0_CLASS_INDEX + count);
if (memberArgumentIndex > 0)
{
if (count > 0)
@@ -501,7 +839,9 @@ implements InstructionVisitor,
ClassUtil.externalClassName(clazz.getName()) +
" accesses a " +
(isDeclared ? "declared " : "") +
- (isField ? "field" : "method") +
+ (isField ? "field" :
+ memberName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ?
+ "constructor" : "method") +
" '" +
externalMemberDescription +
"' dynamically");
@@ -511,9 +851,12 @@ implements InstructionVisitor,
if (isField)
{
- classVisitor =
+ classVisitor = defaultDescriptor == null ?
+ new AllFieldVisitor(
+ new MemberNameFilter(memberName, this)) :
new AllFieldVisitor(
- new MemberNameFilter(memberName, this));
+ new MemberNameFilter(memberName,
+ new MemberDescriptorFilter(defaultDescriptor, this)));
}
else
{
@@ -521,20 +864,16 @@ implements InstructionVisitor,
String methodDescriptor = "(";
for (int count = 0; count < 2; count++)
{
- int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(A + count);
+ int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(PARAMETER0_CLASS_INDEX + count);
if (memberArgumentIndex > 0)
{
- if (count > 0)
- {
- methodDescriptor += ',';
- }
String className = clazz.getClassName(memberArgumentIndex);
methodDescriptor += ClassUtil.isInternalArrayType(className) ?
className :
ClassUtil.internalTypeFromClassName(className);
}
}
- methodDescriptor += ")L///;";
+ methodDescriptor += ")L***;";
classVisitor =
new AllMethodVisitor(
@@ -571,7 +910,7 @@ implements InstructionVisitor,
System.out.println(" Maybe this is program method '" +
ClassUtil.externalFullClassDescription(0, programClass.getName()) +
" { " +
- ClassUtil.externalFullMethodDescription(null, 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) +
+ ClassUtil.externalFullMethodDescription(programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) +
"; }'");
}
}
@@ -597,7 +936,7 @@ implements InstructionVisitor,
System.out.println(" Maybe this is library method '" +
ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
" { " +
- ClassUtil.externalFullMethodDescription(null, 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) +
+ ClassUtil.externalFullMethodDescription(libraryClass.getName(), 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) +
"; }'");
}
}
diff --git a/src/proguard/classfile/util/EnumFieldReferenceInitializer.java b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java
new file mode 100644
index 0000000..dae6db2
--- /dev/null
+++ b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java
@@ -0,0 +1,150 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.*;
+import proguard.classfile.visitor.*;
+import proguard.util.StringMatcher;
+
+/**
+ * This ElementValueVisitor initializes the field references of the
+ * EnumConstantElementValue instances that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class EnumFieldReferenceInitializer
+extends SimplifiedVisitor
+implements ElementValueVisitor,
+ InstructionVisitor,
+ ConstantVisitor
+{
+ /*
+ private static boolean DEBUG = true;
+ /*/
+ private static final boolean DEBUG = false;
+ //*/
+
+ private MemberVisitor enumFieldFinder = new AllAttributeVisitor(
+ new AllInstructionVisitor(this));
+
+ // Fields acting as parameters and return values for the visitors.
+ private String enumTypeName;
+ private String enumConstantName;
+ private boolean enumConstantNameFound;
+ private Clazz referencedEnumClass;
+ private Field referencedEnumField;
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {}
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+
+ if (enumConstantElementValue.referencedClasses != null &&
+ enumConstantElementValue.referencedClasses.length > 0)
+ {
+ referencedEnumClass = enumConstantElementValue.referencedClasses[0];
+ if (referencedEnumClass != null)
+ {
+ // Try to find the enum field through the static enum
+ // initialization code (at least for program classes).
+ enumTypeName = enumConstantElementValue.getTypeName(clazz);
+ enumConstantName = enumConstantElementValue.getConstantName(clazz);
+ referencedEnumField = null;
+ referencedEnumClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
+ enumFieldFinder);
+
+ // Otherwise try to find the enum field through its name.
+ // The constant name could be different from the field name, if
+ // the latter is already obfuscated.
+ if (referencedEnumField == null)
+ {
+ referencedEnumField =
+ referencedEnumClass.findField(enumConstantName,
+ enumTypeName);
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("EnumFieldReferenceInitializer: ["+referencedEnumClass.getName()+"."+enumConstantName+"] -> "+referencedEnumField);
+ }
+
+ enumConstantElementValue.referencedField = referencedEnumField;
+ }
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_LDC:
+ case InstructionConstants.OP_LDC_W:
+ case InstructionConstants.OP_PUTSTATIC:
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ enumConstantNameFound =
+ enumConstantName.equals(stringConstant.getString(clazz));
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ if (enumConstantNameFound)
+ {
+ if (enumTypeName.equals(fieldrefConstant.getType(clazz)))
+ {
+ referencedEnumField = (Field)fieldrefConstant.referencedMember;
+ }
+
+ enumConstantNameFound = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/classfile/util/ExternalTypeEnumeration.java b/src/proguard/classfile/util/ExternalTypeEnumeration.java
index 6371888..e5b7067 100644
--- a/src/proguard/classfile/util/ExternalTypeEnumeration.java
+++ b/src/proguard/classfile/util/ExternalTypeEnumeration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/InstructionSequenceMatcher.java b/src/proguard/classfile/util/InstructionSequenceMatcher.java
index 8a689d5..8c529a9 100644
--- a/src/proguard/classfile/util/InstructionSequenceMatcher.java
+++ b/src/proguard/classfile/util/InstructionSequenceMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
+import java.util.Arrays;
+
/**
* This InstructionVisitor checks whether a given pattern instruction sequence
* occurs in the instructions that are visited. The arguments of the
@@ -40,8 +42,8 @@ implements InstructionVisitor,
ConstantVisitor
{
/*
- private static boolean DEBUG = false;
- public static boolean DEBUG_MORE = false;
+ public static boolean DEBUG = true;
+ public static boolean DEBUG_MORE = true;
/*/
private static final boolean DEBUG = false;
private static final boolean DEBUG_MORE = false;
@@ -60,14 +62,15 @@ implements InstructionVisitor,
private final Constant[] patternConstants;
private final Instruction[] patternInstructions;
- private boolean matching;
- private boolean matchingAnyWildCards;
- private int patternInstructionIndex;
- private final int[] matchedInstructionOffsets;
- private int matchedArgumentFlags;
- private final int[] matchedArguments = new int[7];
- private long matchedConstantFlags;
- private final int[] matchedConstantIndices;
+ private boolean matching;
+ private int patternInstructionIndex;
+ private final int[] matchedInstructionOffsets;
+ private int matchedArgumentFlags;
+ private final int[] matchedArguments = new int[7];
+ private final long[] matchedConstantFlags;
+ private final int[] matchedConstantIndices;
+ private int constantFlags;
+ private int previousConstantFlags;
// Fields acting as a parameter and a return value for visitor methods.
private Constant patternConstant;
@@ -87,6 +90,7 @@ implements InstructionVisitor,
this.patternInstructions = patternInstructions;
matchedInstructionOffsets = new int[patternInstructions.length];
+ matchedConstantFlags = new long[(patternConstants.length + 63) / 64];
matchedConstantIndices = new int[patternConstants.length];
}
@@ -98,34 +102,55 @@ implements InstructionVisitor,
{
patternInstructionIndex = 0;
matchedArgumentFlags = 0;
- matchedConstantFlags = 0L;
- }
+ Arrays.fill(matchedConstantFlags, 0L);
- public boolean isMatching()
- {
- return matching;
+ previousConstantFlags = constantFlags;
+ constantFlags = 0;
}
- public boolean isMatchingAnyWildcards()
+ /**
+ * Returns whether the complete pattern sequence has been matched.
+ */
+ public boolean isMatching()
{
- return matchingAnyWildCards;
+ return matching;
}
+ /**
+ * Returns the number of instructions in the pattern sequence.
+ */
public int instructionCount()
{
return patternInstructions.length;
}
+ /**
+ * Returns the matched instruction offset of the specified pattern
+ * instruction.
+ */
public int matchedInstructionOffset(int index)
{
return matchedInstructionOffsets[index];
}
+ /**
+ * Returns whether the specified wildcard argument was a constant from
+ * the constant pool in the most recent match.
+ */
+ public boolean wasConstant(int argument)
+ {
+ return (previousConstantFlags & (1 << (argument - X))) != 0;
+ }
+
+
+ /**
+ * Returns the value of the specified matched argument (wildcard or not).
+ */
public int matchedArgument(int argument)
{
int argumentIndex = argument - X;
@@ -135,6 +160,9 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the values of the specified matched arguments (wildcard or not).
+ */
public int[] matchedArguments(int[] arguments)
{
int[] matchedArguments = new int[arguments.length];
@@ -148,6 +176,9 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the index of the specified matched constant (wildcard or not).
+ */
public int matchedConstantIndex(int constantIndex)
{
int argumentIndex = constantIndex - X;
@@ -157,6 +188,10 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the value of the specified matched branch offset (wildcard or
+ * not).
+ */
public int matchedBranchOffset(int offset, int branchOffset)
{
int argumentIndex = branchOffset - X;
@@ -166,6 +201,10 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the values of the specified matched jump offsets (wildcard or
+ * not).
+ */
public int[] matchedJumpOffsets(int offset, int[] jumpOffsets)
{
int[] matchedJumpOffsets = new int[jumpOffsets.length];
@@ -387,6 +426,35 @@ implements InstructionVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ InvokeDynamicConstant invokeDynamicPatternConstant = (InvokeDynamicConstant)patternConstant;
+
+ // Check the bootstrap method and the name and type.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ invokeDynamicConstant.getBootstrapMethodAttributeIndex(),
+ invokeDynamicPatternConstant.getBootstrapMethodAttributeIndex()) &&
+ matchingConstantIndices(clazz,
+ invokeDynamicConstant.getNameAndTypeIndex(),
+ invokeDynamicPatternConstant.getNameAndTypeIndex());
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ MethodHandleConstant methodHandlePatternConstant = (MethodHandleConstant)patternConstant;
+
+ // Check the handle type and the name and type.
+ matchingConstant =
+ matchingArguments(methodHandleConstant.getReferenceKind(),
+ methodHandlePatternConstant.getReferenceKind()) &&
+ matchingConstantIndices(clazz,
+ methodHandleConstant.getReferenceIndex(),
+ methodHandlePatternConstant.getReferenceIndex());
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
RefConstant refPatternConstant = (RefConstant)patternConstant;
@@ -414,6 +482,18 @@ implements InstructionVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ MethodTypeConstant typePatternConstant = (MethodTypeConstant)patternConstant;
+
+ // Check the descriptor.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ methodTypeConstant.u2descriptorIndex,
+ typePatternConstant.u2descriptorIndex);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
NameAndTypeConstant typePatternConstant = (NameAndTypeConstant)patternConstant;
@@ -449,11 +529,10 @@ implements InstructionVisitor,
// Check the literal argument.
return argument1 == argument2;
}
- else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0)
+ else if (!isMatchingArgumentIndex(argumentIndex))
{
- // Store a wildcard argument.
- matchedArguments[argumentIndex] = argument1;
- matchedArgumentFlags |= 1 << argumentIndex;
+ // Store the wildcard argument.
+ setMatchingArgument(argumentIndex, argument1);
return true;
}
@@ -465,6 +544,28 @@ implements InstructionVisitor,
}
+ /**
+ * Marks the specified argument (by index) as matching the specified
+ * argument value.
+ */
+ private void setMatchingArgument(int argumentIndex,
+ int argument)
+ {
+ matchedArguments[argumentIndex] = argument;
+ matchedArgumentFlags |= 1 << argumentIndex;
+ }
+
+
+ /**
+ * Returns whether the specified wildcard argument (by index) has been
+ * matched.
+ */
+ private boolean isMatchingArgumentIndex(int argumentIndex)
+ {
+ return (matchedArgumentFlags & (1 << argumentIndex)) != 0;
+ }
+
+
private boolean matchingArguments(int[] arguments1,
int[] arguments2)
{
@@ -491,10 +592,13 @@ implements InstructionVisitor,
{
if (constantIndex2 >= X)
{
+ // Remember that we are trying to match a constant.
+ constantFlags |= 1 << (constantIndex2 - X);
+
// Check the constant index.
return matchingArguments(constantIndex1, constantIndex2);
}
- else if ((matchedConstantFlags & (1L << constantIndex2)) == 0)
+ else if (!isMatchingConstantIndex(constantIndex2))
{
// Check the actual constant.
matchingConstant = false;
@@ -507,8 +611,7 @@ implements InstructionVisitor,
if (matchingConstant)
{
// Store the constant index.
- matchedConstantIndices[constantIndex2] = constantIndex1;
- matchedConstantFlags |= 1L << constantIndex2;
+ setMatchingConstant(constantIndex2, constantIndex1);
}
}
@@ -522,6 +625,27 @@ implements InstructionVisitor,
}
+ /**
+ * Marks the specified constant (by index) as matching the specified
+ * constant index value.
+ */
+ private void setMatchingConstant(int constantIndex,
+ int constantIndex1)
+ {
+ matchedConstantIndices[constantIndex] = constantIndex1;
+ matchedConstantFlags[constantIndex / 64] |= 1L << constantIndex;
+ }
+
+
+ /**
+ * Returns whether the specified wildcard constant has been matched.
+ */
+ private boolean isMatchingConstantIndex(int constantIndex)
+ {
+ return (matchedConstantFlags[constantIndex / 64] & (1L << constantIndex)) != 0;
+ }
+
+
private boolean matchingBranchOffsets(int offset,
int branchOffset1,
int branchOffset2)
@@ -532,11 +656,10 @@ implements InstructionVisitor,
// Check the literal argument.
return branchOffset1 == branchOffset2;
}
- else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0)
+ else if (!isMatchingArgumentIndex(argumentIndex))
{
// Store a wildcard argument.
- matchedArguments[argumentIndex] = offset + branchOffset1;
- matchedArgumentFlags |= 1 << argumentIndex;
+ setMatchingArgument(argumentIndex, offset + branchOffset1);
return true;
}
@@ -595,9 +718,6 @@ implements InstructionVisitor,
// Did we match all instructions in the sequence?
matching = patternInstructionIndex == patternInstructions.length;
- // Did we match any wildcards along the way?
- matchingAnyWildCards = matchedArgumentFlags != 0;
-
if (matching)
{
if (DEBUG)
diff --git a/src/proguard/classfile/util/InternalTypeEnumeration.java b/src/proguard/classfile/util/InternalTypeEnumeration.java
index 76f7e84..9c63ad9 100644
--- a/src/proguard/classfile/util/InternalTypeEnumeration.java
+++ b/src/proguard/classfile/util/InternalTypeEnumeration.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,7 +27,7 @@ import proguard.classfile.ClassConstants;
* An <code>InternalTypeEnumeration</code> provides an enumeration of all
* parameter types listed in a given internal method descriptor or signature.
* The signature can also be a class signature. The return type of a method
- * descriptor can retrieved separately.
+ * descriptor can be retrieved separately.
*
* @author Eric Lafortune
*/
diff --git a/src/proguard/classfile/util/MemberFinder.java b/src/proguard/classfile/util/MemberFinder.java
index 0fdeec0..36c0003 100644
--- a/src/proguard/classfile/util/MemberFinder.java
+++ b/src/proguard/classfile/util/MemberFinder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/MethodLinker.java b/src/proguard/classfile/util/MethodLinker.java
index 5f2ea6f..56b6723 100644
--- a/src/proguard/classfile/util/MethodLinker.java
+++ b/src/proguard/classfile/util/MethodLinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,16 +26,11 @@ import proguard.classfile.visitor.*;
import java.util.*;
/**
- * This ClassVisitor links all corresponding non-private methods in the class
- * hierarchies of all visited classes. Visited classes are typically all class
- * files that are not being subclassed. Chains of links that have been created
- * in previous invocations are merged with new chains of links, in order to
- * create a consistent set of chains.
- * <p>
- * As a MemberVisitor, it links all corresponding class members that it visits,
- * including fields and private class members.
- * <p>
- * Class initialization methods and constructors are always ignored.
+ * This ClassVisitor links all corresponding non-private, non-static,
+ * non-initializer methods in the class hierarchies of all visited classes.
+ * Visited classes are typically all class files that are not being subclassed.
+ * Chains of links that have been created in previous invocations are merged
+ * with new chains of links, in order to create a consistent set of chains.
*
* @author Eric Lafortune
*/
@@ -56,7 +51,7 @@ implements ClassVisitor,
// Collect all non-private members in this class hierarchy.
clazz.hierarchyAccept(true, true, true, false,
new AllMethodVisitor(
- new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
+ new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC,
this)));
// Clean up for the next class hierarchy.
diff --git a/src/proguard/classfile/util/SimplifiedVisitor.java b/src/proguard/classfile/util/SimplifiedVisitor.java
index 87b7fe4..aed46eb 100644
--- a/src/proguard/classfile/util/SimplifiedVisitor.java
+++ b/src/proguard/classfile/util/SimplifiedVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -42,7 +42,7 @@ public abstract class SimplifiedVisitor
/**
* Visits any type of class member of the given class.
*/
- public void visitAnyClass(Clazz Clazz)
+ public void visitAnyClass(Clazz clazz)
{
throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
}
@@ -157,6 +157,18 @@ public abstract class SimplifiedVisitor
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ visitAnyConstant(clazz, invokeDynamicConstant);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ visitAnyConstant(clazz, methodHandleConstant);
+ }
+
+
/**
* Visits any type of RefConstant of the given class.
*/
@@ -199,6 +211,12 @@ public abstract class SimplifiedVisitor
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ visitAnyConstant(clazz, methodTypeConstant);
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
visitAnyConstant(clazz, nameAndTypeConstant);
@@ -222,6 +240,12 @@ public abstract class SimplifiedVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ visitAnyAttribute(clazz, bootstrapMethodsAttribute);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
visitAnyAttribute(clazz, sourceFileAttribute);
diff --git a/src/proguard/classfile/util/StringReferenceInitializer.java b/src/proguard/classfile/util/StringReferenceInitializer.java
index 3884a04..f00f0d3 100644
--- a/src/proguard/classfile/util/StringReferenceInitializer.java
+++ b/src/proguard/classfile/util/StringReferenceInitializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -62,7 +62,8 @@ implements ConstantVisitor
{
// See if we can find the referenced class.
stringConstant.referencedClass =
- findClass(ClassUtil.internalClassName(stringConstant.getString(clazz)));
+ findClass(ClassUtil.internalClassName(
+ ClassUtil.externalBaseType(stringConstant.getString(clazz))));
}
}
diff --git a/src/proguard/classfile/util/StringSharer.java b/src/proguard/classfile/util/StringSharer.java
index 56de7c5..dacb2d1 100644
--- a/src/proguard/classfile/util/StringSharer.java
+++ b/src/proguard/classfile/util/StringSharer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,6 +64,23 @@ implements ClassVisitor,
{
libraryClass.superClassName = superClass.getName();
}
+
+ // Replace the interface name strings by the shared name strings.
+ if (libraryClass.interfaceNames != null)
+ {
+ String[] interfaceNames = libraryClass.interfaceNames;
+ Clazz[] interfaceClasses = new Clazz[interfaceNames.length];
+
+ for (int index = 0; index < interfaceNames.length; index++)
+ {
+ // Keep a reference to the interface class.
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null)
+ {
+ interfaceNames[index] = interfaceClass.getName();
+ }
+ }
+ }
}
@@ -73,7 +90,7 @@ implements ClassVisitor,
public void visitAnyConstant(Clazz clazz, Constant constant) {}
- public void visitAnyStringConstant(Clazz clazz, StringConstant stringConstant)
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
{
Member referencedMember = stringConstant.referencedMember;
if (referencedMember != null)
diff --git a/src/proguard/classfile/util/WarningPrinter.java b/src/proguard/classfile/util/WarningPrinter.java
index 87d8978..39172dd 100644
--- a/src/proguard/classfile/util/WarningPrinter.java
+++ b/src/proguard/classfile/util/WarningPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllClassVisitor.java b/src/proguard/classfile/visitor/AllClassVisitor.java
index 06aca2c..5c6f3de 100644
--- a/src/proguard/classfile/visitor/AllClassVisitor.java
+++ b/src/proguard/classfile/visitor/AllClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllFieldVisitor.java b/src/proguard/classfile/visitor/AllFieldVisitor.java
index 8bff7d4..92c4b05 100644
--- a/src/proguard/classfile/visitor/AllFieldVisitor.java
+++ b/src/proguard/classfile/visitor/AllFieldVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllMemberVisitor.java b/src/proguard/classfile/visitor/AllMemberVisitor.java
index 448470e..ab26bf3 100644
--- a/src/proguard/classfile/visitor/AllMemberVisitor.java
+++ b/src/proguard/classfile/visitor/AllMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllMethodVisitor.java b/src/proguard/classfile/visitor/AllMethodVisitor.java
index 75b919d..5d8e6a3 100644
--- a/src/proguard/classfile/visitor/AllMethodVisitor.java
+++ b/src/proguard/classfile/visitor/AllMethodVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/BottomClassFilter.java b/src/proguard/classfile/visitor/BottomClassFilter.java
index 8f5bdd1..e094ce3 100644
--- a/src/proguard/classfile/visitor/BottomClassFilter.java
+++ b/src/proguard/classfile/visitor/BottomClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassAccessFilter.java b/src/proguard/classfile/visitor/ClassAccessFilter.java
index a8815b6..1855662 100644
--- a/src/proguard/classfile/visitor/ClassAccessFilter.java
+++ b/src/proguard/classfile/visitor/ClassAccessFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassCleaner.java b/src/proguard/classfile/visitor/ClassCleaner.java
index 36165ef..a7ad1f6 100644
--- a/src/proguard/classfile/visitor/ClassCleaner.java
+++ b/src/proguard/classfile/visitor/ClassCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassCollector.java b/src/proguard/classfile/visitor/ClassCollector.java
index a69fe76..a24bb0b 100644
--- a/src/proguard/classfile/visitor/ClassCollector.java
+++ b/src/proguard/classfile/visitor/ClassCollector.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassCounter.java b/src/proguard/classfile/visitor/ClassCounter.java
index c58c090..b6deef2 100644
--- a/src/proguard/classfile/visitor/ClassCounter.java
+++ b/src/proguard/classfile/visitor/ClassCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
index 2e1755e..38ba3d6 100644
--- a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
+++ b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassNameFilter.java b/src/proguard/classfile/visitor/ClassNameFilter.java
index c016a34..bd66eb1 100644
--- a/src/proguard/classfile/visitor/ClassNameFilter.java
+++ b/src/proguard/classfile/visitor/ClassNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -70,7 +70,7 @@ public class ClassNameFilter implements ClassVisitor
/**
* Creates a new ClassNameFilter.
- * @param regularExpressionMatcher the regular expression against which
+ * @param regularExpressionMatcher the string matcher against which
* class names will be matched.
* @param classVisitor the <code>ClassVisitor</code> to which
* visits will be delegated.
diff --git a/src/proguard/classfile/visitor/ClassPoolFiller.java b/src/proguard/classfile/visitor/ClassPoolFiller.java
index e1773de..ae234be 100644
--- a/src/proguard/classfile/visitor/ClassPoolFiller.java
+++ b/src/proguard/classfile/visitor/ClassPoolFiller.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPoolVisitor.java b/src/proguard/classfile/visitor/ClassPoolVisitor.java
index 0b659dc..821304a 100644
--- a/src/proguard/classfile/visitor/ClassPoolVisitor.java
+++ b/src/proguard/classfile/visitor/ClassPoolVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPresenceFilter.java b/src/proguard/classfile/visitor/ClassPresenceFilter.java
index 429c340..0c55d1d 100644
--- a/src/proguard/classfile/visitor/ClassPresenceFilter.java
+++ b/src/proguard/classfile/visitor/ClassPresenceFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPrinter.java b/src/proguard/classfile/visitor/ClassPrinter.java
index 1da7d16..3121e58 100644
--- a/src/proguard/classfile/visitor/ClassPrinter.java
+++ b/src/proguard/classfile/visitor/ClassPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -48,8 +48,9 @@ implements ClassVisitor,
ConstantVisitor,
MemberVisitor,
AttributeVisitor,
- ExceptionInfoVisitor,
+ BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
StackMapFrameVisitor,
VerificationTypeVisitor,
LineNumberInfoVisitor,
@@ -62,7 +63,8 @@ implements ClassVisitor,
private static final String INDENTATION = " ";
private final PrintStream ps;
- private int indentation;
+
+ private int indentation;
/**
@@ -95,6 +97,7 @@ implements ClassVisitor,
println("Superclass: " + programClass.getSuperName());
println("Major version: 0x" + Integer.toHexString(ClassUtil.internalMajorClassVersion(programClass.u4version)));
println("Minor version: 0x" + Integer.toHexString(ClassUtil.internalMinorClassVersion(programClass.u4version)));
+ println(" = target " + ClassUtil.externalClassVersion(programClass.u4version));
println("Access flags: 0x" + Integer.toHexString(programClass.u2accessFlags));
println(" = " +
((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") +
@@ -222,10 +225,30 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ println(visitorInfo(invokeDynamicConstant) + " InvokeDynamic [bootstrap method index = " + invokeDynamicConstant.u2bootstrapMethodAttributeIndex + "]:");
+
+ indent();
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+ outdent();
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ println(visitorInfo(methodHandleConstant) + " MethodHandle [kind = " + methodHandleConstant.u1referenceKind + "]:");
+
+ indent();
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ outdent();
+ }
+
+
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
println(visitorInfo(fieldrefConstant) + " Fieldref [" +
- clazz.getClassName(fieldrefConstant.u2classIndex) + "." +
+ clazz.getClassName(fieldrefConstant.u2classIndex) + "." +
clazz.getName(fieldrefConstant.u2nameAndTypeIndex) + " " +
clazz.getType(fieldrefConstant.u2nameAndTypeIndex) + "]");
}
@@ -256,6 +279,13 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ println(visitorInfo(methodTypeConstant) + " MethodType [" +
+ clazz.getString(methodTypeConstant.u2descriptorIndex) + "]");
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
println(visitorInfo(nameAndTypeConstant) + " NameAndType [" +
@@ -361,6 +391,17 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ println(visitorInfo(bootstrapMethodsAttribute) +
+ " Bootstrap methods attribute (count = " + bootstrapMethodsAttribute.u2bootstrapMethodsCount + "):");
+
+ indent();
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ outdent();
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
println(visitorInfo(sourceFileAttribute) +
@@ -595,6 +636,21 @@ implements ClassVisitor,
}
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ println(visitorInfo(bootstrapMethodInfo) +
+ " BootstrapMethodInfo (argument count = " +
+ bootstrapMethodInfo.u2methodArgumentCount+ "):");
+
+ indent();
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
+ outdent();
+ }
+
+
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
@@ -603,6 +659,8 @@ implements ClassVisitor,
" InnerClassesInfo:");
indent();
+ println("Access flags: 0x" + Integer.toHexString(innerClassesInfo.u2innerClassAccessFlags) + " = " +
+ ClassUtil.externalClassAccessFlags(innerClassesInfo.u2innerClassAccessFlags));
innerClassesInfo.innerClassConstantAccept(clazz, this);
innerClassesInfo.outerClassConstantAccept(clazz, this);
innerClassesInfo.innerNameConstantAccept(clazz, this);
@@ -816,7 +874,7 @@ implements ClassVisitor,
public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
{
- println("#" + localVariableInfo.u2index + ": " +
+ println("v" + localVariableInfo.u2index + ": " +
localVariableInfo.u2startPC + " -> " +
(localVariableInfo.u2startPC + localVariableInfo.u2length) + " [" +
clazz.getString(localVariableInfo.u2descriptorIndex) + " " +
@@ -828,7 +886,7 @@ implements ClassVisitor,
public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
{
- println("#" + localVariableTypeInfo.u2index + ": " +
+ println("v" + localVariableTypeInfo.u2index + ": " +
localVariableTypeInfo.u2startPC + " -> " +
(localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length) + " [" +
clazz.getString(localVariableTypeInfo.u2signatureIndex) + " " +
diff --git a/src/proguard/classfile/visitor/ClassVersionFilter.java b/src/proguard/classfile/visitor/ClassVersionFilter.java
index 578cabf..73bcc6a 100644
--- a/src/proguard/classfile/visitor/ClassVersionFilter.java
+++ b/src/proguard/classfile/visitor/ClassVersionFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,6 +39,19 @@ public class ClassVersionFilter implements ClassVisitor
/**
* Creates a new ClassVersionFilter.
* @param minimumClassVersion the minimum class version number.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ClassVersionFilter(int minimumClassVersion,
+ ClassVisitor classVisitor)
+ {
+ this(minimumClassVersion, Integer.MAX_VALUE, classVisitor);
+ }
+
+
+ /**
+ * Creates a new ClassVersionFilter.
+ * @param minimumClassVersion the minimum class version number.
* @param maximumClassVersion the maximum class version number.
* @param classVisitor the <code>ClassVisitor</code> to which visits
* will be delegated.
diff --git a/src/proguard/classfile/visitor/ClassVersionSetter.java b/src/proguard/classfile/visitor/ClassVersionSetter.java
index 34dfbc1..d3f0183 100644
--- a/src/proguard/classfile/visitor/ClassVersionSetter.java
+++ b/src/proguard/classfile/visitor/ClassVersionSetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassVisitor.java b/src/proguard/classfile/visitor/ClassVisitor.java
index fdba2df..c423446 100644
--- a/src/proguard/classfile/visitor/ClassVisitor.java
+++ b/src/proguard/classfile/visitor/ClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java b/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
index ec3fe68..0b971f0 100644
--- a/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
+++ b/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/DotClassClassVisitor.java b/src/proguard/classfile/visitor/DotClassClassVisitor.java
index 263dbd5..979f846 100644
--- a/src/proguard/classfile/visitor/DotClassClassVisitor.java
+++ b/src/proguard/classfile/visitor/DotClassClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -36,8 +36,6 @@ import proguard.classfile.util.SimplifiedVisitor;
* Note that before JDK 1.5, <code>.class</code> constructs are actually
* compiled differently, using <code>Class.forName</code> constructs.
*
- * @see ClassForNameClassVisitor
- *
* @author Eric Lafortune
*/
public class DotClassClassVisitor
diff --git a/src/proguard/classfile/visitor/ExceptClassFilter.java b/src/proguard/classfile/visitor/ExceptClassFilter.java
index 924485e..25c6e68 100644
--- a/src/proguard/classfile/visitor/ExceptClassFilter.java
+++ b/src/proguard/classfile/visitor/ExceptClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptClassesFilter.java b/src/proguard/classfile/visitor/ExceptClassesFilter.java
index 7380c40..bdf72bd 100644
--- a/src/proguard/classfile/visitor/ExceptClassesFilter.java
+++ b/src/proguard/classfile/visitor/ExceptClassesFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionCounter.java b/src/proguard/classfile/visitor/ExceptionCounter.java
index c324129..5c476b6 100644
--- a/src/proguard/classfile/visitor/ExceptionCounter.java
+++ b/src/proguard/classfile/visitor/ExceptionCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java b/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
index 3911e39..2fd18ae 100644
--- a/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java b/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
index e0fdec3..de7139b 100644
--- a/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
+++ b/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionHandlerFilter.java b/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
index a90fb56..36ead5e 100644
--- a/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionOffsetFilter.java b/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
index e2a4fc9..c84473a 100644
--- a/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionRangeFilter.java b/src/proguard/classfile/visitor/ExceptionRangeFilter.java
index c541b1f..626a32e 100644
--- a/src/proguard/classfile/visitor/ExceptionRangeFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionRangeFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java b/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
index 6fe2e7d..334b85f 100644
--- a/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
+++ b/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ImplementedClassFilter.java b/src/proguard/classfile/visitor/ImplementedClassFilter.java
index 955a74e..abbacfb 100644
--- a/src/proguard/classfile/visitor/ImplementedClassFilter.java
+++ b/src/proguard/classfile/visitor/ImplementedClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java b/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
index 9e9cea3..8e7010d 100644
--- a/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
+++ b/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/LibraryClassFilter.java b/src/proguard/classfile/visitor/LibraryClassFilter.java
index 0e40f2f..7437ed3 100644
--- a/src/proguard/classfile/visitor/LibraryClassFilter.java
+++ b/src/proguard/classfile/visitor/LibraryClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/LibraryMemberFilter.java b/src/proguard/classfile/visitor/LibraryMemberFilter.java
index 0ee80e5..eae0698 100644
--- a/src/proguard/classfile/visitor/LibraryMemberFilter.java
+++ b/src/proguard/classfile/visitor/LibraryMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberAccessFilter.java b/src/proguard/classfile/visitor/MemberAccessFilter.java
index 6fd32e3..6bdc152 100644
--- a/src/proguard/classfile/visitor/MemberAccessFilter.java
+++ b/src/proguard/classfile/visitor/MemberAccessFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberClassAccessFilter.java b/src/proguard/classfile/visitor/MemberClassAccessFilter.java
index 85272ff..3605407 100644
--- a/src/proguard/classfile/visitor/MemberClassAccessFilter.java
+++ b/src/proguard/classfile/visitor/MemberClassAccessFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberCollector.java b/src/proguard/classfile/visitor/MemberCollector.java
index ec68b2d..46665f8 100644
--- a/src/proguard/classfile/visitor/MemberCollector.java
+++ b/src/proguard/classfile/visitor/MemberCollector.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberCounter.java b/src/proguard/classfile/visitor/MemberCounter.java
index c2da72e..58df4a7 100644
--- a/src/proguard/classfile/visitor/MemberCounter.java
+++ b/src/proguard/classfile/visitor/MemberCounter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberDescriptorFilter.java b/src/proguard/classfile/visitor/MemberDescriptorFilter.java
index bd69304..cce515a 100644
--- a/src/proguard/classfile/visitor/MemberDescriptorFilter.java
+++ b/src/proguard/classfile/visitor/MemberDescriptorFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberNameFilter.java b/src/proguard/classfile/visitor/MemberNameFilter.java
index 0fe450e..9996a4e 100644
--- a/src/proguard/classfile/visitor/MemberNameFilter.java
+++ b/src/proguard/classfile/visitor/MemberNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -47,7 +47,8 @@ public class MemberNameFilter implements MemberVisitor
public MemberNameFilter(String regularExpression,
MemberVisitor memberVisitor)
{
- this(new NameParser().parse(regularExpression), memberVisitor);
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ memberVisitor);
}
diff --git a/src/proguard/classfile/visitor/MemberToClassVisitor.java b/src/proguard/classfile/visitor/MemberToClassVisitor.java
index a405cfc..e82e52f 100644
--- a/src/proguard/classfile/visitor/MemberToClassVisitor.java
+++ b/src/proguard/classfile/visitor/MemberToClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberVisitor.java b/src/proguard/classfile/visitor/MemberVisitor.java
index 01fdf71..7b45662 100644
--- a/src/proguard/classfile/visitor/MemberVisitor.java
+++ b/src/proguard/classfile/visitor/MemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MethodImplementationFilter.java b/src/proguard/classfile/visitor/MethodImplementationFilter.java
index 57d923a..893a699 100644
--- a/src/proguard/classfile/visitor/MethodImplementationFilter.java
+++ b/src/proguard/classfile/visitor/MethodImplementationFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MethodImplementationTraveler.java b/src/proguard/classfile/visitor/MethodImplementationTraveler.java
index dc0ea36..c9f942e 100644
--- a/src/proguard/classfile/visitor/MethodImplementationTraveler.java
+++ b/src/proguard/classfile/visitor/MethodImplementationTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiClassPoolVisitor.java b/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
index 044d55a..0e96cf1 100644
--- a/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
+++ b/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiClassVisitor.java b/src/proguard/classfile/visitor/MultiClassVisitor.java
index d34d91e..059e9b7 100644
--- a/src/proguard/classfile/visitor/MultiClassVisitor.java
+++ b/src/proguard/classfile/visitor/MultiClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiMemberVisitor.java b/src/proguard/classfile/visitor/MultiMemberVisitor.java
index cc4629c..800d65f 100644
--- a/src/proguard/classfile/visitor/MultiMemberVisitor.java
+++ b/src/proguard/classfile/visitor/MultiMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedClassVisitor.java b/src/proguard/classfile/visitor/NamedClassVisitor.java
index a14d04a..79e14c9 100644
--- a/src/proguard/classfile/visitor/NamedClassVisitor.java
+++ b/src/proguard/classfile/visitor/NamedClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedFieldVisitor.java b/src/proguard/classfile/visitor/NamedFieldVisitor.java
index 76b66c6..685f62d 100644
--- a/src/proguard/classfile/visitor/NamedFieldVisitor.java
+++ b/src/proguard/classfile/visitor/NamedFieldVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedMethodVisitor.java b/src/proguard/classfile/visitor/NamedMethodVisitor.java
index d4611c1..c2baf19 100644
--- a/src/proguard/classfile/visitor/NamedMethodVisitor.java
+++ b/src/proguard/classfile/visitor/NamedMethodVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ProgramClassFilter.java b/src/proguard/classfile/visitor/ProgramClassFilter.java
index fba3b21..976658c 100644
--- a/src/proguard/classfile/visitor/ProgramClassFilter.java
+++ b/src/proguard/classfile/visitor/ProgramClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ProgramMemberFilter.java b/src/proguard/classfile/visitor/ProgramMemberFilter.java
index 048a1e6..cf187fb 100644
--- a/src/proguard/classfile/visitor/ProgramMemberFilter.java
+++ b/src/proguard/classfile/visitor/ProgramMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ReferencedClassVisitor.java b/src/proguard/classfile/visitor/ReferencedClassVisitor.java
index 986c3f9..e7fe855 100644
--- a/src/proguard/classfile/visitor/ReferencedClassVisitor.java
+++ b/src/proguard/classfile/visitor/ReferencedClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -123,6 +123,13 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Let the visitor visit the class referenced in the reference constant.
+ invokeDynamicConstant.referencedClassesAccept(classVisitor);
+ }
+
+
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
// Let the visitor visit the class referenced in the class constant.
diff --git a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
index c4d34b8..3c59075 100644
--- a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
+++ b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SimilarMemberVisitor.java b/src/proguard/classfile/visitor/SimilarMemberVisitor.java
index 6dc06af..5087f48 100644
--- a/src/proguard/classfile/visitor/SimilarMemberVisitor.java
+++ b/src/proguard/classfile/visitor/SimilarMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SimpleClassPrinter.java b/src/proguard/classfile/visitor/SimpleClassPrinter.java
index a661110..df630c7 100644
--- a/src/proguard/classfile/visitor/SimpleClassPrinter.java
+++ b/src/proguard/classfile/visitor/SimpleClassPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SubclassFilter.java b/src/proguard/classfile/visitor/SubclassFilter.java
index 69ea1a1..6b6f84b 100644
--- a/src/proguard/classfile/visitor/SubclassFilter.java
+++ b/src/proguard/classfile/visitor/SubclassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SubclassTraveler.java b/src/proguard/classfile/visitor/SubclassTraveler.java
index 4170341..32dccb7 100644
--- a/src/proguard/classfile/visitor/SubclassTraveler.java
+++ b/src/proguard/classfile/visitor/SubclassTraveler.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/VariableClassVisitor.java b/src/proguard/classfile/visitor/VariableClassVisitor.java
index 2f575c4..17a5522 100644
--- a/src/proguard/classfile/visitor/VariableClassVisitor.java
+++ b/src/proguard/classfile/visitor/VariableClassVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/VariableMemberVisitor.java b/src/proguard/classfile/visitor/VariableMemberVisitor.java
index c58cff3..34c39f3 100644
--- a/src/proguard/classfile/visitor/VariableMemberVisitor.java
+++ b/src/proguard/classfile/visitor/VariableMemberVisitor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/BasicBranchUnit.java b/src/proguard/evaluation/BasicBranchUnit.java
index 3a2db76..127e922 100644
--- a/src/proguard/evaluation/BasicBranchUnit.java
+++ b/src/proguard/evaluation/BasicBranchUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/BasicInvocationUnit.java b/src/proguard/evaluation/BasicInvocationUnit.java
index bccd866..474556c 100644
--- a/src/proguard/evaluation/BasicInvocationUnit.java
+++ b/src/proguard/evaluation/BasicInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -162,6 +162,7 @@ implements InvocationUnit,
break;
case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
isStatic = true;
break;
@@ -230,6 +231,31 @@ implements InvocationUnit,
}
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ String type = invokeDynamicConstant.getType(clazz);
+
+ // Count the number of parameters.
+ int parameterCount = ClassUtil.internalMethodParameterCount(type);
+ if (!isStatic)
+ {
+ parameterCount++;
+ }
+
+ // Pop the parameters and the class reference, in reverse order.
+ for (int parameterIndex = parameterCount-1; parameterIndex >= 0; parameterIndex--)
+ {
+ stack.pop();
+ }
+
+ // Push the return value, if applicable.
+ String returnType = ClassUtil.internalMethodReturnType(type);
+ if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID)
+ {
+ stack.push(getMethodReturnValue(clazz, invokeDynamicConstant, returnType));
+ }
+ }
+
/**
* Sets the class through which the specified field is accessed.
@@ -340,6 +366,25 @@ implements InvocationUnit,
}
+ /**
+ * Returns the return value of the specified method.
+ */
+ protected Value getMethodReturnValue(Clazz clazz,
+ InvokeDynamicConstant invokeDynamicConstant,
+ String type)
+ {
+ // Try to figure out the class of the return type.
+ Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses;
+
+ Clazz returnTypeClass = referencedClasses == null ? null :
+ referencedClasses[referencedClasses.length - 1];
+
+ return valueFactory.createValue(type,
+ returnTypeClass,
+ true);
+ }
+
+
// Implementations for MemberVisitor.
public void visitProgramField(ProgramClass programClass, ProgramField programField)
diff --git a/src/proguard/evaluation/BranchUnit.java b/src/proguard/evaluation/BranchUnit.java
index b709807..a381da7 100644
--- a/src/proguard/evaluation/BranchUnit.java
+++ b/src/proguard/evaluation/BranchUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/ClassConstantValueFactory.java b/src/proguard/evaluation/ClassConstantValueFactory.java
new file mode 100644
index 0000000..1c418c2
--- /dev/null
+++ b/src/proguard/evaluation/ClassConstantValueFactory.java
@@ -0,0 +1,53 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This class creates java.lang.Class ReferenceValue instances that correspond
+ * to specified constant pool entries.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassConstantValueFactory
+extends ConstantValueFactory
+{
+ public ClassConstantValueFactory(ValueFactory valueFactory)
+ {
+ super(valueFactory);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Create a Class reference instead of a reference to the class.
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS,
+ classConstant.javaLangClassClass,
+ false);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/evaluation/ConstantValueFactory.java b/src/proguard/evaluation/ConstantValueFactory.java
new file mode 100644
index 0000000..0afb20c
--- /dev/null
+++ b/src/proguard/evaluation/ConstantValueFactory.java
@@ -0,0 +1,113 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This class creates Value instance that correspond to specified constant pool
+ * entries.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantValueFactory
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ protected final ValueFactory valueFactory;
+
+ // Field acting as a parameter for the ConstantVisitor methods.
+ protected Value value;
+
+
+ public ConstantValueFactory(ValueFactory valueFactory)
+ {
+ this.valueFactory = valueFactory;
+ }
+
+
+ /**
+ * Returns the Value of the constant pool element at the given index.
+ */
+ public Value constantValue(Clazz clazz,
+ int constantIndex)
+ {
+ // Visit the constant pool entry to get its return value.
+ clazz.constantPoolEntryAccept(constantIndex, this);
+
+ return value;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ value = valueFactory.createIntegerValue(integerConstant.getValue());
+ }
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ value = valueFactory.createLongValue(longConstant.getValue());
+ }
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ value = valueFactory.createFloatValue(floatConstant.getValue());
+ }
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ value = valueFactory.createDoubleValue(doubleConstant.getValue());
+ }
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING,
+ stringConstant.javaLangStringClass,
+ false);
+ }
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE,
+ methodHandleConstant.javaLangInvokeMethodHandleClass,
+ false);
+ }
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ value = valueFactory.createReferenceValue(classConstant.getName(clazz),
+ classConstant.referencedClass,
+ false);
+ }
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE,
+ methodTypeConstant.javaLangInvokeMethodTypeClass,
+ false);
+ }
+} \ No newline at end of file
diff --git a/src/proguard/evaluation/InvocationUnit.java b/src/proguard/evaluation/InvocationUnit.java
index cb4d3c5..e526b35 100644
--- a/src/proguard/evaluation/InvocationUnit.java
+++ b/src/proguard/evaluation/InvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/Processor.java b/src/proguard/evaluation/Processor.java
index 74afd0b..3bfc5f3 100644
--- a/src/proguard/evaluation/Processor.java
+++ b/src/proguard/evaluation/Processor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,11 +22,8 @@ package proguard.evaluation;
import proguard.classfile.*;
import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
import proguard.evaluation.value.*;
/**
@@ -36,9 +33,7 @@ import proguard.evaluation.value.*;
* @author Eric Lafortune
*/
public class Processor
-extends SimplifiedVisitor
-implements InstructionVisitor,
- ConstantVisitor
+implements InstructionVisitor
{
private final Variables variables;
private final Stack stack;
@@ -46,9 +41,8 @@ implements InstructionVisitor,
private final BranchUnit branchUnit;
private final InvocationUnit invocationUnit;
- // Fields acting as parameters for the ConstantVisitor methods.
- private boolean handleClassConstantAsClassValue;
- private Value cpValue;
+ private final ConstantValueFactory constantValueFactory;
+ private final ClassConstantValueFactory classConstantValueFactory;
/**
@@ -69,6 +63,9 @@ implements InstructionVisitor,
this.valueFactory = valueFactory;
this.branchUnit = branchUnit;
this.invocationUnit = invocationUnit;
+
+ constantValueFactory = new ConstantValueFactory(valueFactory);
+ classConstantValueFactory = new ClassConstantValueFactory(valueFactory);
}
@@ -561,7 +558,7 @@ implements InstructionVisitor,
case InstructionConstants.OP_LDC:
case InstructionConstants.OP_LDC_W:
case InstructionConstants.OP_LDC2_W:
- stack.push(cpValue(clazz, constantIndex, true));
+ stack.push(classConstantValueFactory.constantValue(clazz, constantIndex));
break;
case InstructionConstants.OP_GETSTATIC:
@@ -572,16 +569,17 @@ implements InstructionVisitor,
case InstructionConstants.OP_INVOKESPECIAL:
case InstructionConstants.OP_INVOKESTATIC:
case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
invocationUnit.invokeMember(clazz, method, codeAttribute, offset, constantInstruction, stack);
break;
case InstructionConstants.OP_NEW:
- stack.push(cpValue(clazz, constantIndex).referenceValue());
+ stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
break;
case InstructionConstants.OP_ANEWARRAY:
{
- ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue();
+ ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
stack.push(valueFactory.createArrayReferenceValue(referenceValue.internalType(),
referenceValue.getReferencedClass(),
@@ -594,14 +592,14 @@ implements InstructionVisitor,
ReferenceValue castValue = stack.apop();
ReferenceValue castResultValue =
castValue.isNull() == Value.ALWAYS ? castValue :
- castValue.isNull() == Value.NEVER ? cpValue(clazz, constantIndex).referenceValue() :
- cpValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull());
+ castValue.isNull() == Value.NEVER ? constantValueFactory.constantValue(clazz, constantIndex).referenceValue() :
+ constantValueFactory.constantValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull());
stack.push(castResultValue);
break;
case InstructionConstants.OP_INSTANCEOF:
{
- ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue();
+ ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
int instanceOf = stack.apop().instanceOf(referenceValue.getType(),
referenceValue.getReferencedClass());
@@ -621,7 +619,7 @@ implements InstructionVisitor,
IntegerValue arrayLength = stack.ipop();
}
- stack.push(cpValue(clazz, constantIndex).referenceValue());
+ stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
break;
}
@@ -907,73 +905,4 @@ implements InstructionVisitor,
}
}
}
-
-
- // Implementations for ConstantVisitor.
-
- public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
- {
- cpValue = valueFactory.createIntegerValue(integerConstant.getValue());
- }
-
- public void visitLongConstant(Clazz clazz, LongConstant longConstant)
- {
- cpValue = valueFactory.createLongValue(longConstant.getValue());
- }
-
- public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
- {
- cpValue = valueFactory.createFloatValue(floatConstant.getValue());
- }
-
- public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
- {
- cpValue = valueFactory.createDoubleValue(doubleConstant.getValue());
- }
-
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
- {
- cpValue = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING,
- stringConstant.javaLangStringClass,
- false);
- }
-
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
- {
- cpValue = handleClassConstantAsClassValue ?
- valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS,
- classConstant.javaLangClassClass,
- false) :
- valueFactory.createReferenceValue(classConstant.getName(clazz),
- classConstant.referencedClass,
- false);
- }
-
-
- // Small utility methods.
-
- /**
- * Returns the Value of the constant pool element at the given index.
- */
- private Value cpValue(Clazz clazz,
- int constantIndex)
- {
- return cpValue(clazz, constantIndex, false);
- }
-
-
- /**
- * Returns the Value of the constant pool element at the given index.
- */
- private Value cpValue(Clazz clazz,
- int constantIndex,
- boolean handleClassConstantAsClassValue)
- {
- this.handleClassConstantAsClassValue = handleClassConstantAsClassValue;
-
- // Visit the constant pool entry to get its return value.
- clazz.constantPoolEntryAccept(constantIndex, this);
-
- return cpValue;
- }
}
diff --git a/src/proguard/evaluation/Stack.java b/src/proguard/evaluation/Stack.java
index 2808e62..c449e86 100644
--- a/src/proguard/evaluation/Stack.java
+++ b/src/proguard/evaluation/Stack.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,6 +22,8 @@ package proguard.evaluation;
import proguard.evaluation.value.*;
+import java.util.Arrays;
+
/**
* This class represents an operand stack that contains <code>Value</code>
* objects.
@@ -163,10 +165,7 @@ public class Stack
public void clear()
{
// Clear the stack contents.
- for (int index = 0; index < currentSize; index++)
- {
- values[index] = null;
- }
+ Arrays.fill(values, 0, currentSize, null);
currentSize = 0;
}
diff --git a/src/proguard/evaluation/TracedStack.java b/src/proguard/evaluation/TracedStack.java
index c24f783..08778a1 100644
--- a/src/proguard/evaluation/TracedStack.java
+++ b/src/proguard/evaluation/TracedStack.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/TracedVariables.java b/src/proguard/evaluation/TracedVariables.java
index 1ae6ba6..fef54e1 100644
--- a/src/proguard/evaluation/TracedVariables.java
+++ b/src/proguard/evaluation/TracedVariables.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -30,9 +30,6 @@ import proguard.evaluation.value.Value;
* stores. It then generalizes a given collected Value with the producer Value
* of each Value it loads. The producer Value and the initial collected Value
* can be set; the generalized collected Value can be retrieved.
- * <p>
- * In addition, an initialization index can be reset and retrieved, pointing
- * to the most recent variable that has been initialized by a store operation.
*
* @author Eric Lafortune
*/
@@ -43,7 +40,6 @@ public class TracedVariables extends Variables
private Value producerValue;
private Variables producerVariables;
- private int initializationIndex;
/**
@@ -78,24 +74,6 @@ public class TracedVariables extends Variables
/**
- * Resets the initialization index.
- */
- public void resetInitialization()
- {
- initializationIndex = NONE;
- }
-
-
- /**
- * Returns the most recent initialization index since it has been reset.
- */
- public int getInitializationIndex()
- {
- return initializationIndex;
- }
-
-
- /**
* Gets the producer Value for the specified variable, without disturbing it.
* @param index the variable index.
* @return the producer value of the given variable.
@@ -164,14 +142,6 @@ public class TracedVariables extends Variables
public void store(int index, Value value)
{
- // Is this store operation an initialization of the variable?
- Value previousValue = super.load(index);
- if (previousValue == null ||
- previousValue.computationalType() != value.computationalType())
- {
- initializationIndex = index;
- }
-
// Store the value itself in the variable.
super.store(index, value);
diff --git a/src/proguard/evaluation/Variables.java b/src/proguard/evaluation/Variables.java
index 4496aaa..16b39e7 100644
--- a/src/proguard/evaluation/Variables.java
+++ b/src/proguard/evaluation/Variables.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,6 +22,8 @@ package proguard.evaluation;
import proguard.evaluation.value.*;
+import java.util.Arrays;
+
/**
* This class represents a local variable frame that contains <code>Value</code>
* objects. Values are generalizations of all values that have been stored in
@@ -75,10 +77,7 @@ public class Variables
else
{
// Clear the variables.
- for (int index = 0; index < values.length; index++)
- {
- values[index] = null;
- }
+ Arrays.fill(values, null);
}
this.size = size;
diff --git a/src/proguard/evaluation/value/Category1Value.java b/src/proguard/evaluation/value/Category1Value.java
index b8c5db2..a5ebf86 100644
--- a/src/proguard/evaluation/value/Category1Value.java
+++ b/src/proguard/evaluation/value/Category1Value.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/Category2Value.java b/src/proguard/evaluation/value/Category2Value.java
index 65916c7..2be6e71 100644
--- a/src/proguard/evaluation/value/Category2Value.java
+++ b/src/proguard/evaluation/value/Category2Value.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ComparisonValue.java b/src/proguard/evaluation/value/ComparisonValue.java
index e4e2e02..abbf31c 100644
--- a/src/proguard/evaluation/value/ComparisonValue.java
+++ b/src/proguard/evaluation/value/ComparisonValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -35,11 +35,11 @@ final class ComparisonValue extends SpecificIntegerValue
/**
* Creates a new comparison integer value of the two given scalar values.
*/
- public ComparisonValue(Value integerValue1,
- Value integerValue2)
+ public ComparisonValue(Value value1,
+ Value value2)
{
- this.value1 = integerValue1;
- this.value2 = integerValue2;
+ this.value1 = value1;
+ this.value2 = value2;
}
diff --git a/src/proguard/evaluation/value/CompositeDoubleValue.java b/src/proguard/evaluation/value/CompositeDoubleValue.java
index a6d48ef..be739ed 100644
--- a/src/proguard/evaluation/value/CompositeDoubleValue.java
+++ b/src/proguard/evaluation/value/CompositeDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/CompositeFloatValue.java b/src/proguard/evaluation/value/CompositeFloatValue.java
index 4df890a..0961068 100644
--- a/src/proguard/evaluation/value/CompositeFloatValue.java
+++ b/src/proguard/evaluation/value/CompositeFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -36,7 +36,7 @@ final class CompositeFloatValue extends SpecificFloatValue
private final FloatValue floatValue1;
- private final byte operation;
+ private final byte operation;
private final FloatValue floatValue2;
@@ -45,11 +45,11 @@ final class CompositeFloatValue extends SpecificFloatValue
* and the given operation.
*/
public CompositeFloatValue(FloatValue floatValue1,
- byte operation,
- FloatValue floatValue2)
+ byte operation,
+ FloatValue floatValue2)
{
this.floatValue1 = floatValue1;
- this.operation = operation;
+ this.operation = operation;
this.floatValue2 = floatValue2;
}
diff --git a/src/proguard/evaluation/value/CompositeIntegerValue.java b/src/proguard/evaluation/value/CompositeIntegerValue.java
index 6d4f59c..97caa2f 100644
--- a/src/proguard/evaluation/value/CompositeIntegerValue.java
+++ b/src/proguard/evaluation/value/CompositeIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/CompositeLongValue.java b/src/proguard/evaluation/value/CompositeLongValue.java
index 7f63211..3b8a97f 100644
--- a/src/proguard/evaluation/value/CompositeLongValue.java
+++ b/src/proguard/evaluation/value/CompositeLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedByteValue.java b/src/proguard/evaluation/value/ConvertedByteValue.java
index 7ab5d0a..eb1a350 100644
--- a/src/proguard/evaluation/value/ConvertedByteValue.java
+++ b/src/proguard/evaluation/value/ConvertedByteValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedCharacterValue.java b/src/proguard/evaluation/value/ConvertedCharacterValue.java
index 76568d1..a491bed 100644
--- a/src/proguard/evaluation/value/ConvertedCharacterValue.java
+++ b/src/proguard/evaluation/value/ConvertedCharacterValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedDoubleValue.java b/src/proguard/evaluation/value/ConvertedDoubleValue.java
index a6afe34..65fab84 100644
--- a/src/proguard/evaluation/value/ConvertedDoubleValue.java
+++ b/src/proguard/evaluation/value/ConvertedDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedFloatValue.java b/src/proguard/evaluation/value/ConvertedFloatValue.java
index 33683b7..e74ec8d 100644
--- a/src/proguard/evaluation/value/ConvertedFloatValue.java
+++ b/src/proguard/evaluation/value/ConvertedFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedIntegerValue.java b/src/proguard/evaluation/value/ConvertedIntegerValue.java
index aecb533..273b5a1 100644
--- a/src/proguard/evaluation/value/ConvertedIntegerValue.java
+++ b/src/proguard/evaluation/value/ConvertedIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedLongValue.java b/src/proguard/evaluation/value/ConvertedLongValue.java
index ec97008..5cb9104 100644
--- a/src/proguard/evaluation/value/ConvertedLongValue.java
+++ b/src/proguard/evaluation/value/ConvertedLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ConvertedShortValue.java b/src/proguard/evaluation/value/ConvertedShortValue.java
index ab79b49..cef2a20 100644
--- a/src/proguard/evaluation/value/ConvertedShortValue.java
+++ b/src/proguard/evaluation/value/ConvertedShortValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/DoubleValue.java b/src/proguard/evaluation/value/DoubleValue.java
index e39ee5c..6630b2f 100644
--- a/src/proguard/evaluation/value/DoubleValue.java
+++ b/src/proguard/evaluation/value/DoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -342,11 +342,6 @@ public abstract class DoubleValue extends Category2Value
return this;
}
- public Value refresh()
- {
- return this;
- }
-
public final Value generalize(Value other)
{
return this.generalize(other.doubleValue());
diff --git a/src/proguard/evaluation/value/FloatValue.java b/src/proguard/evaluation/value/FloatValue.java
index b30e395..6dc8bee 100644
--- a/src/proguard/evaluation/value/FloatValue.java
+++ b/src/proguard/evaluation/value/FloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedDoubleValue.java b/src/proguard/evaluation/value/IdentifiedDoubleValue.java
index 4009c6e..4ff2466 100644
--- a/src/proguard/evaluation/value/IdentifiedDoubleValue.java
+++ b/src/proguard/evaluation/value/IdentifiedDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedFloatValue.java b/src/proguard/evaluation/value/IdentifiedFloatValue.java
index 87bed64..c8349bc 100644
--- a/src/proguard/evaluation/value/IdentifiedFloatValue.java
+++ b/src/proguard/evaluation/value/IdentifiedFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedIntegerValue.java b/src/proguard/evaluation/value/IdentifiedIntegerValue.java
index 66e88ee..6c3ee5d 100644
--- a/src/proguard/evaluation/value/IdentifiedIntegerValue.java
+++ b/src/proguard/evaluation/value/IdentifiedIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedLongValue.java b/src/proguard/evaluation/value/IdentifiedLongValue.java
index eea1816..e0b68f2 100644
--- a/src/proguard/evaluation/value/IdentifiedLongValue.java
+++ b/src/proguard/evaluation/value/IdentifiedLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IdentifiedReferenceValue.java b/src/proguard/evaluation/value/IdentifiedReferenceValue.java
index cb5efc1..5cfbd60 100644
--- a/src/proguard/evaluation/value/IdentifiedReferenceValue.java
+++ b/src/proguard/evaluation/value/IdentifiedReferenceValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -57,6 +57,17 @@ final class IdentifiedReferenceValue extends ReferenceValue
}
+ // Implementations of binary methods of ReferenceValue.
+
+ public ReferenceValue generalize(ReferenceValue other)
+ {
+ // Remove the ID if both values don't share the same ID.
+ return this.equals(other) ?
+ this :
+ new ReferenceValue(type, referencedClass, mayBeNull).generalize(other);
+ }
+
+
// Implementations for Value.
public boolean isSpecific()
diff --git a/src/proguard/evaluation/value/IdentifiedValueFactory.java b/src/proguard/evaluation/value/IdentifiedValueFactory.java
index 2b14e72..be5c885 100644
--- a/src/proguard/evaluation/value/IdentifiedValueFactory.java
+++ b/src/proguard/evaluation/value/IdentifiedValueFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/InstructionOffsetValue.java b/src/proguard/evaluation/value/InstructionOffsetValue.java
index 10b5a6f..07a44ee 100644
--- a/src/proguard/evaluation/value/InstructionOffsetValue.java
+++ b/src/proguard/evaluation/value/InstructionOffsetValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/IntegerValue.java b/src/proguard/evaluation/value/IntegerValue.java
index 508c5f5..b1824c6 100644
--- a/src/proguard/evaluation/value/IntegerValue.java
+++ b/src/proguard/evaluation/value/IntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/LongValue.java b/src/proguard/evaluation/value/LongValue.java
index f7ba162..e23c13c 100644
--- a/src/proguard/evaluation/value/LongValue.java
+++ b/src/proguard/evaluation/value/LongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedDoubleValue.java b/src/proguard/evaluation/value/NegatedDoubleValue.java
index 2bc9423..7619be7 100644
--- a/src/proguard/evaluation/value/NegatedDoubleValue.java
+++ b/src/proguard/evaluation/value/NegatedDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedFloatValue.java b/src/proguard/evaluation/value/NegatedFloatValue.java
index 0ddf4ab..51b5074 100644
--- a/src/proguard/evaluation/value/NegatedFloatValue.java
+++ b/src/proguard/evaluation/value/NegatedFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedIntegerValue.java b/src/proguard/evaluation/value/NegatedIntegerValue.java
index a89a2d9..1729083 100644
--- a/src/proguard/evaluation/value/NegatedIntegerValue.java
+++ b/src/proguard/evaluation/value/NegatedIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/NegatedLongValue.java b/src/proguard/evaluation/value/NegatedLongValue.java
index c3b22bb..7510524 100644
--- a/src/proguard/evaluation/value/NegatedLongValue.java
+++ b/src/proguard/evaluation/value/NegatedLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ParticularDoubleValue.java b/src/proguard/evaluation/value/ParticularDoubleValue.java
index 05bc559..e8c5aa7 100644
--- a/src/proguard/evaluation/value/ParticularDoubleValue.java
+++ b/src/proguard/evaluation/value/ParticularDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -79,17 +79,23 @@ final class ParticularDoubleValue extends SpecificDoubleValue
public DoubleValue add(DoubleValue other)
{
- return value == 0.0 ? other : other.add(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.add(this);
+ return other.add(this);
}
public DoubleValue subtract(DoubleValue other)
{
- return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ return other.subtractFrom(this);
}
public DoubleValue subtractFrom(DoubleValue other)
{
- return value == 0.0 ? other : other.subtract(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.subtract(this);
+ return other.subtract(this);
}
public DoubleValue multiply(DoubleValue other)
@@ -128,7 +134,10 @@ final class ParticularDoubleValue extends SpecificDoubleValue
public DoubleValue generalize(ParticularDoubleValue other)
{
- return this.value == other.value ? this : ValueFactory.DOUBLE_VALUE;
+ // Also handle NaN and Infinity.
+ return Double.doubleToRawLongBits(this.value) ==
+ Double.doubleToRawLongBits(other.value) ?
+ this : ValueFactory.DOUBLE_VALUE;
}
public DoubleValue add(ParticularDoubleValue other)
@@ -191,8 +200,10 @@ final class ParticularDoubleValue extends SpecificDoubleValue
public boolean equals(Object object)
{
- return super.equals(object) &&
- this.value == ((ParticularDoubleValue)object).value;
+ // Also handle NaN and Infinity.
+ return super.equals(object) &&
+ Double.doubleToLongBits(this.value) ==
+ Double.doubleToLongBits(((ParticularDoubleValue)object).value);
}
diff --git a/src/proguard/evaluation/value/ParticularFloatValue.java b/src/proguard/evaluation/value/ParticularFloatValue.java
index 59e4357..cbdde31 100644
--- a/src/proguard/evaluation/value/ParticularFloatValue.java
+++ b/src/proguard/evaluation/value/ParticularFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -79,17 +79,23 @@ final class ParticularFloatValue extends SpecificFloatValue
public FloatValue add(FloatValue other)
{
- return value == 0.0 ? other : other.add(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.add(this);
+ return other.add(this);
}
public FloatValue subtract(FloatValue other)
{
- return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ return other.subtractFrom(this);
}
public FloatValue subtractFrom(FloatValue other)
{
- return value == 0.0 ? other : other.subtract(this);
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.subtract(this);
+ return other.subtract(this);
}
public FloatValue multiply(FloatValue other)
@@ -128,7 +134,10 @@ final class ParticularFloatValue extends SpecificFloatValue
public FloatValue generalize(ParticularFloatValue other)
{
- return this.value == other.value ? this : ValueFactory.FLOAT_VALUE;
+ // Also handle NaN and Infinity.
+ return Float.floatToRawIntBits(this.value) ==
+ Float.floatToRawIntBits(other.value) ?
+ this : ValueFactory.FLOAT_VALUE;
}
public FloatValue add(ParticularFloatValue other)
@@ -191,8 +200,10 @@ final class ParticularFloatValue extends SpecificFloatValue
public boolean equals(Object object)
{
+ // Also handle NaN and Infinity.
return super.equals(object) &&
- this.value == ((ParticularFloatValue)object).value;
+ Float.floatToIntBits(this.value) ==
+ Float.floatToIntBits(((ParticularFloatValue)object).value);
}
diff --git a/src/proguard/evaluation/value/ParticularIntegerValue.java b/src/proguard/evaluation/value/ParticularIntegerValue.java
index 8a4ac1d..609e95f 100644
--- a/src/proguard/evaluation/value/ParticularIntegerValue.java
+++ b/src/proguard/evaluation/value/ParticularIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ParticularLongValue.java b/src/proguard/evaluation/value/ParticularLongValue.java
index 61d2e04..1903235 100644
--- a/src/proguard/evaluation/value/ParticularLongValue.java
+++ b/src/proguard/evaluation/value/ParticularLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ReferenceValue.java b/src/proguard/evaluation/value/ReferenceValue.java
index 418c6f8..4a52e82 100644
--- a/src/proguard/evaluation/value/ReferenceValue.java
+++ b/src/proguard/evaluation/value/ReferenceValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -280,11 +280,25 @@ public class ReferenceValue extends Category1Value
thisReferencedClass.hierarchyAccept(false, true, true, false,
new ClassCollector(thisSuperClasses));
+ int thisSuperClassesCount = thisSuperClasses.size();
+ if (thisSuperClassesCount == 0 &&
+ thisReferencedClass.getSuperName() != null)
+ {
+ throw new IllegalArgumentException("Can't find any super classes of ["+thisType+"] (not even immediate super class ["+thisReferencedClass.getSuperName()+"])");
+ }
+
// Collect the superclasses and interfaces of the other class.
Set otherSuperClasses = new HashSet();
otherReferencedClass.hierarchyAccept(false, true, true, false,
new ClassCollector(otherSuperClasses));
+ int otherSuperClassesCount = otherSuperClasses.size();
+ if (otherSuperClassesCount == 0 &&
+ otherReferencedClass.getSuperName() != null)
+ {
+ throw new IllegalArgumentException("Can't find any super classes of ["+otherType+"] (not even immediate super class ["+otherReferencedClass.getSuperName()+"])");
+ }
+
if (DEBUG)
{
System.out.println("ReferenceValue.generalize this ["+thisReferencedClass.getName()+"] with other ["+otherReferencedClass.getName()+"]");
@@ -302,7 +316,7 @@ public class ReferenceValue extends Category1Value
// Find a class that is a subclass of all common superclasses,
// or that at least has the maximum number of common superclasses.
- Clazz commonClazz = null;
+ Clazz commonClass = null;
int maximumSuperClassCount = -1;
@@ -317,31 +331,33 @@ public class ReferenceValue extends Category1Value
int superClassCount = superClassCount(commonSuperClass, thisSuperClasses);
if (maximumSuperClassCount < superClassCount ||
(maximumSuperClassCount == superClassCount &&
- commonClazz != null &&
- commonClazz.getName().compareTo(commonSuperClass.getName()) > 0))
+ commonClass != null &&
+ commonClass.getName().compareTo(commonSuperClass.getName()) > 0))
{
- commonClazz = commonSuperClass;
+ commonClass = commonSuperClass;
maximumSuperClassCount = superClassCount;
}
}
- if (commonClazz == null)
+ if (commonClass == null)
{
- throw new IllegalArgumentException("Can't find common super class of ["+thisType+"] and ["+otherType+"]");
+ throw new IllegalArgumentException("Can't find common super class of ["+
+ thisType +"] (with "+thisSuperClassesCount +" known super classes) and ["+
+ otherType+"] (with "+otherSuperClassesCount+" known super classes)");
}
if (DEBUG)
{
- System.out.println(" Best common class: ["+commonClazz.getName()+"]");
+ System.out.println(" Best common class: ["+commonClass.getName()+"]");
}
// TODO: Handle more difficult cases, with multiple global subclasses.
return new ReferenceValue(commonDimensionCount == 0 ?
- commonClazz.getName() :
- ClassUtil.internalArrayTypeFromClassName(commonClazz.getName(),
+ commonClass.getName() :
+ ClassUtil.internalArrayTypeFromClassName(commonClass.getName(),
commonDimensionCount),
- commonClazz,
+ commonClass,
mayBeNull);
}
}
@@ -402,8 +418,6 @@ public class ReferenceValue extends Category1Value
}
}
- //System.out.println("ReferenceValue.superClassCount: ["+subClass.getName()+"]: "+count);
-
return count;
}
diff --git a/src/proguard/evaluation/value/SpecificDoubleValue.java b/src/proguard/evaluation/value/SpecificDoubleValue.java
index 572d891..644f553 100644
--- a/src/proguard/evaluation/value/SpecificDoubleValue.java
+++ b/src/proguard/evaluation/value/SpecificDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -153,9 +153,12 @@ abstract class SpecificDoubleValue extends DoubleValue
public IntegerValue compare(SpecificDoubleValue other)
{
- return this.equals(other) ?
- SpecificValueFactory.INTEGER_VALUE_0 :
- new ComparisonValue(this, other);
+ return ValueFactory.INTEGER_VALUE;
+
+ // Not handling NaN properly.
+ //return this.equals(other) ?
+ // SpecificValueFactory.INTEGER_VALUE_0 :
+ // new ComparisonValue(this, other);
}
diff --git a/src/proguard/evaluation/value/SpecificFloatValue.java b/src/proguard/evaluation/value/SpecificFloatValue.java
index 3bc3679..d88baa3 100644
--- a/src/proguard/evaluation/value/SpecificFloatValue.java
+++ b/src/proguard/evaluation/value/SpecificFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -153,9 +153,12 @@ abstract class SpecificFloatValue extends FloatValue
public IntegerValue compare(SpecificFloatValue other)
{
- return this.equals(other) ?
- SpecificValueFactory.INTEGER_VALUE_0 :
- new ComparisonValue(this, other);
+ return ValueFactory.INTEGER_VALUE;
+
+ // Not handling NaN properly.
+ //return this.equals(other) ?
+ // SpecificValueFactory.INTEGER_VALUE_0 :
+ // new ComparisonValue(this, other);
}
diff --git a/src/proguard/evaluation/value/SpecificIntegerValue.java b/src/proguard/evaluation/value/SpecificIntegerValue.java
index 57c48b1..81f8646 100644
--- a/src/proguard/evaluation/value/SpecificIntegerValue.java
+++ b/src/proguard/evaluation/value/SpecificIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/SpecificLongValue.java b/src/proguard/evaluation/value/SpecificLongValue.java
index 5e12bde..15138b4 100644
--- a/src/proguard/evaluation/value/SpecificLongValue.java
+++ b/src/proguard/evaluation/value/SpecificLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/SpecificValueFactory.java b/src/proguard/evaluation/value/SpecificValueFactory.java
index 72dd1d3..f761938 100644
--- a/src/proguard/evaluation/value/SpecificValueFactory.java
+++ b/src/proguard/evaluation/value/SpecificValueFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -45,6 +45,10 @@ extends ValueFactory
static final DoubleValue DOUBLE_VALUE_1 = new ParticularDoubleValue(1.0);
+ private static int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f);
+ private static long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
+
+
// Implementations for ValueFactory.
public IntegerValue createIntegerValue(int value)
@@ -73,7 +77,9 @@ extends ValueFactory
public FloatValue createFloatValue(float value)
{
- return value == 0.0f ? FLOAT_VALUE_0 :
+ // Make sure to distinguish between +0.0 and -0.0.
+ return value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS
+ ? FLOAT_VALUE_0 :
value == 1.0f ? FLOAT_VALUE_1 :
value == 2.0f ? FLOAT_VALUE_2 :
new ParticularFloatValue(value);
@@ -82,7 +88,9 @@ extends ValueFactory
public DoubleValue createDoubleValue(double value)
{
- return value == 0.0 ? DOUBLE_VALUE_0 :
+ // Make sure to distinguish between +0.0 and -0.0.
+ return value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS
+ ? DOUBLE_VALUE_0 :
value == 1.0 ? DOUBLE_VALUE_1 :
new ParticularDoubleValue(value);
}
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/TopValue.java
index 048a1ff..c7320fa 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/TopValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/UnknownDoubleValue.java b/src/proguard/evaluation/value/UnknownDoubleValue.java
index 79cc4de..f8bad9a 100644
--- a/src/proguard/evaluation/value/UnknownDoubleValue.java
+++ b/src/proguard/evaluation/value/UnknownDoubleValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/UnknownFloatValue.java b/src/proguard/evaluation/value/UnknownFloatValue.java
index 3f9622a..464ceed 100644
--- a/src/proguard/evaluation/value/UnknownFloatValue.java
+++ b/src/proguard/evaluation/value/UnknownFloatValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -120,6 +120,6 @@ public class UnknownFloatValue extends FloatValue
public String toString()
{
- return "d";
+ return "f";
}
} \ No newline at end of file
diff --git a/src/proguard/evaluation/value/UnknownIntegerValue.java b/src/proguard/evaluation/value/UnknownIntegerValue.java
index be5e79d..b273b12 100644
--- a/src/proguard/evaluation/value/UnknownIntegerValue.java
+++ b/src/proguard/evaluation/value/UnknownIntegerValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/UnknownLongValue.java b/src/proguard/evaluation/value/UnknownLongValue.java
index 83a75dc..ee315be 100644
--- a/src/proguard/evaluation/value/UnknownLongValue.java
+++ b/src/proguard/evaluation/value/UnknownLongValue.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/Value.java b/src/proguard/evaluation/value/Value.java
index e24ece1..f8d9327 100644
--- a/src/proguard/evaluation/value/Value.java
+++ b/src/proguard/evaluation/value/Value.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/ValueFactory.java b/src/proguard/evaluation/value/ValueFactory.java
index 8415381..c94ac65 100644
--- a/src/proguard/evaluation/value/ValueFactory.java
+++ b/src/proguard/evaluation/value/ValueFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gradle/ProGuardTask.java b/src/proguard/gradle/ProGuardTask.java
new file mode 100644
index 0000000..f5f96e8
--- /dev/null
+++ b/src/proguard/gradle/ProGuardTask.java
@@ -0,0 +1,1532 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gradle;
+
+import groovy.lang.Closure;
+import org.gradle.api.*;
+import org.gradle.api.file.*;
+import org.gradle.api.logging.*;
+import org.gradle.api.tasks.*;
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This Task allows to configure and run ProGuard from Gradle.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuardTask extends DefaultTask
+{
+ // Accumulated input and output, for the sake of Gradle's lazy file
+ // resolution and lazy task execution.
+ private final List inJarFiles = new ArrayList();
+ private final List inJarFilters = new ArrayList();
+ private final List outJarFiles = new ArrayList();
+ private final List outJarFilters = new ArrayList();
+ private final List inJarCounts = new ArrayList();
+ private final List libraryJarFiles = new ArrayList();
+ private final List libraryJarFilters = new ArrayList();
+ private final List configurationFiles = new ArrayList();
+
+ // Accumulated configuration.
+ private final Configuration configuration = new Configuration();
+
+ // Field acting as a parameter for the class member specification methods.
+ private ClassSpecification classSpecification;
+
+
+ // Gradle task inputs and outputs, because annotations on the List fields
+ // (private or not) don't seem to work. Private methods don't work either,
+ // but package visible or protected methods are ok.
+
+ @InputFiles
+ protected FileCollection getInJarFiles() throws ParseException
+ {
+ return getProject().files(inJarFiles);
+ }
+
+ @Optional @OutputFiles
+ protected FileCollection getOutJarFiles() throws ParseException
+ {
+ return getProject().files(outJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getLibraryJarFiles() throws ParseException
+ {
+ return getProject().files(libraryJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getConfigurationFiles() throws ParseException
+ {
+ return getProject().files(configurationFiles);
+ }
+
+
+ // Gradle task settings corresponding to all ProGuard options.
+
+ public void configuration(Object configurationFiles)
+ throws ParseException, IOException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.configurationFiles.add(configurationFiles);
+ }
+
+ public void injars(Object inJarFiles)
+ throws ParseException
+ {
+ injars(null, inJarFiles);
+ }
+
+ public void injars(Map filterArgs, Object inJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.inJarFiles.add(inJarFiles);
+ this.inJarFilters.add(filterArgs);
+ }
+
+ public void outjars(Object outJarFiles)
+ throws ParseException
+ {
+ outjars(null, outJarFiles);
+ }
+
+ public void outjars(Map filterArgs, Object outJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.outJarFiles.add(getProject().file(outJarFiles));
+ this.outJarFilters.add(filterArgs);
+ this.inJarCounts.add(Integer.valueOf(inJarFiles.size()));
+ }
+
+ public void libraryjars(Object libraryJarFiles)
+ throws ParseException
+ {
+ libraryjars(null, libraryJarFiles);
+ }
+
+ public void libraryjars(Map filterArgs, Object libraryJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.libraryJarFiles.add(libraryJarFiles);
+ this.libraryJarFilters.add(filterArgs);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getskipnonpubliclibraryclasses()
+ {
+ skipnonpubliclibraryclasses();
+ return null;
+ }
+
+ public void skipnonpubliclibraryclasses()
+ {
+ configuration.skipNonPublicLibraryClasses = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontskipnonpubliclibraryclassmembers()
+ {
+ dontskipnonpubliclibraryclassmembers();
+ return null;
+ }
+
+ public void dontskipnonpubliclibraryclassmembers()
+ {
+ configuration.skipNonPublicLibraryClassMembers = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepdirectories()
+ {
+ keepdirectories();
+ return null;
+ }
+
+ public void keepdirectories()
+ {
+ keepdirectories(null);
+ }
+
+ public void keepdirectories(String filter)
+ {
+ configuration.keepDirectories =
+ extendFilter(configuration.keepDirectories, filter);
+ }
+
+ public void target(String targetClassVersion)
+ {
+ configuration.targetClassVersion =
+ ClassUtil.internalClassVersion(targetClassVersion);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getforceprocessing()
+ {
+ forceprocessing();
+ return null;
+ }
+
+ public void forceprocessing()
+ {
+ configuration.lastModified = Long.MAX_VALUE;
+ }
+
+ public void keep(String classSpecificationString)
+ throws ParseException
+ {
+ keep(null, classSpecificationString);
+ }
+
+ public void keep(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keep(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keep(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keep(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembers(null, classSpecificationString);
+ }
+
+ public void keepclassmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembers(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepnames(String classSpecificationString)
+ throws ParseException
+ {
+ keepnames(null, classSpecificationString);
+ }
+
+ public void keepnames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepnames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembernames(null, classSpecificationString);
+ }
+
+ public void keepclassmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembernames(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintseeds()
+ {
+ printseeds();
+ return null;
+ }
+
+ public void printseeds()
+ {
+ configuration.printSeeds = Configuration.STD_OUT;
+ }
+
+ public void printseeds(Object printSeeds)
+ throws ParseException
+ {
+ configuration.printSeeds = getProject().file(printSeeds);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontshrink()
+ {
+ dontshrink();
+ return null;
+ }
+
+ public void dontshrink()
+ {
+ configuration.shrink = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintusage()
+ {
+ printusage();
+ return null;
+ }
+
+ public void printusage()
+ {
+ configuration.printUsage = Configuration.STD_OUT;
+ }
+
+ public void printusage(Object printUsage)
+ throws ParseException
+ {
+ configuration.printUsage = getProject().file(printUsage);
+ }
+
+ public void whyareyoukeeping(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs)
+ throws ParseException
+ {
+ whyareyoukeeping(classSpecificationArgs, null);
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontoptimize()
+ {
+ dontoptimize();
+ return null;
+ }
+
+ public void dontoptimize()
+ {
+ configuration.optimize = false;
+ }
+
+ public void optimizations(String filter)
+ {
+ configuration.optimizations =
+ extendFilter(configuration.optimizations, filter);
+ }
+
+
+ public void optimizationpasses(int optimizationPasses)
+ {
+ configuration.optimizationPasses = optimizationPasses;
+ }
+
+ public void assumenosideeffects(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void assumenosideeffects(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getallowaccessmodification()
+ {
+ allowaccessmodification();
+ return null;
+ }
+
+ public void allowaccessmodification()
+ {
+ configuration.allowAccessModification = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmergeinterfacesaggressively()
+ {
+ mergeinterfacesaggressively();
+ return null;
+ }
+
+ public void mergeinterfacesaggressively()
+ {
+ configuration.mergeInterfacesAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontobfuscate()
+ {
+ dontobfuscate();
+ return null;
+ }
+
+ public void dontobfuscate()
+ {
+ configuration.obfuscate = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintmapping()
+ {
+ printmapping();
+ return null;
+ }
+
+ public void printmapping()
+ {
+ configuration.printMapping = Configuration.STD_OUT;
+ }
+
+ public void printmapping(Object printMapping)
+ throws ParseException
+ {
+ configuration.printMapping = getProject().file(printMapping);
+ }
+
+ public void applymapping(Object applyMapping)
+ throws ParseException
+ {
+ configuration.applyMapping = getProject().file(applyMapping);
+ }
+
+ public void obfuscationdictionary(Object obfuscationDictionary)
+ throws ParseException
+ {
+ configuration.obfuscationDictionary =
+ getProject().file(obfuscationDictionary);
+ }
+
+ public void classobfuscationdictionary(Object classObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.classObfuscationDictionary =
+ getProject().file(classObfuscationDictionary);
+ }
+
+ public void packageobfuscationdictionary(Object packageObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.packageObfuscationDictionary =
+ getProject().file(packageObfuscationDictionary);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getoverloadaggressively()
+ {
+ overloadaggressively();
+ return null;
+ }
+
+ public void overloadaggressively()
+ {
+ configuration.overloadAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getuseuniqueclassmembernames()
+ {
+ useuniqueclassmembernames();
+ return null;
+ }
+
+ public void useuniqueclassmembernames()
+ {
+ configuration.useUniqueClassMemberNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontusemixedcaseclassnames()
+ {
+ dontusemixedcaseclassnames();
+ return null;
+ }
+
+ public void dontusemixedcaseclassnames()
+ {
+ configuration.useMixedCaseClassNames = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeeppackagenames()
+ {
+ keeppackagenames();
+ return null;
+ }
+
+ public void keeppackagenames()
+ {
+ keeppackagenames(null);
+ }
+
+ public void keeppackagenames(String filter)
+ {
+ configuration.keepPackageNames =
+ extendFilter(configuration.keepPackageNames, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getflattenpackagehierarchy()
+ {
+ flattenpackagehierarchy();
+ return null;
+ }
+
+ public void flattenpackagehierarchy()
+ {
+ flattenpackagehierarchy("");
+ }
+
+ public void flattenpackagehierarchy(String flattenPackageHierarchy)
+ {
+ configuration.flattenPackageHierarchy =
+ ClassUtil.internalClassName(flattenPackageHierarchy);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrepackageclasses()
+ {
+ repackageclasses();
+ return null;
+ }
+
+ public void repackageclasses()
+ {
+ repackageclasses("");
+ }
+
+ public void repackageclasses(String repackageClasses)
+ {
+ configuration.repackageClasses =
+ ClassUtil.internalClassName(repackageClasses);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepattributes()
+ {
+ keepattributes();
+ return null;
+ }
+
+ public void keepattributes()
+ {
+ keepattributes(null);
+ }
+
+ public void keepattributes(String filter)
+ {
+ configuration.keepAttributes =
+ extendFilter(configuration.keepAttributes, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepparameternames()
+ {
+ keepparameternames();
+ return null;
+ }
+
+ public void keepparameternames()
+ {
+ configuration.keepParameterNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrenamesourcefileattribute()
+ {
+ renamesourcefileattribute();
+ return null;
+ }
+
+ public void renamesourcefileattribute()
+ {
+ renamesourcefileattribute("");
+ }
+
+ public void renamesourcefileattribute(String newSourceFileAttribute)
+ {
+ configuration.newSourceFileAttribute = newSourceFileAttribute;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptclassstrings()
+ {
+ adaptclassstrings();
+ return null;
+ }
+
+ public void adaptclassstrings()
+ {
+ adaptclassstrings(null);
+ }
+
+ public void adaptclassstrings(String filter)
+ {
+ configuration.adaptClassStrings =
+ extendFilter(configuration.adaptClassStrings, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilenames()
+ {
+ adaptresourcefilenames();
+ return null;
+ }
+
+ public void adaptresourcefilenames()
+ {
+ adaptresourcefilenames(null);
+ }
+
+ public void adaptresourcefilenames(String filter)
+ {
+ configuration.adaptResourceFileNames =
+ extendFilter(configuration.adaptResourceFileNames, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilecontents()
+ {
+ adaptresourcefilecontents();
+ return null;
+ }
+
+ public void adaptresourcefilecontents()
+ {
+ adaptresourcefilecontents(null);
+ }
+
+ public void adaptresourcefilecontents(String filter)
+ {
+ configuration.adaptResourceFileContents =
+ extendFilter(configuration.adaptResourceFileContents, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontpreverify()
+ {
+ dontpreverify();
+ return null;
+ }
+
+ public void dontpreverify()
+ {
+ configuration.preverify = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmicroedition()
+ {
+ microedition();
+ return null;
+ }
+
+ public void microedition()
+ {
+ configuration.microEdition = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getverbose()
+ {
+ verbose();
+ return null;
+ }
+
+ public void verbose()
+ {
+ configuration.verbose = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontnote()
+ {
+ dontnote();
+ return null;
+ }
+
+ public void dontnote()
+ {
+ dontnote(null);
+ }
+
+ public void dontnote(String filter)
+ {
+ configuration.note = extendFilter(configuration.note, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontwarn()
+ {
+ dontwarn();
+ return null;
+ }
+
+ public void dontwarn()
+ {
+ dontwarn(null);
+ }
+
+ public void dontwarn(String filter)
+ {
+ configuration.warn = extendFilter(configuration.warn, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getignorewarnings()
+ {
+ ignorewarnings();
+ return null;
+ }
+
+ public void ignorewarnings()
+ {
+ configuration.ignoreWarnings = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintconfiguration()
+ {
+ printconfiguration();
+ return null;
+ }
+
+ public void printconfiguration()
+ {
+ configuration.printConfiguration = Configuration.STD_OUT;
+ }
+
+ public void printconfiguration(Object printConfiguration)
+ throws ParseException
+ {
+ configuration.printConfiguration =
+ getProject().file(printConfiguration);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdump()
+ {
+ dump();
+ return null;
+ }
+
+ public void dump()
+ {
+ configuration.dump = Configuration.STD_OUT;
+ }
+
+ public void dump(Object dump)
+ throws ParseException
+ {
+ configuration.dump = getProject().file(dump);
+ }
+
+
+ // Class member methods.
+
+ public void field(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'field' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addField(createMemberSpecification(false,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ public void constructor(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'constructor' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ true,
+ memberSpecificationArgs));
+ }
+
+
+ public void method(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'method' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ // Gradle task execution.
+
+ @TaskAction
+ public void proguard()
+ throws ParseException, IOException
+ {
+ // Weave the input jars and the output jars into a single class path,
+ // with lazy resolution of the files.
+ configuration.programJars = new ClassPath();
+
+ int outJarIndex = 0;
+
+ int inJarCount = inJarCounts.size() == 0 ? -1 :
+ ((Integer)inJarCounts.get(0)).intValue();
+
+ for (int inJarIndex = 0; inJarIndex < inJarFiles.size(); inJarIndex++)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ inJarFiles.get(inJarIndex),
+ (Map)inJarFilters.get(inJarIndex),
+ false);
+
+ while (inJarIndex == inJarCount - 1)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ outJarFiles.get(outJarIndex),
+ (Map)outJarFilters.get(outJarIndex),
+ true);
+
+ outJarIndex++;
+
+ inJarCount = inJarCounts.size() == outJarIndex ? -1 :
+ ((Integer)inJarCounts.get(outJarIndex)).intValue();
+ }
+ }
+
+ // Copy the library jars into a single class path, with lazy resolution
+ // of the files.
+ configuration.libraryJars = new ClassPath();
+
+ for (int libraryJarIndex = 0; libraryJarIndex < libraryJarFiles.size(); libraryJarIndex++)
+ {
+ configuration.libraryJars =
+ extendClassPath(configuration.libraryJars,
+ libraryJarFiles.get(libraryJarIndex),
+ (Map)libraryJarFilters.get(libraryJarIndex),
+ false);
+ }
+
+ // Lazily apply the external configuration files.
+ ConfigurableFileCollection fileCollection =
+ getProject().files(configurationFiles);
+
+ Iterator<File> files = fileCollection.iterator();
+ while (files.hasNext())
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(files.next(), System.getProperties());
+
+ try
+ {
+ parser.parse(configuration);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+
+ // Make sure the code is processed. Gradle has already checked that it
+ // was necessary.
+ configuration.lastModified = Long.MAX_VALUE;
+
+ // Let the logging manager capture the standard output and errors from
+ // ProGuard.
+ LoggingManager loggingManager = getLogging();
+ loggingManager.captureStandardOutput(LogLevel.INFO);
+ loggingManager.captureStandardError(LogLevel.WARN);
+
+ // Run ProGuard with the collected configuration.
+ new ProGuard(configuration).execute();
+
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Extends the given class path with the given filtered input or output
+ * files.
+ */
+ private ClassPath extendClassPath(ClassPath classPath,
+ Object files,
+ Map filterArgs,
+ boolean output)
+ {
+ ConfigurableFileCollection fileCollection = getProject().files(files);
+
+ if (classPath == null)
+ {
+ classPath = new ClassPath();
+ }
+
+ Iterator fileIterator = fileCollection.iterator();
+ while (fileIterator.hasNext())
+ {
+ File file = (File)fileIterator.next();
+ if (output || file.exists())
+ {
+ // Create the class path entry.
+ ClassPathEntry classPathEntry = new ClassPathEntry(file, output);
+
+ // Add any filters to the class path entry.
+ if (filterArgs != null)
+ {
+ classPathEntry.setFilter(ListUtil.commaSeparatedList((String)filterArgs.get("filter")));
+ classPathEntry.setJarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("jarfilter")));
+ classPathEntry.setWarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("warfilter")));
+ classPathEntry.setEarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("earfilter")));
+ classPathEntry.setZipFilter(ListUtil.commaSeparatedList((String)filterArgs.get("zipfilter")));
+ }
+
+ classPath.add(classPathEntry);
+ }
+ }
+
+ return classPath;
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationString);
+
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ keepArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure);
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ classSpecificationArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ ClassSpecification classSpecification)
+ {
+ return
+ new KeepClassSpecification(markClasses,
+ markConditionally,
+ retrieveBoolean(keepArgs, "allowshrinking", allowShrinking),
+ retrieveBoolean(keepArgs, "allowoptimization", false),
+ retrieveBoolean(keepArgs, "allowobfuscation", false),
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given ProGuard-style class specification.
+ */
+ private ClassSpecification createClassSpecification(String classSpecificationString)
+ throws ParseException
+ {
+ try
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(new String[] { classSpecificationString }, null);
+
+ try
+ {
+ return parser.parseClassSpecificationArguments();
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ParseException(e.getMessage());
+ }
+ }
+
+
+ /**
+ * Creates a specification of classes and class members, based on the
+ * given parameters.
+ */
+ private ClassSpecification createClassSpecification(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String type = (String)classSpecificationArgs.get("type");
+ String name = (String)classSpecificationArgs.get("name");
+ String extendsAnnotation = (String)classSpecificationArgs.get("extendsannotation");
+ String extends_ = (String)classSpecificationArgs.get("extends");
+ if (extends_ == null)
+ {
+ extends_ = (String)classSpecificationArgs.get("implements");
+ }
+
+ // Create the class specification.
+ ClassSpecification classSpecification =
+ new ClassSpecification(null,
+ requiredClassAccessFlags(true, access, type),
+ requiredClassAccessFlags(false, access, type),
+ annotation != null ? ClassUtil.internalType(annotation) : null,
+ name != null ? ClassUtil.internalClassName(name) : null,
+ extendsAnnotation != null ? ClassUtil.internalType(extendsAnnotation) : null,
+ extends_ != null ? ClassUtil.internalClassName(extends_) : null);
+
+ // Initialize the class specification with its closure.
+ if (classMembersClosure != null)
+ {
+ // Temporarily remember the class specification, so we can add
+ // class member specifications.
+ this.classSpecification = classSpecification;
+ classMembersClosure.call(classSpecification);
+ this.classSpecification = null;
+ }
+
+ return classSpecification;
+ }
+
+
+ /**
+ * Parses the class access flags that must be set (or not), based on the
+ * given ProGuard-style flag specification.
+ */
+ private int requiredClassAccessFlags(boolean set,
+ String access,
+ String type)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ if (type != null && (type.startsWith("!") ^ set))
+ {
+ int accessFlag =
+ type.equals("class") ? 0 :
+ type.equals( ClassConstants.EXTERNAL_ACC_INTERFACE) ||
+ type.equals("!" + ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE :
+ type.equals( ClassConstants.EXTERNAL_ACC_ENUM) ||
+ type.equals("!" + ClassConstants.EXTERNAL_ACC_ENUM) ? ClassConstants.INTERNAL_ACC_ENUM :
+ -1;
+ if (accessFlag == -1)
+ {
+ throw new ParseException("Incorrect class type ["+type+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Creates a specification of class members, based on the given parameters.
+ */
+ private MemberSpecification createMemberSpecification(boolean isMethod,
+ boolean isConstructor,
+ Map classSpecificationArgs)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String type = (String)classSpecificationArgs.get("type");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String name = (String)classSpecificationArgs.get("name");
+ String parameters = (String)classSpecificationArgs.get("parameters");
+
+ // Perform some basic conversions and checks on the attributes.
+ if (annotation != null)
+ {
+ annotation = ClassUtil.internalType(annotation);
+ }
+
+ if (isMethod)
+ {
+ if (isConstructor)
+ {
+ if (type != null)
+ {
+ throw new ParseException("Type attribute not allowed in constructor specification ["+type+"]");
+ }
+
+ if (parameters != null)
+ {
+ type = ClassConstants.EXTERNAL_TYPE_VOID;
+ }
+
+ name = ClassConstants.INTERNAL_METHOD_NAME_INIT;
+ }
+ else if ((type != null) ^ (parameters != null))
+ {
+ throw new ParseException("Type and parameters attributes must always be present in combination in method specification");
+ }
+ }
+ else
+ {
+ if (parameters != null)
+ {
+ throw new ParseException("Parameters attribute not allowed in field specification ["+parameters+"]");
+ }
+ }
+
+ List parameterList = ListUtil.commaSeparatedList(parameters);
+
+ String descriptor =
+ parameters != null ? ClassUtil.internalMethodDescriptor(type, parameterList) :
+ type != null ? ClassUtil.internalType(type) :
+ null;
+
+ return new MemberSpecification(requiredMemberAccessFlags(true, access),
+ requiredMemberAccessFlags(false, access),
+ annotation,
+ name,
+ descriptor);
+ }
+
+
+ /**
+ * Parses the class member access flags that must be set (or not), based on
+ * the given ProGuard-style flag specification.
+ */
+ private int requiredMemberAccessFlags(boolean set,
+ String access)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PRIVATE) ? ClassConstants.INTERNAL_ACC_PRIVATE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PROTECTED) ? ClassConstants.INTERNAL_ACC_PROTECTED :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_STATIC) ? ClassConstants.INTERNAL_ACC_STATIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class member access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Retrieves a specified boolean flag from the given map.
+ */
+ private boolean retrieveBoolean(Map args, String name, boolean defaultValue)
+ {
+ if (args == null)
+ {
+ return defaultValue;
+ }
+
+ Object arg = args.get(name);
+
+ return arg == null ? defaultValue : ((Boolean)arg).booleanValue();
+ }
+
+
+ /**
+ * Adds the given class specification to the given list, creating a new list
+ * if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ ClassSpecification classSpecification)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.add(classSpecification);
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given class specifications to the given list, creating a new
+ * list if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ List additionalClassSpecifications)
+ {
+ if (additionalClassSpecifications != null)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.addAll(additionalClassSpecifications);
+ }
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary.
+ */
+ private List extendFilter(List filter,
+ String filterString)
+ {
+ return extendFilter(filter, filterString, false);
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary. External class names are converted to internal class names,
+ * if requested.
+ */
+ private List extendFilter(List filter,
+ String filterString,
+ boolean convertExternalClassNames)
+ {
+ if (filter == null)
+ {
+ filter = new ArrayList();
+ }
+
+ if (filterString == null)
+ {
+ // Clear the filter to keep all names.
+ filter.clear();
+ }
+ else
+ {
+ if (convertExternalClassNames)
+ {
+ filterString = ClassUtil.internalClassName(filterString);
+ }
+
+ // Append the filter.
+ filter.addAll(ListUtil.commaSeparatedList(filterString));
+ }
+
+ return filter;
+ }
+}
diff --git a/src/proguard/gui/ClassPathPanel.java b/src/proguard/gui/ClassPathPanel.java
index 95f3d1b..8f41db6 100644
--- a/src/proguard/gui/ClassPathPanel.java
+++ b/src/proguard/gui/ClassPathPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,7 +26,7 @@ import proguard.util.ListUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
-import java.io.File;
+import java.io.*;
import java.util.List;
/**
@@ -141,7 +141,7 @@ class ClassPathPanel extends ListPanel
// Up to JDK 1.3.1, setSelectedFiles doesn't show in the file
// chooser, so we just use setSelectedFile first. It also sets
// the current directory.
- chooser.setSelectedFile(selectedFiles[0]);
+ chooser.setSelectedFile(selectedFiles[0].getAbsoluteFile());
chooser.setSelectedFiles(selectedFiles);
int returnValue = chooser.showOpenDialog(owner);
@@ -432,7 +432,7 @@ class ClassPathPanel extends ListPanel
filter = new StringBuffer().append('(');
}
- filter.append(ListUtil.commaSeparatedString(additionalFilter));
+ filter.append(ListUtil.commaSeparatedString(additionalFilter, true));
}
return filter;
diff --git a/src/proguard/gui/ClassSpecificationDialog.java b/src/proguard/gui/ClassSpecificationDialog.java
index 36d80d4..38a3146 100644
--- a/src/proguard/gui/ClassSpecificationDialog.java
+++ b/src/proguard/gui/ClassSpecificationDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -63,9 +63,10 @@ final class ClassSpecificationDialog extends JDialog
private final JRadioButton[] publicRadioButtons;
private final JRadioButton[] finalRadioButtons;
private final JRadioButton[] abstractRadioButtons;
- private final JRadioButton[] enumRadioButtons;
- private final JRadioButton[] annotationRadioButtons;
private final JRadioButton[] interfaceRadioButtons;
+ private final JRadioButton[] annotationRadioButtons;
+ private final JRadioButton[] enumRadioButtons;
+ private final JRadioButton[] syntheticRadioButtons;
private final JTextField annotationTypeTextField = new JTextField(20);
private final JTextField classNameTextField = new JTextField(20);
@@ -199,9 +200,10 @@ final class ClassSpecificationDialog extends JDialog
publicRadioButtons = addRadioButtonTriplet("Public", accessPanel);
finalRadioButtons = addRadioButtonTriplet("Final", accessPanel);
abstractRadioButtons = addRadioButtonTriplet("Abstract", accessPanel);
- enumRadioButtons = addRadioButtonTriplet("Enum", accessPanel);
- annotationRadioButtons = addRadioButtonTriplet("Annotation", accessPanel);
interfaceRadioButtons = addRadioButtonTriplet("Interface", accessPanel);
+ annotationRadioButtons = addRadioButtonTriplet("Annotation", accessPanel);
+ enumRadioButtons = addRadioButtonTriplet("Enum", accessPanel);
+ syntheticRadioButtons = addRadioButtonTriplet("Synthetic", accessPanel);
// Create the annotation type panel.
final JPanel annotationTypePanel = new JPanel(layout);
@@ -393,9 +395,10 @@ final class ClassSpecificationDialog extends JDialog
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons);
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
- setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
- setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE, interfaceRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
// Set the class and annotation text fields.
annotationTypeTextField .setText(annotationType == null ? "" : ClassUtil.externalType(annotationType));
@@ -453,9 +456,10 @@ final class ClassSpecificationDialog extends JDialog
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons);
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
- getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
- getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE, interfaceRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
// Get the keep class member option lists.
classSpecification.fieldSpecifications = memberSpecificationsPanel.getMemberSpecifications(true);
diff --git a/src/proguard/gui/ClassSpecificationsPanel.java b/src/proguard/gui/ClassSpecificationsPanel.java
index 2cf0b1d..bc29247 100644
--- a/src/proguard/gui/ClassSpecificationsPanel.java
+++ b/src/proguard/gui/ClassSpecificationsPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ExtensionFileFilter.java b/src/proguard/gui/ExtensionFileFilter.java
index d67be40..ee09714 100644
--- a/src/proguard/gui/ExtensionFileFilter.java
+++ b/src/proguard/gui/ExtensionFileFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/FilterBuilder.java b/src/proguard/gui/FilterBuilder.java
index e46193f..c362cb6 100644
--- a/src/proguard/gui/FilterBuilder.java
+++ b/src/proguard/gui/FilterBuilder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/FilterDialog.java b/src/proguard/gui/FilterDialog.java
index 1567a31..88dbd8b 100644
--- a/src/proguard/gui/FilterDialog.java
+++ b/src/proguard/gui/FilterDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -182,7 +182,7 @@ public class FilterDialog extends JDialog
*/
public void setFilter(List filter)
{
- filterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_FILTER);
+ filterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_FILTER);
}
@@ -202,7 +202,7 @@ public class FilterDialog extends JDialog
*/
public void setJarFilter(List filter)
{
- jarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_JAR_FILTER);
+ jarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_JAR_FILTER);
}
@@ -222,7 +222,7 @@ public class FilterDialog extends JDialog
*/
public void setWarFilter(List filter)
{
- warFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_WAR_FILTER);
+ warFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_WAR_FILTER);
}
@@ -242,7 +242,7 @@ public class FilterDialog extends JDialog
*/
public void setEarFilter(List filter)
{
- earFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_EAR_FILTER);
+ earFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_EAR_FILTER);
}
@@ -262,7 +262,7 @@ public class FilterDialog extends JDialog
*/
public void setZipFilter(List filter)
{
- zipFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter) : DEFAULT_ZIP_FILTER);
+ zipFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_ZIP_FILTER);
}
diff --git a/src/proguard/gui/GUIResources.java b/src/proguard/gui/GUIResources.java
index 85d582c..3d7c6c6 100644
--- a/src/proguard/gui/GUIResources.java
+++ b/src/proguard/gui/GUIResources.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/GUIResources.properties b/src/proguard/gui/GUIResources.properties
index 86ab7a1..b27075d 100644
--- a/src/proguard/gui/GUIResources.properties
+++ b/src/proguard/gui/GUIResources.properties
@@ -1,5 +1,5 @@
# ProGuard -- shrinking, optimization, and obfuscation of Java class files.
-# Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+# Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
#
# Tab names.
@@ -25,7 +25,7 @@ preverification = Preverification
#
# Panel titles.
#
-welcome = Welcome to ProGuard, version 4.4
+welcome = Welcome to ProGuard, version 4.10
options = Options
keepAdditional = Keep additional classes and class members
keepNamesAdditional = Keep additional class names and class member names
@@ -51,20 +51,26 @@ whyAreYouKeepingTip = \
# Info texts.
#
proGuardInfo = \
- ProGuard is a free class file shrinker, optimizer, obfuscator, and preverifier.\
- \n\n\
- With this GUI, you can create, load, modify, and save ProGuard configurations. \
- \n\
+ <html>ProGuard is a free class file shrinker, optimizer, obfuscator, and preverifier.\
+ <p>\
+ With this GUI, you can create, load, modify, and save ProGuard configurations.\
+ <br>\
You can then process your code right away, or you can run ProGuard from the \
- command line using your saved configuration. \
- \n\n\
+ command line using your saved configuration.\
+ <p>\
With the ReTrace part of this GUI you can de-obfuscate your stack traces.\
- \n\n\
+ <p>\
ProGuard and ReTrace are written and maintained by Eric Lafortune.\
- \n\n\
+ <p>\
+ Official site at Sourceforge: \
+ <a href="http://proguard.sourceforge.net/\">http://proguard.sourceforge.net/</a>\
+ <br>\
+ Professional support by Saikoa: \
+ <a href="http://www.saikoa.com/\">http://www.saikoa.com/</a>\
+ <p>\
Distributed under the GNU General Public License.\
- \n\
- Copyright (c) 2002-2009.
+ <br>\
+ Copyright &copy; 2002-2013.</html>
processingInfo = \
You can now start processing your code, \
@@ -105,6 +111,7 @@ flattenPackageHierarchy = Flatten package hierarchy
repackageClasses = Repackage classes
useMixedCaseClassNames = Use mixed-case class names
keepAttributes = Keep attributes
+keepParameterNames = Keep parameter names
renameSourceFileAttribute = Rename SourceFile attribute
adaptClassStrings = Adapt class strings
adaptResourceFileNames = Adapt resource file names
@@ -115,14 +122,14 @@ microEdition = Micro Edition
verbose = Verbose
note = Note potential mistakes in the configuration
-warn = Warn about possibly erronous input
-ignoreWarnings = Ignore warnings about possibly erronous input
+warn = Warn about possibly erroneous input
+ignoreWarnings = Ignore warnings about possibly erroneous input
skipNonPublicLibraryClasses = Skip non-public library classes
skipNonPublicLibraryClassMembers = Skip non-public library class members
keepDirectories = Keep directories
forceProcessing = Force processing
target = Target
-targets = 1.0,1.1,1.2,1.3,1.4,1.5,1.6
+targets = 1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7
printSeeds = Print seeds
printConfiguration = Print configuration
dump = Print class files
@@ -209,6 +216,9 @@ attributesTip = \
<li>"*Annotations*" is necessary for preserving annotations.\
</ul>\
The wildcard <code>*</code> and the negator <code>!</code> are allowed.</html>
+keepParameterNamesTip = \
+ <html>Keep parameter names and types in "LocalVariable*Table" attributes<br>\
+ in methods that are not obfuscated.</html>
renameSourceFileAttributeTip = \
<html>Put the given string in the "SourceFile" attribute of the processed class files.<br>\
It will appear as the file name of the classes in stack traces.</html>
@@ -246,12 +256,12 @@ noteTip = \
noteFilterTip = \
A filter matching classes for which no notes should be printed.
warnTip = \
- <html>Print out warnings about possibly erronous input.<br>\
+ <html>Print out warnings about possibly erroneous input.<br>\
<i>Only unset this option if you know what you're doing!</i></html>
warnFilterTip = \
A filter matching classes for which no warnings should be printed.
ignoreWarningsTip = \
- <html>Ignore any warnings about possibly erronous input.<br>\
+ <html>Ignore any warnings about possibly erroneous input.<br>\
<i>Only set this option if you know what you're doing!</i></html>
skipNonPublicLibraryClassesTip = \
<html>Skip reading non-public library classes, for efficiency.<br>\
@@ -495,6 +505,8 @@ code_simplification_fieldTip = \
Perform peephole optimizations for field loading and storing.
code_simplification_branchTip = \
Perform peephole optimizations for branch instructions.
+code_simplification_stringTip = \
+ Perform peephole optimizations for constant strings.
code_simplification_advancedTip = \
Simplify code based on control flow analysis and data flow analysis.
code_removal_advancedTip = \
@@ -504,7 +516,7 @@ code_removal_simpleTip = \
code_removal_variableTip = \
Remove unused variables from the local variable frame.
code_removal_exceptionTip = \
- Remove exceptions with empty catch blocks.
+ Remove exceptions with empty try blocks.
code_allocation_variableTip = \
Optimize variable allocation on the local variable frame.
diff --git a/src/proguard/gui/KeepSpecificationsPanel.java b/src/proguard/gui/KeepSpecificationsPanel.java
index 4c3c953..908f028 100644
--- a/src/proguard/gui/KeepSpecificationsPanel.java
+++ b/src/proguard/gui/KeepSpecificationsPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ListPanel.java b/src/proguard/gui/ListPanel.java
index 0132340..19a0c4d 100644
--- a/src/proguard/gui/ListPanel.java
+++ b/src/proguard/gui/ListPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/MemberSpecificationDialog.java b/src/proguard/gui/MemberSpecificationDialog.java
index 46a3f6f..4bf72ca 100644
--- a/src/proguard/gui/MemberSpecificationDialog.java
+++ b/src/proguard/gui/MemberSpecificationDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -56,6 +56,7 @@ final class MemberSpecificationDialog extends JDialog
private final JRadioButton[] protectedRadioButtons;
private final JRadioButton[] staticRadioButtons;
private final JRadioButton[] finalRadioButtons;
+ private final JRadioButton[] syntheticRadioButtons;
private JRadioButton[] volatileRadioButtons;
private JRadioButton[] transientRadioButtons;
@@ -64,6 +65,8 @@ final class MemberSpecificationDialog extends JDialog
private JRadioButton[] nativeRadioButtons;
private JRadioButton[] abstractRadioButtons;
private JRadioButton[] strictRadioButtons;
+ private JRadioButton[] bridgeRadioButtons;
+ private JRadioButton[] varargsRadioButtons;
private final JTextField annotationTypeTextField = new JTextField(20);
private final JTextField nameTextField = new JTextField(20);
@@ -166,6 +169,7 @@ final class MemberSpecificationDialog extends JDialog
protectedRadioButtons = addRadioButtonTriplet("Protected", accessPanel);
staticRadioButtons = addRadioButtonTriplet("Static", accessPanel);
finalRadioButtons = addRadioButtonTriplet("Final", accessPanel);
+ syntheticRadioButtons = addRadioButtonTriplet("Synthetic", accessPanel);
if (isField)
{
@@ -178,6 +182,8 @@ final class MemberSpecificationDialog extends JDialog
nativeRadioButtons = addRadioButtonTriplet("Native", accessPanel);
abstractRadioButtons = addRadioButtonTriplet("Abstract", accessPanel);
strictRadioButtons = addRadioButtonTriplet("Strict", accessPanel);
+ bridgeRadioButtons = addRadioButtonTriplet("Bridge", accessPanel);
+ varargsRadioButtons = addRadioButtonTriplet("Varargs", accessPanel);
}
// Create the type panel.
@@ -332,12 +338,15 @@ final class MemberSpecificationDialog extends JDialog
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNCHRONIZED, synchronizedRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_BRIDGE, bridgeRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VARARGS, varargsRadioButtons);
// Set the class name text fields.
nameTextField.setText(name == null ? "*" : name);
@@ -403,12 +412,15 @@ final class MemberSpecificationDialog extends JDialog
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_SYNCHRONIZED, synchronizedRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_BRIDGE, bridgeRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_VARARGS, varargsRadioButtons);
return memberSpecification;
}
diff --git a/src/proguard/gui/MemberSpecificationsPanel.java b/src/proguard/gui/MemberSpecificationsPanel.java
index 20b2f17..6a72a1d 100644
--- a/src/proguard/gui/MemberSpecificationsPanel.java
+++ b/src/proguard/gui/MemberSpecificationsPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/MessageDialogRunnable.java b/src/proguard/gui/MessageDialogRunnable.java
index e58f1c6..6c2152c 100644
--- a/src/proguard/gui/MessageDialogRunnable.java
+++ b/src/proguard/gui/MessageDialogRunnable.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/OptimizationsDialog.java b/src/proguard/gui/OptimizationsDialog.java
index 044c338..0af0979 100644
--- a/src/proguard/gui/OptimizationsDialog.java
+++ b/src/proguard/gui/OptimizationsDialog.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ProGuardGUI.java b/src/proguard/gui/ProGuardGUI.java
index f27d698..6b08aa8 100644
--- a/src/proguard/gui/ProGuardGUI.java
+++ b/src/proguard/gui/ProGuardGUI.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -33,7 +33,6 @@ import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.List;
-import java.lang.reflect.InvocationTargetException;
/**
@@ -110,6 +109,7 @@ public class ProGuardGUI extends JFrame
private final JCheckBox flattenPackageHierarchyCheckBox = new JCheckBox(msg("flattenPackageHierarchy"));
private final JCheckBox repackageClassesCheckBox = new JCheckBox(msg("repackageClasses"));
private final JCheckBox keepAttributesCheckBox = new JCheckBox(msg("keepAttributes"));
+ private final JCheckBox keepParameterNamesCheckBox = new JCheckBox(msg("keepParameterNames"));
private final JCheckBox newSourceFileAttributeCheckBox = new JCheckBox(msg("renameSourceFileAttribute"));
private final JCheckBox adaptClassStringsCheckBox = new JCheckBox(msg("adaptClassStrings"));
private final JCheckBox adaptResourceFileNamesCheckBox = new JCheckBox(msg("adaptResourceFileNames"));
@@ -202,13 +202,13 @@ public class ProGuardGUI extends JFrame
splashPanelConstraints.anchor = GridBagConstraints.NORTHWEST;
//splashPanelConstraints.insets = constraints.insets;
- GridBagConstraints welcomeTextAreaConstraints = new GridBagConstraints();
- welcomeTextAreaConstraints.gridwidth = GridBagConstraints.REMAINDER;
- welcomeTextAreaConstraints.fill = GridBagConstraints.NONE;
- welcomeTextAreaConstraints.weightx = 1.0;
- welcomeTextAreaConstraints.weighty = 0.01;
- welcomeTextAreaConstraints.anchor = GridBagConstraints.CENTER;//NORTHWEST;
- welcomeTextAreaConstraints.insets = new Insets(20, 40, 20, 40);
+ GridBagConstraints welcomePaneConstraints = new GridBagConstraints();
+ welcomePaneConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ welcomePaneConstraints.fill = GridBagConstraints.NONE;
+ welcomePaneConstraints.weightx = 1.0;
+ welcomePaneConstraints.weighty = 0.01;
+ welcomePaneConstraints.anchor = GridBagConstraints.CENTER;//NORTHWEST;
+ welcomePaneConstraints.insets = new Insets(20, 40, 20, 40);
GridBagConstraints panelConstraints = new GridBagConstraints();
panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
@@ -295,18 +295,19 @@ public class ProGuardGUI extends JFrame
splashPanel = new SplashPanel(splash, 0.5, 5500L);
splashPanel.setPreferredSize(new Dimension(0, 200));
- JTextArea welcomeTextArea = new JTextArea(msg("proGuardInfo"), 18, 50);
- welcomeTextArea.setOpaque(false);
- welcomeTextArea.setEditable(false);
- welcomeTextArea.setLineWrap(true);
- welcomeTextArea.setWrapStyleWord(true);
- welcomeTextArea.setPreferredSize(new Dimension(0, 0));
- welcomeTextArea.setBorder(new EmptyBorder(20, 20, 20, 20));
- addBorder(welcomeTextArea, "welcome");
+ JEditorPane welcomePane = new JEditorPane("text/html", msg("proGuardInfo"));
+ welcomePane.setPreferredSize(new Dimension(640, 350));
+ // The constant HONOR_DISPLAY_PROPERTIES isn't present yet in JDK 1.4.
+ //welcomePane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
+ welcomePane.putClientProperty("JEditorPane.honorDisplayProperties", Boolean.TRUE);
+ welcomePane.setOpaque(false);
+ welcomePane.setEditable(false);
+ welcomePane.setBorder(new EmptyBorder(20, 20, 20, 20));
+ addBorder(welcomePane, "welcome");
JPanel proGuardPanel = new JPanel(layout);
proGuardPanel.add(splashPanel, splashPanelConstraints);
- proGuardPanel.add(welcomeTextArea, welcomeTextAreaConstraints);
+ proGuardPanel.add(welcomePane, welcomePaneConstraints);
// Create the input panel.
// TODO: properly clone the ClassPath objects.
@@ -403,6 +404,7 @@ public class ProGuardGUI extends JFrame
obfuscationOptionsPanel.add(tip(repackageClassesTextField, "packageTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(keepAttributesCheckBox, "keepAttributesTip"), constraints);
obfuscationOptionsPanel.add(tip(keepAttributesTextField, "attributesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(keepParameterNamesCheckBox, "keepParameterNamesTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(newSourceFileAttributeCheckBox, "renameSourceFileAttributeTip"), constraints);
obfuscationOptionsPanel.add(tip(newSourceFileAttributeTextField, "sourceFileAttributeTip"), constraintsLastStretch);
obfuscationOptionsPanel.add(tip(adaptClassStringsCheckBox, "adaptClassStringsTip"), constraints);
@@ -631,11 +633,14 @@ public class ProGuardGUI extends JFrame
reTracePanel .add(tip(loadStackTraceButton, "loadStackTraceTip"), bottomButtonConstraints);
reTracePanel .add(tip(reTraceButton, "reTraceTip"), lastBottomButtonConstraints);
+ // Add the main tabs to the frame.
+ getContentPane().add(tabs);
+
+ // Pack the entire GUI before setting some default values.
+ pack();
+
// Initialize the GUI settings to reasonable defaults.
loadConfiguration(this.getClass().getResource(DEFAULT_CONFIGURATION));
-
- // Add the main tabs to the frame and pack it.
- getContentPane().add(tabs);
}
@@ -661,7 +666,9 @@ public class ProGuardGUI extends JFrame
{
// Parse the boilerplate configuration file.
ConfigurationParser parser = new ConfigurationParser(
- this.getClass().getResource(BOILERPLATE_CONFIGURATION));
+ this.getClass().getResource(BOILERPLATE_CONFIGURATION),
+ System.getProperties());
+
Configuration configuration = new Configuration();
try
@@ -1019,6 +1026,7 @@ public class ProGuardGUI extends JFrame
flattenPackageHierarchyCheckBox .setSelected(configuration.flattenPackageHierarchy != null);
repackageClassesCheckBox .setSelected(configuration.repackageClasses != null);
keepAttributesCheckBox .setSelected(configuration.keepAttributes != null);
+ keepParameterNamesCheckBox .setSelected(configuration.keepParameterNames);
newSourceFileAttributeCheckBox .setSelected(configuration.newSourceFileAttribute != null);
adaptClassStringsCheckBox .setSelected(configuration.adaptClassStrings != null);
adaptResourceFileNamesCheckBox .setSelected(configuration.adaptResourceFileNames != null);
@@ -1041,21 +1049,23 @@ public class ProGuardGUI extends JFrame
dumpCheckBox .setSelected(configuration.dump != null);
printUsageTextField .setText(fileName(configuration.printUsage));
- optimizationsTextField .setText(configuration.optimizations == null ? OPTIMIZATIONS_DEFAULT : ListUtil.commaSeparatedString(configuration.optimizations));
+ optimizationsTextField .setText(configuration.optimizations == null ? OPTIMIZATIONS_DEFAULT : ListUtil.commaSeparatedString(configuration.optimizations, true));
printMappingTextField .setText(fileName(configuration.printMapping));
applyMappingTextField .setText(fileName(configuration.applyMapping));
obfuscationDictionaryTextField .setText(fileName(configuration.obfuscationDictionary));
- keepPackageNamesTextField .setText(configuration.keepPackageNames == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.keepPackageNames)));
+ classObfuscationDictionaryTextField .setText(fileName(configuration.classObfuscationDictionary));
+ packageObfuscationDictionaryTextField .setText(fileName(configuration.packageObfuscationDictionary));
+ keepPackageNamesTextField .setText(configuration.keepPackageNames == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.keepPackageNames, true)));
flattenPackageHierarchyTextField .setText(configuration.flattenPackageHierarchy);
repackageClassesTextField .setText(configuration.repackageClasses);
- keepAttributesTextField .setText(configuration.keepAttributes == null ? KEEP_ATTRIBUTE_DEFAULT : ListUtil.commaSeparatedString(configuration.keepAttributes));
+ keepAttributesTextField .setText(configuration.keepAttributes == null ? KEEP_ATTRIBUTE_DEFAULT : ListUtil.commaSeparatedString(configuration.keepAttributes, true));
newSourceFileAttributeTextField .setText(configuration.newSourceFileAttribute == null ? SOURCE_FILE_ATTRIBUTE_DEFAULT : configuration.newSourceFileAttribute);
- adaptClassStringsTextField .setText(configuration.adaptClassStrings == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.adaptClassStrings)));
- adaptResourceFileNamesTextField .setText(configuration.adaptResourceFileNames == null ? ADAPT_RESOURCE_FILE_NAMES_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileNames));
- adaptResourceFileContentsTextField .setText(configuration.adaptResourceFileContents == null ? ADAPT_RESOURCE_FILE_CONTENTS_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileContents));
- noteTextField .setText(ListUtil.commaSeparatedString(configuration.note));
- warnTextField .setText(ListUtil.commaSeparatedString(configuration.warn));
- keepDirectoriesTextField .setText(ListUtil.commaSeparatedString(configuration.keepDirectories));
+ adaptClassStringsTextField .setText(configuration.adaptClassStrings == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.adaptClassStrings, true)));
+ adaptResourceFileNamesTextField .setText(configuration.adaptResourceFileNames == null ? ADAPT_RESOURCE_FILE_NAMES_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileNames, true));
+ adaptResourceFileContentsTextField .setText(configuration.adaptResourceFileContents == null ? ADAPT_RESOURCE_FILE_CONTENTS_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileContents, true));
+ noteTextField .setText(ListUtil.commaSeparatedString(configuration.note, true));
+ warnTextField .setText(ListUtil.commaSeparatedString(configuration.warn, true));
+ keepDirectoriesTextField .setText(ListUtil.commaSeparatedString(configuration.keepDirectories, true));
printSeedsTextField .setText(fileName(configuration.printSeeds));
printConfigurationTextField .setText(fileName(configuration.printConfiguration));
dumpTextField .setText(fileName(configuration.dump));
@@ -1182,6 +1192,7 @@ public class ProGuardGUI extends JFrame
configuration.flattenPackageHierarchy = flattenPackageHierarchyCheckBox .isSelected() ? ClassUtil.internalClassName(flattenPackageHierarchyTextField .getText()) : null;
configuration.repackageClasses = repackageClassesCheckBox .isSelected() ? ClassUtil.internalClassName(repackageClassesTextField .getText()) : null;
configuration.keepAttributes = keepAttributesCheckBox .isSelected() ? ListUtil.commaSeparatedList(keepAttributesTextField .getText()) : null;
+ configuration.keepParameterNames = keepParameterNamesCheckBox .isSelected();
configuration.newSourceFileAttribute = newSourceFileAttributeCheckBox .isSelected() ? newSourceFileAttributeTextField .getText() : null;
configuration.adaptClassStrings = adaptClassStringsCheckBox .isSelected() ? adaptClassStringsTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(adaptClassStringsTextField.getText())) : new ArrayList() : null;
configuration.adaptResourceFileNames = adaptResourceFileNamesCheckBox .isSelected() ? ListUtil.commaSeparatedList(adaptResourceFileNamesTextField .getText()) : null;
@@ -1339,7 +1350,9 @@ public class ProGuardGUI extends JFrame
try
{
// Parse the configuration file.
- ConfigurationParser parser = new ConfigurationParser(file);
+ ConfigurationParser parser = new ConfigurationParser(file,
+ System.getProperties());
+
Configuration configuration = new Configuration();
try
@@ -1379,7 +1392,9 @@ public class ProGuardGUI extends JFrame
try
{
// Parse the configuration file.
- ConfigurationParser parser = new ConfigurationParser(url);
+ ConfigurationParser parser = new ConfigurationParser(url,
+ System.getProperties());
+
Configuration configuration = new Configuration();
try
@@ -1436,13 +1451,13 @@ public class ProGuardGUI extends JFrame
/**
* Loads the given stack trace into the GUI.
*/
- private void loadStackTrace(String fileName)
+ private void loadStackTrace(File file)
{
try
{
StringBuffer buffer = new StringBuffer(1024);
- Reader reader = new BufferedReader(new FileReader(fileName));
+ Reader reader = new BufferedReader(new FileReader(file));
try
{
while (true)
@@ -1467,7 +1482,7 @@ public class ProGuardGUI extends JFrame
catch (IOException ex)
{
JOptionPane.showMessageDialog(getContentPane(),
- msg("cantOpenStackTraceFile", fileName),
+ msg("cantOpenStackTraceFile", fileName(file)),
msg("warning"),
JOptionPane.ERROR_MESSAGE);
}
@@ -1600,10 +1615,8 @@ public class ProGuardGUI extends JFrame
int returnValue = fileChooser.showOpenDialog(ProGuardGUI.this);
if (returnValue == JFileChooser.APPROVE_OPTION)
{
- File selectedFile = fileChooser.getSelectedFile();
- String fileName = selectedFile.getPath();
- loadStackTrace(fileName);
+ loadStackTrace(fileChooser.getSelectedFile());
}
}
}
@@ -1641,11 +1654,26 @@ public class ProGuardGUI extends JFrame
// Small utility methods.
/**
- * Returns the file name of the given file, if any.
+ * Returns the canonical file name for the given file, or the empty string
+ * if the file name is empty.
*/
- private static String fileName(File file)
+ private String fileName(File file)
{
- return file == null ? "" : file.getAbsolutePath();
+ if (file == null)
+ {
+ return "";
+ }
+ else
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
}
@@ -1693,46 +1721,51 @@ public class ProGuardGUI extends JFrame
{
public void run()
{
- ProGuardGUI gui = new ProGuardGUI();
- gui.pack();
-
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- Dimension guiSize = gui.getSize();
- gui.setLocation((screenSize.width - guiSize.width) / 2,
- (screenSize.height - guiSize.height) / 2);
- gui.show();
-
- // Start the splash animation, unless specified otherwise.
- int argIndex = 0;
- if (argIndex < args.length &&
- NO_SPLASH_OPTION.startsWith(args[argIndex]))
- {
- gui.skipSplash();
- argIndex++;
- }
- else
- {
- gui.startSplash();
- }
-
- // Load an initial configuration, if specified.
- if (argIndex < args.length)
+ try
{
- gui.loadConfiguration(new File(args[argIndex]));
- argIndex++;
+ ProGuardGUI gui = new ProGuardGUI();
+
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension guiSize = gui.getSize();
+ gui.setLocation((screenSize.width - guiSize.width) / 2,
+ (screenSize.height - guiSize.height) / 2);
+ gui.show();
+
+ // Start the splash animation, unless specified otherwise.
+ int argIndex = 0;
+ if (argIndex < args.length &&
+ NO_SPLASH_OPTION.startsWith(args[argIndex]))
+ {
+ gui.skipSplash();
+ argIndex++;
+ }
+ else
+ {
+ gui.startSplash();
+ }
+
+ // Load an initial configuration, if specified.
+ if (argIndex < args.length)
+ {
+ gui.loadConfiguration(new File(args[argIndex]));
+ argIndex++;
+ }
+
+ if (argIndex < args.length)
+ {
+ System.out.println(gui.getClass().getName() + ": ignoring extra arguments [" + args[argIndex] + "...]");
+ }
}
-
- if (argIndex < args.length)
+ catch (Exception e)
{
- System.out.println(gui.getClass().getName() + ": ignoring extra arguments [" + args[argIndex] + "...]");
+ System.out.println("Internal problem starting the ProGuard GUI (" + e.getMessage() + ")");
}
-
}
});
}
catch (Exception e)
{
- // Nothing.
+ System.out.println("Internal problem starting the ProGuard GUI (" + e.getMessage() + ")");
}
}
}
diff --git a/src/proguard/gui/ProGuardRunnable.java b/src/proguard/gui/ProGuardRunnable.java
index c5c5937..b341b7b 100644
--- a/src/proguard/gui/ProGuardRunnable.java
+++ b/src/proguard/gui/ProGuardRunnable.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ReTraceRunnable.java b/src/proguard/gui/ReTraceRunnable.java
index 1ca19ca..6f1b135 100644
--- a/src/proguard/gui/ReTraceRunnable.java
+++ b/src/proguard/gui/ReTraceRunnable.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/SwingUtil.java b/src/proguard/gui/SwingUtil.java
index 75d2f02..373fdc9 100644
--- a/src/proguard/gui/SwingUtil.java
+++ b/src/proguard/gui/SwingUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/TabbedPane.java b/src/proguard/gui/TabbedPane.java
index a6460f5..c6b6678 100644
--- a/src/proguard/gui/TabbedPane.java
+++ b/src/proguard/gui/TabbedPane.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/TextAreaOutputStream.java b/src/proguard/gui/TextAreaOutputStream.java
index 57f983d..84ba562 100644
--- a/src/proguard/gui/TextAreaOutputStream.java
+++ b/src/proguard/gui/TextAreaOutputStream.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/boilerplate.pro b/src/proguard/gui/boilerplate.pro
index 70efb82..711c07d 100644
--- a/src/proguard/gui/boilerplate.pro
+++ b/src/proguard/gui/boilerplate.pro
@@ -257,13 +257,6 @@
public boolean isInfinite();
public int compareTo(java.lang.Double);
- public <init>(byte);
- public <init>(short);
- public <init>(int);
- public <init>(long);
- public <init>(float);
- public <init>(double);
- public <init>(java.lang.String);
public byte byteValue();
public short shortValue();
public int intValue();
@@ -280,17 +273,6 @@
# Remove - String method calls. Remove all invocations of String
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.String {
- public java.lang.String();
- public java.lang.String(byte[]);
- public java.lang.String(byte[],int);
- public java.lang.String(byte[],int,int);
- public java.lang.String(byte[],int,int,int);
- public java.lang.String(byte[],int,int,java.lang.String);
- public java.lang.String(byte[],java.lang.String);
- public java.lang.String(char[]);
- public java.lang.String(char[],int,int);
- public java.lang.String(java.lang.String);
- public java.lang.String(java.lang.StringBuffer);
public static java.lang.String copyValueOf(char[]);
public static java.lang.String copyValueOf(char[],int,int);
public static java.lang.String valueOf(boolean);
@@ -348,10 +330,6 @@
# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuffer {
- public java.lang.StringBuffer();
- public java.lang.StringBuffer(int);
- public java.lang.StringBuffer(java.lang.String);
- public java.lang.StringBuffer(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
@@ -368,10 +346,6 @@
# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuilder {
- public java.lang.StringBuilder();
- public java.lang.StringBuilder(int);
- public java.lang.StringBuilder(java.lang.String);
- public java.lang.StringBuilder(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
diff --git a/src/proguard/gui/default.pro b/src/proguard/gui/default.pro
index 3bfe2d6..752c9b2 100644
--- a/src/proguard/gui/default.pro
+++ b/src/proguard/gui/default.pro
@@ -190,13 +190,6 @@
public boolean isNaN();
public boolean isInfinite();
public int compareTo(java.lang.Double);
- public <init>(byte);
- public <init>(short);
- public <init>(int);
- public <init>(long);
- public <init>(float);
- public <init>(double);
- public <init>(java.lang.String);
public byte byteValue();
public short shortValue();
public int intValue();
@@ -212,17 +205,6 @@
# Remove - String method calls. Remove all invocations of String
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.String {
- public <init>();
- public <init>(byte[]);
- public <init>(byte[],int);
- public <init>(byte[],int,int);
- public <init>(byte[],int,int,int);
- public <init>(byte[],int,int,java.lang.String);
- public <init>(byte[],java.lang.String);
- public <init>(char[]);
- public <init>(char[],int,int);
- public <init>(java.lang.String);
- public <init>(java.lang.StringBuffer);
public static java.lang.String copyValueOf(char[]);
public static java.lang.String copyValueOf(char[],int,int);
public static java.lang.String valueOf(boolean);
@@ -280,10 +262,6 @@
# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuffer {
- public <init>();
- public <init>(int);
- public <init>(java.lang.String);
- public <init>(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
@@ -300,10 +278,6 @@
# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuilder {
- public <init>();
- public <init>(int);
- public <init>(java.lang.String);
- public <init>(java.lang.CharSequence);
public java.lang.String toString();
public char charAt(int);
public int capacity();
diff --git a/src/proguard/gui/splash/BufferedSprite.java b/src/proguard/gui/splash/BufferedSprite.java
index 8427832..5625acb 100644
--- a/src/proguard/gui/splash/BufferedSprite.java
+++ b/src/proguard/gui/splash/BufferedSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/CircleSprite.java b/src/proguard/gui/splash/CircleSprite.java
index 5dc65eb..0443a0c 100644
--- a/src/proguard/gui/splash/CircleSprite.java
+++ b/src/proguard/gui/splash/CircleSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ClipSprite.java b/src/proguard/gui/splash/ClipSprite.java
index 55f9eac..a8ac368 100644
--- a/src/proguard/gui/splash/ClipSprite.java
+++ b/src/proguard/gui/splash/ClipSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ColorSprite.java b/src/proguard/gui/splash/ColorSprite.java
index 3f9bc3b..95153a2 100644
--- a/src/proguard/gui/splash/ColorSprite.java
+++ b/src/proguard/gui/splash/ColorSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/CompositeSprite.java b/src/proguard/gui/splash/CompositeSprite.java
index 2480ead..68cbe35 100644
--- a/src/proguard/gui/splash/CompositeSprite.java
+++ b/src/proguard/gui/splash/CompositeSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantColor.java b/src/proguard/gui/splash/ConstantColor.java
index 94c78df..fa7f3a5 100644
--- a/src/proguard/gui/splash/ConstantColor.java
+++ b/src/proguard/gui/splash/ConstantColor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantDouble.java b/src/proguard/gui/splash/ConstantDouble.java
index 0874d6d..c969332 100644
--- a/src/proguard/gui/splash/ConstantDouble.java
+++ b/src/proguard/gui/splash/ConstantDouble.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantFont.java b/src/proguard/gui/splash/ConstantFont.java
index 3f1ac03..26691b9 100644
--- a/src/proguard/gui/splash/ConstantFont.java
+++ b/src/proguard/gui/splash/ConstantFont.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantInt.java b/src/proguard/gui/splash/ConstantInt.java
index 537196d..ff79dd0 100644
--- a/src/proguard/gui/splash/ConstantInt.java
+++ b/src/proguard/gui/splash/ConstantInt.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantString.java b/src/proguard/gui/splash/ConstantString.java
index 7617c3f..e76f1eb 100644
--- a/src/proguard/gui/splash/ConstantString.java
+++ b/src/proguard/gui/splash/ConstantString.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantTiming.java b/src/proguard/gui/splash/ConstantTiming.java
index dfde644..b6a7762 100644
--- a/src/proguard/gui/splash/ConstantTiming.java
+++ b/src/proguard/gui/splash/ConstantTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/FontSprite.java b/src/proguard/gui/splash/FontSprite.java
index 9a554ba..42f165d 100644
--- a/src/proguard/gui/splash/FontSprite.java
+++ b/src/proguard/gui/splash/FontSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ImageSprite.java b/src/proguard/gui/splash/ImageSprite.java
index 6e7c189..f7704f9 100644
--- a/src/proguard/gui/splash/ImageSprite.java
+++ b/src/proguard/gui/splash/ImageSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearColor.java b/src/proguard/gui/splash/LinearColor.java
index 3a7674d..283a1c9 100644
--- a/src/proguard/gui/splash/LinearColor.java
+++ b/src/proguard/gui/splash/LinearColor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearDouble.java b/src/proguard/gui/splash/LinearDouble.java
index 046ae84..bf926b0 100644
--- a/src/proguard/gui/splash/LinearDouble.java
+++ b/src/proguard/gui/splash/LinearDouble.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearInt.java b/src/proguard/gui/splash/LinearInt.java
index 8d299bc..46c35bc 100644
--- a/src/proguard/gui/splash/LinearInt.java
+++ b/src/proguard/gui/splash/LinearInt.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearTiming.java b/src/proguard/gui/splash/LinearTiming.java
index 9b26644..c35348e 100644
--- a/src/proguard/gui/splash/LinearTiming.java
+++ b/src/proguard/gui/splash/LinearTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/OverrideGraphics2D.java b/src/proguard/gui/splash/OverrideGraphics2D.java
index 4333459..81a9429 100644
--- a/src/proguard/gui/splash/OverrideGraphics2D.java
+++ b/src/proguard/gui/splash/OverrideGraphics2D.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/RectangleSprite.java b/src/proguard/gui/splash/RectangleSprite.java
index d204831..547b549 100644
--- a/src/proguard/gui/splash/RectangleSprite.java
+++ b/src/proguard/gui/splash/RectangleSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SawToothTiming.java b/src/proguard/gui/splash/SawToothTiming.java
index 076d5e2..393f27e 100644
--- a/src/proguard/gui/splash/SawToothTiming.java
+++ b/src/proguard/gui/splash/SawToothTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ShadowedSprite.java b/src/proguard/gui/splash/ShadowedSprite.java
index c3504f3..fadca5f 100644
--- a/src/proguard/gui/splash/ShadowedSprite.java
+++ b/src/proguard/gui/splash/ShadowedSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SineTiming.java b/src/proguard/gui/splash/SineTiming.java
index eb0a7cc..ab3d0c1 100644
--- a/src/proguard/gui/splash/SineTiming.java
+++ b/src/proguard/gui/splash/SineTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SmoothTiming.java b/src/proguard/gui/splash/SmoothTiming.java
index a985712..a691d3c 100644
--- a/src/proguard/gui/splash/SmoothTiming.java
+++ b/src/proguard/gui/splash/SmoothTiming.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SplashPanel.java b/src/proguard/gui/splash/SplashPanel.java
index 23a9ce4..af959e9 100644
--- a/src/proguard/gui/splash/SplashPanel.java
+++ b/src/proguard/gui/splash/SplashPanel.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/Sprite.java b/src/proguard/gui/splash/Sprite.java
index ada7a81..f1f6e72 100644
--- a/src/proguard/gui/splash/Sprite.java
+++ b/src/proguard/gui/splash/Sprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TextSprite.java b/src/proguard/gui/splash/TextSprite.java
index bbf37d4..69bd4c7 100644
--- a/src/proguard/gui/splash/TextSprite.java
+++ b/src/proguard/gui/splash/TextSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TimeSwitchSprite.java b/src/proguard/gui/splash/TimeSwitchSprite.java
index 921bef2..dd292ad 100644
--- a/src/proguard/gui/splash/TimeSwitchSprite.java
+++ b/src/proguard/gui/splash/TimeSwitchSprite.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/Timing.java b/src/proguard/gui/splash/Timing.java
index 887d737..bb15900 100644
--- a/src/proguard/gui/splash/Timing.java
+++ b/src/proguard/gui/splash/Timing.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TypeWriterString.java b/src/proguard/gui/splash/TypeWriterString.java
index 9f1441e..d304dca 100644
--- a/src/proguard/gui/splash/TypeWriterString.java
+++ b/src/proguard/gui/splash/TypeWriterString.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableColor.java b/src/proguard/gui/splash/VariableColor.java
index 6a30062..ce573aa 100644
--- a/src/proguard/gui/splash/VariableColor.java
+++ b/src/proguard/gui/splash/VariableColor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableDouble.java b/src/proguard/gui/splash/VariableDouble.java
index 39302dd..7317403 100644
--- a/src/proguard/gui/splash/VariableDouble.java
+++ b/src/proguard/gui/splash/VariableDouble.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableFont.java b/src/proguard/gui/splash/VariableFont.java
index a7de8d7..0668c38 100644
--- a/src/proguard/gui/splash/VariableFont.java
+++ b/src/proguard/gui/splash/VariableFont.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableInt.java b/src/proguard/gui/splash/VariableInt.java
index 68a33af..b4523ef 100644
--- a/src/proguard/gui/splash/VariableInt.java
+++ b/src/proguard/gui/splash/VariableInt.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableSizeFont.java b/src/proguard/gui/splash/VariableSizeFont.java
index e36d28c..52b8ab2 100644
--- a/src/proguard/gui/splash/VariableSizeFont.java
+++ b/src/proguard/gui/splash/VariableSizeFont.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableString.java b/src/proguard/gui/splash/VariableString.java
index 1dec23b..81ca8f6 100644
--- a/src/proguard/gui/splash/VariableString.java
+++ b/src/proguard/gui/splash/VariableString.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/CascadingDataEntryWriter.java b/src/proguard/io/CascadingDataEntryWriter.java
index 15719e6..62f3bf7 100644
--- a/src/proguard/io/CascadingDataEntryWriter.java
+++ b/src/proguard/io/CascadingDataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ClassFilter.java b/src/proguard/io/ClassFilter.java
index bf591ab..aabc5ba 100644
--- a/src/proguard/io/ClassFilter.java
+++ b/src/proguard/io/ClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ClassReader.java b/src/proguard/io/ClassReader.java
index e21968c..0ad382b 100644
--- a/src/proguard/io/ClassReader.java
+++ b/src/proguard/io/ClassReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -109,7 +109,7 @@ public class ClassReader implements DataEntryReader
}
catch (Exception ex)
{
- throw new IOException("Can't process class ["+dataEntry.getName()+"] ("+ex.getMessage()+")");
+ throw (IOException)new IOException("Can't process class ["+dataEntry.getName()+"] ("+ex.getMessage()+")").initCause(ex);
}
}
}
diff --git a/src/proguard/io/ClassRewriter.java b/src/proguard/io/ClassRewriter.java
index bd19e1d..97e8aef 100644
--- a/src/proguard/io/ClassRewriter.java
+++ b/src/proguard/io/ClassRewriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntry.java b/src/proguard/io/DataEntry.java
index af0e373..681331b 100644
--- a/src/proguard/io/DataEntry.java
+++ b/src/proguard/io/DataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryClassWriter.java b/src/proguard/io/DataEntryClassWriter.java
new file mode 100644
index 0000000..e9f0327
--- /dev/null
+++ b/src/proguard/io/DataEntryClassWriter.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.*;
+import proguard.classfile.io.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.io.*;
+
+/**
+ * This ClassVisitor writes out the ProgramClass objects that it visits to the
+ * given DataEntry, modified to have the correct name.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryClassWriter
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final DataEntryWriter dataEntryWriter;
+ private final DataEntry templateDataEntry;
+
+
+ /**
+ * Creates a new DataEntryClassWriter for writing to the given
+ * DataEntryWriter, based on the given template DataEntry.
+ */
+ public DataEntryClassWriter(DataEntryWriter dataEntryWriter,
+ DataEntry templateDataEntry)
+ {
+ this.dataEntryWriter = dataEntryWriter;
+ this.templateDataEntry = templateDataEntry;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Rename the data entry if necessary.
+ String actualClassName = programClass.getName();
+ DataEntry actualDataEntry =
+ new RenamedDataEntry(templateDataEntry,
+ actualClassName + ClassConstants.CLASS_FILE_EXTENSION);
+
+ try
+ {
+ // Get the output entry corresponding to this input entry.
+ OutputStream outputStream = dataEntryWriter.getOutputStream(actualDataEntry);
+ if (outputStream != null)
+ {
+ // Write the class to the output entry.
+ DataOutputStream classOutputStream = new DataOutputStream(outputStream);
+
+ new ProgramClassWriter(classOutputStream).visitProgramClass(programClass);
+
+ classOutputStream.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Can't write program class ["+actualClassName+"] to ["+actualDataEntry+"] ("+e.getMessage()+")", e);
+ }
+ }
+}
diff --git a/src/proguard/io/DataEntryCopier.java b/src/proguard/io/DataEntryCopier.java
index faaa555..440e73b 100644
--- a/src/proguard/io/DataEntryCopier.java
+++ b/src/proguard/io/DataEntryCopier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -64,11 +64,16 @@ public class DataEntryCopier implements DataEntryReader
{
InputStream inputStream = dataEntry.getInputStream();
- // Copy the data from the input entry to the output entry.
- copyData(inputStream, outputStream);
-
- // Close the data entries.
- dataEntry.closeInputStream();
+ try
+ {
+ // Copy the data from the input entry to the output entry.
+ copyData(inputStream, outputStream);
+ }
+ finally
+ {
+ // Close the data entries.
+ dataEntry.closeInputStream();
+ }
}
}
}
@@ -76,6 +81,10 @@ public class DataEntryCopier implements DataEntryReader
{
System.err.println("Warning: can't write resource [" + dataEntry.getName() + "] (" + ex.getMessage() + ")");
}
+ catch (Exception ex)
+ {
+ throw (IOException)new IOException("Can't write resource ["+dataEntry.getName()+"] ("+ex.getMessage()+")").initCause(ex);
+ }
}
diff --git a/src/proguard/io/DataEntryDirectoryFilter.java b/src/proguard/io/DataEntryDirectoryFilter.java
index bb36f3e..5bf46bb 100644
--- a/src/proguard/io/DataEntryDirectoryFilter.java
+++ b/src/proguard/io/DataEntryDirectoryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryFilter.java b/src/proguard/io/DataEntryFilter.java
index ddcd0be..b8b6b20 100644
--- a/src/proguard/io/DataEntryFilter.java
+++ b/src/proguard/io/DataEntryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryNameFilter.java b/src/proguard/io/DataEntryNameFilter.java
index d6afd2e..5aebcdd 100644
--- a/src/proguard/io/DataEntryNameFilter.java
+++ b/src/proguard/io/DataEntryNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryObfuscator.java b/src/proguard/io/DataEntryObfuscator.java
index aa63af1..c5742e9 100644
--- a/src/proguard/io/DataEntryObfuscator.java
+++ b/src/proguard/io/DataEntryObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -75,7 +75,7 @@ public class DataEntryObfuscator implements DataEntryReader
String dataEntryName = dataEntry.getName();
// Try to find a corresponding class name by removing increasingly
- // long suffixes,
+ // long suffixes.
for (int suffixIndex = dataEntryName.length() - 1;
suffixIndex > 0;
suffixIndex--)
@@ -106,25 +106,44 @@ public class DataEntryObfuscator implements DataEntryReader
return new RenamedDataEntry(dataEntry, newDataEntryName);
}
-
- // Otherwise stop looking.
- break;
+ else
+ {
+ // Otherwise stop looking.
+ return dataEntry;
+ }
}
}
}
- // Did the package get a new name?
- String packagePrefix = ClassUtil.internalPackagePrefix(dataEntryName);
- String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
- if (newPackagePrefix != null &&
- !packagePrefix.equals(newPackagePrefix))
+ // Try to find a corresponding package name by increasingly removing
+ // more subpackages.
+ String packagePrefix = dataEntryName;
+ do
{
- // Return a renamed data entry.
- String newDataEntryName =
- newPackagePrefix + dataEntryName.substring(packagePrefix.length());
+ // Chop off the class name or the last subpackage name.
+ packagePrefix = ClassUtil.internalPackagePrefix(packagePrefix);
- return new RenamedDataEntry(dataEntry, newDataEntryName);
+ // Is there a package corresponding to the package prefix?
+ String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
+ if (newPackagePrefix != null)
+ {
+ // Did the package get a new name?
+ if (!packagePrefix.equals(newPackagePrefix))
+ {
+ // Return a renamed data entry.
+ String newDataEntryName =
+ newPackagePrefix + dataEntryName.substring(packagePrefix.length());
+
+ return new RenamedDataEntry(dataEntry, newDataEntryName);
+ }
+ else
+ {
+ // Otherwise stop looking.
+ return dataEntry;
+ }
+ }
}
+ while (packagePrefix.length() > 0);
return dataEntry;
}
diff --git a/src/proguard/io/DataEntryParentFilter.java b/src/proguard/io/DataEntryParentFilter.java
index fbeac4f..1cc1997 100644
--- a/src/proguard/io/DataEntryParentFilter.java
+++ b/src/proguard/io/DataEntryParentFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryPump.java b/src/proguard/io/DataEntryPump.java
index bfe22a3..ddf946b 100644
--- a/src/proguard/io/DataEntryPump.java
+++ b/src/proguard/io/DataEntryPump.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryReader.java b/src/proguard/io/DataEntryReader.java
index e77f7bf..39dc82d 100644
--- a/src/proguard/io/DataEntryReader.java
+++ b/src/proguard/io/DataEntryReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryRenamer.java b/src/proguard/io/DataEntryRenamer.java
index 45c61ee..99600ae 100644
--- a/src/proguard/io/DataEntryRenamer.java
+++ b/src/proguard/io/DataEntryRenamer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -87,7 +87,7 @@ public class DataEntryRenamer implements DataEntryReader
String newName = (String)nameMap.get(name);
if (newName != null)
{
- // Add remove the directory separator if necessary.
+ // Remove the directory separator if necessary.
if (dataEntry.isDirectory() &&
newName.length() > 0)
{
@@ -101,4 +101,4 @@ public class DataEntryRenamer implements DataEntryReader
missingDataEntryReader.read(dataEntry);
}
}
-} \ No newline at end of file
+}
diff --git a/src/proguard/io/DataEntryRewriter.java b/src/proguard/io/DataEntryRewriter.java
index eefced4..ec07767 100644
--- a/src/proguard/io/DataEntryRewriter.java
+++ b/src/proguard/io/DataEntryRewriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryWriter.java b/src/proguard/io/DataEntryWriter.java
index 9ecf79b..871f823 100644
--- a/src/proguard/io/DataEntryWriter.java
+++ b/src/proguard/io/DataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryFilter.java b/src/proguard/io/DirectoryFilter.java
index a45d1aa..72e2e6d 100644
--- a/src/proguard/io/DirectoryFilter.java
+++ b/src/proguard/io/DirectoryFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryPump.java b/src/proguard/io/DirectoryPump.java
index cab2ff3..cd6c2ab 100644
--- a/src/proguard/io/DirectoryPump.java
+++ b/src/proguard/io/DirectoryPump.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryWriter.java b/src/proguard/io/DirectoryWriter.java
index c6605df..7948ee2 100644
--- a/src/proguard/io/DirectoryWriter.java
+++ b/src/proguard/io/DirectoryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FileDataEntry.java b/src/proguard/io/FileDataEntry.java
index d0449ee..618a092 100644
--- a/src/proguard/io/FileDataEntry.java
+++ b/src/proguard/io/FileDataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FilteredDataEntryReader.java b/src/proguard/io/FilteredDataEntryReader.java
index 11da0d4..03b5dd8 100644
--- a/src/proguard/io/FilteredDataEntryReader.java
+++ b/src/proguard/io/FilteredDataEntryReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FilteredDataEntryWriter.java b/src/proguard/io/FilteredDataEntryWriter.java
index 40a8c64..b3b751c 100644
--- a/src/proguard/io/FilteredDataEntryWriter.java
+++ b/src/proguard/io/FilteredDataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/Finisher.java b/src/proguard/io/Finisher.java
index 8c4cc1e..7d5f93f 100644
--- a/src/proguard/io/Finisher.java
+++ b/src/proguard/io/Finisher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/JarReader.java b/src/proguard/io/JarReader.java
index f96b4aa..be4c97b 100644
--- a/src/proguard/io/JarReader.java
+++ b/src/proguard/io/JarReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/JarWriter.java b/src/proguard/io/JarWriter.java
index 3e40cdf..d85e63b 100644
--- a/src/proguard/io/JarWriter.java
+++ b/src/proguard/io/JarWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ManifestRewriter.java b/src/proguard/io/ManifestRewriter.java
index f10307e..8a8c7ae 100644
--- a/src/proguard/io/ManifestRewriter.java
+++ b/src/proguard/io/ManifestRewriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -55,13 +55,14 @@ public class ManifestRewriter extends DataEntryRewriter
/**
- * This Reader reads manifest files, joining any split lines.
+ * This Reader reads manifest files, joining any split lines. It replaces
+ * the allowed CR/LF/CR+LF alternatives by simple LF in the process.
*/
private static class SplitLineReader extends FilterReader
{
- private char[] buffer = new char[2];
- private int bufferIndex = 0;
- private int bufferSize = 0;
+ private static final int NONE = -2;
+
+ private int bufferedCharacter = NONE;
public SplitLineReader(Reader reader)
@@ -76,45 +77,39 @@ public class ManifestRewriter extends DataEntryRewriter
{
while (true)
{
- if (bufferIndex < bufferSize)
- {
- return buffer[bufferIndex++];
- }
+ // Get the buffered character or the first character.
+ int c1 = bufferedCharacter != NONE ?
+ bufferedCharacter :
+ super.read();
+
+ // Clear the buffered character.
+ bufferedCharacter = NONE;
- // Read the first character.
- int c1 = super.read();
+ // Return it if it's an ordinary character.
if (c1 != '\n' && c1 != '\r')
{
return c1;
}
- bufferIndex = 0;
- bufferSize = 0;
- buffer[bufferSize++] = '\n';
-
- // Read the second character.
+ // It's a newline. Read the second character to see if it's a
+ // continuation.
int c2 = super.read();
- if (c2 == ' ')
- {
- bufferSize = 0;
- continue;
- }
- if (c1 != '\r' || c2 != '\n')
+ // Skip any corresponding, redundant \n or \r.
+ if ((c2 == '\n' || c2 == '\r') && c1 != c2)
{
- buffer[bufferSize++] = (char)c2;
- continue;
+ c2 = super.read();
}
- // Read the third character.
- int c3 = super.read();
- if (c3 == ' ')
+ // Isn't it a continuation after all?
+ if (c2 != ' ')
{
- bufferSize = 0;
- continue;
+ // Buffer the second character and return a newline.
+ bufferedCharacter = c2;
+ return '\n';
}
- buffer[bufferSize++] = (char)c3;
+ // Just continue after the continuation characters.
}
}
@@ -184,7 +179,7 @@ public class ManifestRewriter extends DataEntryRewriter
}
else if (counter == 70)
{
- // Insert are newline and space.
+ // Insert a newline and a space.
super.write('\n');
super.write(' ');
diff --git a/src/proguard/io/NameFilter.java b/src/proguard/io/NameFilter.java
index 2a9fbc3..67d630e 100644
--- a/src/proguard/io/NameFilter.java
+++ b/src/proguard/io/NameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ParentDataEntryWriter.java b/src/proguard/io/ParentDataEntryWriter.java
index 4f16d12..f24ef37 100644
--- a/src/proguard/io/ParentDataEntryWriter.java
+++ b/src/proguard/io/ParentDataEntryWriter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/RenamedDataEntry.java b/src/proguard/io/RenamedDataEntry.java
index ae2d267..a0f5657 100644
--- a/src/proguard/io/RenamedDataEntry.java
+++ b/src/proguard/io/RenamedDataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ZipDataEntry.java b/src/proguard/io/ZipDataEntry.java
index 5779fd8..20a9d3b 100644
--- a/src/proguard/io/ZipDataEntry.java
+++ b/src/proguard/io/ZipDataEntry.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/AttributeShrinker.java b/src/proguard/obfuscate/AttributeShrinker.java
index a8bc36b..0c3ab94 100644
--- a/src/proguard/obfuscate/AttributeShrinker.java
+++ b/src/proguard/obfuscate/AttributeShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,6 +26,8 @@ import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.*;
+import java.util.Arrays;
+
/**
* This ClassVisitor removes attributes that are not marked as being used or
* required.
@@ -111,10 +113,7 @@ implements ClassVisitor,
}
// Clear the remaining array elements.
- for (int index = counter; index < length; index++)
- {
- array[index] = null;
- }
+ Arrays.fill(array, counter, length, null);
return counter;
}
diff --git a/src/proguard/obfuscate/AttributeUsageMarker.java b/src/proguard/obfuscate/AttributeUsageMarker.java
index e772324..32a512b 100644
--- a/src/proguard/obfuscate/AttributeUsageMarker.java
+++ b/src/proguard/obfuscate/AttributeUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,7 +26,7 @@ import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.SimplifiedVisitor;
/**
- * This ClassVisitor marks all attributes that it visits.
+ * This AttributeVisitor marks all attributes that it visits.
*
* @see AttributeShrinker
*
diff --git a/src/proguard/obfuscate/ClassObfuscator.java b/src/proguard/obfuscate/ClassObfuscator.java
index 9af0c82..9e1a91c 100644
--- a/src/proguard/obfuscate/ClassObfuscator.java
+++ b/src/proguard/obfuscate/ClassObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -164,6 +164,14 @@ implements ClassVisitor,
}
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // This can happen for dubious input, if the outer class of a program
+ // class is a library class, and its name is requested.
+ newClassName = libraryClass.getName();
+ }
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -469,13 +477,25 @@ implements ClassVisitor,
{
// Come up with class names until we get an original one.
String newClassName;
+ String newMixedCaseClassName;
do
{
// Let the factory produce a class name.
newClassName = newPackagePrefix +
classNameFactory.nextName();
+
+ newMixedCaseClassName = mixedCaseClassName(newClassName);
+ }
+ while (classNamesToAvoid.contains(newMixedCaseClassName));
+
+ // Explicitly make sure the name isn't used again if we have a
+ // user-specified dictionary and we're not allowed to have mixed case
+ // class names -- just to protect against problematic dictionaries.
+ if (this.classNameFactory != null &&
+ !useMixedCaseClassNames)
+ {
+ classNamesToAvoid.add(newMixedCaseClassName);
}
- while (classNamesToAvoid.contains(mixedCaseClassName(newClassName)));
return newClassName;
}
diff --git a/src/proguard/obfuscate/ClassRenamer.java b/src/proguard/obfuscate/ClassRenamer.java
index 143e3fb..4c5e496 100644
--- a/src/proguard/obfuscate/ClassRenamer.java
+++ b/src/proguard/obfuscate/ClassRenamer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/DictionaryNameFactory.java b/src/proguard/obfuscate/DictionaryNameFactory.java
index f262664..4a7e28c 100644
--- a/src/proguard/obfuscate/DictionaryNameFactory.java
+++ b/src/proguard/obfuscate/DictionaryNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MapCleaner.java b/src/proguard/obfuscate/MapCleaner.java
index fdefec5..d11f443 100644
--- a/src/proguard/obfuscate/MapCleaner.java
+++ b/src/proguard/obfuscate/MapCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingKeeper.java b/src/proguard/obfuscate/MappingKeeper.java
index c9d6aa6..7ab1e25 100644
--- a/src/proguard/obfuscate/MappingKeeper.java
+++ b/src/proguard/obfuscate/MappingKeeper.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingPrinter.java b/src/proguard/obfuscate/MappingPrinter.java
index aa8b13e..a28d10c 100644
--- a/src/proguard/obfuscate/MappingPrinter.java
+++ b/src/proguard/obfuscate/MappingPrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,8 @@
package proguard.obfuscate;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
@@ -38,7 +40,8 @@ import java.io.PrintStream;
public class MappingPrinter
extends SimplifiedVisitor
implements ClassVisitor,
- MemberVisitor
+ MemberVisitor,
+ AttributeVisitor
{
private final PrintStream ps;
@@ -80,11 +83,6 @@ implements ClassVisitor,
}
- public void visitLibraryClass(LibraryClass libraryClass)
- {
- }
-
-
// Implementations for MemberVisitor.
public void visitProgramField(ProgramClass programClass, ProgramField programField)
@@ -93,7 +91,6 @@ implements ClassVisitor,
if (newName != null)
{
ps.println(" " +
- //lineNumberRange(programClass, programField) +
ClassUtil.externalFullFieldDescription(
0,
programField.getName(programClass),
@@ -118,9 +115,9 @@ implements ClassVisitor,
String newName = MemberObfuscator.newMemberName(programMethod);
if (newName != null)
{
- ps.println(" " +
- lineNumberRange(programClass, programMethod) +
- ClassUtil.externalFullMethodDescription(
+ ps.print(" ");
+ programMethod.attributesAccept(programClass, this);
+ ps.println(ClassUtil.externalFullMethodDescription(
programClass.getName(),
0,
programMethod.getName(programClass),
@@ -131,17 +128,20 @@ implements ClassVisitor,
}
- // Small utility methods.
+ // Implementations for AttributeVisitor.
- /**
- * Returns the line number range of the given class member, followed by a
- * colon, or just an empty String if no range is available.
- */
- private static String lineNumberRange(ProgramClass programClass, ProgramMember programMember)
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
- String range = programMember.getLineNumberRange(programClass);
- return range != null ?
- (range + ":") :
- "";
+ ps.print(lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ":");
}
}
diff --git a/src/proguard/obfuscate/MappingProcessor.java b/src/proguard/obfuscate/MappingProcessor.java
index 01c1809..92a916a 100644
--- a/src/proguard/obfuscate/MappingProcessor.java
+++ b/src/proguard/obfuscate/MappingProcessor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingReader.java b/src/proguard/obfuscate/MappingReader.java
index 24fd26c..51d14ac 100644
--- a/src/proguard/obfuscate/MappingReader.java
+++ b/src/proguard/obfuscate/MappingReader.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameCleaner.java b/src/proguard/obfuscate/MemberNameCleaner.java
index c41c59d..5205fee 100644
--- a/src/proguard/obfuscate/MemberNameCleaner.java
+++ b/src/proguard/obfuscate/MemberNameCleaner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameCollector.java b/src/proguard/obfuscate/MemberNameCollector.java
index c248820..1544901 100644
--- a/src/proguard/obfuscate/MemberNameCollector.java
+++ b/src/proguard/obfuscate/MemberNameCollector.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameConflictFixer.java b/src/proguard/obfuscate/MemberNameConflictFixer.java
index b9093a6..68e7c05 100644
--- a/src/proguard/obfuscate/MemberNameConflictFixer.java
+++ b/src/proguard/obfuscate/MemberNameConflictFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameFilter.java b/src/proguard/obfuscate/MemberNameFilter.java
new file mode 100644
index 0000000..6d95270
--- /dev/null
+++ b/src/proguard/obfuscate/MemberNameFilter.java
@@ -0,0 +1,120 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member has a new name.
+ * Constructors are judged based on the class name.
+ *
+ * @see ClassObfuscator
+ * @see MemberObfuscator
+ *
+ * @author Eric Lafortune
+ */
+public class MemberNameFilter implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberNameFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MemberNameFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (hasName(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (hasName(programClass, programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (hasName(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (hasName(libraryClass, libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given class has a new name.
+ */
+ private boolean hasName(Clazz clazz)
+ {
+ return ClassObfuscator.newClassName(clazz) != null;
+ }
+
+
+ /**
+ * Returns whether the given method has a new name.
+ */
+ private boolean hasName(Clazz clazz, Method method)
+ {
+ return
+ hasName(method) ||
+ (hasName(clazz) &&
+ method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT));
+ }
+
+
+ /**
+ * Returns whether the given class member has a new name.
+ */
+ private boolean hasName(Member member)
+ {
+ return MemberObfuscator.newMemberName(member) != null;
+ }
+}
diff --git a/src/proguard/obfuscate/MemberObfuscator.java b/src/proguard/obfuscate/MemberObfuscator.java
index 332b849..adf590c 100644
--- a/src/proguard/obfuscate/MemberObfuscator.java
+++ b/src/proguard/obfuscate/MemberObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberSpecialNameFilter.java b/src/proguard/obfuscate/MemberSpecialNameFilter.java
index f83374b..0eb4d2d 100644
--- a/src/proguard/obfuscate/MemberSpecialNameFilter.java
+++ b/src/proguard/obfuscate/MemberSpecialNameFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -54,7 +54,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- if (isSpecialName(programField))
+ if (hasSpecialName(programField))
{
memberVisitor.visitProgramField(programClass, programField);
}
@@ -63,7 +63,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- if (isSpecialName(programMethod))
+ if (hasSpecialName(programMethod))
{
memberVisitor.visitProgramMethod(programClass, programMethod);
}
@@ -72,7 +72,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
{
- if (isSpecialName(libraryField))
+ if (hasSpecialName(libraryField))
{
memberVisitor.visitLibraryField(libraryClass, libraryField);
}
@@ -81,7 +81,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
{
- if (isSpecialName(libraryMethod))
+ if (hasSpecialName(libraryMethod))
{
memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
}
@@ -94,7 +94,7 @@ public class MemberSpecialNameFilter implements MemberVisitor
* Returns whether the given class member has a special new name.
* @param member the class member.
*/
- private static boolean isSpecialName(Member member)
+ private static boolean hasSpecialName(Member member)
{
return SpecialNameFactory.isSpecialName(MemberObfuscator.newMemberName(member));
}
diff --git a/src/proguard/obfuscate/MultiMappingProcessor.java b/src/proguard/obfuscate/MultiMappingProcessor.java
index 4074ff8..051260f 100644
--- a/src/proguard/obfuscate/MultiMappingProcessor.java
+++ b/src/proguard/obfuscate/MultiMappingProcessor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameAndTypeShrinker.java b/src/proguard/obfuscate/NameAndTypeShrinker.java
deleted file mode 100644
index 1284c82..0000000
--- a/src/proguard/obfuscate/NameAndTypeShrinker.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package proguard.obfuscate;
-
-import proguard.classfile.*;
-import proguard.classfile.constant.Constant;
-import proguard.classfile.editor.ConstantPoolRemapper;
-import proguard.classfile.visitor.ClassVisitor;
-
-
-/**
- * This ClassVisitor removes NameAndType constant pool entries
- * that are not marked as being used.
- *
- * @see NameAndTypeUsageMarker
- *
- * @author Eric Lafortune
- */
-public class NameAndTypeShrinker implements ClassVisitor
-{
- private int[] constantIndexMap;
- private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
-
-
- // Implementations for ClassVisitor.
-
- public void visitProgramClass(ProgramClass programClass)
- {
- // Shift the used constant pool entries together, filling out the
- // index map.
- programClass.u2constantPoolCount =
- shrinkConstantPool(programClass.constantPool,
- programClass.u2constantPoolCount);
-
-
- // Remap all constant pool references.
- constantPoolRemapper.setConstantIndexMap(constantIndexMap);
- constantPoolRemapper.visitProgramClass(programClass);
- }
-
-
- public void visitLibraryClass(LibraryClass libraryClass)
- {
- }
-
-
- // Small utility methods.
-
- /**
- * Removes all NameAndType entries that are not marked as being used
- * from the given constant pool.
- * @return the new number of entries.
- */
- private int shrinkConstantPool(Constant[] constantPool, int length)
- {
- // Create a new index map, if necessary.
- if (constantIndexMap == null ||
- constantIndexMap.length < length)
- {
- constantIndexMap = new int[length];
- }
-
- int counter = 1;
- boolean isUsed = false;
-
- // Shift the used constant pool entries together.
- for (int index = 1; index < length; index++)
- {
- constantIndexMap[index] = counter;
-
- Constant constant = constantPool[index];
-
- // Don't update the flag if this is the second half of a long entry.
- if (constant != null)
- {
- isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType ||
- NameAndTypeUsageMarker.isUsed(constant);
- }
-
- if (isUsed)
- {
- constantPool[counter++] = constant;
- }
- }
-
- // Clear the remaining constant pool elements.
- for (int index = counter; index < length; index++)
- {
- constantPool[index] = null;
- }
-
- return counter;
- }
-}
diff --git a/src/proguard/obfuscate/NameFactory.java b/src/proguard/obfuscate/NameFactory.java
index c64d1ad..97ebe5a 100644
--- a/src/proguard/obfuscate/NameFactory.java
+++ b/src/proguard/obfuscate/NameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameFactoryResetter.java b/src/proguard/obfuscate/NameFactoryResetter.java
index b6ba6ad..b04d12e 100644
--- a/src/proguard/obfuscate/NameFactoryResetter.java
+++ b/src/proguard/obfuscate/NameFactoryResetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameMarker.java b/src/proguard/obfuscate/NameMarker.java
index 2ce0ee9..5283ef3 100644
--- a/src/proguard/obfuscate/NameMarker.java
+++ b/src/proguard/obfuscate/NameMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NumericNameFactory.java b/src/proguard/obfuscate/NumericNameFactory.java
index cc21c4b..b1e38b1 100644
--- a/src/proguard/obfuscate/NumericNameFactory.java
+++ b/src/proguard/obfuscate/NumericNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Obfuscator.java b/src/proguard/obfuscate/Obfuscator.java
index dce563a..cc79b0d 100644
--- a/src/proguard/obfuscate/Obfuscator.java
+++ b/src/proguard/obfuscate/Obfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -99,19 +99,30 @@ public class Obfuscator
libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker));
// Mark attributes that have to be kept.
- AttributeUsageMarker requiredAttributeUsageMarker =
- new AttributeUsageMarker();
+ AttributeVisitor attributeUsageMarker =
+ new NonEmptyAttributeFilter(
+ new AttributeUsageMarker());
AttributeVisitor optionalAttributeUsageMarker =
configuration.keepAttributes == null ? null :
new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes),
- requiredAttributeUsageMarker);
+ attributeUsageMarker);
programClassPool.classesAccept(
new AllAttributeVisitor(true,
- new RequiredAttributeFilter(requiredAttributeUsageMarker,
+ new RequiredAttributeFilter(attributeUsageMarker,
optionalAttributeUsageMarker)));
+ // Keep parameter names and types if specified.
+ if (configuration.keepParameterNames)
+ {
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new MemberNameFilter(
+ new AllAttributeVisitor(true,
+ new ParameterNameMarker(attributeUsageMarker)))));
+ }
+
// Remove the attributes that can be discarded. Note that the attributes
// may only be discarded after the seeds have been marked, since the
// configuration may rely on annotations.
@@ -135,17 +146,23 @@ public class Obfuscator
reader.pump(keeper);
// Print out a summary of the warnings if necessary.
- int mappingWarningCount = warningPrinter.getWarningCount();
- if (mappingWarningCount > 0)
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
{
- System.err.println("Warning: there were " + mappingWarningCount +
- " kept classes and class members that were remapped anyway.");
+ System.err.println("Warning: there were " + warningCount +
+ " kept classes and class members that were remapped anyway.");
System.err.println(" You should adapt your configuration or edit the mapping file.");
if (!configuration.ignoreWarnings)
{
- System.err.println(" If you are sure this remapping won't hurt,");
- System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ System.err.println(" If you are sure this remapping won't hurt, you could try your luck");
+ System.err.println(" using the '-ignorewarnings' option.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#mappingconflict1)");
+
+ if (!configuration.ignoreWarnings)
+ {
throw new IOException("Please correct the above warnings first.");
}
}
@@ -248,6 +265,19 @@ public class Obfuscator
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)))),
+ // Collect all member names from interfaces of abstract
+ // classes down the hierarchy.
+ // Due to an error in the JLS/JVMS, virtual invocations
+ // may end up at a private method otherwise (Sun/Oracle
+ // bugs #6691741 and #6684387, ProGuard bug #3471941,
+ // and ProGuard test #1180).
+ new ClassHierarchyTraveler(false, false, false, true,
+ new ClassAccessFilter(ClassConstants.INTERNAL_ACC_ABSTRACT, 0,
+ new ClassHierarchyTraveler(false, false, true, false,
+ new AllMemberVisitor(
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap))))),
+
// Assign new names to all private members in this class.
new AllMemberVisitor(
new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0,
@@ -361,6 +391,12 @@ public class Obfuscator
{
System.err.println(" If you are sure the conflicts are harmless,");
System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#mappingconflict2)");
+
+ if (!configuration.ignoreWarnings)
+ {
throw new IOException("Please correct the above warnings first.");
}
}
@@ -368,14 +404,20 @@ public class Obfuscator
// Print out the mapping, if requested.
if (configuration.printMapping != null)
{
- PrintStream ps = isFile(configuration.printMapping) ?
- new PrintStream(new BufferedOutputStream(new FileOutputStream(configuration.printMapping))) :
- System.out;
+ PrintStream ps =
+ configuration.printMapping == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(configuration.printMapping)));
// Print out items that will be removed.
programClassPool.classesAcceptAlphabetically(new MappingPrinter(ps));
- if (ps != System.out)
+ if (ps == System.out)
+ {
+ ps.flush();
+ }
+ else
{
ps.close();
}
@@ -398,32 +440,27 @@ public class Obfuscator
programClassPool.classesAccept(
new AllConstantVisitor(
new AccessFixer()));
+
+ // Fix the access flags of the inner classes information.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllInnerClassesInfoVisitor(
+ new InnerClassesAccessFixer())));
}
+ // Fix the bridge method flags.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new BridgeMethodFixer()));
+
// Rename the source file attributes, if requested.
if (configuration.newSourceFileAttribute != null)
{
programClassPool.classesAccept(new SourceFileRenamer(configuration.newSourceFileAttribute));
}
- // Mark NameAndType constant pool entries that have to be kept
- // and remove the other ones.
- programClassPool.classesAccept(new NameAndTypeUsageMarker());
- programClassPool.classesAccept(new NameAndTypeShrinker());
-
- // Mark Utf8 constant pool entries that have to be kept
- // and remove the other ones.
- programClassPool.classesAccept(new Utf8UsageMarker());
- programClassPool.classesAccept(new Utf8Shrinker());
- }
-
-
- /**
- * Returns whether the given file is actually a file, or just a placeholder
- * for the standard output.
- */
- private boolean isFile(File file)
- {
- return file.getPath().length() > 0;
+ // Remove unused constants.
+ programClassPool.classesAccept(
+ new ConstantPoolShrinker());
}
}
diff --git a/src/proguard/obfuscate/ParameterNameMarker.java b/src/proguard/obfuscate/ParameterNameMarker.java
new file mode 100644
index 0000000..22af125
--- /dev/null
+++ b/src/proguard/obfuscate/ParameterNameMarker.java
@@ -0,0 +1,128 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This AttributeVisitor trims and marks all local variable (type) table
+ * attributes that it visits. It keeps parameter names and types and removes
+ * the ordinary local variable names and types.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterNameMarker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final AttributeVisitor attributeUsageMarker;
+
+
+ /**
+ * Constructs a new ParameterNameMarker.
+ * @param attributeUsageMarker the marker that will be used to mark
+ * attributes containing local variable info.
+ */
+ public ParameterNameMarker(AttributeVisitor attributeUsageMarker)
+ {
+ this.attributeUsageMarker = attributeUsageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (!AttributeUsageMarker.isUsed(localVariableTableAttribute) &&
+ hasParameters(clazz, method))
+ {
+ // Shift the entries that start at offset 0 to the front.
+ int newIndex = 0;
+
+ for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++)
+ {
+ LocalVariableInfo localVariableInfo =
+ localVariableTableAttribute.localVariableTable[index];
+
+ if (localVariableInfo.u2startPC == 0)
+ {
+ localVariableTableAttribute.localVariableTable[newIndex++] =
+ localVariableInfo;
+ }
+ }
+
+ // Trim the table.
+ localVariableTableAttribute.u2localVariableTableLength = newIndex;
+
+ // Mark the table if there are any entries.
+ if (newIndex > 0)
+ {
+ attributeUsageMarker.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (!AttributeUsageMarker.isUsed(localVariableTypeTableAttribute) &&
+ hasParameters(clazz, method))
+ {
+ // Shift the entries that start at offset 0 to the front.
+ int newIndex = 0;
+
+ for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo =
+ localVariableTypeTableAttribute.localVariableTypeTable[index];
+
+ if (localVariableTypeInfo.u2startPC == 0)
+ {
+ localVariableTypeTableAttribute.localVariableTypeTable[newIndex++] =
+ localVariableTypeInfo;
+ }
+ }
+
+ // Trim the table.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength = newIndex;
+
+ // Mark the table if there are any entries.
+ if (newIndex > 0)
+ {
+ attributeUsageMarker.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean hasParameters(Clazz clazz, Method method)
+ {
+ return method.getDescriptor(clazz).charAt(1) != ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE;
+ }
+} \ No newline at end of file
diff --git a/src/proguard/obfuscate/SimpleNameFactory.java b/src/proguard/obfuscate/SimpleNameFactory.java
index bce22de..0473852 100644
--- a/src/proguard/obfuscate/SimpleNameFactory.java
+++ b/src/proguard/obfuscate/SimpleNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/SourceFileRenamer.java b/src/proguard/obfuscate/SourceFileRenamer.java
index cbf1b63..248d18f 100644
--- a/src/proguard/obfuscate/SourceFileRenamer.java
+++ b/src/proguard/obfuscate/SourceFileRenamer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/SpecialNameFactory.java b/src/proguard/obfuscate/SpecialNameFactory.java
index a5431ca..596f919 100644
--- a/src/proguard/obfuscate/SpecialNameFactory.java
+++ b/src/proguard/obfuscate/SpecialNameFactory.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Utf8Shrinker.java b/src/proguard/obfuscate/Utf8Shrinker.java
deleted file mode 100644
index 87ada80..0000000
--- a/src/proguard/obfuscate/Utf8Shrinker.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package proguard.obfuscate;
-
-import proguard.classfile.*;
-import proguard.classfile.constant.Constant;
-import proguard.classfile.editor.ConstantPoolRemapper;
-import proguard.classfile.visitor.ClassVisitor;
-
-
-/**
- * This ClassVisitor removes UTF-8 constant pool entries that are not marked
- * as being used.
- *
- * @see Utf8UsageMarker
- *
- * @author Eric Lafortune
- */
-public class Utf8Shrinker implements ClassVisitor
-{
- private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
- private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
-
-
- // Implementations for ClassVisitor.
-
- public void visitProgramClass(ProgramClass programClass)
- {
- // Shift the used constant pool entries together, filling out the
- // index map.
- programClass.u2constantPoolCount =
- shrinkConstantPool(programClass.constantPool,
- programClass.u2constantPoolCount);
-
- // Remap all constant pool references.
- constantPoolRemapper.setConstantIndexMap(constantIndexMap);
- constantPoolRemapper.visitProgramClass(programClass);
- }
-
-
- public void visitLibraryClass(LibraryClass libraryClass)
- {
- }
-
-
- // Small utility methods.
-
- /**
- * Removes all UTF-8 entries that are not marked as being used
- * from the given constant pool.
- * @return the new number of entries.
- */
- private int shrinkConstantPool(Constant[] constantPool, int length)
- {
- // Create a new index map, if necessary.
- if (constantIndexMap.length < length)
- {
- constantIndexMap = new int[length];
- }
-
- int counter = 1;
- boolean isUsed = false;
-
- // Shift the used constant pool entries together.
- for (int index = 1; index < length; index++)
- {
- constantIndexMap[index] = counter;
-
- Constant constant = constantPool[index];
-
- // Don't update the flag if this is the second half of a long entry.
- if (constant != null)
- {
- isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 ||
- Utf8UsageMarker.isUsed(constant);
- }
-
- if (isUsed)
- {
- constantPool[counter++] = constant;
- }
- }
-
- // Clear the remaining constant pool elements.
- for (int index = counter; index < length; index++)
- {
- constantPool[index] = null;
- }
-
- return counter;
- }
-}
diff --git a/src/proguard/optimize/BootstrapMethodArgumentShrinker.java b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java
new file mode 100644
index 0000000..26f1349
--- /dev/null
+++ b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java
@@ -0,0 +1,103 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.ConstantPoolEditor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.*;
+import proguard.optimize.peephole.VariableShrinker;
+
+/**
+ * This BootstrapMethodInfoVisitor removes unused constant arguments from
+ * bootstrap method entries that it visits.
+ *
+ * @see ParameterUsageMarker
+ * @see VariableUsageMarker
+ * @see VariableShrinker
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodArgumentShrinker
+extends SimplifiedVisitor
+implements BootstrapMethodInfoVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ private long usedParameters;
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Check which method parameters are used.
+ usedParameters = -1L;
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
+
+ // Remove the unused arguments.
+ int methodArgumentCount = bootstrapMethodInfo.u2methodArgumentCount;
+ int[] methodArguments = bootstrapMethodInfo.u2methodArguments;
+
+ int newArgumentIndex = 0;
+
+ for (int argumentIndex = 0; argumentIndex < methodArgumentCount; argumentIndex++)
+ {
+ if (argumentIndex >= 64 ||
+ (usedParameters & (1L << argumentIndex)) != 0L)
+ {
+ methodArguments[newArgumentIndex++] = methodArguments[argumentIndex];
+ }
+ }
+
+ // Update the number of arguments.
+ bootstrapMethodInfo.u2methodArgumentCount = newArgumentIndex;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the referenced bootstrap method.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Check the referenced class member itself.
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ usedParameters = ParameterUsageMarker.getUsedParameters(programMethod);
+ }
+}
diff --git a/src/proguard/optimize/ChangedCodePrinter.java b/src/proguard/optimize/ChangedCodePrinter.java
index 67a79ab..668d43d 100644
--- a/src/proguard/optimize/ChangedCodePrinter.java
+++ b/src/proguard/optimize/ChangedCodePrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -54,6 +54,12 @@ implements AttributeVisitor
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute);
diff --git a/src/proguard/optimize/ConstantMemberFilter.java b/src/proguard/optimize/ConstantMemberFilter.java
index 56437c3..1f30a30 100644
--- a/src/proguard/optimize/ConstantMemberFilter.java
+++ b/src/proguard/optimize/ConstantMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/ConstantParameterFilter.java b/src/proguard/optimize/ConstantParameterFilter.java
index 24a7040..1500fd0 100644
--- a/src/proguard/optimize/ConstantParameterFilter.java
+++ b/src/proguard/optimize/ConstantParameterFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/DuplicateInitializerFixer.java b/src/proguard/optimize/DuplicateInitializerFixer.java
index 746d182..95bc2f1 100644
--- a/src/proguard/optimize/DuplicateInitializerFixer.java
+++ b/src/proguard/optimize/DuplicateInitializerFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -86,7 +86,7 @@ implements MemberVisitor,
if (!programMethod.equals(similarMethod))
{
// Should this initializer be preserved?
- if (!KeepMarker.isKept(programMethod))
+ if (KeepMarker.isKept(programMethod))
{
// Fix the other initializer.
programMethod = (ProgramMethod)similarMethod;
@@ -95,12 +95,23 @@ implements MemberVisitor,
int index = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
// Try to find a new, unique descriptor.
- for (int typeIndex = 0; typeIndex < TYPES.length; typeIndex++)
+ int typeCounter = 0;
+ while (true)
{
- String newDescriptor =
- descriptor.substring(0, index) +
- TYPES[typeIndex] +
- descriptor.substring(index);
+ // Construct the new descriptor by inserting a new type
+ // as an additional last argument.
+ StringBuffer newDescriptorBuffer =
+ new StringBuffer(descriptor.substring(0, index));
+
+ for (int arrayDimension = 0; arrayDimension < typeCounter / TYPES.length; arrayDimension++)
+ {
+ newDescriptorBuffer.append(ClassConstants.INTERNAL_TYPE_ARRAY);
+ }
+
+ newDescriptorBuffer.append(TYPES[typeCounter % TYPES.length]);
+ newDescriptorBuffer.append(descriptor.substring(index));
+
+ String newDescriptor = newDescriptorBuffer.toString();
// Is the new initializer descriptor unique?
if (programClass.findMethod(name, newDescriptor) == null)
@@ -108,7 +119,7 @@ implements MemberVisitor,
if (DEBUG)
{
System.out.println("DuplicateInitializerFixer:");
- System.out.println(" ["+programClass.getName()+"]: "+name+descriptor+" -> "+newDescriptor);
+ System.out.println(" ["+programClass.getName()+"."+name+descriptor+"] ("+ClassUtil.externalClassAccessFlags(programMethod.getAccessFlags())+") -> ["+newDescriptor+"]");
}
// Update the descriptor.
@@ -130,12 +141,9 @@ implements MemberVisitor,
// We're done with this constructor.
return;
}
- }
- throw new IllegalStateException("Can't find unique constructor descriptor for ["+
- programClass.getName()+"."+
- programMethod.getName(programClass)+
- programMethod.getDescriptor(programClass)+"]");
+ typeCounter++;
+ }
}
}
}
diff --git a/src/proguard/optimize/DuplicateInitializerInvocationFixer.java b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
index ca24481..5edaba0 100644
--- a/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
+++ b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,7 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.editor.CodeAttributeEditor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
/**
@@ -48,12 +48,12 @@ implements AttributeVisitor,
private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
- private String descriptor;
- private boolean hasBeenFixed;
+ private String descriptor;
+ private int descriptorLengthDelta;
/**
- * Creates a new EvaluationSimplifier.
+ * Creates a new DuplicateInitializerInvocationFixer.
*/
public DuplicateInitializerInvocationFixer()
{
@@ -62,7 +62,7 @@ implements AttributeVisitor,
/**
- * Creates a new EvaluationSimplifier.
+ * Creates a new DuplicateInitializerInvocationFixer.
* @param extraAddedInstructionVisitor an optional extra visitor for all
* added instructions.
*/
@@ -102,21 +102,22 @@ implements AttributeVisitor,
{
if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL)
{
- hasBeenFixed = false;
+ descriptorLengthDelta = 0;
clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
- if (hasBeenFixed)
+ if (descriptorLengthDelta > 0)
{
Instruction extraInstruction =
- new SimpleInstruction(InstructionConstants.OP_ICONST_0);
+ new SimpleInstruction(descriptorLengthDelta == 1 ?
+ InstructionConstants.OP_ICONST_0 :
+ InstructionConstants.OP_ACONST_NULL);
codeAttributeEditor.insertBeforeInstruction(offset,
extraInstruction);
if (DEBUG)
{
- System.out.println("DuplicateInitializerInvocationFixer:");
- System.out.println(" Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset));
+ System.out.println(" ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset));
}
if (extraAddedInstructionVisitor != null)
@@ -145,6 +146,16 @@ implements AttributeVisitor,
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- hasBeenFixed = !descriptor.equals(programMethod.getDescriptor(programClass));
+ descriptorLengthDelta =
+ programMethod.getDescriptor(programClass).length() - descriptor.length();
+
+ if (DEBUG)
+ {
+ if (descriptorLengthDelta > 0)
+ {
+ System.out.println("DuplicateInitializerInvocationFixer:");
+ System.out.println(" ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] ("+ClassUtil.externalClassAccessFlags(programMethod.getAccessFlags())+") referenced by:");
+ }
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/proguard/optimize/KeepMarker.java b/src/proguard/optimize/KeepMarker.java
index 4297996..b0eab7b 100644
--- a/src/proguard/optimize/KeepMarker.java
+++ b/src/proguard/optimize/KeepMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,6 +23,7 @@ package proguard.optimize;
import proguard.classfile.*;
import proguard.classfile.util.MethodLinker;
import proguard.classfile.visitor.*;
+import proguard.optimize.info.NoSideEffectMethodMarker;
/**
@@ -30,6 +31,7 @@ import proguard.classfile.visitor.*;
* marks classes and class members it visits. The marked elements
* will remain unchanged as necessary in the optimization step.
*
+ * @see NoSideEffectMethodMarker
* @author Eric Lafortune
*/
public class KeepMarker
@@ -90,6 +92,12 @@ implements ClassVisitor,
public static boolean isKept(VisitorAccepter visitorAccepter)
{
- return MethodLinker.lastVisitorAccepter(visitorAccepter).getVisitorInfo() == KEPT;
+ // We're also checking for the constant in NoSideEffectMethodMarker,
+ // to keep things simple.
+ Object visitorInfo =
+ MethodLinker.lastVisitorAccepter(visitorAccepter).getVisitorInfo();
+
+ return visitorInfo == KEPT ||
+ visitorInfo == NoSideEffectMethodMarker.KEPT_BUT_NO_SIDE_EFFECTS;
}
}
diff --git a/src/proguard/optimize/KeptClassFilter.java b/src/proguard/optimize/KeptClassFilter.java
new file mode 100644
index 0000000..60a9d3e
--- /dev/null
+++ b/src/proguard/optimize/KeptClassFilter.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are marked as kept.
+ *
+ * @see KeepMarker
+ *
+ * @author Eric Lafortune
+ */
+public class KeptClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new KeptClassFilter.
+ * @param classVisitor the class visitor to which the visiting will be
+ * delegated.
+ */
+ public KeptClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (KeepMarker.isKept(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (KeepMarker.isKept(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/KeptMemberFilter.java b/src/proguard/optimize/KeptMemberFilter.java
new file mode 100644
index 0000000..1bdadb4
--- /dev/null
+++ b/src/proguard/optimize/KeptMemberFilter.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Member objects that are marked as kept.
+ *
+ * @see KeepMarker
+ *
+ * @author Eric Lafortune
+ */
+public class KeptMemberFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new KeptMemberFilter.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public KeptMemberFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (KeepMarker.isKept(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (KeepMarker.isKept(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (KeepMarker.isKept(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (KeepMarker.isKept(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/MemberDescriptorSpecializer.java b/src/proguard/optimize/MemberDescriptorSpecializer.java
index 0d0b841..4dce62e 100644
--- a/src/proguard/optimize/MemberDescriptorSpecializer.java
+++ b/src/proguard/optimize/MemberDescriptorSpecializer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,7 +39,7 @@ public class MemberDescriptorSpecializer
extends SimplifiedVisitor
implements MemberVisitor
{
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private final MemberVisitor extraParameterMemberVisitor;
diff --git a/src/proguard/optimize/MethodDescriptorShrinker.java b/src/proguard/optimize/MethodDescriptorShrinker.java
index 48374e7..d8d4425 100644
--- a/src/proguard/optimize/MethodDescriptorShrinker.java
+++ b/src/proguard/optimize/MethodDescriptorShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,7 @@ package proguard.optimize;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.editor.ConstantPoolEditor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
@@ -95,11 +95,9 @@ implements MemberVisitor,
if (DEBUG)
{
System.out.println("MethodDescriptorShrinker:");
- System.out.println(" Class file = "+programClass.getName());
- System.out.println(" Method name = "+name);
- System.out.println(" -> "+newName);
- System.out.println(" Method descriptor = "+descriptor);
- System.out.println(" -> "+newDescriptor);
+ System.out.println(" ["+programClass.getName()+"."+
+ name+descriptor+"] -> ["+
+ newName+newDescriptor+"]");
}
ConstantPoolEditor constantPoolEditor =
diff --git a/src/proguard/optimize/MethodStaticizer.java b/src/proguard/optimize/MethodStaticizer.java
index 8dd11e1..c8bdd11 100644
--- a/src/proguard/optimize/MethodStaticizer.java
+++ b/src/proguard/optimize/MethodStaticizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/OptimizationInfoMemberFilter.java b/src/proguard/optimize/OptimizationInfoMemberFilter.java
index 8760aee..2c5454c 100644
--- a/src/proguard/optimize/OptimizationInfoMemberFilter.java
+++ b/src/proguard/optimize/OptimizationInfoMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/Optimizer.java b/src/proguard/optimize/Optimizer.java
index a3e8a6e..8042825 100644
--- a/src/proguard/optimize/Optimizer.java
+++ b/src/proguard/optimize/Optimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,8 @@ package proguard.optimize;
import proguard.*;
import proguard.classfile.*;
import proguard.classfile.attribute.visitor.*;
-import proguard.classfile.constant.visitor.AllConstantVisitor;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.visitor.*;
import proguard.classfile.editor.*;
import proguard.classfile.instruction.visitor.*;
import proguard.classfile.util.MethodLinker;
@@ -66,6 +67,7 @@ public class Optimizer
private static final String CODE_SIMPLIFICATION_CAST = "code/simplification/cast";
private static final String CODE_SIMPLIFICATION_FIELD = "code/simplification/field";
private static final String CODE_SIMPLIFICATION_BRANCH = "code/simplification/branch";
+ private static final String CODE_SIMPLIFICATION_STRING = "code/simplification/string";
private static final String CODE_SIMPLIFICATION_ADVANCED = "code/simplification/advanced";
private static final String CODE_REMOVAL_ADVANCED = "code/removal/advanced";
private static final String CODE_REMOVAL_SIMPLE = "code/removal/simple";
@@ -80,6 +82,7 @@ public class Optimizer
CLASS_MERGING_VERTICAL,
CLASS_MERGING_HORIZONTAL,
FIELD_REMOVAL_WRITEONLY,
+ FIELD_MARKING_PRIVATE,
FIELD_PROPAGATION_VALUE,
METHOD_MARKING_PRIVATE,
METHOD_MARKING_STATIC,
@@ -96,6 +99,7 @@ public class Optimizer
CODE_SIMPLIFICATION_CAST,
CODE_SIMPLIFICATION_FIELD,
CODE_SIMPLIFICATION_BRANCH,
+ CODE_SIMPLIFICATION_STRING,
CODE_SIMPLIFICATION_ADVANCED,
CODE_REMOVAL_ADVANCED,
CODE_REMOVAL_SIMPLE,
@@ -157,6 +161,7 @@ public class Optimizer
boolean codeSimplificationCast = filter.matches(CODE_SIMPLIFICATION_CAST);
boolean codeSimplificationField = filter.matches(CODE_SIMPLIFICATION_FIELD);
boolean codeSimplificationBranch = filter.matches(CODE_SIMPLIFICATION_BRANCH);
+ boolean codeSimplificationString = filter.matches(CODE_SIMPLIFICATION_STRING);
boolean codeSimplificationAdvanced = filter.matches(CODE_SIMPLIFICATION_ADVANCED);
boolean codeRemovalAdvanced = filter.matches(CODE_REMOVAL_ADVANCED);
boolean codeRemovalSimple = filter.matches(CODE_REMOVAL_SIMPLE);
@@ -186,13 +191,15 @@ public class Optimizer
InstructionCounter codeSimplificationCastCounter = new InstructionCounter();
InstructionCounter codeSimplificationFieldCounter = new InstructionCounter();
InstructionCounter codeSimplificationBranchCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationStringCounter = new InstructionCounter();
InstructionCounter codeSimplificationAdvancedCounter = new InstructionCounter();
InstructionCounter deletedCounter = new InstructionCounter();
InstructionCounter addedCounter = new InstructionCounter();
MemberCounter codeRemovalVariableCounter = new MemberCounter();
ExceptionCounter codeRemovalExceptionCounter = new ExceptionCounter();
MemberCounter codeAllocationVariableCounter = new MemberCounter();
- MemberCounter initializerFixCounter = new MemberCounter();
+ MemberCounter initializerFixCounter1 = new MemberCounter();
+ MemberCounter initializerFixCounter2 = new MemberCounter();
// Some optimizations are required by other optimizations.
codeSimplificationAdvanced =
@@ -250,10 +257,27 @@ public class Optimizer
new AllInstructionVisitor(
new DotClassClassVisitor(keepMarker)))));
- // We also keep all classes that are involved in Class.forName constructs.
+ // We also keep all classes that are accessed dynamically.
programClassPool.classesAccept(
new AllConstantVisitor(
- new ClassForNameClassVisitor(keepMarker)));
+ new ConstantTagFilter(ClassConstants.CONSTANT_String,
+ new ReferencedClassVisitor(keepMarker))));
+
+ // We also keep all class members that are accessed dynamically.
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new ConstantTagFilter(ClassConstants.CONSTANT_String,
+ new ReferencedMemberVisitor(keepMarker))));
+
+ // We also keep all bootstrap method signatures.
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_7,
+ new AllAttributeVisitor(
+ new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods,
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodHandleTraveler(
+ new MethodrefTraveler(
+ new ReferencedMemberVisitor(keepMarker))))))));
// Attach some optimization info to all classes and class members, so
// it can be filled out later.
@@ -320,6 +344,9 @@ public class Optimizer
new ParameterUsageMarker(!methodMarkingStatic,
!methodRemovalParameter))));
+ // Mark all classes that have static initializers.
+ programClassPool.classesAccept(new StaticInitializerContainingClassMarker());
+
// Mark all methods that have side effects.
programClassPool.accept(new SideEffectMethodMarker());
@@ -347,18 +374,29 @@ public class Optimizer
new AllAttributeVisitor(
new PartialEvaluator(valueFactory, storingInvocationUnit, false))));
- // Count the constant fields and methods.
- programClassPool.classesAccept(
- new MultiClassVisitor(
- new ClassVisitor[]
- {
+ if (fieldPropagationValue)
+ {
+ // Count the constant fields.
+ programClassPool.classesAccept(
new AllFieldVisitor(
- new ConstantMemberFilter(fieldPropagationValueCounter)),
+ new ConstantMemberFilter(fieldPropagationValueCounter)));
+ }
+
+ if (methodPropagationParameter)
+ {
+ // Count the constant method parameters.
+ programClassPool.classesAccept(
new AllMethodVisitor(
- new ConstantParameterFilter(methodPropagationParameterCounter)),
+ new ConstantParameterFilter(methodPropagationParameterCounter)));
+ }
+
+ if (methodPropagationReturnvalue)
+ {
+ // Count the constant method return values.
+ programClassPool.classesAccept(
new AllMethodVisitor(
- new ConstantMemberFilter(methodPropagationReturnvalueCounter)),
- }));
+ new ConstantMemberFilter(methodPropagationReturnvalueCounter)));
+ }
}
InvocationUnit loadingInvocationUnit =
@@ -418,6 +456,12 @@ public class Optimizer
// This operation also updates the stack sizes.
programClassPool.classesAccept(
new MemberReferenceFixer());
+
+ // Remove unused bootstrap method arguments.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodArgumentShrinker())));
}
if (methodRemovalParameter ||
@@ -441,17 +485,39 @@ public class Optimizer
new StackSizeUpdater())));
}
-// // Specializing the class member descriptors seems to increase the
-// // class file size, on average.
-// // Specialize all class member descriptors.
-// programClassPool.classesAccept(new AllMemberVisitor(
-// new OptimizationInfoMemberFilter(
-// new MemberDescriptorSpecializer())));
-//
-// // Fix all references to classes, for MemberDescriptorSpecializer.
-// programClassPool.classesAccept(new AllMemberVisitor(
-// new OptimizationInfoMemberFilter(
-// new ClassReferenceFixer(true))));
+ if (methodRemovalParameter &&
+ methodRemovalParameterCounter.getCount() > 0)
+ {
+ // Tweak the descriptors of duplicate initializers, due to removed
+ // method parameters.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new DuplicateInitializerFixer(initializerFixCounter1)));
+
+ if (initializerFixCounter1.getCount() > 0)
+ {
+ // Fix all invocations of tweaked initializers.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new DuplicateInitializerInvocationFixer(addedCounter))));
+
+ // Fix all references to tweaked initializers.
+ programClassPool.classesAccept(new MemberReferenceFixer());
+ }
+ }
+
+ //// Specializing the class member descriptors seems to increase the
+ //// class file size, on average.
+ //// Specialize all class member descriptors.
+ //programClassPool.classesAccept(new AllMemberVisitor(
+ // new OptimizationInfoMemberFilter(
+ // new MemberDescriptorSpecializer())));
+ //
+ //// Fix all references to classes, for MemberDescriptorSpecializer.
+ //programClassPool.classesAccept(new AllMemberVisitor(
+ // new OptimizationInfoMemberFilter(
+ // new ClassReferenceFixer(true))));
// Mark all classes with package visible members.
// Mark all exception catches of methods.
@@ -461,13 +527,13 @@ public class Optimizer
new MultiClassVisitor(
new ClassVisitor[]
{
+ new PackageVisibleMemberContainingClassMarker(),
new AllConstantVisitor(
new PackageVisibleMemberInvokingClassMarker()),
new AllMethodVisitor(
new MultiMemberVisitor(
new MemberVisitor[]
{
- new PackageVisibleMemberContainingClassMarker(),
new AllAttributeVisitor(
new MultiAttributeVisitor(
new AttributeVisitor[]
@@ -511,8 +577,8 @@ public class Optimizer
classMergingHorizontalCounter));
}
- if (classMergingVertical ||
- classMergingHorizontal)
+ if (classMergingVerticalCounter .getCount() > 0 ||
+ classMergingHorizontalCounter.getCount() > 0)
{
// Clean up inner class attributes to avoid loops.
programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover());
@@ -530,18 +596,20 @@ public class Optimizer
new AllConstantVisitor(
new AccessFixer()));
}
- }
- if (methodRemovalParameter ||
- classMergingVertical ||
- classMergingHorizontal)
- {
- // Tweak the descriptors of duplicate initializers.
+ // Fix the access flags of the inner classes information.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllInnerClassesInfoVisitor(
+ new InnerClassesAccessFixer())));
+
+ // Tweak the descriptors of duplicate initializers, due to merged
+ // parameter classes.
programClassPool.classesAccept(
new AllMethodVisitor(
- new DuplicateInitializerFixer(initializerFixCounter)));
+ new DuplicateInitializerFixer(initializerFixCounter2)));
- if (initializerFixCounter.getCount() > 0)
+ if (initializerFixCounter2.getCount() > 0)
{
// Fix all invocations of tweaked initializers.
programClassPool.classesAccept(
@@ -595,14 +663,14 @@ public class Optimizer
new NonPrivateMemberMarker());
}
- if (fieldMarkingPrivate ||
- methodMarkingPrivate)
+ if (fieldMarkingPrivate)
{
// Make all non-private fields private, whereever possible.
programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.INTERNAL_ACC_INTERFACE,
new AllFieldVisitor(
new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
- new MemberPrivatizer(fieldMarkingPrivateCounter))));
+ new MemberPrivatizer(fieldMarkingPrivateCounter)))));
}
if (methodMarkingPrivate)
@@ -615,9 +683,9 @@ public class Optimizer
new MemberPrivatizer(methodMarkingPrivateCounter)))));
}
- if ((methodInliningUnique ||
- methodInliningShort ||
- methodInliningTailrecursion) &&
+ if ((methodInliningUniqueCounter .getCount() > 0 ||
+ methodInliningShortCounter .getCount() > 0 ||
+ methodInliningTailrecursionCounter.getCount() > 0) &&
configuration.allowAccessModification)
{
// Fix the access flags of referenced classes and class members,
@@ -627,10 +695,10 @@ public class Optimizer
new AccessFixer()));
}
- if (methodRemovalParameter ||
- classMergingVertical ||
- classMergingHorizontal ||
- methodMarkingPrivate)
+ if (methodRemovalParameterCounter .getCount() > 0 ||
+ classMergingVerticalCounter .getCount() > 0 ||
+ classMergingHorizontalCounter .getCount() > 0 ||
+ methodMarkingPrivateCounter .getCount() > 0 )
{
// Fix invocations of interface methods, of methods that have become
// non-abstract or private, and of methods that have moved to a
@@ -707,6 +775,15 @@ public class Optimizer
new GotoReturnReplacer(codeAttributeEditor, codeSimplificationBranchCounter));
}
+ if (codeSimplificationString)
+ {
+ // Peephole optimizations involving branches.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS,
+ InstructionSequenceConstants.STRING,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationStringCounter));
+ }
+
if (!peepholeOptimizations.isEmpty())
{
// Convert the list into an array.
@@ -749,14 +826,6 @@ public class Optimizer
new AllAttributeVisitor(
new VariableShrinker(codeRemovalVariableCounter))));
}
- else
- {
- // Clean up all unused local variables.
- programClassPool.classesAccept(
- new AllMethodVisitor(
- new AllAttributeVisitor(
- new VariableCleaner())));
- }
if (codeAllocationVariable)
{
@@ -767,6 +836,11 @@ public class Optimizer
new VariableOptimizer(false, codeAllocationVariableCounter))));
}
+
+ // Remove unused constants.
+ programClassPool.classesAccept(
+ new ConstantPoolShrinker());
+
int classMarkingFinalCount = classMarkingFinalCounter .getCount();
int classMergingVerticalCount = classMergingVerticalCounter .getCount();
int classMergingHorizontalCount = classMergingHorizontalCounter .getCount();
@@ -776,7 +850,7 @@ public class Optimizer
int methodMarkingPrivateCount = methodMarkingPrivateCounter .getCount();
int methodMarkingStaticCount = methodMarkingStaticCounter .getCount();
int methodMarkingFinalCount = methodMarkingFinalCounter .getCount();
- int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter.getCount();
+ int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter1.getCount() - initializerFixCounter2.getCount();
int methodPropagationParameterCount = methodPropagationParameterCounter .getCount();
int methodPropagationReturnvalueCount = methodPropagationReturnvalueCounter.getCount();
int methodInliningShortCount = methodInliningShortCounter .getCount();
@@ -788,12 +862,23 @@ public class Optimizer
int codeSimplificationCastCount = codeSimplificationCastCounter .getCount();
int codeSimplificationFieldCount = codeSimplificationFieldCounter .getCount();
int codeSimplificationBranchCount = codeSimplificationBranchCounter .getCount();
+ int codeSimplificationStringCount = codeSimplificationStringCounter .getCount();
int codeSimplificationAdvancedCount = codeSimplificationAdvancedCounter .getCount();
int codeRemovalCount = deletedCounter .getCount() - addedCounter.getCount();
int codeRemovalVariableCount = codeRemovalVariableCounter .getCount();
int codeRemovalExceptionCount = codeRemovalExceptionCounter .getCount();
int codeAllocationVariableCount = codeAllocationVariableCounter .getCount();
+ // Forget about constant fields, parameters, and return values, if they
+ // didn't lead to any useful optimizations. We want to avoid fruitless
+ // additional optimization passes.
+ if (codeSimplificationAdvancedCount == 0)
+ {
+ fieldPropagationValueCount = 0;
+ methodPropagationParameterCount = 0;
+ methodPropagationReturnvalueCount = 0;
+ }
+
if (configuration.verbose)
{
System.out.println(" Number of finalized classes: " + classMarkingFinalCount + disabled(classMarkingFinal));
@@ -817,6 +902,7 @@ public class Optimizer
System.out.println(" Number of cast peephole optimizations: " + codeSimplificationCastCount + disabled(codeSimplificationCast));
System.out.println(" Number of field peephole optimizations: " + codeSimplificationFieldCount + disabled(codeSimplificationField));
System.out.println(" Number of branch peephole optimizations: " + codeSimplificationBranchCount + disabled(codeSimplificationBranch));
+ System.out.println(" Number of string peephole optimizations: " + codeSimplificationStringCount + disabled(codeSimplificationString));
System.out.println(" Number of simplified instructions: " + codeSimplificationAdvancedCount + disabled(codeSimplificationAdvanced));
System.out.println(" Number of removed instructions: " + codeRemovalCount + disabled(codeRemovalAdvanced));
System.out.println(" Number of removed local variables: " + codeRemovalVariableCount + disabled(codeRemovalVariable));
@@ -845,6 +931,7 @@ public class Optimizer
codeSimplificationCastCount > 0 ||
codeSimplificationFieldCount > 0 ||
codeSimplificationBranchCount > 0 ||
+ codeSimplificationStringCount > 0 ||
codeSimplificationAdvancedCount > 0 ||
codeRemovalCount > 0 ||
codeRemovalVariableCount > 0 ||
diff --git a/src/proguard/optimize/ParameterShrinker.java b/src/proguard/optimize/ParameterShrinker.java
index a2bc6d3..33d37d1 100644
--- a/src/proguard/optimize/ParameterShrinker.java
+++ b/src/proguard/optimize/ParameterShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,7 @@ package proguard.optimize;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.editor.*;
+import proguard.classfile.editor.VariableRemapper;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
import proguard.optimize.info.ParameterUsageMarker;
diff --git a/src/proguard/optimize/TailRecursionSimplifier.java b/src/proguard/optimize/TailRecursionSimplifier.java
index 0946b6a..f820566 100644
--- a/src/proguard/optimize/TailRecursionSimplifier.java
+++ b/src/proguard/optimize/TailRecursionSimplifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -54,9 +54,9 @@ implements AttributeVisitor,
private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
+ private final MyRecursionChecker recursionChecker = new MyRecursionChecker();
private Method targetMethod;
- private boolean recursive;
private boolean inlinedAny;
@@ -105,38 +105,31 @@ implements AttributeVisitor,
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
- targetMethod = method;
- inlinedAny = false;
+ targetMethod = method;
+ inlinedAny = false;
codeAttributeComposer.reset();
- // Append the body of the code.
- copyCode(clazz, method, codeAttribute);
+ // The code may expand, due to expanding constant and variable
+ // instructions.
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+
+ // Copy the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
// Update the code attribute if any code has been inlined.
if (inlinedAny)
{
- codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
- }
- }
- }
+ // Copy the exceptions.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
- /**
- * Appends the code of the given code attribute.
- */
- private void copyCode(Clazz clazz, Method method, CodeAttribute codeAttribute)
- {
- // The code may expand, due to expanding constant and variable
- // instructions.
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
-
- // Copy the instructions.
- codeAttribute.instructionsAccept(clazz, method, this);
+ codeAttributeComposer.endCodeFragment();
- // Append a label just after the code.
- codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
-
- codeAttributeComposer.endCodeFragment();
+ codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
}
@@ -145,7 +138,7 @@ implements AttributeVisitor,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
// Copy the instruction.
- codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, instruction);
}
@@ -159,9 +152,9 @@ implements AttributeVisitor,
case InstructionConstants.OP_INVOKESTATIC:
{
// Is it a recursive call?
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, recursionChecker);
- if (recursive)
+ if (recursionChecker.isRecursive())
{
// Is the next instruction a return?
int nextOffset =
@@ -180,13 +173,13 @@ implements AttributeVisitor,
case InstructionConstants.OP_RETURN:
{
// Isn't the recursive call inside a try/catch block?
- codeAttribute.exceptionsAccept(clazz, method, offset, this);
+ codeAttribute.exceptionsAccept(clazz, method, offset, recursionChecker);
- if (recursive)
+ if (recursionChecker.isRecursive())
{
if (DEBUG)
{
- System.out.println("TailRecursionSimplifier.visitConstantInstruction: ["+
+ System.out.println("TailRecursionSimplifier: ["+
clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"], inlining "+constantInstruction.toString(offset));
}
@@ -223,23 +216,56 @@ implements AttributeVisitor,
}
// Copy the instruction.
- codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, constantInstruction);
}
- // Implementations for ConstantVisitor.
+ // Implementations for ExceptionInfoVisitor.
- public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- recursive = targetMethod.equals(methodrefConstant.referencedMember);
+ codeAttributeComposer.appendException(new ExceptionInfo(exceptionInfo.u2startPC,
+ exceptionInfo.u2endPC,
+ exceptionInfo.u2handlerPC,
+ exceptionInfo.u2catchType));
}
- // Implementations for ExceptionInfoVisitor.
-
- public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ /**
+ * This ConstantVisitor and ExceptionInfoVisitor returns whether a method
+ * invocation can be treated as tail-recursive.
+ */
+ private class MyRecursionChecker
+ extends SimplifiedVisitor
+ implements ConstantVisitor,
+ ExceptionInfoVisitor
{
- recursive = false;
+ private boolean recursive;
+
+
+ /**
+ * Returns whether the method invocation can be treated as
+ * tail-recursive.
+ */
+ public boolean isRecursive()
+ {
+ return recursive;
+ }
+
+ // Implementations for ConstantVisitor.
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ recursive = targetMethod.equals(methodrefConstant.referencedMember);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ recursive = false;
+ }
}
@@ -257,7 +283,6 @@ implements AttributeVisitor,
(method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0;
// Count the number of parameters, taking into account their categories.
- int parameterCount = ClassUtil.internalMethodParameterCount(descriptor);
int parameterSize = ClassUtil.internalMethodParameterSize(descriptor);
int parameterOffset = isStatic ? 0 : 1;
@@ -315,7 +340,7 @@ implements AttributeVisitor,
}
codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
- new VariableInstruction(opcode, parameterOffset + parameterIndex).shrink());
+ new VariableInstruction(opcode, parameterOffset + parameterIndex));
}
}
@@ -323,7 +348,7 @@ implements AttributeVisitor,
if (!isStatic)
{
codeAttributeComposer.appendInstruction(parameterSize,
- new VariableInstruction(InstructionConstants.OP_ASTORE, 0).shrink());
+ new VariableInstruction(InstructionConstants.OP_ASTORE, 0));
}
codeAttributeComposer.endCodeFragment();
diff --git a/src/proguard/optimize/WriteOnlyFieldFilter.java b/src/proguard/optimize/WriteOnlyFieldFilter.java
index 578beb2..762bd91 100644
--- a/src/proguard/optimize/WriteOnlyFieldFilter.java
+++ b/src/proguard/optimize/WriteOnlyFieldFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/EvaluationShrinker.java b/src/proguard/optimize/evaluation/EvaluationShrinker.java
index 1463feb..2e86532 100644
--- a/src/proguard/optimize/evaluation/EvaluationShrinker.java
+++ b/src/proguard/optimize/evaluation/EvaluationShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -34,6 +34,8 @@ import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.info.*;
+import java.util.Arrays;
+
/**
* This AttributeVisitor simplifies the code attributes that it visits, based
* on partial evaluation.
@@ -52,21 +54,55 @@ implements AttributeVisitor
private static boolean DEBUG = true;
//*/
+ private static final int UNSUPPORTED = -1;
+ private static final int NOP = InstructionConstants.OP_NOP & 0xff;
+ private static final int POP = InstructionConstants.OP_POP & 0xff;
+ private static final int POP2 = InstructionConstants.OP_POP2 & 0xff;
+ private static final int DUP = InstructionConstants.OP_DUP & 0xff;
+ private static final int DUP_X1 = InstructionConstants.OP_DUP_X1 & 0xff;
+ private static final int DUP_X2 = InstructionConstants.OP_DUP_X2 & 0xff;
+ private static final int DUP2 = InstructionConstants.OP_DUP2 & 0xff;
+ private static final int DUP2_X1 = InstructionConstants.OP_DUP2_X1 & 0xff;
+ private static final int DUP2_X2 = InstructionConstants.OP_DUP2_X2 & 0xff;
+ private static final int SWAP = InstructionConstants.OP_SWAP & 0xff;
+ private static final int MOV_X2 = DUP_X2 | (POP << 8);
+ private static final int MOV2_X1 = DUP2_X1 | (POP2 << 8);
+ private static final int MOV2_X2 = DUP2_X2 | (POP2 << 8);
+ private static final int POP_X1 = SWAP | (POP << 8);
+ private static final int POP_X2 = DUP2_X1 | (POP2 << 8) | (POP << 16);
+ private static final int POP_X3 = UNSUPPORTED;
+ private static final int POP2_X1 = DUP_X2 | (POP << 8) | (POP2 << 16);
+ private static final int POP2_X2 = DUP2_X2 | (POP2 << 8) | (POP2 << 16);
+ private static final int POP3 = POP2 | (POP << 8);
+ private static final int POP4 = POP2 | (POP2 << 8);
+ private static final int POP_DUP = POP | (DUP << 8);
+ private static final int POP_SWAP_POP = POP | (SWAP << 8) | (POP << 16);
+ private static final int POP2_SWAP_POP = POP2 | (SWAP << 8) | (POP << 16);
+ private static final int SWAP_DUP_X1 = SWAP | (DUP_X1 << 8);
+ private static final int SWAP_DUP_X1_SWAP = SWAP | (DUP_X1 << 8) | (SWAP << 16);
+ private static final int SWAP_POP_DUP = SWAP | (POP << 8) | (DUP << 16);
+ private static final int SWAP_POP_DUP_X1 = SWAP | (POP << 8) | (DUP_X1 << 16);
+ private static final int DUP_X2_POP2 = DUP_X2 | (POP2 << 8);
+ private static final int DUP2_X1_POP3 = DUP2_X1 | (POP2 << 8) | (POP << 16);
+ private static final int DUP2_X2_POP3 = DUP2_X2 | (POP2 << 8) | (POP << 16);
+ private static final int DUP2_X2_SWAP_POP = DUP2_X2 | (SWAP << 8) | (POP << 16);
+
+
private final InstructionVisitor extraDeletedInstructionVisitor;
private final InstructionVisitor extraAddedInstructionVisitor;
- private final PartialEvaluator partialEvaluator;
- private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
- private final MyUnusedParameterSimplifier unusedParameterSimplifier = new MyUnusedParameterSimplifier();
- private final MyProducerMarker producerMarker = new MyProducerMarker();
- private final MyStackConsistencyFixer stackConsistencyFixer = new MyStackConsistencyFixer();
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false);
+ private final PartialEvaluator partialEvaluator;
+ private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true);
+ private final MyUnusedParameterSimplifier unusedParameterSimplifier = new MyUnusedParameterSimplifier();
+ private final MyProducerMarker producerMarker = new MyProducerMarker();
+ private final MyVariableInitializationMarker variableInitializationMarker = new MyVariableInitializationMarker();
+ private final MyStackConsistencyFixer stackConsistencyFixer = new MyStackConsistencyFixer();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, false);
- private boolean[][] variablesNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_VARIABLES_SIZE];
- private boolean[][] stacksNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
- private boolean[][] stacksSimplifiedBefore = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
- private boolean[] instructionsNecessary = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+ private boolean[][] stacksNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
+ private boolean[][] stacksSimplifiedBefore = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
+ private boolean[] instructionsNecessary = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
private int maxMarkedOffset;
@@ -154,6 +190,9 @@ implements AttributeVisitor
// Evaluate the method.
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+ // Evaluate the method the way the JVM verifier would do it.
+ simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
int codeLength = codeAttribute.u4codeLength;
// Reset the code changes.
@@ -272,22 +311,13 @@ implements AttributeVisitor
for (int offset = 0; offset < codeLength; offset++)
{
- // Is it a variable initialization that hasn't been marked yet?
- if (partialEvaluator.isTraced(offset) &&
- !isInstructionNecessary(offset))
+ if (isInstructionNecessary(offset))
{
- // Is the corresponding variable necessary anywhere in the code,
- // accoriding to a simple partial evaluation?
- int variableIndex = partialEvaluator.initializedVariable(offset);
- if (variableIndex >= 0 &&
- isVariableInitializationNecessary(clazz,
- method,
- codeAttribute,
- offset,
- variableIndex))
- {
- markInstruction(offset);
- }
+ // Mark initializations of the required instruction.
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, variableInitializationMarker);
}
}
if (DEBUG) System.out.println();
@@ -383,12 +413,9 @@ implements AttributeVisitor
offset);
if (!isInstructionNecessary(offset))
{
+ codeAttributeEditor.clearModifications(offset);
codeAttributeEditor.deleteInstruction(offset);
- codeAttributeEditor.insertBeforeInstruction(offset, (Instruction)null);
- codeAttributeEditor.replaceInstruction(offset, (Instruction)null);
- codeAttributeEditor.insertAfterInstruction(offset, (Instruction)null);
-
// Visit the instruction, if required.
if (extraDeletedInstructionVisitor != null)
{
@@ -467,7 +494,9 @@ implements AttributeVisitor
*/
private class MyUnusedParameterSimplifier
extends SimplifiedVisitor
- implements InstructionVisitor, ConstantVisitor, MemberVisitor
+ implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
{
private int invocationOffset;
private ConstantInstruction invocationInstruction;
@@ -614,8 +643,8 @@ implements AttributeVisitor
public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
{
- // Is the variable being loaded (or incremented)?
- if (variableInstruction.opcode < InstructionConstants.OP_ISTORE)
+ // Is the variable being loaded or incremented?
+ if (variableInstruction.isLoad())
{
markVariableProducers(offset, variableInstruction.variableIndex);
}
@@ -657,6 +686,32 @@ implements AttributeVisitor
/**
+ * This InstructionVisitor marks variable initializations that are
+ * necessary to appease the JVM.
+ */
+ private class MyVariableInitializationMarker
+ extends SimplifiedVisitor
+ implements InstructionVisitor
+ {
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Is the variable being loaded or incremented?
+ if (variableInstruction.isLoad())
+ {
+ // Mark any variable initializations for this variable load that
+ // are required according to the JVM.
+ markVariableInitializers(offset, variableInstruction.variableIndex);
+ }
+ }
+ }
+
+
+ /**
* This InstructionVisitor fixes instructions locally, popping any unused
* produced stack entries after marked instructions, and popping produced
* stack entries and pushing missing stack entries instead of unmarked
@@ -682,17 +737,25 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackBefore(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int requiredPushCount = 0;
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
- // Is the stack entry required by other consumers?
- if (!isStackSimplifiedBefore(offset, top - stackIndex) &&
- !isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex))
+ if (!isStackSimplifiedBefore(offset, stackIndex))
{
- // Remember to push it.
- requiredPushCount++;
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
+ {
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+ }
+ else
+ {
+ // Remember to push it.
+ requiredPushCount++;
+ }
}
}
@@ -703,13 +766,39 @@ implements AttributeVisitor
if (requiredPushCount > (instruction.isCategory2() ? 2 : 1))
{
- throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"]");
+ throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"] at ["+offset+"]");
}
insertPushInstructions(offset, false, tracedStack.getTop(0).computationalType());
}
}
+ // Check all other stack entries, if this is a return
+ // instruction.
+ // Typical case: the code returns, but there are still other
+ // entries left on the stack. These have to be consistent.
+ InstructionOffsetValue branchTargets =
+ partialEvaluator.branchTargets(offset);
+ if (branchTargets != null &&
+ branchTargets.instructionOffsetCount() == 0)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(offset);
+
+ int unpoppedStackSize = tracedStack.size() - popCount;
+
+ for (int stackIndex = 0; stackIndex < unpoppedStackSize; stackIndex++)
+ {
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
+ {
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+ }
+ }
+ }
+
// Check all stack entries that are pushed.
// Typical case: a return value that wasn't really required and
// that should be popped.
@@ -719,13 +808,13 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackAfter(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int requiredPopCount = 0;
- for (int stackIndex = 0; stackIndex < pushCount; stackIndex++)
+ for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
{
// Is the stack entry required by consumers?
- if (!isStackEntryNecessaryAfter(offset, top - stackIndex))
+ if (!isStackEntryNecessaryAfter(offset, stackIndex))
{
// Remember to pop it.
requiredPopCount++;
@@ -752,14 +841,18 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackBefore(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int expectedPopCount = 0;
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
- // Is the stack entry required by other consumers?
- if (isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex))
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
{
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+
// Remember to pop it.
expectedPopCount++;
}
@@ -782,13 +875,13 @@ implements AttributeVisitor
TracedStack tracedStack =
partialEvaluator.getStackAfter(offset);
- int top = tracedStack.size() - 1;
+ int stackSize = tracedStack.size();
int expectedPushCount = 0;
- for (int stackIndex = 0; stackIndex < pushCount; stackIndex++)
+ for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
{
// Is the stack entry required by consumers?
- if (isStackEntryNecessaryAfter(offset, top - stackIndex))
+ if (isStackEntryNecessaryAfter(offset, stackIndex))
{
// Remember to push it.
expectedPushCount++;
@@ -812,44 +905,546 @@ implements AttributeVisitor
if (isInstructionNecessary(offset) &&
isDupOrSwap(simpleInstruction))
{
- fixDupInstruction(clazz, codeAttribute, offset, simpleInstruction);
+ int stackSizeBefore = partialEvaluator.getStackBefore(offset).size();
+
+ // Check all stack entries that are popped.
+ // Typical case: a freshly marked variable initialization that
+ // requires some value on the stack.
+ int popCount = simpleInstruction.stackPopCount(clazz);
+ if (popCount > 0)
+ {
+ for (int stackIndex = stackSizeBefore - popCount; stackIndex < stackSizeBefore; stackIndex++)
+ {
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
+ {
+ // Mark all produced stack entries.
+ markStackEntryProducers(offset, stackIndex);
+ }
+ }
+ }
+
+ int topBefore = stackSizeBefore - 1;
+ int topAfter = partialEvaluator.getStackAfter(offset).size() - 1;
+
+ byte oldOpcode = simpleInstruction.opcode;
+
+ // Simplify the dup/swap instruction if possible.
+ int newOpcodes = fixDupSwap(offset, oldOpcode, topBefore, topAfter);
+
+ // Did we find a suitabe (extended) opcode?
+ if (newOpcodes == UNSUPPORTED)
+ {
+ // We can't easily emulate some constructs.
+ throw new UnsupportedOperationException("Can't handle "+simpleInstruction.toString()+" instruction at ["+offset +"]");
+ }
+
+ // Is there a single replacement opcode?
+ if ((newOpcodes & ~0xff) == 0)
+ {
+ byte newOpcode = (byte)newOpcodes;
+
+ if (newOpcode == InstructionConstants.OP_NOP)
+ {
+ // Delete the instruction.
+ codeAttributeEditor.deleteInstruction(offset);
+
+ if (extraDeletedInstructionVisitor != null)
+ {
+ extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
+ }
+
+ if (DEBUG) System.out.println(" Deleting marked instruction "+simpleInstruction.toString(offset));
+ }
+ else if (newOpcode == oldOpcode)
+ {
+ // Leave the instruction unchanged.
+ codeAttributeEditor.undeleteInstruction(offset);
+
+ if (DEBUG) System.out.println(" Marking unchanged instruction "+simpleInstruction.toString(offset));
+ }
+ else
+ {
+ // Replace the instruction.
+ Instruction replacementInstruction = new SimpleInstruction(newOpcode);
+ codeAttributeEditor.replaceInstruction(offset,
+ replacementInstruction);
+
+ if (DEBUG) System.out.println(" Replacing instruction "+simpleInstruction.toString(offset)+" by "+replacementInstruction.toString());
+ }
+ }
+ else
+ {
+ // Collect the replacement instructions.
+ Instruction[] replacementInstructions = new Instruction[4];
+
+ if (DEBUG) System.out.println(" Replacing instruction "+simpleInstruction.toString(offset)+" by");
+ int count = 0;
+ while (newOpcodes != 0)
+ {
+ SimpleInstruction replacementInstruction = new SimpleInstruction((byte)newOpcodes);
+ replacementInstructions[count++] = replacementInstruction;
+
+ if (DEBUG) System.out.println(" "+replacementInstruction.toString());
+ newOpcodes >>>= 8;
+ }
+
+ // Create a properly sized array.
+ if (count < 4)
+ {
+ Instruction[] newInstructions = new Instruction[count];
+ System.arraycopy(replacementInstructions, 0, newInstructions, 0, count);
+ replacementInstructions = newInstructions;
+ }
+
+ codeAttributeEditor.replaceInstruction(offset,
+ replacementInstructions);
+ }
}
else
{
visitAnyInstruction(clazz, method, codeAttribute, offset, simpleInstruction);
}
}
+
+
+ /**
+ * Returns a dup/swap opcode that is corrected for the stack entries
+ * that are present before the instruction and necessary after the
+ * instruction. The returned integer opcode may contain multiple byte
+ * opcodes (least significant byte first).
+ * @param instructionOffset the offset of the dup/swap instruction.
+ * @param dupSwapOpcode the original dup/swap opcode.
+ * @param topBefore the index of the top stack entry before
+ * the instruction (counting from the bottom).
+ * @param topAfter the index of the top stack entry after
+ * the instruction (counting from the bottom).
+ * @return the corrected opcode.
+ */
+ private int fixDupSwap(int instructionOffset,
+ byte dupSwapOpcode,
+ int topBefore,
+ int topAfter)
+ {
+ switch (dupSwapOpcode)
+ {
+ case InstructionConstants.OP_DUP: return fixedDup (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP_X1: return fixedDup_x1 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP_X2: return fixedDup_x2 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2: return fixedDup2 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2_X1: return fixedDup2_x1(instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2_X2: return fixedDup2_x2(instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_SWAP: return fixedSwap (instructionOffset, topBefore, topAfter);
+ default: throw new IllegalArgumentException("Not a dup/swap opcode ["+dupSwapOpcode+"]");
+ }
+ }
+
+
+ private int fixedDup(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary0 ?
+ stackEntryNecessary1 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ stackEntryNecessary1 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup_x1(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...XO -> ...OXO
+ SWAP : // ...XO -> ...OX
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? NOP : // ...XO -> ...XO
+ stackEntryPresent0 ? POP : // ...XO -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...XO -> ...OO
+ POP_X1 : // ...XO -> ...O
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? POP_X1 : // ...XO -> ...O
+ stackEntryPresent0 ? POP2 : // ...XO -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup_x2(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore(instructionOffset, topBefore - 2);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 3);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X2 : // ...XYO -> ...OXYO
+ MOV_X2 : // ...XYO -> ...OXY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...XYO -> ...XYO
+ stackEntryPresent0 ? POP : // ...XYO -> ...XY
+ NOP : // ...XY -> ...XY
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ // stackEntryNecessary0 ? UNSUPPORTED : // ...XYO -> ...OYO
+ UNSUPPORTED : // ...XYO -> ...OY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X2 : // ...XYO -> ...YO
+ stackEntryPresent0 ? POP_SWAP_POP : // ...XYO -> ...Y
+ POP_X1 : // ...XY -> ...Y
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...YO -> ...OYO
+ SWAP : // ...YO -> ...OY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...YO -> ...YO
+ stackEntryPresent0 ? POP : // ...YO -> ...Y
+ NOP : // ...Y -> ...Y
+ stackEntryPresent1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP_X1 : // ...XYO -> ...OXO
+ DUP_X2_POP2 : // ...XYO -> ...OX
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...XYO -> ...XO
+ stackEntryPresent0 ? POP2 : // ...XYO -> ...X
+ POP : // ...XY -> ...X
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? UNSUPPORTED : // ...XYO -> ...OO
+ POP2_X1 : // ...XYO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP2_X1 : // ...XYO -> ...O
+ stackEntryPresent0 ? POP3 : // ...XYO -> ...
+ POP2 : // ...XY -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...YO -> ...OO
+ POP_X1 : // ...YO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...YO -> ...O
+ stackEntryPresent0 ? POP2 : // ...YO -> ...
+ POP : // ...Y -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...XO -> ...OXO
+ SWAP : // ...XO -> ...OX
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...XO -> ...XO
+ stackEntryPresent0 ? POP : // ...XO -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...XO -> ...OO
+ POP_X1 : // ...XO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...XO -> ...O
+ stackEntryPresent0 ? POP2 : // ...XO -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 3);
+
+ return
+ stackEntryNecessary3 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? DUP2 : // ...AB -> ...ABAB
+ SWAP_DUP_X1 : // ...AB -> ...ABA
+ // !stackEntryNecessary1
+ stackEntryNecessary0 ? DUP : // ...AB -> ...ABB
+ NOP : // ...AB -> ...AB
+ // !stackEntryNecessary2
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? SWAP_DUP_X1_SWAP : // ...AB -> ...AAB
+ stackEntryPresent0 ? POP_DUP : // ...AB -> ...AA
+ DUP : // ...A -> ...AA
+ // !stackEntryNecessary1
+ stackEntryNecessary0 ? NOP : // ...AB -> ...AB
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ // !stackEntryNecessary3
+ stackEntryNecessary2 ?
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...AB -> ...BAB
+ SWAP : // ...AB -> ...BA
+ stackEntryPresent1 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...AB -> ...BB
+ POP_X1 : // ...AB -> ...B
+ // !stackEntryPresent1
+ stackEntryNecessary0 ? POP : // ...B -> ...BB
+ NOP : // ...B -> ...B
+ // !stackEntryNecessary2
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? NOP : // ...AB -> ...AB
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ stackEntryPresent1 ?
+ stackEntryNecessary0 ? POP_X1 : // ...AB -> ...B
+ stackEntryPresent0 ? POP2 : // ...AB -> ...
+ POP : // ...A -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary0 ? NOP : // ...B -> ...B
+ stackEntryPresent0 ? POP : // ...B -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2_x1(int instructionOffset, int topBefore, int topAfter)
+ {
+ // We're currently assuming the value to be duplicated
+ // is a long or a double, taking up two slots, or at
+ // least consistent.
+ boolean stackEntriesPresent01 = isStackEntriesPresentBefore(instructionOffset, topBefore - 0, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore( instructionOffset, topBefore - 2);
+
+ boolean stackEntriesNecessary01 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 0, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 2);
+ boolean stackEntriesNecessary34 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 3, topAfter - 4);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary2 ?
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...XAB -> ...ABXAB
+ MOV2_X1 : // ...XAB -> ...ABX
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? NOP : // ...XAB -> ...XAB
+ stackEntriesPresent01 ? POP2 : // ...XAB -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent2 ?
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XAB -> ...ABAB
+ POP_X2 : // ...XAB -> ...AB
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? DUP2_X1_POP3 : // ...XAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...XAB -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent2
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? DUP2 : // ...AB -> ...ABAB
+ NOP : // ...AB -> ...AB
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? NOP : // ...AB -> ...AB
+ stackEntriesPresent01 ? POP2 : // ...AB -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2_x2(int instructionOffset, int topBefore, int topAfter)
+ {
+ // We're currently assuming the value to be duplicated
+ // is a long or a double, taking up two slots, or at
+ // least consistent.
+ boolean stackEntriesPresent01 = isStackEntriesPresentBefore(instructionOffset, topBefore - 0, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore( instructionOffset, topBefore - 2);
+ boolean stackEntryPresent3 = isStackEntryPresentBefore( instructionOffset, topBefore - 3);
+
+ boolean stackEntriesNecessary01 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 0, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 3);
+ boolean stackEntriesNecessary45 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 4, topAfter - 5);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X2 : // ...XYAB -> ...ABXYAB
+ MOV2_X2 : // ...XYAB -> ...ABXY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...XYAB -> ...XYAB
+ stackEntriesPresent01 ? POP2 : // ...XYAB -> ...XY
+ NOP : // ...XY -> ...XY
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABYAB
+ DUP2_X2_SWAP_POP : // ...XYAB -> ...ABY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X3 : // ...XYAB -> ...YAB
+ stackEntriesPresent01 ? POP2_SWAP_POP : // ...XYAB -> ...Y
+ POP_X1 : // ...XY -> ...Y
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...YAB -> ...ABYAB
+ MOV2_X1 : // ...YAB -> ...ABY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...YAB -> ...YAB
+ stackEntriesPresent01 ? POP2 : // ...YAB -> ...Y
+ NOP : // ...Y -> ...Y
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABXAB
+ DUP2_X2_POP3 : // ...XYAB -> ...ABX
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...XYAB -> ...XAB
+ stackEntriesPresent01 ? POP3 : // ...XYAB -> ...X
+ POP : // ...XY -> ...X
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABAB
+ POP2_X2 : // ...XYAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP2_X2 : // ...XYAB -> ...AB
+ stackEntriesPresent01 ? POP4 : // ...XYAB -> ...
+ POP2 : // ...XY -> ...
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...YAB -> ...ABAB
+ POP_X2 : // ...YAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...YAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...YAB -> ...
+ POP : // ...Y -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...XAB -> ...ABXAB
+ MOV2_X1 : // ...XAB -> ...ABX
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...XAB -> ...XAB
+ stackEntriesPresent01 ? POP2 : // ...XAB -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XAB -> ...ABAB
+ POP_X2 : // ...XAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...XAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...XAB -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2 : // ...AB -> ...ABAB
+ NOP : // ...AB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...AB -> ...AB
+ stackEntriesPresent01 ? POP2 : // ...AB -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedSwap(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+
+ // Figure out which stack entries should be moved
+ // or removed.
+ return
+ stackEntryNecessary0 ?
+ stackEntryNecessary1 ? SWAP : // ...AB -> ...BA
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ stackEntryPresent1 ? POP_X1 : // ...AB -> ...B
+ NOP; // ...B -> ...B
+ }
}
// Small utility methods.
/**
- * Marks the variable and the corresponding producing instructions
- * of the consumer at the given offset.
- * @param consumerOffset the offset of the consumer.
- * @param variableIndex the index of the variable to be marked.
+ * Marks the producing instructions of the variable consumer at the given
+ * offset.
+ * @param consumerOffset the offset of the variable consumer.
+ * @param variableIndex the index of the variable that is loaded.
*/
private void markVariableProducers(int consumerOffset,
int variableIndex)
{
- TracedVariables tracedVariables =
- partialEvaluator.getVariablesBefore(consumerOffset);
+ InstructionOffsetValue producerOffsets =
+ partialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
- // Mark the producer of the loaded value.
- markVariableProducers(tracedVariables.getProducerValue(variableIndex).instructionOffsetValue(),
- variableIndex);
+ if (producerOffsets != null)
+ {
+ int offsetCount = producerOffsets.instructionOffsetCount();
+ for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
+ {
+ // Make sure the variable and the instruction are marked
+ // at the producing offset.
+ int offset = producerOffsets.instructionOffset(offsetIndex);
+
+ markInstruction(offset);
+ }
+ }
}
/**
- * Marks the variable and its producing instructions at the given offsets.
- * @param producerOffsets the offsets of the producers to be marked.
- * @param variableIndex the index of the variable to be marked.
+ * Marks the initializing instructions of the variable consumer at the given
+ * offset.
+ * @param consumerOffset the offset of the variable consumer.
+ * @param variableIndex the index of the variable that is loaded.
*/
- private void markVariableProducers(InstructionOffsetValue producerOffsets,
- int variableIndex)
+ private void markVariableInitializers(int consumerOffset,
+ int variableIndex)
{
+ InstructionOffsetValue producerOffsets =
+ simplePartialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
+
if (producerOffsets != null)
{
int offsetCount = producerOffsets.instructionOffsetCount();
@@ -859,8 +1454,15 @@ implements AttributeVisitor
// at the producing offset.
int offset = producerOffsets.instructionOffset(offsetIndex);
- markVariableAfter(offset, variableIndex);
- markInstruction(offset);
+ if (!isInstructionNecessary(offset) &&
+ isVariableInitialization(offset, variableIndex))
+ {
+ if (DEBUG) System.out.print(" Marking initialization of v"+variableIndex+" at ");
+
+ markInstruction(offset);
+
+ if (DEBUG) System.out.println();
+ }
}
}
}
@@ -877,9 +1479,14 @@ implements AttributeVisitor
int consumerOffset,
Instruction consumer)
{
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(consumerOffset);
+
+ int stackSize = tracedStack.size();
+
// Mark the producers of the popped values.
int popCount = consumer.stackPopCount(clazz);
- for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
markStackEntryProducers(consumerOffset, stackIndex);
}
@@ -891,20 +1498,22 @@ implements AttributeVisitor
* of the consumer at the given offset, if the stack entry of the
* consumer is marked.
* @param consumerOffset the offset of the consumer.
- * @param consumerStackIndex the index of the stack entry to be checked
+ * @param consumerTopStackIndex the index of the stack entry to be checked
* (counting from the top).
- * @param producerStackIndex the index of the stack entry to be marked
+ * @param producerTopStackIndex the index of the stack entry to be marked
* (counting from the top).
*/
private void conditionallyMarkStackEntryProducers(int consumerOffset,
- int consumerStackIndex,
- int producerStackIndex)
+ int consumerTopStackIndex,
+ int producerTopStackIndex)
{
- int top = partialEvaluator.getStackAfter(consumerOffset).size() - 1;
+ int consumerBottomStackIndex = partialEvaluator.getStackAfter(consumerOffset).size() - consumerTopStackIndex - 1;
- if (isStackEntryNecessaryAfter(consumerOffset, top - consumerStackIndex))
+ if (isStackEntryNecessaryAfter(consumerOffset, consumerBottomStackIndex))
{
- markStackEntryProducers(consumerOffset, producerStackIndex);
+ int producerBottomStackIndex = partialEvaluator.getStackBefore(consumerOffset).size() - producerTopStackIndex - 1;
+
+ markStackEntryProducers(consumerOffset, producerBottomStackIndex);
}
}
@@ -914,20 +1523,15 @@ implements AttributeVisitor
* of the consumer at the given offset.
* @param consumerOffset the offset of the consumer.
* @param stackIndex the index of the stack entry to be marked
- * (counting from the top).
+ * (counting from the bottom).
*/
private void markStackEntryProducers(int consumerOffset,
int stackIndex)
{
- TracedStack tracedStack =
- partialEvaluator.getStackBefore(consumerOffset);
-
- int stackBottomIndex = tracedStack.size() - 1 - stackIndex;
-
- if (!isStackSimplifiedBefore(consumerOffset, stackBottomIndex))
+ if (!isStackSimplifiedBefore(consumerOffset, stackIndex))
{
- markStackEntryProducers(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(),
- stackBottomIndex);
+ markStackEntryProducers(partialEvaluator.getStackBefore(consumerOffset).getBottomProducerValue(stackIndex).instructionOffsetValue(),
+ stackIndex);
}
}
@@ -1036,244 +1640,6 @@ implements AttributeVisitor
/**
- * Marks the specified instruction if it is a required dup/swap instruction,
- * replacing it by an appropriate variant if necessary.
- * @param clazz the class that is being checked.
- * @param codeAttribute the code that is being checked.
- * @param dupOffset the offset of the dup/swap instruction.
- * @param instruction the dup/swap instruction.
- */
- private void fixDupInstruction(Clazz clazz,
- CodeAttribute codeAttribute,
- int dupOffset,
- Instruction instruction)
- {
- int top = partialEvaluator.getStackAfter(dupOffset).size() - 1;
-
- byte oldOpcode = instruction.opcode;
- byte newOpcode = 0;
-
- // Simplify the popping instruction if possible.
- switch (oldOpcode)
- {
- case InstructionConstants.OP_DUP:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent1)
- {
- // Should both the original element and the copy be present?
- if (stackEntryPresent0 &&
- stackEntryPresent1)
- {
- newOpcode = InstructionConstants.OP_DUP;
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP_X1:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent2)
- {
- // Should the copy be present?
- if (stackEntryPresent2)
- {
- // Compute the number of elements to be skipped.
- int skipCount = stackEntryPresent1 ? 1 : 0;
-
- // Should the original element be present?
- if (stackEntryPresent0)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount);
- }
- else if (skipCount == 1)
- {
- // Move the original element.
- newOpcode = InstructionConstants.OP_SWAP;
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP_X2:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, top - 3);
-
- // Should either the original element or the copy be present?
- if (stackEntryPresent0 ||
- stackEntryPresent3)
- {
- // Should the copy be present?
- if (stackEntryPresent3)
- {
- int skipCount = (stackEntryPresent1 ? 1 : 0) +
- (stackEntryPresent2 ? 1 : 0);
-
- // Should the original element be present?
- if (stackEntryPresent0)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP + skipCount);
- }
- else if (skipCount == 1)
- {
- // Move the original element.
- newOpcode = InstructionConstants.OP_SWAP;
- }
- else if (skipCount == 2)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup_x2 instruction moving original element across two elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntriesPresent23 = isStackEntriesNecessaryAfter(dupOffset, top - 2, top - 3);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent23)
- {
- // Should both the original element and the copy be present?
- if (stackEntriesPresent01 &&
- stackEntriesPresent23)
- {
- newOpcode = InstructionConstants.OP_DUP2;
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2_X1:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntriesPresent34 = isStackEntriesNecessaryAfter(dupOffset, top - 3, top - 4);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent34)
- {
- // Should the copy be present?
- if (stackEntriesPresent34)
- {
- int skipCount = stackEntryPresent2 ? 1 : 0;
-
- // Should the original element be present?
- if (stackEntriesPresent01)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount);
- }
- else if (skipCount > 0)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup2_x1 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_DUP2_X2:
- {
- boolean stackEntriesPresent01 = isStackEntriesNecessaryAfter(dupOffset, top - 0, top - 1);
- boolean stackEntryPresent2 = isStackEntryNecessaryAfter(dupOffset, top - 2);
- boolean stackEntryPresent3 = isStackEntryNecessaryAfter(dupOffset, top - 3);
- boolean stackEntriesPresent45 = isStackEntriesNecessaryAfter(dupOffset, top - 4, top - 5);
-
- // Should either the original element or the copy be present?
- if (stackEntriesPresent01 ||
- stackEntriesPresent45)
- {
- // Should the copy be present?
- if (stackEntriesPresent45)
- {
- int skipCount = (stackEntryPresent2 ? 1 : 0) +
- (stackEntryPresent3 ? 1 : 0);
-
- // Should the original element be present?
- if (stackEntriesPresent01)
- {
- // Copy the original element.
- newOpcode = (byte)(InstructionConstants.OP_DUP2 + skipCount);
- }
- else if (skipCount > 0)
- {
- // We can't easily move the original element.
- throw new UnsupportedOperationException("Can't handle dup2_x2 instruction moving original element across "+skipCount+" elements at ["+dupOffset +"]");
- }
- }
- }
- break;
- }
- case InstructionConstants.OP_SWAP:
- {
- boolean stackEntryPresent0 = isStackEntryNecessaryAfter(dupOffset, top - 0);
- boolean stackEntryPresent1 = isStackEntryNecessaryAfter(dupOffset, top - 1);
-
- // Will either element be present?
- if (stackEntryPresent0 ||
- stackEntryPresent1)
- {
- // Will both elements be present?
- if (stackEntryPresent0 &&
- stackEntryPresent1)
- {
- newOpcode = InstructionConstants.OP_SWAP;
- }
- }
- break;
- }
- }
-
- if (newOpcode == 0)
- {
- // Delete the instruction.
- codeAttributeEditor.deleteInstruction(dupOffset);
-
- if (extraDeletedInstructionVisitor != null)
- {
- extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, dupOffset, null);
- }
-
- if (DEBUG) System.out.println(" Marking but deleting instruction "+instruction.toString(dupOffset));
- }
- else if (newOpcode == oldOpcode)
- {
- // Leave the instruction unchanged.
- codeAttributeEditor.undeleteInstruction(dupOffset);
-
- if (DEBUG) System.out.println(" Marking unchanged instruction "+instruction.toString(dupOffset));
- }
- else
- {
- // Replace the instruction.
- Instruction replacementInstruction = new SimpleInstruction(newOpcode);
- codeAttributeEditor.replaceInstruction(dupOffset,
- replacementInstruction);
-
- if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString());
- }
- }
-
-
- /**
* Pushes a specified type of stack entry before or at the given offset.
* The instruction is marked as necessary.
*/
@@ -1445,7 +1811,7 @@ implements AttributeVisitor
// Remember the replacement instruction.
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
- constantInstruction.constantIndex).shrink();
+ constantInstruction.constantIndex);
if (DEBUG) System.out.println(" Replacing by static invocation "+constantInstruction.toString(offset)+" -> "+replacementInstruction.toString());
@@ -1587,22 +1953,6 @@ implements AttributeVisitor
int maxStack = codeAttribute.u2maxStack;
// Create new arrays for storing information at each instruction offset.
- if (variablesNecessaryAfter.length < codeLength ||
- variablesNecessaryAfter[0].length < maxLocals)
- {
- variablesNecessaryAfter = new boolean[codeLength][maxLocals];
- }
- else
- {
- for (int offset = 0; offset < codeLength; offset++)
- {
- for (int index = 0; index < maxLocals; index++)
- {
- variablesNecessaryAfter[offset][index] = false;
- }
- }
- }
-
if (stacksNecessaryAfter.length < codeLength ||
stacksNecessaryAfter[0].length < maxStack)
{
@@ -1612,10 +1962,7 @@ implements AttributeVisitor
{
for (int offset = 0; offset < codeLength; offset++)
{
- for (int index = 0; index < maxStack; index++)
- {
- stacksNecessaryAfter[offset][index] = false;
- }
+ Arrays.fill(stacksNecessaryAfter[offset], 0, maxStack, false);
}
}
@@ -1628,10 +1975,7 @@ implements AttributeVisitor
{
for (int offset = 0; offset < codeLength; offset++)
{
- for (int index = 0; index < maxStack; index++)
- {
- stacksSimplifiedBefore[offset][index] = false;
- }
+ Arrays.fill(stacksSimplifiedBefore[offset], 0, maxStack, false);
}
}
@@ -1641,103 +1985,61 @@ implements AttributeVisitor
}
else
{
- for (int index = 0; index < codeLength; index++)
- {
- instructionsNecessary[index] = false;
- }
+ Arrays.fill(instructionsNecessary, 0, codeLength, false);
}
}
/**
- * Returns whether the given stack entry is present after execution of the
- * instruction at the given offset.
+ * Returns whether the specified variable is initialized at the specified
+ * offset.
*/
- private boolean isStackEntriesNecessaryAfter(int instructionOffset,
- int stackIndex1,
- int stackIndex2)
- {
- boolean present1 = isStackEntryNecessaryAfter(instructionOffset, stackIndex1);
- boolean present2 = isStackEntryNecessaryAfter(instructionOffset, stackIndex2);
-
-// if (present1 ^ present2)
-// {
-// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
-// }
-
- return present1 || present2;
- }
-
-
- /**
- * Returns whether the specified variable must be initialized at the
- * specified offset, according to the verifier of the JVM.
- */
- private boolean isVariableInitializationNecessary(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- int initializationOffset,
- int variableIndex)
+ private boolean isVariableInitialization(int instructionOffset,
+ int variableIndex)
{
- int codeLength = codeAttribute.u4codeLength;
-
- // Is the variable necessary anywhere at all?
- if (isVariableNecessaryAfterAny(0, codeLength, variableIndex))
+ // Wasn't the variable set yet?
+ Value valueBefore = partialEvaluator.getVariablesBefore(instructionOffset).getValue(variableIndex);
+ if (valueBefore == null)
{
- if (DEBUG) System.out.println("Simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
-
- // Lazily compute perform simple partial evaluation, the way the
- // JVM preverifier would do it.
- simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+ return true;
+ }
- if (DEBUG) System.out.println("End of simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
+ // Is the computational type different now?
+ Value valueAfter = partialEvaluator.getVariablesAfter(instructionOffset).getValue(variableIndex);
+ if (valueAfter.computationalType() != valueBefore.computationalType())
+ {
+ return true;
+ }
- // Check if the variable is necessary elsewhere.
- for (int offset = 0; offset < codeLength; offset++)
- {
- if (isInstructionNecessary(offset))
- {
- Value producer = partialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
- if (producer != null)
- {
- Value simpleProducer = simplePartialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
- if (simpleProducer != null)
- {
- InstructionOffsetValue producerOffsets =
- producer.instructionOffsetValue();
- InstructionOffsetValue simpleProducerOffsets =
- simpleProducer.instructionOffsetValue();
-
- // Does the sophisticated partial evaluation have fewer
- // producers than the simple one?
- // And does the simple partial evaluation point to an
- // initialization of the variable?
- if (producerOffsets.instructionOffsetCount() <
- simpleProducerOffsets.instructionOffsetCount() &&
- isVariableNecessaryAfterAny(producerOffsets, variableIndex) &&
- simpleProducerOffsets.contains(initializationOffset))
- {
- // Then the initialization is necessary.
- return true;
- }
- }
- }
- }
- }
+ // Is the reference type different now?
+ if (valueAfter.computationalType() == Value.TYPE_REFERENCE &&
+ (valueAfter.referenceValue().isNull() == Value.ALWAYS ||
+ !valueAfter.referenceValue().getType().equals(valueBefore.referenceValue().getType())))
+ {
+ return true;
}
- return false;
+ // Was the producer an argument (which may be removed)?
+ Value producersBefore = partialEvaluator.getVariablesBefore(instructionOffset).getProducerValue(variableIndex);
+ return producersBefore.instructionOffsetValue().instructionOffsetCount() == 1 &&
+ producersBefore.instructionOffsetValue().instructionOffset(0) == PartialEvaluator.AT_METHOD_ENTRY;
}
- private void markVariableAfter(int instructionOffset,
- int variableIndex)
+ /**
+ * Marks the stack entry after the given offset.
+ * @param instructionOffset the offset of the stack entry to be marked.
+ * @param stackIndex the index of the stack entry to be marked
+ * (counting from the bottom).
+ */
+ private void markStackEntryAfter(int instructionOffset,
+ int stackIndex)
{
- if (!isVariableNecessaryAfter(instructionOffset, variableIndex))
+ if (!isStackEntryNecessaryAfter(instructionOffset, stackIndex))
{
- if (DEBUG) System.out.print("["+instructionOffset+".v"+variableIndex+"],");
+ if (DEBUG) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
- variablesNecessaryAfter[instructionOffset][variableIndex] = true;
+ stacksNecessaryAfter[instructionOffset][stackIndex] = true;
if (maxMarkedOffset < instructionOffset)
{
@@ -1747,73 +2049,74 @@ implements AttributeVisitor
}
+
/**
- * Returns whether the specified variable is ever necessary after any
- * instruction in the specified block.
+ * Returns whether the stack specified entries before the given offset are
+ * present.
*/
- private boolean isVariableNecessaryAfterAny(int startOffset,
- int endOffset,
- int variableIndex)
+ private boolean isStackEntriesPresentBefore(int instructionOffset,
+ int stackIndex1,
+ int stackIndex2)
{
- for (int offset = startOffset; offset < endOffset; offset++)
- {
- if (isVariableNecessaryAfter(offset, variableIndex))
- {
- return true;
- }
- }
+ boolean present1 = isStackEntryPresentBefore(instructionOffset, stackIndex1);
+ boolean present2 = isStackEntryPresentBefore(instructionOffset, stackIndex2);
- return false;
+// if (present1 ^ present2)
+// {
+// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
+// }
+
+ return present1 || present2;
}
/**
- * Returns whether the specified variable is ever necessary after any
- * instruction in the specified set of instructions offsets.
+ * Returns whether the specified stack entry before the given offset is
+ * present.
+ * @param instructionOffset the offset of the stack entry to be checked.
+ * @param stackIndex the index of the stack entry to be checked
+ * (counting from the bottom).
*/
- private boolean isVariableNecessaryAfterAny(InstructionOffsetValue instructionOffsetValue,
- int variableIndex)
+ private boolean isStackEntryPresentBefore(int instructionOffset,
+ int stackIndex)
{
- int count = instructionOffsetValue.instructionOffsetCount();
-
- for (int index = 0; index < count; index++)
- {
- if (isVariableNecessaryAfter(instructionOffsetValue.instructionOffset(index),
- variableIndex))
- {
- return true;
- }
- }
-
- return false;
- }
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(instructionOffset);
+ InstructionOffsetValue producerOffsets =
+ tracedStack.getBottomProducerValue(stackIndex).instructionOffsetValue();
- private boolean isVariableNecessaryAfter(int instructionOffset,
- int variableIndex)
- {
- return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
- variablesNecessaryAfter[instructionOffset][variableIndex];
+ return isAnyStackEntryNecessaryAfter(producerOffsets, stackIndex);
}
- private void markStackEntryAfter(int instructionOffset,
- int stackIndex)
+ /**
+ * Returns whether the stack specified entries after the given offset are
+ * necessary.
+ */
+ private boolean isStackEntriesNecessaryAfter(int instructionOffset,
+ int stackIndex1,
+ int stackIndex2)
{
- if (!isStackEntryNecessaryAfter(instructionOffset, stackIndex))
- {
- if (DEBUG) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
+ boolean present1 = isStackEntryNecessaryAfter(instructionOffset, stackIndex1);
+ boolean present2 = isStackEntryNecessaryAfter(instructionOffset, stackIndex2);
- stacksNecessaryAfter[instructionOffset][stackIndex] = true;
+// if (present1 ^ present2)
+// {
+// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
+// }
- if (maxMarkedOffset < instructionOffset)
- {
- maxMarkedOffset = instructionOffset;
- }
- }
+ return present1 || present2;
}
+ /**
+ * Returns whether any of the stack entries after the given offsets are
+ * necessary.
+ * @param instructionOffsets the offsets of the stack entries to be checked.
+ * @param stackIndex the index of the stack entries to be checked
+ * (counting from the bottom).
+ */
private boolean isAnyStackEntryNecessaryAfter(InstructionOffsetValue instructionOffsets,
int stackIndex)
{
@@ -1831,6 +2134,13 @@ implements AttributeVisitor
}
+ /**
+ * Returns whether the specified stack entry after the given offset is
+ * necessary.
+ * @param instructionOffset the offset of the stack entry to be checked.
+ * @param stackIndex the index of the stack entry to be checked
+ * (counting from the bottom).
+ */
private boolean isStackEntryNecessaryAfter(int instructionOffset,
int stackIndex)
{
@@ -1909,4 +2219,4 @@ implements AttributeVisitor
return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
instructionsNecessary[instructionOffset];
}
-} \ No newline at end of file
+}
diff --git a/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
index 0c3a9c7..e6e73d9 100644
--- a/src/proguard/optimize/evaluation/EvaluationSimplifier.java
+++ b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -43,17 +43,20 @@ extends SimplifiedVisitor
implements AttributeVisitor,
InstructionVisitor
{
+ private static final int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f);
+ private static final long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
+
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = true;
//*/
private final InstructionVisitor extraInstructionVisitor;
private final PartialEvaluator partialEvaluator;
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false);
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true);
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true);
/**
@@ -426,8 +429,9 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
int value = pushedValue.integerValue().value();
- if (value << 16 >> 16 == value)
+ if ((short)value == value)
{
replaceConstantPushInstruction(clazz,
offset,
@@ -442,13 +446,14 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC,
- constantPoolEditor.addIntegerConstant(value)).shrink();
+ constantPoolEditor.addIntegerConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
@@ -459,6 +464,7 @@ implements AttributeVisitor,
instruction,
InstructionConstants.OP_ILOAD,
variableIndex);
+ break;
}
}
}
@@ -492,6 +498,7 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
long value = pushedValue.longValue().value();
if (value == 0L ||
value == 1L)
@@ -509,17 +516,21 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC2_W,
- constantPoolEditor.addLongConstant(value)).shrink();
+ constantPoolEditor.addLongConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
- if (pushedValue.equals(variables.load(variableIndex)))
+ // Note that we have to check the second part as well.
+ if (pushedValue.equals(variables.load(variableIndex)) &&
+ variables.load(variableIndex + 1) != null &&
+ variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
{
replaceVariablePushInstruction(clazz,
offset,
@@ -559,10 +570,12 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
+ // Make sure to distinguish between +0.0 and -0.0.
float value = pushedValue.floatValue().value();
- if (value == 0f ||
- value == 1f ||
- value == 2f)
+ if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
+ value == 1.0f ||
+ value == 2.0f)
{
replaceConstantPushInstruction(clazz,
offset,
@@ -577,13 +590,14 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC,
- constantPoolEditor.addFloatConstant(value)).shrink();
+ constantPoolEditor.addFloatConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
@@ -627,8 +641,10 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
+ // Push a constant instead.
+ // Make sure to distinguish between +0.0 and -0.0.
double value = pushedValue.doubleValue().value();
- if (value == 0.0 ||
+ if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
value == 1.0)
{
replaceConstantPushInstruction(clazz,
@@ -644,17 +660,21 @@ implements AttributeVisitor,
Instruction replacementInstruction =
new ConstantInstruction(InstructionConstants.OP_LDC2_W,
- constantPoolEditor.addDoubleConstant(value)).shrink();
+ constantPoolEditor.addDoubleConstant(value));
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
}
else if (pushedValue.isSpecific())
{
+ // Load an equivalent lower-numbered variable instead, if any.
TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
{
- if (pushedValue.equals(variables.load(variableIndex)))
+ // Note that we have to check the second part as well.
+ if (pushedValue.equals(variables.load(variableIndex)) &&
+ variables.load(variableIndex + 1) != null &&
+ variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
{
replaceVariablePushInstruction(clazz,
offset,
@@ -699,7 +719,7 @@ implements AttributeVisitor,
int value)
{
Instruction replacementInstruction =
- new SimpleInstruction(replacementOpcode, value).shrink();
+ new SimpleInstruction(replacementOpcode, value);
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
@@ -716,7 +736,7 @@ implements AttributeVisitor,
int variableIndex)
{
Instruction replacementInstruction =
- new VariableInstruction(replacementOpcode, variableIndex).shrink();
+ new VariableInstruction(replacementOpcode, variableIndex);
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
@@ -794,8 +814,8 @@ implements AttributeVisitor,
{
// Replace the branch instruction by a simple branch instruction.
Instruction replacementInstruction =
- new BranchInstruction(InstructionConstants.OP_GOTO_W,
- branchOffset).shrink();
+ new BranchInstruction(InstructionConstants.OP_GOTO,
+ branchOffset);
replaceInstruction(clazz, offset, instruction, replacementInstruction);
}
diff --git a/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
index 9915027..5ce8ccb 100644
--- a/src/proguard/optimize/evaluation/LivenessAnalyzer.java
+++ b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -79,6 +79,16 @@ implements AttributeVisitor,
/**
+ * Returns whether the instruction at the given offset has ever been
+ * executed during the partial evaluation.
+ */
+ public boolean isTraced(int instructionOffset)
+ {
+ return partialEvaluator.isTraced(instructionOffset);
+ }
+
+
+ /**
* Returns whether the specified variable is alive before the instruction
* at the given offset.
*/
diff --git a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
index 8379c57..d6baa67 100644
--- a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -35,9 +35,9 @@ import proguard.evaluation.value.*;
public class LoadingInvocationUnit
extends BasicInvocationUnit
{
- private boolean loadFieldValues;
- private boolean loadMethodParameterValues;
- private boolean loadMethodReturnValues;
+ private final boolean loadFieldValues;
+ private final boolean loadMethodParameterValues;
+ private final boolean loadMethodReturnValues;
/**
@@ -84,8 +84,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
}
@@ -110,8 +108,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
}
@@ -134,8 +130,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
@@ -163,8 +157,6 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
-// // Make sure the value is refreshed.
-// return refresh(value);
}
}
}
@@ -173,8 +165,8 @@ extends BasicInvocationUnit
refConstant,
type);
}
-//
-//
+
+
// // Small utility methods.
//
// private Value refresh(Value value)
diff --git a/src/proguard/optimize/evaluation/PartialEvaluator.java b/src/proguard/optimize/evaluation/PartialEvaluator.java
index 5790a36..6a5bedf 100644
--- a/src/proguard/optimize/evaluation/PartialEvaluator.java
+++ b/src/proguard/optimize/evaluation/PartialEvaluator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -31,6 +31,8 @@ import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.peephole.BranchTargetFinder;
+import java.util.Arrays;
+
/**
* This AttributeVisitor performs partial evaluation on the code attributes
* that it visits.
@@ -68,7 +70,6 @@ implements AttributeVisitor,
private TracedStack[] stacksAfter = new TracedStack[ClassConstants.TYPICAL_CODE_LENGTH];
private boolean[] generalizedContexts = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
private int[] evaluationCounts = new int[ClassConstants.TYPICAL_CODE_LENGTH];
- private int[] initializedVariables = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private boolean evaluateExceptions;
private final BasicBranchUnit branchUnit;
@@ -189,6 +190,47 @@ implements AttributeVisitor,
if (DEBUG)
{
method.accept(clazz, new ClassPrinter());
+
+ System.out.println("Evaluation results:");
+
+ int offset = 0;
+ do
+ {
+ if (isBranchOrExceptionTarget(offset))
+ {
+ System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
+ if (isTraced(offset))
+ {
+ System.out.println(" Vars: "+variablesBefore[offset]);
+ System.out.println(" Stack: "+stacksBefore[offset]);
+ }
+ }
+
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+ System.out.println(instruction.toString(offset));
+
+ if (isTraced(offset))
+ {
+ int initializationOffset = branchTargetFinder.initializationOffset(offset);
+ if (initializationOffset != NONE)
+ {
+ System.out.println(" is to be initialized at ["+initializationOffset+"]");
+ }
+
+ InstructionOffsetValue branchTargets = branchTargets(offset);
+ if (branchTargets != null)
+ {
+ System.out.println(" has overall been branching to "+branchTargets);
+ }
+
+ System.out.println(" Vars: "+variablesAfter[offset]);
+ System.out.println(" Stack: "+stacksAfter[offset]);
+ }
+
+ offset += instruction.length(offset);
+ }
+ while (offset < codeAttribute.u4codeLength);
}
throw ex;
@@ -212,7 +254,8 @@ implements AttributeVisitor,
TracedStack stack = new TracedStack(codeAttribute.u2maxStack);
// Initialize the reusable arrays and variables.
- initializeVariables(clazz, method, codeAttribute, variables, stack);
+ initializeArrays(codeAttribute);
+ initializeParameters(clazz, method, codeAttribute, variables);
// Find all instruction offsets,...
codeAttribute.accept(clazz, method, branchTargetFinder);
@@ -249,12 +292,6 @@ implements AttributeVisitor,
if (isTraced(offset))
{
- int variableIndex = initializedVariable(offset);
- if (variableIndex >= 0)
- {
- System.out.println(" is initializing variable v"+variableIndex);
- }
-
int initializationOffset = branchTargetFinder.initializationOffset(offset);
if (initializationOffset != NONE)
{
@@ -479,16 +516,6 @@ implements AttributeVisitor,
}
- /**
- * Returns the variable that is initialized at the given instruction offset,
- * or <code>NONE</code> if no variable was initialized.
- */
- public int initializedVariable(int instructionOffset)
- {
- return initializedVariables[instructionOffset];
- }
-
-
// Utility methods to evaluate instruction blocks.
/**
@@ -702,9 +729,6 @@ implements AttributeVisitor,
// Reset the trace value.
InstructionOffsetValue traceValue = InstructionOffsetValue.EMPTY_VALUE;
- // Reset the initialization flag.
- variables.resetInitialization();
-
// Note that the instruction is only volatile.
Instruction instruction = InstructionFactory.create(code, instructionOffset);
@@ -743,9 +767,6 @@ implements AttributeVisitor,
throw ex;
}
- // Collect the offsets of the instructions whose results were used.
- initializedVariables[instructionOffset] = variables.getInitializationIndex();
-
// Collect the branch targets from the branch unit.
InstructionOffsetValue branchTargets = branchUnit.getTraceBranchTargets();
int branchTargetCount = branchTargets.instructionOffsetCount();
@@ -844,8 +865,7 @@ implements AttributeVisitor,
if (instruction.opcode == InstructionConstants.OP_JSR ||
instruction.opcode == InstructionConstants.OP_JSR_W)
{
- // Evaluate the subroutine, possibly in another partial
- // evaluator.
+ // Evaluate the subroutine in another partial evaluator.
evaluateSubroutine(clazz,
method,
codeAttribute,
@@ -887,21 +907,13 @@ implements AttributeVisitor,
if (DEBUG) System.out.println("Evaluating subroutine from "+subroutineStart+" to "+subroutineEnd);
- PartialEvaluator subroutinePartialEvaluator = this;
-
- // Create a temporary partial evaluator if necessary.
- if (evaluationCounts[subroutineStart] > 0)
- {
- if (DEBUG) System.out.println("Creating new partial evaluator for subroutine");
-
- subroutinePartialEvaluator = new PartialEvaluator(this);
+ // Create a temporary partial evaluator, so there are no conflicts
+ // with variables that are alive across subroutine invocations, between
+ // different invocations.
+ PartialEvaluator subroutinePartialEvaluator =
+ new PartialEvaluator(this);
- subroutinePartialEvaluator.initializeVariables(clazz,
- method,
- codeAttribute,
- variables,
- stack);
- }
+ subroutinePartialEvaluator.initializeArrays(codeAttribute);
// Evaluate the subroutine.
subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz,
@@ -912,11 +924,9 @@ implements AttributeVisitor,
subroutineStart,
subroutineEnd);
- // Merge back the temporary partial evaluator if necessary.
- if (subroutinePartialEvaluator != this)
- {
- generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
- }
+ // Merge back the temporary partial evaluator. This way, we'll get
+ // the lowest common denominator of stacks and variables.
+ generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
if (DEBUG) System.out.println("Ending subroutine from "+subroutineStart+" to "+subroutineEnd);
}
@@ -952,13 +962,12 @@ implements AttributeVisitor,
if (evaluationCounts[offset] == 0)
{
- variablesBefore[offset] = other.variablesBefore[offset];
- stacksBefore[offset] = other.stacksBefore[offset];
- variablesAfter[offset] = other.variablesAfter[offset];
- stacksAfter[offset] = other.stacksAfter[offset];
- generalizedContexts[offset] = other.generalizedContexts[offset];
- evaluationCounts[offset] = other.evaluationCounts[offset];
- initializedVariables[offset] = other.initializedVariables[offset];
+ variablesBefore[offset] = other.variablesBefore[offset];
+ stacksBefore[offset] = other.stacksBefore[offset];
+ variablesAfter[offset] = other.variablesAfter[offset];
+ stacksAfter[offset] = other.stacksAfter[offset];
+ generalizedContexts[offset] = other.generalizedContexts[offset];
+ evaluationCounts[offset] = other.evaluationCounts[offset];
}
else
{
@@ -968,7 +977,6 @@ implements AttributeVisitor,
stacksAfter[offset] .generalize(other.stacksAfter[offset]);
//generalizedContexts[offset]
evaluationCounts[offset] += other.evaluationCounts[offset];
- //initializedVariables[offset]
}
}
}
@@ -1094,11 +1102,7 @@ implements AttributeVisitor,
/**
* Initializes the data structures for the variables, stack, etc.
*/
- private void initializeVariables(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- TracedVariables variables,
- TracedStack stack)
+ private void initializeArrays(CodeAttribute codeAttribute)
{
int codeLength = codeAttribute.u4codeLength;
@@ -1106,33 +1110,25 @@ implements AttributeVisitor,
if (variablesAfter.length < codeLength)
{
// Create new arrays.
- branchOriginValues = new InstructionOffsetValue[codeLength];
- branchTargetValues = new InstructionOffsetValue[codeLength];
- variablesBefore = new TracedVariables[codeLength];
- stacksBefore = new TracedStack[codeLength];
- variablesAfter = new TracedVariables[codeLength];
- stacksAfter = new TracedStack[codeLength];
- generalizedContexts = new boolean[codeLength];
- evaluationCounts = new int[codeLength];
- initializedVariables = new int[codeLength];
-
- // Reset the arrays.
- for (int index = 0; index < codeLength; index++)
- {
- initializedVariables[index] = NONE;
- }
+ branchOriginValues = new InstructionOffsetValue[codeLength];
+ branchTargetValues = new InstructionOffsetValue[codeLength];
+ variablesBefore = new TracedVariables[codeLength];
+ stacksBefore = new TracedStack[codeLength];
+ variablesAfter = new TracedVariables[codeLength];
+ stacksAfter = new TracedStack[codeLength];
+ generalizedContexts = new boolean[codeLength];
+ evaluationCounts = new int[codeLength];
}
else
{
// Reset the arrays.
+ Arrays.fill(branchOriginValues, null);
+ Arrays.fill(branchTargetValues, null);
+ Arrays.fill(generalizedContexts, false);
+ Arrays.fill(evaluationCounts, 0);
+
for (int index = 0; index < codeLength; index++)
{
- branchOriginValues[index] = null;
- branchTargetValues[index] = null;
- generalizedContexts[index] = false;
- evaluationCounts[index] = 0;
- initializedVariables[index] = NONE;
-
if (variablesBefore[index] != null)
{
variablesBefore[index].reset(codeAttribute.u2maxLocals);
@@ -1154,7 +1150,17 @@ implements AttributeVisitor,
}
}
}
+ }
+
+ /**
+ * Initializes the data structures for the variables, stack, etc.
+ */
+ private void initializeParameters(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables)
+ {
// Create the method parameters.
TracedVariables parameters = new TracedVariables(codeAttribute.u2maxLocals);
diff --git a/src/proguard/optimize/evaluation/StoringInvocationUnit.java b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
index bcbb69f..846f685 100644
--- a/src/proguard/optimize/evaluation/StoringInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/TracedBranchUnit.java b/src/proguard/optimize/evaluation/TracedBranchUnit.java
index fa5bb79..e6acf6f 100644
--- a/src/proguard/optimize/evaluation/TracedBranchUnit.java
+++ b/src/proguard/optimize/evaluation/TracedBranchUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/VariableOptimizer.java b/src/proguard/optimize/evaluation/VariableOptimizer.java
index b3ae81c..73efddc 100644
--- a/src/proguard/optimize/evaluation/VariableOptimizer.java
+++ b/src/proguard/optimize/evaluation/VariableOptimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,10 +21,10 @@
package proguard.optimize.evaluation;
import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.editor.*;
import proguard.classfile.visitor.MemberVisitor;
import proguard.classfile.attribute.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.editor.VariableRemapper;
import proguard.classfile.util.*;
/**
@@ -35,7 +35,9 @@ import proguard.classfile.util.*;
*/
public class VariableOptimizer
extends SimplifiedVisitor
-implements AttributeVisitor
+implements AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor
{
//*
private static final boolean DEBUG = false;
@@ -51,6 +53,7 @@ implements AttributeVisitor
private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
private final VariableRemapper variableRemapper = new VariableRemapper();
+ private VariableCleaner variableCleaner = new VariableCleaner();
private int[] variableMap = new int[ClassConstants.TYPICAL_VARIABLES_SIZE];
@@ -101,6 +104,11 @@ implements AttributeVisitor
// Analyze the liveness of the variables in the code.
livenessAnalyzer.visitCodeAttribute(clazz, method, codeAttribute);
+ // Trim the variables in the local variable tables, because even
+ // clipping the tables individually may leave some inconsistencies
+ // between them.
+ codeAttribute.attributesAccept(clazz, method, this);
+
int startIndex =
(method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ||
reuseThis ? 0 : 1;
@@ -142,23 +150,19 @@ implements AttributeVisitor
}
}
- // Remap the variables.
+ // Have we been able to remap any variables?
if (remapping)
{
if (DEBUG)
{
- System.out.println("Remapping variables:");
- System.out.println(" Class "+ ClassUtil.externalClassName(clazz.getName()));
- System.out.println(" Method "+ClassUtil.externalFullMethodDescription(clazz.getName(),
- 0,
- method.getName(clazz),
- method.getDescriptor(clazz)));
- for (int index = 0; index < variableSize; index++)
+ System.out.println("VariableOptimizer: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ for (int index= 0; index < variableSize; index++)
{
- System.out.println(" ["+index+"] -> ["+variableMap[index]+"]");
+ System.out.println(" v"+index+" -> "+variableMap[index]);
}
}
+ // Remap the variables.
variableRemapper.setVariableMap(variableMap);
variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
@@ -168,6 +172,71 @@ implements AttributeVisitor
method.accept(clazz, extraVariableMemberVisitor);
}
}
+ else
+ {
+ // Just clean up any empty variables.
+ variableCleaner.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Trim the variables in the local variable table.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Trim the variables in the local variable type table.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Trim the local variable to the instructions at which it is alive.
+ int variable = localVariableInfo.u2index;
+ int startPC = localVariableInfo.u2startPC;
+ int endPC = startPC + localVariableInfo.u2length;
+
+ startPC = firstLiveness(startPC, endPC, variable);
+ endPC = lastLiveness(startPC, endPC, variable);
+
+ // Leave the start address of unused variables unchanged.
+ int length = endPC - startPC;
+ if (length > 0)
+ {
+ localVariableInfo.u2startPC = startPC;
+ }
+
+ localVariableInfo.u2length = length;
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Trim the local variable type to the instructions at which it is alive.
+ int variable = localVariableTypeInfo.u2index;
+ int startPC = localVariableTypeInfo.u2startPC;
+ int endPC = startPC + localVariableTypeInfo.u2length;
+
+ startPC = firstLiveness(startPC, endPC, variable);
+ endPC = lastLiveness(startPC, endPC, variable);
+
+ // Leave the start address of unused variables unchanged.
+ int length = endPC - startPC;
+ if (length > 0)
+ {
+ localVariableTypeInfo.u2startPC = startPC;
+ }
+
+ localVariableTypeInfo.u2length = length;
}
@@ -241,4 +310,48 @@ implements AttributeVisitor
}
}
}
+
+
+ /**
+ * Returns the first instruction offset between the given offsets at which
+ * the given variable goes alive.
+ */
+ private int firstLiveness(int startOffset, int endOffset, int variableIndex)
+ {
+ for (int offset = startOffset; offset < endOffset; offset++)
+ {
+ if (livenessAnalyzer.isTraced(offset) &&
+ livenessAnalyzer.isAliveBefore(offset, variableIndex))
+ {
+ return offset;
+ }
+ }
+
+ return endOffset;
+ }
+
+
+ /**
+ * Returns the last instruction offset between the given offsets before
+ * which the given variable is still alive.
+ */
+ private int lastLiveness(int startOffset, int endOffset, int variableIndex)
+ {
+ int previousOffset = endOffset;
+
+ for (int offset = endOffset-1; offset >= startOffset; offset--)
+ {
+ if (livenessAnalyzer.isTraced(offset))
+ {
+ if (livenessAnalyzer.isAliveBefore(offset, variableIndex))
+ {
+ return previousOffset;
+ }
+
+ previousOffset = offset;
+ }
+ }
+
+ return endOffset;
+ }
}
diff --git a/src/proguard/optimize/info/AccessMethodMarker.java b/src/proguard/optimize/info/AccessMethodMarker.java
index 6965cec..e4c8d7c 100644
--- a/src/proguard/optimize/info/AccessMethodMarker.java
+++ b/src/proguard/optimize/info/AccessMethodMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,7 +21,8 @@
package proguard.optimize.info;
import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
@@ -71,6 +72,20 @@ implements InstructionVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Check the bootstrap method.
+ invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the method reference.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
// Check the referenced class.
diff --git a/src/proguard/optimize/info/BackwardBranchMarker.java b/src/proguard/optimize/info/BackwardBranchMarker.java
index 9e09b0f..07bfefb 100644
--- a/src/proguard/optimize/info/BackwardBranchMarker.java
+++ b/src/proguard/optimize/info/BackwardBranchMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/CatchExceptionMarker.java b/src/proguard/optimize/info/CatchExceptionMarker.java
index 3f2a06f..8f87a08 100644
--- a/src/proguard/optimize/info/CatchExceptionMarker.java
+++ b/src/proguard/optimize/info/CatchExceptionMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/CaughtClassFilter.java b/src/proguard/optimize/info/CaughtClassFilter.java
index 5e17763..762e7de 100644
--- a/src/proguard/optimize/info/CaughtClassFilter.java
+++ b/src/proguard/optimize/info/CaughtClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/CaughtClassMarker.java b/src/proguard/optimize/info/CaughtClassMarker.java
index 0cc350e..1752f0c 100644
--- a/src/proguard/optimize/info/CaughtClassMarker.java
+++ b/src/proguard/optimize/info/CaughtClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,8 +25,9 @@ import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
/**
- * This InstructionVisitor marks all classes that are used in an 'instanceof'
- * test by any of the instructions that it visits.
+ * This ClassVisitor marks all program classes that it visits as caught.
+ * This means that these classes are exception classes that occur in exception
+ * handlers.
*
* @author Eric Lafortune
*/
diff --git a/src/proguard/optimize/info/ClassOptimizationInfo.java b/src/proguard/optimize/info/ClassOptimizationInfo.java
index 99b6e7b..dbe041e 100644
--- a/src/proguard/optimize/info/ClassOptimizationInfo.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -34,6 +34,7 @@ public class ClassOptimizationInfo
private boolean isInstanceofed = false;
private boolean isDotClassed = false;
private boolean isCaught = false;
+ private boolean containsStaticInitializer = false;
private boolean containsPackageVisibleMembers = false;
private boolean invokesPackageVisibleMembers = false;
private Clazz targetClass;
@@ -87,6 +88,18 @@ public class ClassOptimizationInfo
}
+ public void setContainsStaticInitializer()
+ {
+ containsStaticInitializer = true;
+ }
+
+
+ public boolean containsStaticInitializer()
+ {
+ return containsStaticInitializer;
+ }
+
+
public void setContainsPackageVisibleMembers()
{
containsPackageVisibleMembers = true;
@@ -129,6 +142,7 @@ public class ClassOptimizationInfo
this.isInstanceofed |= other.isInstanceofed;
this.isDotClassed |= other.isDotClassed;
this.isCaught |= other.isCaught;
+ this.containsStaticInitializer |= other.containsStaticInitializer;
this.containsPackageVisibleMembers |= other.containsPackageVisibleMembers;
this.invokesPackageVisibleMembers |= other.invokesPackageVisibleMembers;
}
diff --git a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
index 9cb167c..f3d78e2 100644
--- a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/DotClassFilter.java b/src/proguard/optimize/info/DotClassFilter.java
index 8cbe7f0..c3fd878 100644
--- a/src/proguard/optimize/info/DotClassFilter.java
+++ b/src/proguard/optimize/info/DotClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/DotClassMarker.java b/src/proguard/optimize/info/DotClassMarker.java
index b5f12a7..ef5cfd1 100644
--- a/src/proguard/optimize/info/DotClassMarker.java
+++ b/src/proguard/optimize/info/DotClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/ExceptionInstructionChecker.java b/src/proguard/optimize/info/ExceptionInstructionChecker.java
index 2792d90..4bfa96f 100644
--- a/src/proguard/optimize/info/ExceptionInstructionChecker.java
+++ b/src/proguard/optimize/info/ExceptionInstructionChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -67,34 +67,39 @@ implements InstructionVisitor
byte opcode = simpleInstruction.opcode;
// Check for instructions that may throw exceptions.
- if (opcode == InstructionConstants.OP_IDIV ||
- opcode == InstructionConstants.OP_LDIV ||
- opcode == InstructionConstants.OP_IREM ||
- opcode == InstructionConstants.OP_LREM ||
- opcode == InstructionConstants.OP_IALOAD ||
- opcode == InstructionConstants.OP_LALOAD ||
- opcode == InstructionConstants.OP_FALOAD ||
- opcode == InstructionConstants.OP_DALOAD ||
- opcode == InstructionConstants.OP_AALOAD ||
- opcode == InstructionConstants.OP_BALOAD ||
- opcode == InstructionConstants.OP_CALOAD ||
- opcode == InstructionConstants.OP_SALOAD ||
- opcode == InstructionConstants.OP_IASTORE ||
- opcode == InstructionConstants.OP_LASTORE ||
- opcode == InstructionConstants.OP_FASTORE ||
- opcode == InstructionConstants.OP_DASTORE ||
- opcode == InstructionConstants.OP_AASTORE ||
- opcode == InstructionConstants.OP_BASTORE ||
- opcode == InstructionConstants.OP_CASTORE ||
- opcode == InstructionConstants.OP_SASTORE ||
- opcode == InstructionConstants.OP_NEWARRAY ||
- opcode == InstructionConstants.OP_ARRAYLENGTH ||
- opcode == InstructionConstants.OP_ATHROW ||
- opcode == InstructionConstants.OP_MONITORENTER ||
- opcode == InstructionConstants.OP_MONITOREXIT)
+ // Note that monitorexit can not sensibly throw exceptions, except the
+ // broken and deprecated asynchronous ThreadDeath. Removing the
+ // artificial infinite looping exception blocks that recent compilers
+ // add does not strictly follow the JVM specs, but it does have the
+ // additional benefit of avoiding a bug in the JVM in JDK 1.1.
+ switch (opcode)
{
- // These instructions may throw exceptions.
- mayThrowExceptions = true;
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_NEWARRAY:
+ case InstructionConstants.OP_ARRAYLENGTH:
+ case InstructionConstants.OP_ATHROW:
+ case InstructionConstants.OP_MONITORENTER:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
}
}
@@ -105,31 +110,32 @@ implements InstructionVisitor
byte opcode = constantInstruction.opcode;
// Check for instructions that may throw exceptions.
- if (opcode == InstructionConstants.OP_GETSTATIC ||
- opcode == InstructionConstants.OP_PUTSTATIC ||
- opcode == InstructionConstants.OP_GETFIELD ||
- opcode == InstructionConstants.OP_PUTFIELD ||
- opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
- opcode == InstructionConstants.OP_INVOKESPECIAL ||
- opcode == InstructionConstants.OP_INVOKESTATIC ||
- opcode == InstructionConstants.OP_INVOKEINTERFACE ||
- opcode == InstructionConstants.OP_NEW ||
- opcode == InstructionConstants.OP_ANEWARRAY ||
- opcode == InstructionConstants.OP_CHECKCAST ||
- opcode == InstructionConstants.OP_MULTIANEWARRAY)
+ switch (opcode)
{
- // These instructions may throw exceptions.
- mayThrowExceptions = true;
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ case InstructionConstants.OP_NEW:
+ case InstructionConstants.OP_ANEWARRAY:
+ case InstructionConstants.OP_CHECKCAST:
+ case InstructionConstants.OP_INSTANCEOF:
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
}
-// else
-// if (opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
-// opcode == InstructionConstants.OP_INVOKESPECIAL ||
-// opcode == InstructionConstants.OP_INVOKESTATIC ||
-// opcode == InstructionConstants.OP_INVOKEINTERFACE)
-// {
+
+// case InstructionConstants.OP_INVOKEVIRTUAL:
+// case InstructionConstants.OP_INVOKESPECIAL:
+// case InstructionConstants.OP_INVOKESTATIC:
+// case InstructionConstants.OP_INVOKEINTERFACE:
// // Check if the invoking the method may throw an exception.
// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
-// }
}
diff --git a/src/proguard/optimize/info/FieldOptimizationInfo.java b/src/proguard/optimize/info/FieldOptimizationInfo.java
index 7a2d068..0fa9167 100644
--- a/src/proguard/optimize/info/FieldOptimizationInfo.java
+++ b/src/proguard/optimize/info/FieldOptimizationInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,8 +21,11 @@
package proguard.optimize.info;
import proguard.classfile.*;
-import proguard.classfile.util.MethodLinker;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.*;
import proguard.evaluation.value.*;
+import proguard.evaluation.ConstantValueFactory;
/**
* This class stores some optimization information that can be attached to
@@ -31,8 +34,11 @@ import proguard.evaluation.value.*;
* @author Eric Lafortune
*/
public class FieldOptimizationInfo
+extends SimplifiedVisitor
+implements AttributeVisitor
{
- private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory();
+ private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory();
+ private static final ConstantValueFactory CONSTANT_VALUE_FACTORY = new ConstantValueFactory(VALUE_FACTORY);
private boolean isWritten;
private boolean isRead;
@@ -43,9 +49,33 @@ public class FieldOptimizationInfo
public FieldOptimizationInfo(Clazz clazz, Field field)
{
+ int accessFlags = field.getAccessFlags();
+
isWritten =
- isRead = (field.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0;
- value = initialValue(field.getDescriptor(clazz));
+ isRead = (accessFlags & ClassConstants.INTERNAL_ACC_VOLATILE) != 0;
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0)
+ {
+ // See if we can initialize the static field with a constant value.
+ field.accept(clazz, new AllAttributeVisitor(this));
+ }
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) == 0 &&
+ value == null)
+ {
+ // Otherwise initialize the non-final field with the default value.
+ value = initialValue(field.getDescriptor(clazz));
+ }
+ }
+
+
+ public FieldOptimizationInfo(FieldOptimizationInfo FieldOptimizationInfo)
+ {
+ this.isWritten = FieldOptimizationInfo.isWritten;
+ this.isRead = FieldOptimizationInfo.isRead;
+ this.canBeMadePrivate = FieldOptimizationInfo.canBeMadePrivate;
+ this.referencedClass = FieldOptimizationInfo.referencedClass;
+ this.value = FieldOptimizationInfo.value;
}
@@ -113,6 +143,18 @@ public class FieldOptimizationInfo
}
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ // Retrieve the initial static field value.
+ value = CONSTANT_VALUE_FACTORY.constantValue(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
// Small utility methods.
private Value initialValue(String type)
@@ -147,13 +189,13 @@ public class FieldOptimizationInfo
public static void setFieldOptimizationInfo(Clazz clazz, Field field)
{
- MethodLinker.lastMember(field).setVisitorInfo(new FieldOptimizationInfo(clazz, field));
+ field.setVisitorInfo(new FieldOptimizationInfo(clazz, field));
}
public static FieldOptimizationInfo getFieldOptimizationInfo(Field field)
{
- Object visitorInfo = MethodLinker.lastMember(field).getVisitorInfo();
+ Object visitorInfo = field.getVisitorInfo();
return visitorInfo instanceof FieldOptimizationInfo ?
(FieldOptimizationInfo)visitorInfo :
diff --git a/src/proguard/optimize/info/InstanceofClassFilter.java b/src/proguard/optimize/info/InstanceofClassFilter.java
index 35e1d77..7cd85bc 100644
--- a/src/proguard/optimize/info/InstanceofClassFilter.java
+++ b/src/proguard/optimize/info/InstanceofClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/InstanceofClassMarker.java b/src/proguard/optimize/info/InstanceofClassMarker.java
index c60e1f8..96d5baf 100644
--- a/src/proguard/optimize/info/InstanceofClassMarker.java
+++ b/src/proguard/optimize/info/InstanceofClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/InstantiationClassFilter.java b/src/proguard/optimize/info/InstantiationClassFilter.java
index a24e617..a659f06 100644
--- a/src/proguard/optimize/info/InstantiationClassFilter.java
+++ b/src/proguard/optimize/info/InstantiationClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/InstantiationClassMarker.java b/src/proguard/optimize/info/InstantiationClassMarker.java
index 124c23b..b4afffd 100644
--- a/src/proguard/optimize/info/InstantiationClassMarker.java
+++ b/src/proguard/optimize/info/InstantiationClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
index a170a8e..3c27c93 100644
--- a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -38,22 +38,22 @@ implements MemberVisitor
{
// Implementations for MemberVisitor.
- public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- if (!KeepMarker.isKept(programMethod))
+ if (!KeepMarker.isKept(programField))
{
- MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
- programMethod);
+ FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
+ programField);
}
}
- public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- if (!KeepMarker.isKept(programField))
+ if (!KeepMarker.isKept(programMethod))
{
- FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
- programField);
+ MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
+ programMethod);
}
}
}
diff --git a/src/proguard/optimize/info/MethodInvocationMarker.java b/src/proguard/optimize/info/MethodInvocationMarker.java
index 2528c94..afb2336 100644
--- a/src/proguard/optimize/info/MethodInvocationMarker.java
+++ b/src/proguard/optimize/info/MethodInvocationMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/MethodOptimizationInfo.java b/src/proguard/optimize/info/MethodOptimizationInfo.java
index d3b1bde..fe754e5 100644
--- a/src/proguard/optimize/info/MethodOptimizationInfo.java
+++ b/src/proguard/optimize/info/MethodOptimizationInfo.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -204,7 +204,7 @@ public class MethodOptimizationInfo
public void setParameterUsed(int parameterIndex)
{
- usedParameters |= 1 << parameterIndex;
+ usedParameters |= 1L << parameterIndex;
}
@@ -216,7 +216,7 @@ public class MethodOptimizationInfo
public boolean isParameterUsed(int parameterIndex)
{
- return parameterIndex >= 64 || (usedParameters & (1 << parameterIndex)) != 0;
+ return parameterIndex >= 64 || (usedParameters & (1L << parameterIndex)) != 0;
}
diff --git a/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
index 5c78408..bf5ce45 100644
--- a/src/proguard/optimize/info/NoSideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -38,7 +38,7 @@ implements MemberVisitor
{
// A visitor info flag to indicate the visitor accepter is being kept,
// but that it doesn't have any side effects.
- private static final Object KEPT_BUT_NO_SIDE_EFFECTS = new Object();
+ public static final Object KEPT_BUT_NO_SIDE_EFFECTS = new Object();
// Implementations for MemberVisitor.
diff --git a/src/proguard/optimize/info/NonPrivateMemberMarker.java b/src/proguard/optimize/info/NonPrivateMemberMarker.java
index d451643..06f8500 100644
--- a/src/proguard/optimize/info/NonPrivateMemberMarker.java
+++ b/src/proguard/optimize/info/NonPrivateMemberMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -77,15 +77,9 @@ implements ClassVisitor,
public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
{
- Clazz referencedClass = stringConstant.referencedClass;
-
- // Is it refering to another class or class member?
- if (referencedClass != null &&
- !referencedClass.equals(clazz))
- {
- // The referenced class member, if any, can never be made private.
- stringConstant.referencedMemberAccept(this);
- }
+ // The referenced class member, if any, can never be made private,
+ // even if it's in the same class.
+ stringConstant.referencedMemberAccept(this);
}
@@ -93,7 +87,7 @@ implements ClassVisitor,
{
Clazz referencedClass = refConstant.referencedClass;
- // Is it refering to a class member in another class?
+ // Is it referring to a class member in another class?
// The class member might be in another class, or
// it may be referenced through another class.
if (referencedClass != null &&
diff --git a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
index d40bc6b..02e1a18 100644
--- a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
+++ b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,18 +22,36 @@ package proguard.optimize.info;
import proguard.classfile.*;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.MemberVisitor;
+import proguard.classfile.visitor.*;
/**
- * This MemberVisitor marks all classes that contain visited package visible
- * members.
+ * This ClassVisitor marks all classes that contain package visible members.
*
* @author Eric Lafortune
*/
public class PackageVisibleMemberContainingClassMarker
extends SimplifiedVisitor
-implements MemberVisitor
+implements ClassVisitor,
+ MemberVisitor
{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ // Check the class itself.
+ if ((clazz.getAccessFlags() & ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
+ {
+ setPackageVisibleMembers(clazz);
+ }
+ else
+ {
+ // Check the members.
+ clazz.fieldsAccept(this);
+ clazz.methodsAccept(this);
+ }
+ }
+
+
// Implementations for MemberVisitor.
public void visitAnyMember(Clazz clazz, Member member)
diff --git a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
index 9ec8ec6..3148e3d 100644
--- a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
+++ b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,39 +24,87 @@ import proguard.classfile.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.constant.*;
import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
/**
- * This ConstantVisitor marks all classes that invoke package visible members
- * in other classes.
+ * This ConstantVisitor marks all classes that refer to package visible classes
+ * or class members.
*
* @author Eric Lafortune
*/
public class PackageVisibleMemberInvokingClassMarker
extends SimplifiedVisitor
-implements ConstantVisitor
+implements ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
{
+ private Clazz referencingClass;
+
+
// Implementations for ConstantVisitor.
public void visitAnyConstant(Clazz clazz, Constant constant) {}
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Check the referenced class and class member, if any.
+ if (stringConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ stringConstant.referencedClassAccept(this);
+ stringConstant.referencedMemberAccept(this);
+ }
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
- Clazz referencedClass = refConstant.referencedClass;
- if (referencedClass != null &&
- (referencedClass.getAccessFlags() &
+ // Check the referenced class and class member.
+ if (refConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ refConstant.referencedClassAccept(this);
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check the referenced class.
+ if (classConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ classConstant.referencedClassAccept(this);
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if ((clazz.getAccessFlags() &
ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
{
- setInvokesPackageVisibleMembers(clazz);
+ setInvokesPackageVisibleMembers(referencingClass);
}
+ }
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null &&
- (referencedMember.getAccessFlags() &
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ if ((member.getAccessFlags() &
(ClassConstants.INTERNAL_ACC_PUBLIC |
ClassConstants.INTERNAL_ACC_PRIVATE)) == 0)
{
- setInvokesPackageVisibleMembers(clazz);
+ setInvokesPackageVisibleMembers(referencingClass);
}
}
diff --git a/src/proguard/optimize/info/ParameterUsageMarker.java b/src/proguard/optimize/info/ParameterUsageMarker.java
index 15ce88a..a2a264d 100644
--- a/src/proguard/optimize/info/ParameterUsageMarker.java
+++ b/src/proguard/optimize/info/ParameterUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,14 +21,14 @@
package proguard.optimize.info;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.attribute.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
import proguard.optimize.evaluation.PartialEvaluator;
-import proguard.evaluation.value.*;
/**
* This MemberVisitor counts the parameters and marks the used parameters
diff --git a/src/proguard/optimize/info/ReadWriteFieldMarker.java b/src/proguard/optimize/info/ReadWriteFieldMarker.java
index 57d8561..6bd4b2f 100644
--- a/src/proguard/optimize/info/ReadWriteFieldMarker.java
+++ b/src/proguard/optimize/info/ReadWriteFieldMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/SideEffectInstructionChecker.java b/src/proguard/optimize/info/SideEffectInstructionChecker.java
index 8be9dc1..91f1f02 100644
--- a/src/proguard/optimize/info/SideEffectInstructionChecker.java
+++ b/src/proguard/optimize/info/SideEffectInstructionChecker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,11 +29,14 @@ import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.*;
+import java.util.*;
+
/**
- * This class can tell whether an instruction has any side effects. Return
- * instructions can be included or not.
+ * This class can tell whether an instruction has any side effects outside of
+ * its method. Return instructions can be included or not.
*
* @see ReadWriteFieldMarker
+ * @see StaticInitializerContainingClassMarker
* @see NoSideEffectMethodMarker
* @see SideEffectMethodMarker
* @author Eric Lafortune
@@ -44,23 +47,38 @@ implements InstructionVisitor,
ConstantVisitor,
MemberVisitor
{
+ private static final boolean OPTIMIZE_CONSERVATIVELY = System.getProperty("optimize.conservatively") != null;
+
+
private final boolean includeReturnInstructions;
+ private final boolean includeLocalFieldAccess;
// A return value for the visitor methods.
+ private Clazz referencingClass;
private boolean hasSideEffects;
- public SideEffectInstructionChecker(boolean includeReturnInstructions)
+ public SideEffectInstructionChecker(boolean includeReturnInstructions,
+ boolean includeLocalFieldAccess)
{
this.includeReturnInstructions = includeReturnInstructions;
+ this.includeLocalFieldAccess = includeLocalFieldAccess;
}
- public boolean hasSideEffects(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ /**
+ * Returns whether the given instruction has side effects outside of its
+ * method.
+ */
+ public boolean hasSideEffects(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction)
{
hasSideEffects = false;
- instruction.accept(clazz, method, codeAttribute, offset, this);
+ instruction.accept(clazz, method, codeAttribute, offset, this);
return hasSideEffects;
}
@@ -76,29 +94,46 @@ implements InstructionVisitor,
byte opcode = simpleInstruction.opcode;
// Check for instructions that might cause side effects.
- if (opcode == InstructionConstants.OP_IASTORE ||
- opcode == InstructionConstants.OP_LASTORE ||
- opcode == InstructionConstants.OP_FASTORE ||
- opcode == InstructionConstants.OP_DASTORE ||
- opcode == InstructionConstants.OP_AASTORE ||
- opcode == InstructionConstants.OP_BASTORE ||
- opcode == InstructionConstants.OP_CASTORE ||
- opcode == InstructionConstants.OP_SASTORE ||
- opcode == InstructionConstants.OP_ATHROW ||
- opcode == InstructionConstants.OP_MONITORENTER ||
- opcode == InstructionConstants.OP_MONITOREXIT ||
- (includeReturnInstructions &&
- (opcode == InstructionConstants.OP_IRETURN ||
- opcode == InstructionConstants.OP_LRETURN ||
- opcode == InstructionConstants.OP_FRETURN ||
- opcode == InstructionConstants.OP_DRETURN ||
- opcode == InstructionConstants.OP_ARETURN ||
- opcode == InstructionConstants.OP_RETURN)))
+ switch (opcode)
{
- // These instructions always cause a side effect.
- hasSideEffects = true;
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException, ArrayIndexOutOfBoundsException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
+
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_ATHROW :
+ case InstructionConstants.OP_MONITORENTER:
+ case InstructionConstants.OP_MONITOREXIT:
+ // These instructions always cause a side effect.
+ hasSideEffects = true;
+ break;
+
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+ // These instructions may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
}
-
}
@@ -107,10 +142,12 @@ implements InstructionVisitor,
byte opcode = variableInstruction.opcode;
// Check for instructions that might cause side effects.
- if (includeReturnInstructions &&
- opcode == InstructionConstants.OP_RET)
+ switch (opcode)
{
- hasSideEffects = true;
+ case InstructionConstants.OP_RET:
+ // This instruction may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
}
}
@@ -120,16 +157,41 @@ implements InstructionVisitor,
byte opcode = constantInstruction.opcode;
// Check for instructions that might cause side effects.
- if (opcode == InstructionConstants.OP_PUTSTATIC ||
- opcode == InstructionConstants.OP_PUTFIELD ||
- opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
- opcode == InstructionConstants.OP_INVOKESPECIAL ||
- opcode == InstructionConstants.OP_INVOKESTATIC ||
- opcode == InstructionConstants.OP_INVOKEINTERFACE)
+ switch (opcode)
{
- // Check if the field is write-only or volatile, or if the invoked
- // method is causing any side effects.
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ // Check if the field is write-only or volatile, or if the
+ // invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ if (OPTIMIZE_CONSERVATIVELY)
+ {
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException).
+ hasSideEffects = true;
+ }
+ else
+ {
+ // Check if the field is write-only or volatile, or if the
+ // invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ break;
+
+ case InstructionConstants.OP_CHECKCAST:
+ // This instructions strictly taken may cause a side effect
+ // (ClassCastException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
}
}
@@ -139,59 +201,48 @@ implements InstructionVisitor,
byte opcode = branchInstruction.opcode;
// Check for instructions that might cause side effects.
- if (includeReturnInstructions &&
- (opcode == InstructionConstants.OP_JSR ||
- opcode == InstructionConstants.OP_JSR_W))
+ switch (opcode)
{
- hasSideEffects = true;
+ case InstructionConstants.OP_JSR:
+ case InstructionConstants.OP_JSR_W:
+ hasSideEffects = includeReturnInstructions;
+ break;
}
}
// Implementations for ConstantVisitor.
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+ }
+
+
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
+ // Pass the referencing class.
+ referencingClass = clazz;
+
// We'll have to assume accessing an unknown field has side effects.
hasSideEffects = true;
- // Check the referenced field.
+ // Check the referenced field, if known.
fieldrefConstant.referencedMemberAccept(this);
}
public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
{
- Member referencedMember = refConstant.referencedMember;
+ // Pass the referencing class.
+ referencingClass = clazz;
- // Do we have a reference to the method?
- if (referencedMember == null)
- {
- // We'll have to assume invoking the unknown method has side effects.
- hasSideEffects = true;
- }
- else
- {
- // First check the referenced method itself.
- refConstant.referencedMemberAccept(this);
-
- // If the result isn't conclusive, check down the hierarchy.
- if (!hasSideEffects)
- {
- Clazz referencedClass = refConstant.referencedClass;
- Method referencedMethod = (Method)referencedMember;
-
- // Check all other implementations of the method down the class
- // hierarchy.
- if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_PRIVATE) == 0)
- {
- clazz.hierarchyAccept(false, false, false, true,
- new NamedMethodVisitor(referencedMethod.getName(referencedClass),
- referencedMethod.getDescriptor(referencedClass),
- this));
- }
- }
- }
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+
+ // Check the referenced method, if known.
+ refConstant.referencedMemberAccept(this);
}
@@ -199,14 +250,25 @@ implements InstructionVisitor,
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- hasSideEffects = ReadWriteFieldMarker.isRead(programField);
+ hasSideEffects =
+ (includeLocalFieldAccess || !programClass.equals(referencingClass)) &&
+ ((ReadWriteFieldMarker.isRead(programField) &&
+ ReadWriteFieldMarker.isWritten(programField)) ||
+ ((programField.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0) ||
+ (!programClass.equals(referencingClass) &&
+ !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- hasSideEffects = hasSideEffects ||
- SideEffectMethodMarker.hasSideEffects(programMethod);
+ // Note that side effects already include synchronization of some
+ // implementation of the method.
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(programMethod) &&
+ (SideEffectMethodMarker.hasSideEffects(programMethod) ||
+ (!programClass.equals(referencingClass) &&
+ !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
}
@@ -218,7 +280,28 @@ implements InstructionVisitor,
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
{
- hasSideEffects = hasSideEffects ||
- !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ }
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
+ new SideEffectMethodFilter(
+ new MemberToClassVisitor(
+ new ClassCollector(set))))));
+
+ return set;
}
}
diff --git a/src/proguard/optimize/info/SideEffectMethodFilter.java b/src/proguard/optimize/info/SideEffectMethodFilter.java
new file mode 100644
index 0000000..52e072a
--- /dev/null
+++ b/src/proguard/optimize/info/SideEffectMethodFilter.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Method objects that are marked as having side effects.
+ *
+ * @see SideEffectMethodMarker
+ *
+ * @author Eric Lafortune
+ */
+public class SideEffectMethodFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new SideEffectMethodFilter.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public SideEffectMethodFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField) {}
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java
index 25fda72..f7953c0 100644
--- a/src/proguard/optimize/info/SideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/SideEffectMethodMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -41,8 +41,9 @@ implements ClassPoolVisitor,
MemberVisitor,
AttributeVisitor
{
- // A reusable object for checking whether instructions have side effects.
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false);
+ // Reusable objects for checking whether instructions have side effects.
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false, true);
+ private final SideEffectInstructionChecker initializerSideEffectInstructionChecker = new SideEffectInstructionChecker(false, false);
// Parameters and values for visitor methods.
private int newSideEffectCount;
@@ -130,6 +131,11 @@ implements ClassPoolVisitor,
byte[] code = codeAttribute.code;
int length = codeAttribute.u4codeLength;
+ SideEffectInstructionChecker checker =
+ method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ?
+ initializerSideEffectInstructionChecker :
+ sideEffectInstructionChecker;
+
// Go over all instructions.
int offset = 0;
do
@@ -138,11 +144,11 @@ implements ClassPoolVisitor,
Instruction instruction = InstructionFactory.create(code, offset);
// Check if it may be throwing exceptions.
- if (sideEffectInstructionChecker.hasSideEffects(clazz,
- method,
- codeAttribute,
- offset,
- instruction))
+ if (checker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction))
{
return true;
}
diff --git a/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
new file mode 100644
index 0000000..36aa392
--- /dev/null
+++ b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are instantiated.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public StaticInitializerContainingClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
new file mode 100644
index 0000000..3a7e642
--- /dev/null
+++ b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor marks all classes that contain static initializers.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassMarker
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if (clazz.findMethod(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT) != null)
+ {
+ setStaticInitializer(clazz);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setContainsStaticInitializer();
+ }
+ }
+
+
+ public static boolean containsStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.containsStaticInitializer();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/SuperInvocationMarker.java b/src/proguard/optimize/info/SuperInvocationMarker.java
index 6f3d3bd..37b118a 100644
--- a/src/proguard/optimize/info/SuperInvocationMarker.java
+++ b/src/proguard/optimize/info/SuperInvocationMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/VariableUsageMarker.java b/src/proguard/optimize/info/VariableUsageMarker.java
index 660c4ba..b189ca9 100644
--- a/src/proguard/optimize/info/VariableUsageMarker.java
+++ b/src/proguard/optimize/info/VariableUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor marks the local variables that are used in the code
* attributes that it visits.
@@ -62,14 +64,13 @@ implements AttributeVisitor,
// Try to reuse the previous array.
if (variableUsed.length < maxLocals)
{
+ // Create a new array.
variableUsed = new boolean[maxLocals];
}
else
{
- for (int index = 0; index < maxLocals; index++)
- {
- variableUsed[index] = false;
- }
+ // Reset the array.
+ Arrays.fill(variableUsed, 0, maxLocals, false);
}
codeAttribute.instructionsAccept(clazz, method, this);
diff --git a/src/proguard/optimize/peephole/BranchTargetFinder.java b/src/proguard/optimize/peephole/BranchTargetFinder.java
index 8f650bb..79499f1 100644
--- a/src/proguard/optimize/peephole/BranchTargetFinder.java
+++ b/src/proguard/optimize/peephole/BranchTargetFinder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,6 +29,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor finds all instruction offsets, branch targets, and
* exception targets in the CodeAttribute objects that it visits.
@@ -45,12 +47,15 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = System.getProperty("btf") != null;
//*/
public static final int NONE = -2;
public static final int AT_METHOD_ENTRY = -1;
+ public static final int UNKNOWN = -1;
+ public static final int NO_SUBROUTINE = -2;
+
private static final short INSTRUCTION = 1 << 0;
private static final short BRANCH_ORIGIN = 1 << 1;
private static final short BRANCH_TARGET = 1 << 2;
@@ -70,9 +75,10 @@ implements AttributeVisitor,
private int[] creationOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int[] initializationOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int superInitializationOffset;
+ private boolean containsSubroutines;
+ private boolean repeat;
private int currentSubroutineStart;
- private int currentSubroutineEnd;
private int[] recentCreationOffsets = new int[MAXIMUM_CREATION_OFFSETS];
private int recentCreationOffsetIndex;
private boolean isInitializer;
@@ -189,7 +195,7 @@ implements AttributeVisitor,
*/
public boolean isSubroutine(int offset)
{
- return subroutineStarts[offset] != NONE;
+ return subroutineStarts[offset] >= 0;
}
@@ -289,6 +295,16 @@ implements AttributeVisitor,
}
+ /**
+ * Returns whether the method contains subroutines, in the CodeAttribute
+ * that was visited most recently.
+ */
+ public boolean containsSubroutines()
+ {
+ return containsSubroutines;
+ }
+
+
// Implementations for AttributeVisitor.
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -312,106 +328,98 @@ implements AttributeVisitor,
initializationOffsets = new int[codeLength];
// Reset the arrays.
- for (int index = 0; index < codeLength; index++)
- {
- subroutineStarts[index] = NONE;
- subroutineEnds[index] = NONE;
- creationOffsets[index] = NONE;
- initializationOffsets[index] = NONE;
- }
+ Arrays.fill(subroutineStarts, 0, codeLength, UNKNOWN);
+ Arrays.fill(subroutineEnds, 0, codeLength, UNKNOWN);
+ Arrays.fill(creationOffsets, 0, codeLength, NONE);
+ Arrays.fill(initializationOffsets, 0, codeLength, NONE);
}
else
{
// Reset the arrays.
- for (int index = 0; index < codeLength; index++)
- {
- instructionMarks[index] = 0;
- subroutineStarts[index] = NONE;
- subroutineEnds[index] = NONE;
- creationOffsets[index] = NONE;
- initializationOffsets[index] = NONE;
- }
+ Arrays.fill(instructionMarks, 0, codeLength, (short)0);
+ Arrays.fill(subroutineStarts, 0, codeLength, UNKNOWN);
+ Arrays.fill(subroutineEnds, 0, codeLength, UNKNOWN);
+ Arrays.fill(creationOffsets, 0, codeLength, NONE);
+ Arrays.fill(initializationOffsets, 0, codeLength, NONE);
instructionMarks[codeLength] = 0;
}
superInitializationOffset = NONE;
+ containsSubroutines = false;
- // We're assuming all subroutines are contiguous blocks of code.
- // We're not starting in a subroutine.
- currentSubroutineStart = NONE;
- currentSubroutineEnd = NONE;
+ // Iterate until all subroutines have been fully marked.
+ do
+ {
+ repeat = false;
+ currentSubroutineStart = NO_SUBROUTINE;
+ recentCreationOffsetIndex = 0;
- recentCreationOffsetIndex = 0;
+ // Initialize the stack of 'new' instruction offsets if this method
+ // is an instance initializer.
+ if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
+ {
+ recentCreationOffsets[recentCreationOffsetIndex++] = AT_METHOD_ENTRY;
+ }
- // Initialize the stack of 'new' instruction offsets if this method is
- // an instance initializer.
- if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
- {
- recentCreationOffsets[recentCreationOffsetIndex++] = AT_METHOD_ENTRY;
+ // Mark branch targets by going over all instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
}
+ while (repeat);
// The end of the code is a branch target sentinel.
instructionMarks[codeLength] = BRANCH_TARGET;
- // Mark branch targets by going over all instructions.
- codeAttribute.instructionsAccept(clazz, method, this);
-
// Mark branch targets in the exception table.
codeAttribute.exceptionsAccept(clazz, method, this);
- // Fill out any gaps in the subroutine starts and the subroutine ends
- // and subroutine returning flags, working backward.
-
- // We're not starting in a subroutine.
- int subroutineStart = NONE;
- int subroutineEnd = codeLength;
- boolean subroutineReturning = false;
-
- for (int index = codeLength - 1; index >= 0; index--)
+ if (containsSubroutines)
{
- if (isInstruction(index))
- {
- // Are we inside a previously marked subroutine?
- if (subroutineStarts[index] != NONE)
- {
- // Update the current subroutine start.
- subroutineStart = subroutineStarts[index];
- }
- else if (subroutineStart != NONE)
- {
- // Mark the subroutine start.
- subroutineStarts[index] = subroutineStart;
- }
+ // Set the subroutine returning flag and the subroutine end at each
+ // subroutine start.
+ int previousSubroutineStart = NO_SUBROUTINE;
- // Did we reach the start of the subroutine.
- if (isSubroutineStart(index))
- {
- // Stop marking it.
- subroutineStart = NONE;
- }
-
- // Are we inside a subroutine?
- if (isSubroutine(index))
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (isInstruction(offset))
{
- // Mark the subroutine end.
- subroutineEnds[index] = subroutineEnd;
+ int subroutineStart = subroutineStarts[offset];
- // Update or mark the subroutine returning flag.
- if (isSubroutineReturning(index))
+ if (subroutineStart >= 0 &&
+ isSubroutineReturning(offset))
{
- subroutineReturning = true;
+ instructionMarks[subroutineStart] |= SUBROUTINE_RETURNING;
}
- else if (subroutineReturning)
+
+ if (previousSubroutineStart >= 0)
{
- instructionMarks[index] |= SUBROUTINE_RETURNING;
+ subroutineEnds[previousSubroutineStart] = offset;
}
+
+ previousSubroutineStart = subroutineStart;
}
- else
+ }
+
+ if (previousSubroutineStart >= 0)
+ {
+ subroutineEnds[previousSubroutineStart] = codeLength;
+ }
+
+ // Set the subroutine returning flag and the subroutine end at each
+ // subroutine instruction, based on the marks at the subroutine
+ // start.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (isSubroutine(offset))
{
- // Update the subroutine end and returning flag.
- subroutineEnd = index;
- subroutineReturning = false;
+ int subroutineStart = subroutineStarts[offset];
+
+ if (isSubroutineReturning(subroutineStart))
+ {
+ instructionMarks[offset] |= SUBROUTINE_RETURNING;
+ }
+
+ subroutineEnds[offset] = subroutineEnds[subroutineStart];
}
}
}
@@ -451,7 +459,7 @@ implements AttributeVisitor,
// Mark the instruction.
instructionMarks[offset] |= INSTRUCTION;
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
byte opcode = simpleInstruction.opcode;
@@ -476,7 +484,7 @@ implements AttributeVisitor,
// Mark the instruction.
instructionMarks[offset] |= INSTRUCTION;
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
// Check if the instruction is a 'new' instruction.
@@ -517,15 +525,18 @@ implements AttributeVisitor,
// Mark the instruction.
instructionMarks[offset] |= INSTRUCTION;
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
if (variableInstruction.opcode == InstructionConstants.OP_RET)
{
+ // Mark the method.
+ containsSubroutines = true;
+
// Mark the branch origin.
markBranchOrigin(offset);
- // Mark the regular subroutine return.
+ // Mark the subroutine return at its return instruction.
instructionMarks[offset] |= SUBROUTINE_RETURNING;
// Mark the next instruction.
@@ -536,28 +547,39 @@ implements AttributeVisitor,
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
{
+ int branchOffset = branchInstruction.branchOffset;
+ int targetOffset = offset + branchOffset;
+
// Mark the branch origin.
markBranchOrigin(offset);
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
// Mark the branch target.
- markBranchTarget(offset, branchInstruction.branchOffset);
+ markBranchTarget(offset, branchOffset);
byte opcode = branchInstruction.opcode;
if (opcode == InstructionConstants.OP_JSR ||
opcode == InstructionConstants.OP_JSR_W)
{
+ // Mark the method.
+ containsSubroutines = true;
+
// Mark the subroutine invocation.
instructionMarks[offset] |= SUBROUTINE_INVOCATION;
- // Mark the subroutine start.
- int targetOffset = offset + branchInstruction.branchOffset;
- subroutineStarts[targetOffset] = targetOffset;
+ // Mark the new subroutine start.
+ markBranchSubroutineStart(offset, branchOffset, targetOffset);
}
- else if (opcode == InstructionConstants.OP_GOTO ||
- opcode == InstructionConstants.OP_GOTO_W)
+ else if (currentSubroutineStart != UNKNOWN)
+ {
+ // Mark the continued subroutine start.
+ markBranchSubroutineStart(offset, branchOffset, currentSubroutineStart);
+ }
+
+ if (opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W)
{
// Mark the next instruction.
markAfterBranchOrigin(offset + branchInstruction.length(offset));
@@ -570,15 +592,14 @@ implements AttributeVisitor,
// Mark the branch origin.
markBranchOrigin(offset);
- // Check if this is the first instruction of a subroutine.
+ // Check if this is an instruction of a subroutine.
checkSubroutine(offset);
// Mark the branch targets of the default jump offset.
- markBranchTarget(offset, switchInstruction.defaultOffset);
+ markBranch(offset, switchInstruction.defaultOffset);
// Mark the branch targets of the jump offsets.
- markBranchTargets(offset,
- switchInstruction.jumpOffsets);
+ markBranches(offset, switchInstruction.jumpOffsets);
// Mark the next instruction.
markAfterBranchOrigin(offset + switchInstruction.length(offset));
@@ -610,19 +631,32 @@ implements AttributeVisitor,
// Small utility methods.
/**
- * Marks the branch targets of the given jump offsets for the instruction
- * at the given offset.
+ * Marks the branch targets and their subroutine starts at the given
+ * offsets.
*/
- private void markBranchTargets(int offset, int[] jumpOffsets)
+ private void markBranches(int offset, int[] jumpOffsets)
{
for (int index = 0; index < jumpOffsets.length; index++)
{
- markBranchTarget(offset, jumpOffsets[index]);
+ markBranch(offset, jumpOffsets[index]);
}
}
/**
+ * Marks the branch target and its subroutine start at the given offset.
+ */
+ private void markBranch(int offset, int jumpOffset)
+ {
+ markBranchTarget(offset, jumpOffset);
+
+ if (currentSubroutineStart != UNKNOWN)
+ {
+ markBranchSubroutineStart(offset, jumpOffset, currentSubroutineStart);
+ }
+ }
+
+ /**
* Marks the branch origin at the given offset.
*/
private void markBranchOrigin(int offset)
@@ -639,18 +673,37 @@ implements AttributeVisitor,
int targetOffset = offset + jumpOffset;
instructionMarks[targetOffset] |= BRANCH_TARGET;
+ }
- // Are we inside a previously marked subroutine?
- if (isSubroutine(offset))
- {
- // Mark the subroutine start of the target.
- subroutineStarts[targetOffset] = currentSubroutineStart;
- // Update the current subroutine end.
- if (currentSubroutineEnd < targetOffset)
+ /**
+ * Marks the subroutine start at the given offset, if applicable.
+ */
+ private void markBranchSubroutineStart(int offset,
+ int jumpOffset,
+ int subroutineStart)
+ {
+ int targetOffset = offset + jumpOffset;
+
+ // Are we marking a subroutine and branching to an offset that hasn't
+ // been marked yet?
+ if (subroutineStarts[targetOffset] == UNKNOWN)
+ {
+ // Is it a backward branch?
+ if (jumpOffset < 0)
{
- currentSubroutineEnd = targetOffset;
+ // Remember the smallest subroutine start.
+ if (subroutineStart > targetOffset)
+ {
+ subroutineStart = targetOffset;
+ }
+
+ // We'll have to go over all instructions again.
+ repeat = true;
}
+
+ // Mark the subroutine start of the target.
+ subroutineStarts[targetOffset] = subroutineStart;
}
}
@@ -662,12 +715,8 @@ implements AttributeVisitor,
{
instructionMarks[nextOffset] |= AFTER_BRANCH;
- // Are we at the end of the current subroutine?
- if (currentSubroutineEnd <= nextOffset)
- {
- // Reset the subroutine start.
- currentSubroutineStart = NONE;
- }
+ // Stop marking a subroutine.
+ currentSubroutineStart = UNKNOWN;
}
@@ -677,15 +726,23 @@ implements AttributeVisitor,
private void checkSubroutine(int offset)
{
// Are we inside a previously marked subroutine?
- if (isSubroutine(offset))
+ if (subroutineStarts[offset] != UNKNOWN)
{
- // Update the current subroutine start.
+ // Start marking a subroutine.
currentSubroutineStart = subroutineStarts[offset];
}
- else
+
+ // Are we marking a subroutine?
+ else if (currentSubroutineStart != UNKNOWN)
{
- // Mark the subroutine start (or NONE).
+ // Mark the subroutine start.
subroutineStarts[offset] = currentSubroutineStart;
+
+ if (currentSubroutineStart >= 0)
+ {
+ // Mark the subroutine end at the subroutine start.
+ subroutineEnds[currentSubroutineStart] = offset;
+ }
}
}
}
diff --git a/src/proguard/optimize/peephole/ClassFinalizer.java b/src/proguard/optimize/peephole/ClassFinalizer.java
index b5e54f8..378f972 100644
--- a/src/proguard/optimize/peephole/ClassFinalizer.java
+++ b/src/proguard/optimize/peephole/ClassFinalizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/ClassMerger.java b/src/proguard/optimize/peephole/ClassMerger.java
index 1e1a950..aa40c75 100644
--- a/src/proguard/optimize/peephole/ClassMerger.java
+++ b/src/proguard/optimize/peephole/ClassMerger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,7 @@
package proguard.optimize.peephole;
import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeNameFilter;
import proguard.classfile.constant.visitor.*;
import proguard.classfile.editor.*;
import proguard.classfile.util.*;
@@ -50,7 +51,7 @@ implements ClassVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = System.getProperty("cm") != null;
//*/
@@ -59,6 +60,8 @@ implements ClassVisitor,
private final boolean mergeInterfacesAggressively;
private final ClassVisitor extraClassVisitor;
+ private final MemberVisitor fieldOptimizationInfoCopier = new FieldOptimizationInfoCopier();
+
/**
* Creates a new ClassMerger that will merge classes into the given target
@@ -151,7 +154,7 @@ implements ClassVisitor,
// infinite recursion.
(programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_ANNOTATTION) == 0 &&
- // Only merge classes if we can change the access permissioms, or
+ // Only merge classes if we can change the access permissions, or
// if they are in the same package, or
// if they are public and don't contain or invoke package visible
// class members.
@@ -196,12 +199,19 @@ implements ClassVisitor,
!(DotClassMarker.isDotClassed(programClass) &&
DotClassMarker.isDotClassed(targetClass)) &&
+ // The classes must not have clashing fields.
+ !haveAnyIdenticalFields(programClass, targetClass) &&
+
// The two classes must not introduce any unwanted fields.
!introducesUnwantedFields(programClass, targetClass) &&
!introducesUnwantedFields(targetClass, programClass) &&
- // The classes must not have clashing constructors.
- !haveAnyIdenticalInitializers(programClass, targetClass) &&
+ // The two classes must not shadow each others fields.
+ !shadowsAnyFields(programClass, targetClass) &&
+ !shadowsAnyFields(targetClass, programClass) &&
+
+ // The classes must not have clashing methods.
+ !haveAnyIdenticalMethods(programClass, targetClass) &&
// The classes must not introduce abstract methods, unless
// explicitly allowed.
@@ -226,6 +236,10 @@ implements ClassVisitor,
System.out.println(" Target subclasses ["+targetClass.subClasses+"]");
System.out.println(" Source superclass ["+programClass.getSuperClass().getName()+"]");
System.out.println(" Target superclass ["+targetClass.getSuperClass().getName()+"]");
+
+ //System.out.println("=== Before ===");
+ //programClass.accept(new ClassPrinter());
+ //targetClass.accept(new ClassPrinter());
}
// Combine the access flags.
@@ -235,11 +249,12 @@ implements ClassVisitor,
targetClass.u2accessFlags =
((targetAccessFlags &
sourceAccessFlags) &
- (ClassConstants.INTERNAL_ACC_INTERFACE |
+ (ClassConstants.INTERNAL_ACC_INTERFACE |
ClassConstants.INTERNAL_ACC_ABSTRACT)) |
((targetAccessFlags |
sourceAccessFlags) &
- (ClassConstants.INTERNAL_ACC_PUBLIC |
+ (ClassConstants.INTERNAL_ACC_PUBLIC |
+ ClassConstants.INTERNAL_ACC_SUPER |
ClassConstants.INTERNAL_ACC_ANNOTATTION |
ClassConstants.INTERNAL_ACC_ENUM));
@@ -260,14 +275,18 @@ implements ClassVisitor,
// Copy over the class members.
MemberAdder memberAdder =
- new MemberAdder(targetClass);
+ new MemberAdder(targetClass, fieldOptimizationInfoCopier);
programClass.fieldsAccept(memberAdder);
programClass.methodsAccept(memberAdder);
// Copy over the other attributes.
programClass.attributesAccept(
- new AttributeAdder(targetClass, true));
+ new AttributeNameFilter(new NotMatcher(new OrMatcher(new OrMatcher(
+ new FixedStringMatcher(ClassConstants.ATTR_SourceFile),
+ new FixedStringMatcher(ClassConstants.ATTR_InnerClasses)),
+ new FixedStringMatcher(ClassConstants.ATTR_EnclosingMethod))),
+ new AttributeAdder(targetClass, true)));
// Update the optimization information of the target class.
ClassOptimizationInfo info =
@@ -280,6 +299,12 @@ implements ClassVisitor,
// Remember to replace the inlined class by the target class.
setTargetClass(programClass, targetClass);
+ //if (DEBUG)
+ //{
+ // System.out.println("=== After ====");
+ // targetClass.accept(new ClassPrinter());
+ //}
+
// Visit the merged class, if required.
if (extraClassVisitor != null)
{
@@ -336,10 +361,8 @@ implements ClassVisitor,
// Visit all superclasses and interfaces, collecting the ones that have
// static initializers.
clazz.hierarchyAccept(true, true, true, false,
- new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
- ClassConstants.INTERNAL_METHOD_TYPE_INIT,
- new MemberToClassVisitor(
- new ClassCollector(set))));
+ new StaticInitializerContainingClassFilter(
+ new ClassCollector(set)));
return set;
}
@@ -368,9 +391,16 @@ implements ClassVisitor,
*/
private Set caughtSuperClasses(Clazz clazz)
{
+ // Don't bother if this isn't an exception at all.
+ if (!clazz.extends_(ClassConstants.INTERNAL_NAME_JAVA_LANG_THROWABLE))
+ {
+ return Collections.EMPTY_SET;
+ }
+
+ // Visit all superclasses, collecting the ones that are caught
+ // (plus java.lang.Object, in the current implementation).
Set set = new HashSet();
- // Visit all superclasses, collecting the ones that are caught.
clazz.hierarchyAccept(true, true, false, false,
new CaughtClassFilter(
new ClassCollector(set)));
@@ -380,38 +410,82 @@ implements ClassVisitor,
/**
+ * Returns whether the two given classes have class members with the same
+ * name and descriptor.
+ */
+ private boolean haveAnyIdenticalFields(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all fields, counting the with the same name and descriptor in
+ // the target class.
+ clazz.fieldsAccept(new SimilarMemberVisitor(targetClass, true, false, false, false,
+ counter));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
* Returns whether the given class would introduce any unwanted fields
* in the target class.
*/
private boolean introducesUnwantedFields(ProgramClass programClass,
ProgramClass targetClass)
{
- // The class must not have any fields, or it must not be instantiated,
- // without any other subclasses.
- return
- programClass.u2fieldsCount != 0 &&
- (InstantiationClassMarker.isInstantiated(targetClass) ||
- (targetClass.subClasses != null &&
- !isOnlySubClass(programClass, targetClass)));
+ // It's ok if the target class is never instantiated, without any other
+ // subclasses except for maybe the source class.
+ if (!InstantiationClassMarker.isInstantiated(targetClass) &&
+ (targetClass.subClasses == null ||
+ isOnlySubClass(programClass, targetClass)))
+ {
+ return false;
+ }
+
+ MemberCounter counter = new MemberCounter();
+
+ // Count all non-static fields in the the source class.
+ programClass.fieldsAccept(new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_STATIC,
+ counter));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
+ * Returns whether the given class or its subclasses shadow any fields in
+ * the given target class.
+ */
+ private boolean shadowsAnyFields(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all fields, counting the ones that are shadowing non-private
+ // fields in the class hierarchy of the target class.
+ clazz.hierarchyAccept(true, false, false, true,
+ new AllFieldVisitor(
+ new SimilarMemberVisitor(targetClass, true, true, true, false,
+ new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
+ counter))));
+
+ return counter.getCount() > 0;
}
/**
- * Returns whether the two given classes have initializers with the same
- * descriptors.
+ * Returns whether the two given classes have class members with the same
+ * name and descriptor.
*/
- private boolean haveAnyIdenticalInitializers(Clazz clazz, Clazz targetClass)
+ private boolean haveAnyIdenticalMethods(Clazz clazz, Clazz targetClass)
{
MemberCounter counter = new MemberCounter();
- // TODO: Currently checking shared methods, not just initializers.
- // TODO: Allow identical methods.
- // Visit all methods, counting the ones that are also present in the
- // target class.
- clazz.methodsAccept(//new MemberNameFilter(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT),
+ // Visit all non-abstract methods, counting the ones that are also
+ // present in the target class.
+ clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_ABSTRACT,
new SimilarMemberVisitor(targetClass, true, false, false, false,
new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_ABSTRACT,
- counter)));
+ counter))));
return counter.getCount() > 0;
}
@@ -538,4 +612,30 @@ implements ClassVisitor,
targetClass = clazz;
}
}
+
+
+ /**
+ * This MemberVisitor copies field optimization info from copied fields.
+ */
+ private static class FieldOptimizationInfoCopier
+ extends SimplifiedVisitor
+ implements MemberVisitor
+ {
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Copy the optimization info from the field that was just copied.
+ ProgramField copiedField = (ProgramField)programField.getVisitorInfo();
+ Object info = copiedField.getVisitorInfo();
+
+ programField.setVisitorInfo(info instanceof FieldOptimizationInfo ?
+ new FieldOptimizationInfo((FieldOptimizationInfo)info) :
+ info);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Linked methods share their optimization info.
+ }
+ }
} \ No newline at end of file
diff --git a/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java b/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
index 4833275..3bfd98c 100644
--- a/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
+++ b/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -50,7 +50,7 @@ implements AttributeVisitor,
private final InstructionVisitor extraInstructionVisitor;
private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(true, false);
/**
@@ -123,10 +123,7 @@ implements AttributeVisitor,
int deleteOffset = offset - delta;
if (branchTargetFinder.isInstruction(deleteOffset))
{
- codeAttributeEditor.replaceInstruction( deleteOffset, (Instruction)null);
- codeAttributeEditor.insertBeforeInstruction(deleteOffset, (Instruction)null);
- codeAttributeEditor.insertAfterInstruction( deleteOffset, (Instruction)null);
-
+ codeAttributeEditor.clearModifications(deleteOffset);
codeAttributeEditor.deleteInstruction(deleteOffset);
}
}
@@ -136,7 +133,7 @@ implements AttributeVisitor,
if (newBranchOffset != branchInstruction.length(offset))
{
Instruction newGotoInstruction =
- new BranchInstruction(opcode, newBranchOffset);
+ new BranchInstruction(opcode, newBranchOffset).shrink();
codeAttributeEditor.replaceInstruction(offset,
newGotoInstruction);
}
diff --git a/src/proguard/optimize/peephole/GotoGotoReplacer.java b/src/proguard/optimize/peephole/GotoGotoReplacer.java
index 7d7e66c..4a490a1 100644
--- a/src/proguard/optimize/peephole/GotoGotoReplacer.java
+++ b/src/proguard/optimize/peephole/GotoGotoReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -84,8 +84,9 @@ implements InstructionVisitor
int branchOffset = branchInstruction.branchOffset;
int targetOffset = offset + branchOffset;
- if (branchOffset != branchInstruction.length(offset) &&
- !codeAttributeEditor.isModified(offset) &&
+ if (branchOffset != 0 &&
+ branchOffset != branchInstruction.length(offset) &&
+ !codeAttributeEditor.isModified(offset) &&
!codeAttributeEditor.isModified(targetOffset))
{
Instruction targetInstruction =
diff --git a/src/proguard/optimize/peephole/GotoReturnReplacer.java b/src/proguard/optimize/peephole/GotoReturnReplacer.java
index 5c3eb77..b6deec8 100644
--- a/src/proguard/optimize/peephole/GotoReturnReplacer.java
+++ b/src/proguard/optimize/peephole/GotoReturnReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/HorizontalClassMerger.java b/src/proguard/optimize/peephole/HorizontalClassMerger.java
index a37b9a5..31d3d33 100644
--- a/src/proguard/optimize/peephole/HorizontalClassMerger.java
+++ b/src/proguard/optimize/peephole/HorizontalClassMerger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/InstructionSequenceConstants.java b/src/proguard/optimize/peephole/InstructionSequenceConstants.java
index b33204b..4ab9056 100644
--- a/src/proguard/optimize/peephole/InstructionSequenceConstants.java
+++ b/src/proguard/optimize/peephole/InstructionSequenceConstants.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -20,81 +20,207 @@
*/
package proguard.optimize.peephole;
+import proguard.classfile.*;
import proguard.classfile.constant.*;
import proguard.classfile.instruction.*;
-import proguard.classfile.util.InstructionSequenceMatcher;
+import proguard.classfile.visitor.ClassPrinter;
/**
* This class contains a set of instruction sequences and their suggested
* replacements.
*
* @see InstructionSequencesReplacer
+ * @see InstructionSequenceReplacer
* @author Eric Lafortune
*/
public class InstructionSequenceConstants
{
- public static final int X = InstructionSequenceMatcher.X;
- public static final int Y = InstructionSequenceMatcher.Y;
- public static final int Z = InstructionSequenceMatcher.Z;
+ private static final int X = InstructionSequenceReplacer.X;
+ private static final int Y = InstructionSequenceReplacer.Y;
+ private static final int Z = InstructionSequenceReplacer.Z;
- public static final int A = InstructionSequenceMatcher.A;
- public static final int B = InstructionSequenceMatcher.B;
- public static final int C = InstructionSequenceMatcher.C;
- public static final int D = InstructionSequenceMatcher.D;
+ private static final int A = InstructionSequenceReplacer.A;
+ private static final int B = InstructionSequenceReplacer.B;
+ private static final int C = InstructionSequenceReplacer.C;
+ private static final int D = InstructionSequenceReplacer.D;
+ private static final int STRING_A_LENGTH = InstructionSequenceReplacer.STRING_A_LENGTH;
+ private static final int BOOLEAN_A_STRING = InstructionSequenceReplacer.BOOLEAN_A_STRING;
+ private static final int CHAR_A_STRING = InstructionSequenceReplacer.CHAR_A_STRING;
+ private static final int INT_A_STRING = InstructionSequenceReplacer.INT_A_STRING;
+ private static final int LONG_A_STRING = InstructionSequenceReplacer.LONG_A_STRING;
+ private static final int FLOAT_A_STRING = InstructionSequenceReplacer.FLOAT_A_STRING;
+ private static final int DOUBLE_A_STRING = InstructionSequenceReplacer.DOUBLE_A_STRING;
+ private static final int STRING_A_STRING = InstructionSequenceReplacer.STRING_A_STRING;
+ private static final int BOOLEAN_B_STRING = InstructionSequenceReplacer.BOOLEAN_B_STRING;
+ private static final int CHAR_B_STRING = InstructionSequenceReplacer.CHAR_B_STRING;
+ private static final int INT_B_STRING = InstructionSequenceReplacer.INT_B_STRING;
+ private static final int LONG_B_STRING = InstructionSequenceReplacer.LONG_B_STRING;
+ private static final int FLOAT_B_STRING = InstructionSequenceReplacer.FLOAT_B_STRING;
+ private static final int DOUBLE_B_STRING = InstructionSequenceReplacer.DOUBLE_B_STRING;
+ private static final int STRING_B_STRING = InstructionSequenceReplacer.STRING_B_STRING;
- private static final int I_32768 = 0;
- private static final int I_65536 = 1;
- private static final int I_16777216 = 2;
+ private static final int I_32768 = 0;
+ private static final int I_65536 = 1;
+ private static final int I_16777216 = 2;
// private static final int I_0x000000ff
- private static final int I_0x0000ff00 = 3;
- private static final int I_0x00ff0000 = 4;
- private static final int I_0xff000000 = 5;
- private static final int I_0x0000ffff = 6;
- private static final int I_0xffff0000 = 7;
+ private static final int I_0x0000ff00 = 3;
+ private static final int I_0x00ff0000 = 4;
+ private static final int I_0xff000000 = 5;
+ private static final int I_0x0000ffff = 6;
+ private static final int I_0xffff0000 = 7;
- private static final int L_M1 = 8;
- private static final int L_2 = 9;
- private static final int L_4 = 10;
- private static final int L_8 = 11;
- private static final int L_16 = 12;
- private static final int L_32 = 13;
- private static final int L_64 = 14;
- private static final int L_128 = 15;
- private static final int L_256 = 16;
- private static final int L_512 = 17;
- private static final int L_1024 = 18;
- private static final int L_2048 = 19;
- private static final int L_4096 = 20;
- private static final int L_8192 = 21;
- private static final int L_16384 = 22;
- private static final int L_32768 = 23;
- private static final int L_65536 = 24;
- private static final int L_16777216 = 25;
- private static final int L_4294967296 = 26;
+ private static final int L_M1 = 8;
+ private static final int L_2 = 9;
+ private static final int L_4 = 10;
+ private static final int L_8 = 11;
+ private static final int L_16 = 12;
+ private static final int L_32 = 13;
+ private static final int L_64 = 14;
+ private static final int L_128 = 15;
+ private static final int L_256 = 16;
+ private static final int L_512 = 17;
+ private static final int L_1024 = 18;
+ private static final int L_2048 = 19;
+ private static final int L_4096 = 20;
+ private static final int L_8192 = 21;
+ private static final int L_16384 = 22;
+ private static final int L_32768 = 23;
+ private static final int L_65536 = 24;
+ private static final int L_16777216 = 25;
+ private static final int L_4294967296 = 26;
- private static final int L_0x00000000ffffffff = 27;
- private static final int L_0xffffffff00000000 = 28;
+ private static final int L_0x00000000ffffffff = 27;
+ private static final int L_0xffffffff00000000 = 28;
- private static final int F_M1 = 29;
+ private static final int F_M1 = 29;
- private static final int D_M1 = 30;
+ private static final int D_M1 = 30;
- private static final int FIELD_I = 31;
- private static final int FIELD_L = 32;
- private static final int FIELD_F = 33;
- private static final int FIELD_D = 34;
+ private static final int STRING_EMPTY = 31;
- private static final int NAME_AND_TYPE_I = 35;
- private static final int NAME_AND_TYPE_L = 36;
- private static final int NAME_AND_TYPE_F = 37;
- private static final int NAME_AND_TYPE_D = 38;
+ private static final int FIELD_I = 32; // Implicitly uses X and Y.
+ private static final int FIELD_L = 33; // Implicitly uses X and Y.
+ private static final int FIELD_F = 34; // Implicitly uses X and Y.
+ private static final int FIELD_D = 35; // Implicitly uses X and Y.
- private static final int TYPE_I = 39;
- private static final int TYPE_L = 40;
- private static final int TYPE_F = 41;
- private static final int TYPE_D = 42;
+ private static final int METHOD_STRING_EQUALS = 36;
+ private static final int METHOD_STRING_LENGTH = 37;
+ private static final int METHOD_STRING_VALUEOF_Z = 38;
+ private static final int METHOD_STRING_VALUEOF_C = 39;
+ private static final int METHOD_STRING_VALUEOF_I = 40;
+ private static final int METHOD_STRING_VALUEOF_J = 41;
+ private static final int METHOD_STRING_VALUEOF_F = 42;
+ private static final int METHOD_STRING_VALUEOF_D = 43;
+ private static final int METHOD_STRING_VALUEOF_OBJECT = 44;
+ private static final int METHOD_STRINGBUFFER_INIT = 45;
+ private static final int METHOD_STRINGBUFFER_INIT_STRING = 46;
+ private static final int METHOD_STRINGBUFFER_APPEND_Z = 47;
+ private static final int METHOD_STRINGBUFFER_APPEND_C = 48;
+ private static final int METHOD_STRINGBUFFER_APPEND_I = 49;
+ private static final int METHOD_STRINGBUFFER_APPEND_J = 50;
+ private static final int METHOD_STRINGBUFFER_APPEND_F = 51;
+ private static final int METHOD_STRINGBUFFER_APPEND_D = 52;
+ private static final int METHOD_STRINGBUFFER_APPEND_STRING = 53;
+ private static final int METHOD_STRINGBUFFER_APPEND_OBJECT = 54;
+ private static final int METHOD_STRINGBUFFER_LENGTH = 55;
+ private static final int METHOD_STRINGBUFFER_TOSTRING = 56;
+ private static final int METHOD_STRINGBUILDER_INIT = 57;
+ private static final int METHOD_STRINGBUILDER_INIT_STRING = 58;
+ private static final int METHOD_STRINGBUILDER_APPEND_Z = 59;
+ private static final int METHOD_STRINGBUILDER_APPEND_C = 60;
+ private static final int METHOD_STRINGBUILDER_APPEND_I = 61;
+ private static final int METHOD_STRINGBUILDER_APPEND_J = 62;
+ private static final int METHOD_STRINGBUILDER_APPEND_F = 63;
+ private static final int METHOD_STRINGBUILDER_APPEND_D = 64;
+ private static final int METHOD_STRINGBUILDER_APPEND_STRING = 65;
+ private static final int METHOD_STRINGBUILDER_APPEND_OBJECT = 66;
+ private static final int METHOD_STRINGBUILDER_LENGTH = 67;
+ private static final int METHOD_STRINGBUILDER_TOSTRING = 68;
+
+ private static final int CLASS_STRING = 69;
+ private static final int CLASS_STRINGBUFFER = 70;
+ private static final int CLASS_STRINGBUILDER = 71;
+
+ private static final int NAME_AND_TYPE_I = 72; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_L = 73; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_F = 74; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_D = 75; // Implicitly uses Y.
+
+ private static final int NAME_AND_TYPE_EQUALS = 76;
+ private static final int NAME_AND_TYPE_LENGTH = 77;
+ private static final int NAME_AND_TYPE_VALUEOF_Z = 78;
+ private static final int NAME_AND_TYPE_VALUEOF_C = 79;
+ private static final int NAME_AND_TYPE_VALUEOF_I = 80;
+ private static final int NAME_AND_TYPE_VALUEOF_J = 81;
+ private static final int NAME_AND_TYPE_VALUEOF_F = 82;
+ private static final int NAME_AND_TYPE_VALUEOF_D = 83;
+ private static final int NAME_AND_TYPE_VALUEOF_OBJECT = 84;
+ private static final int NAME_AND_TYPE_INIT = 85;
+ private static final int NAME_AND_TYPE_INIT_STRING = 86;
+ private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUFFER = 87;
+ private static final int NAME_AND_TYPE_APPEND_C_STRINGBUFFER = 88;
+ private static final int NAME_AND_TYPE_APPEND_I_STRINGBUFFER = 89;
+ private static final int NAME_AND_TYPE_APPEND_J_STRINGBUFFER = 90;
+ private static final int NAME_AND_TYPE_APPEND_F_STRINGBUFFER = 91;
+ private static final int NAME_AND_TYPE_APPEND_D_STRINGBUFFER = 92;
+ private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUFFER = 93;
+ private static final int NAME_AND_TYPE_APPEND_OBJECT_STRINGBUFFER = 94;
+ private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUILDER = 95;
+ private static final int NAME_AND_TYPE_APPEND_C_STRINGBUILDER = 96;
+ private static final int NAME_AND_TYPE_APPEND_I_STRINGBUILDER = 97;
+ private static final int NAME_AND_TYPE_APPEND_J_STRINGBUILDER = 98;
+ private static final int NAME_AND_TYPE_APPEND_F_STRINGBUILDER = 99;
+ private static final int NAME_AND_TYPE_APPEND_D_STRINGBUILDER = 100;
+ private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUILDER = 101;
+ private static final int NAME_AND_TYPE_APPEND_OBJECT_STRINGBUILDER = 102;
+ private static final int NAME_AND_TYPE_TOSTRING = 103;
+
+ private static final int UTF8_EMPTY = 104;
+ private static final int UTF8_I = 105;
+ private static final int UTF8_L = 106;
+ private static final int UTF8_F = 107;
+ private static final int UTF8_D = 108;
+ private static final int UTF8_STRING = 109;
+ private static final int UTF8_STRINGBUFFER = 110;
+ private static final int UTF8_STRINGBUILDER = 111;
+ private static final int UTF8_EQUALS = 112;
+ private static final int UTF8_OBJECT_Z = 113;
+ private static final int UTF8_LENGTH = 114;
+ private static final int UTF8__I = 115;
+ private static final int UTF8_VALUEOF = 116;
+ private static final int UTF8_Z_STRING = 117;
+ private static final int UTF8_C_STRING = 118;
+ private static final int UTF8_I_STRING = 119;
+ private static final int UTF8_J_STRING = 120;
+ private static final int UTF8_F_STRING = 121;
+ private static final int UTF8_D_STRING = 122;
+ private static final int UTF8_OBJECT_STRING = 123;
+ private static final int UTF8_INIT = 124;
+ private static final int UTF8__VOID = 125;
+ private static final int UTF8_STRING_VOID = 126;
+ private static final int UTF8_TOSTRING = 127;
+ private static final int UTF8__STRING = 128;
+ private static final int UTF8_APPEND = 129;
+ private static final int UTF8_Z_STRINGBUFFER = 130;
+ private static final int UTF8_C_STRINGBUFFER = 131;
+ private static final int UTF8_I_STRINGBUFFER = 132;
+ private static final int UTF8_J_STRINGBUFFER = 133;
+ private static final int UTF8_F_STRINGBUFFER = 134;
+ private static final int UTF8_D_STRINGBUFFER = 135;
+ private static final int UTF8_STRING_STRINGBUFFER = 136;
+ private static final int UTF8_OBJECT_STRINGBUFFER = 137;
+ private static final int UTF8_Z_STRINGBUILDER = 138;
+ private static final int UTF8_C_STRINGBUILDER = 139;
+ private static final int UTF8_I_STRINGBUILDER = 140;
+ private static final int UTF8_J_STRINGBUILDER = 141;
+ private static final int UTF8_F_STRINGBUILDER = 142;
+ private static final int UTF8_D_STRINGBUILDER = 143;
+ private static final int UTF8_STRING_STRINGBUILDER = 144;
+ private static final int UTF8_OBJECT_STRINGBUILDER = 145;
+
+ private static final int SENTINEL = 146;
public static final Constant[] CONSTANTS = new Constant[]
@@ -136,23 +262,128 @@ public class InstructionSequenceConstants
new DoubleConstant(-1d),
+ new StringConstant(UTF8_EMPTY, null, null),
+
new FieldrefConstant(X, NAME_AND_TYPE_I, null, null),
new FieldrefConstant(X, NAME_AND_TYPE_L, null, null),
new FieldrefConstant(X, NAME_AND_TYPE_F, null, null),
new FieldrefConstant(X, NAME_AND_TYPE_D, null, null),
- new NameAndTypeConstant(Y, TYPE_I),
- new NameAndTypeConstant(Y, TYPE_L),
- new NameAndTypeConstant(Y, TYPE_F),
- new NameAndTypeConstant(Y, TYPE_D),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_EQUALS, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_Z, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_C, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_I, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_J, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_F, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_D, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_OBJECT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_INIT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_INIT_STRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_Z_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_C_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_I_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_J_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_F_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_D_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_STRING_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_OBJECT_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_TOSTRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_INIT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_INIT_STRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_Z_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_C_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_I_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_J_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_F_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_D_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_STRING_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_OBJECT_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_TOSTRING, null, null),
+
+ new ClassConstant(UTF8_STRING, null),
+ new ClassConstant(UTF8_STRINGBUFFER, null),
+ new ClassConstant(UTF8_STRINGBUILDER, null),
+ new NameAndTypeConstant(Y, UTF8_I),
+ new NameAndTypeConstant(Y, UTF8_L),
+ new NameAndTypeConstant(Y, UTF8_F),
+ new NameAndTypeConstant(Y, UTF8_D),
+ new NameAndTypeConstant(UTF8_EQUALS, UTF8_OBJECT_Z),
+ new NameAndTypeConstant(UTF8_LENGTH, UTF8__I),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_Z_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_C_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_I_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_J_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_F_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_D_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_OBJECT_STRING),
+ new NameAndTypeConstant(UTF8_INIT, UTF8__VOID),
+ new NameAndTypeConstant(UTF8_INIT, UTF8_STRING_VOID),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_Z_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_C_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_I_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_J_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_F_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_D_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_STRING_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_OBJECT_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_Z_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_C_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_I_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_J_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_F_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_D_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_STRING_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_OBJECT_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_TOSTRING, UTF8__STRING),
+
+ new Utf8Constant(""),
new Utf8Constant("I"),
new Utf8Constant("J"),
new Utf8Constant("F"),
new Utf8Constant("D"),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_EQUALS),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_EQUALS),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_LENGTH),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_LENGTH),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_VALUEOF),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_BOOLEAN),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_CHAR),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_INT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_LONG),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_FLOAT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_DOUBLE),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_VALUEOF_OBJECT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_INIT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_INIT),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_STRING_VOID),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_TOSTRING),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_TOSTRING),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_APPEND),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CHAR_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_INT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_LONG_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_FLOAT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_STRING_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_OBJECT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_BOOLEAN_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CHAR_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_INT_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_LONG_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_FLOAT_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOUBLE_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_STRING_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_OBJECT_STRING_BUILDER),
};
-
public static final Instruction[][][] VARIABLE = new Instruction[][][]
{
{ // nop = nothing
@@ -237,7 +468,7 @@ public class InstructionSequenceConstants
{ // a = a = nothing
{
new VariableInstruction(InstructionConstants.OP_ALOAD, X),
- new SimpleInstruction(InstructionConstants.OP_POP),
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
},{
// Nothing.
},
@@ -382,12 +613,12 @@ public class InstructionSequenceConstants
},
{ // c * i = i * c
{
- new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
new VariableInstruction(InstructionConstants.OP_ILOAD, X),
new SimpleInstruction(InstructionConstants.OP_IMUL),
},{
new VariableInstruction(InstructionConstants.OP_ILOAD, X),
- new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
new SimpleInstruction(InstructionConstants.OP_IMUL),
},
},
@@ -548,7 +779,7 @@ public class InstructionSequenceConstants
{ // i = i + c = i += c
{
new VariableInstruction(InstructionConstants.OP_ILOAD, X),
- new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
new SimpleInstruction(InstructionConstants.OP_IADD),
new VariableInstruction(InstructionConstants.OP_ISTORE, X),
},{
@@ -651,22 +882,23 @@ public class InstructionSequenceConstants
// Nothing.
},
},
- { // ... + 0f = ...
- {
- new SimpleInstruction(InstructionConstants.OP_FCONST_0),
- new SimpleInstruction(InstructionConstants.OP_FADD),
- },{
- // Nothing.
- },
- },
- { // ... + 0d = ...
- {
- new SimpleInstruction(InstructionConstants.OP_DCONST_0),
- new SimpleInstruction(InstructionConstants.OP_DADD),
- },{
- // Nothing.
- },
- },
+ // Not valid for -0.0.
+// { // ... + 0f = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_FADD),
+// },{
+// // Nothing.
+// },
+// },
+// { // ... + 0d = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_DADD),
+// },{
+// // Nothing.
+// },
+// },
{ // ... - 0 = ...
{
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -1072,7 +1304,8 @@ public class InstructionSequenceConstants
new SimpleInstruction(InstructionConstants.OP_FNEG),
},
},
-// { // ... * 0f = 0f (or NaN)
+ // Not valid for -0.0 and for NaN.
+// { // ... * 0f = 0f
// {
// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
// new SimpleInstruction(InstructionConstants.OP_FMUL),
@@ -1097,7 +1330,8 @@ public class InstructionSequenceConstants
new SimpleInstruction(InstructionConstants.OP_DNEG),
},
},
-// { // ... * 0d = 0d (or NaN)
+ // Not valid for -0.0 and for NaN.
+// { // ... * 0d = 0d
// {
// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
// new SimpleInstruction(InstructionConstants.OP_DMUL),
@@ -1504,6 +1738,7 @@ public class InstructionSequenceConstants
new SimpleInstruction(InstructionConstants.OP_ICONST_0),
},
},
+ // Not valid for negative values.
// { // ... % 2 = ... & 0x1
// {
// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
@@ -3348,4 +3583,1508 @@ public class InstructionSequenceConstants
// },
// }
};
-} \ No newline at end of file
+
+ public static final Instruction[][][] STRING = new Instruction[][][]
+ {
+ { // "...".equals("...") = true
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRING_EQUALS),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ },
+ },
+ { // "...".length() = ...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRING_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // String.valueOf(Z) = "....
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ },
+ },
+ { // String.valueOf(C) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ },
+ },
+ { // String.valueOf(Cc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ },
+ },
+ { // String.valueOf(I) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ },
+ },
+ { // String.valueOf(Ic) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ },
+ },
+ { // String.valueOf(J) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ },
+ },
+ { // String.valueOf(Jc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ },
+ },
+ { // String.valueOf(F) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ },
+ },
+ { // String.valueOf(Fc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ },
+ },
+ { // String.valueOf(D) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ },
+ },
+ { // String.valueOf(Dc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ },
+ },
+
+ { // new StringBuffer("...").toString() = "..." (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ },
+ },
+ { // new StringBuffer(string).toString() = string (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuffer("...").length() = length
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // new StringBuffer() (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...") (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer()/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...")/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(z)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(c)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(i)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(l)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(f)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(d)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(s)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // StringBuffer#toString()/pop = pop
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // StringBuffer#append("") = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_EMPTY),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer().append(Z) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(C) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Cc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(I) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Ic) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(J) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Jc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(F) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Fc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(D) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Dc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append("...") = new StringBuffer("...")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Z) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(C) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Cc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(I) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Ic) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(J) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Jc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(F) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Fc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(D) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Dc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append("...") = new StringBuffer("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Z) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(C) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Cc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(I) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Ic) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(J) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Jc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(F) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Fc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(D) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Dc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append("...") = StringBuffer#append("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // new StringBuffer().append(z).toString() = String.valueOf(z)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },
+ },
+ { // new StringBuffer().append(c).toString() = String.valueOf(c)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },
+ },
+ { // new StringBuffer().append(i).toString() = String.valueOf(i)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },
+ },
+ { // new StringBuffer().append(j).toString() = String.valueOf(j)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },
+ },
+ { // new StringBuffer().append(f).toString() = String.valueOf(f)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },
+ },
+ { // new StringBuffer().append(d).toString() = String.valueOf(d)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },
+ },
+ { // new StringBuffer().append(string).toString() = string
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuffer().append(object).toString() = String.valueOf(object)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_OBJECT),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_OBJECT),
+ },
+ },
+
+ { // new StringBuilder("...").toString() = "..." (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ },
+ },
+ { // new StringBuilder(string).toString() = string (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuilder("...").length() = length
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // new StringBuilder() (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...") (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder()/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...")/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(z)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(c)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(i)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(l)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(f)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(d)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(s)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // StringBuilder#toString()/pop = pop
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // StringBuilder#append("") = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_EMPTY),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder().append(Z) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(C) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Cc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(I) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Ic) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(J) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Jc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(F) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Fc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(D) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Dc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append("...") = new StringBuilder("...")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Z) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(C) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Cc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(I) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Ic) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(J) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Jc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(F) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Fc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(D) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Dc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append("...") = new StringBuilder("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Z) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(C) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Cc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(I) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Ic) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(J) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Jc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(F) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Fc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(D) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Dc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append("...") = StringBuilder#append("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // new StringBuilder().append(z).toString() = String.valueOf(z)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },
+ },
+ { // new StringBuilder().append(c).toString() = String.valueOf(c)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },
+ },
+ { // new StringBuilder().append(i).toString() = String.valueOf(i)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },
+ },
+ { // new StringBuilder().append(j).toString() = String.valueOf(j)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },
+ },
+ { // new StringBuilder().append(f).toString() = String.valueOf(f)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },
+ },
+ { // new StringBuilder().append(d).toString() = String.valueOf(d)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },
+ },
+ { // new StringBuilder().append(string).toString() = string
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuilder().append(object).toString() = String.valueOf(object)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_OBJECT),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_OBJECT),
+ },
+ },
+ };
+
+
+ /**
+ * Prints out the constants and the instruction sequences.
+ */
+ public static void main(String[] args)
+ {
+ ProgramClass clazz = new ProgramClass();
+ clazz.constantPool = CONSTANTS;
+
+ ClassPrinter printer = new ClassPrinter();
+
+ for (int index = 0; index < CONSTANTS.length; index++)
+ {
+ System.out.print("["+index+"] ");
+ try
+ {
+ CONSTANTS[index].accept(clazz, printer);
+ }
+ catch (Exception e)
+ {
+ System.out.println("("+e.getClass().getName()+")");
+ }
+ }
+
+ if (CONSTANTS.length != SENTINEL)
+ {
+ throw new IllegalStateException("Constants length ["+CONSTANTS.length+"] different from number of constant names ["+SENTINEL+"]");
+ }
+
+ Instruction[][][] sequences = STRING;
+
+ for (int sequence = 0; sequence < sequences.length; sequence++)
+ {
+ System.out.println();
+ Instruction[] instructions = sequences[sequence][0];
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+ try
+ {
+ instruction.accept(clazz, null, null, index, new ClassPrinter());
+ }
+ catch (Exception e) {}
+ }
+
+ System.out.println("=>");
+ instructions = sequences[sequence][1];
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+ try
+ {
+ instruction.accept(clazz, null, null, index, new ClassPrinter());
+ }
+ catch (Exception e) {}
+ }
+ }
+ }
+}
diff --git a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
index bce06e2..7ec1a95 100644
--- a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
+++ b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,9 +22,9 @@ package proguard.optimize.peephole;
import proguard.classfile.*;
import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
-import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.editor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
@@ -42,10 +42,48 @@ extends SimplifiedVisitor
implements InstructionVisitor,
ConstantVisitor
{
+ //*
private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = true;
+ //*/
+
+ public static final int X = InstructionSequenceMatcher.X;
+ public static final int Y = InstructionSequenceMatcher.Y;
+ public static final int Z = InstructionSequenceMatcher.Z;
+
+ public static final int A = InstructionSequenceMatcher.A;
+ public static final int B = InstructionSequenceMatcher.B;
+ public static final int C = InstructionSequenceMatcher.C;
+ public static final int D = InstructionSequenceMatcher.D;
+
+ private static final int BOOLEAN_STRING = 0x1;
+ private static final int CHAR_STRING = 0x2;
+ private static final int INT_STRING = 0x3;
+ private static final int LONG_STRING = 0x4;
+ private static final int FLOAT_STRING = 0x5;
+ private static final int DOUBLE_STRING = 0x6;
+ private static final int STRING_STRING = 0x7;
+
+ public static final int STRING_A_LENGTH = 0x20000000;
+ public static final int BOOLEAN_A_STRING = 0x20000001;
+ public static final int CHAR_A_STRING = 0x20000002;
+ public static final int INT_A_STRING = 0x20000003;
+ public static final int LONG_A_STRING = 0x20000004;
+ public static final int FLOAT_A_STRING = 0x20000005;
+ public static final int DOUBLE_A_STRING = 0x20000006;
+ public static final int STRING_A_STRING = 0x20000007;
+ public static final int BOOLEAN_B_STRING = 0x20000010;
+ public static final int CHAR_B_STRING = 0x20000020;
+ public static final int INT_B_STRING = 0x20000030;
+ public static final int LONG_B_STRING = 0x20000040;
+ public static final int FLOAT_B_STRING = 0x20000050;
+ public static final int DOUBLE_B_STRING = 0x20000060;
+ public static final int STRING_B_STRING = 0x20000070;
private final InstructionSequenceMatcher instructionSequenceMatcher;
+ private final Constant[] patternConstants;
private final Instruction[] replacementInstructions;
private final BranchTargetFinder branchTargetFinder;
private final CodeAttributeEditor codeAttributeEditor;
@@ -101,6 +139,7 @@ implements InstructionVisitor,
InstructionVisitor extraInstructionVisitor)
{
this.instructionSequenceMatcher = new InstructionSequenceMatcher(patternConstants, patternInstructions);
+ this.patternConstants = patternConstants;
this.replacementInstructions = replacementInstructions;
this.branchTargetFinder = branchTargetFinder;
this.codeAttributeEditor = codeAttributeEditor;
@@ -140,7 +179,7 @@ implements InstructionVisitor,
for (int index = 0; index < replacementInstructions.length; index++)
{
int matchedOffset = instructionSequenceMatcher.matchedInstructionOffset(index);
- System.out.println(" "+replacementInstructionFactory.create(index).shrink().toString(matchedOffset));
+ System.out.println(" "+replacementInstructionFactory.create(clazz, index).shrink().toString(matchedOffset));
}
}
@@ -148,7 +187,7 @@ implements InstructionVisitor,
for (int index = 0; index < replacementInstructions.length; index++)
{
codeAttributeEditor.replaceInstruction(instructionSequenceMatcher.matchedInstructionOffset(index),
- replacementInstructionFactory.create(index).shrink());
+ replacementInstructionFactory.create(clazz, index));
}
// Delete any remaining instructions in the from sequence.
@@ -204,17 +243,17 @@ implements InstructionVisitor,
* Creates the replacement instruction for the given index in the
* instruction sequence.
*/
- public Instruction create(int index)
+ public Instruction create(Clazz clazz, int index)
{
// Create the instruction.
- replacementInstructions[index].accept(null,
+ replacementInstructions[index].accept(clazz,
null,
null,
instructionSequenceMatcher.matchedInstructionOffset(index),
this);
// Return it.
- return replacementInstruction.shrink();
+ return replacementInstruction;
}
@@ -224,7 +263,7 @@ implements InstructionVisitor,
{
replacementInstruction =
new SimpleInstruction(simpleInstruction.opcode,
- instructionSequenceMatcher.matchedArgument(simpleInstruction.constant));
+ matchedArgument(clazz, simpleInstruction.constant));
}
@@ -241,7 +280,8 @@ implements InstructionVisitor,
{
replacementInstruction =
new ConstantInstruction(constantInstruction.opcode,
- instructionSequenceMatcher.matchedConstantIndex(constantInstruction.constantIndex),
+ matchedConstantIndex((ProgramClass)clazz,
+ constantInstruction.constantIndex),
instructionSequenceMatcher.matchedArgument(constantInstruction.constant));
}
@@ -250,7 +290,8 @@ implements InstructionVisitor,
{
replacementInstruction =
new BranchInstruction(branchInstruction.opcode,
- instructionSequenceMatcher.matchedBranchOffset(offset, branchInstruction.branchOffset));
+ instructionSequenceMatcher.matchedBranchOffset(offset,
+ branchInstruction.branchOffset));
}
@@ -261,7 +302,8 @@ implements InstructionVisitor,
instructionSequenceMatcher.matchedBranchOffset(offset, tableSwitchInstruction.defaultOffset),
instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.lowCase),
instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.highCase),
- instructionSequenceMatcher.matchedJumpOffsets(offset, tableSwitchInstruction.jumpOffsets));
+ instructionSequenceMatcher.matchedJumpOffsets(offset,
+ tableSwitchInstruction.jumpOffsets));
}
@@ -274,5 +316,105 @@ implements InstructionVisitor,
instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases),
instructionSequenceMatcher.matchedJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets));
}
+
+
+ /**
+ * Returns the matched argument for the given pattern argument.
+ */
+ private int matchedArgument(Clazz clazz, int argument)
+ {
+ // Special case: do we have to compute the string length?
+ if (argument == STRING_A_LENGTH)
+ {
+ // Return the string length.
+ return clazz.getStringString(instructionSequenceMatcher.matchedArgument(A)).length();
+ }
+
+ // Otherwise, just return the matched argument.
+ return instructionSequenceMatcher.matchedArgument(argument);
+ }
+
+
+ /**
+ * Returns the matched or newly created constant index for the given
+ * pattern constant index.
+ */
+ private int matchedConstantIndex(ProgramClass programClass, int constantIndex)
+ {
+ // Special case: do we have to create a concatenated string?
+ if (constantIndex >= BOOLEAN_A_STRING &&
+ constantIndex <= (STRING_A_STRING | STRING_B_STRING))
+ {
+ // Create a new string constant and return its index.
+ return new ConstantPoolEditor(programClass).addStringConstant(
+ argumentAsString(programClass, constantIndex & 0xf, A) +
+ argumentAsString(programClass, (constantIndex >>> 4) & 0xf, B),
+ null,
+ null);
+ }
+
+ int matchedConstantIndex =
+ instructionSequenceMatcher.matchedConstantIndex(constantIndex);
+
+ // Do we have a matched constant index?
+ if (matchedConstantIndex > 0)
+ {
+ // Return its index.
+ return matchedConstantIndex;
+ }
+
+ // Otherwise, we still have to create a new constant.
+ // This currently only works for constants without any wildcards.
+ ProgramClass dummyClass = new ProgramClass();
+ dummyClass.constantPool = patternConstants;
+
+ return new ConstantAdder(programClass).addConstant(dummyClass, constantIndex);
+ }
+
+
+ private String argumentAsString(ProgramClass programClass,
+ int valueType,
+ int argument)
+ {
+ switch (valueType)
+ {
+ case BOOLEAN_STRING:
+ return Boolean.toString((instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument)) != 0);
+
+ case CHAR_STRING:
+ return Character.toString((char)(instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument)));
+
+ case INT_STRING:
+ return Integer.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case LONG_STRING:
+ return Long.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((LongConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case FLOAT_STRING:
+ return Float.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((FloatConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case DOUBLE_STRING:
+ return Double.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((DoubleConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case STRING_STRING:
+ return
+ programClass.getStringString(instructionSequenceMatcher.matchedConstantIndex(argument));
+
+ default:
+ return "";
+ }
+ }
}
}
diff --git a/src/proguard/optimize/peephole/InstructionSequencesReplacer.java b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
index f12b51a..22fb6cd 100644
--- a/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
+++ b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MemberPrivatizer.java b/src/proguard/optimize/peephole/MemberPrivatizer.java
index 55b2f31..f57281c 100644
--- a/src/proguard/optimize/peephole/MemberPrivatizer.java
+++ b/src/proguard/optimize/peephole/MemberPrivatizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MethodFinalizer.java b/src/proguard/optimize/peephole/MethodFinalizer.java
index af1811b..89174ac 100644
--- a/src/proguard/optimize/peephole/MethodFinalizer.java
+++ b/src/proguard/optimize/peephole/MethodFinalizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MethodInliner.java b/src/proguard/optimize/peephole/MethodInliner.java
index 55f9ccb..947cd43 100644
--- a/src/proguard/optimize/peephole/MethodInliner.java
+++ b/src/proguard/optimize/peephole/MethodInliner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -29,10 +29,11 @@ import proguard.classfile.editor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
-import proguard.classfile.visitor.MemberVisitor;
+import proguard.classfile.visitor.*;
+import proguard.optimize.*;
import proguard.optimize.info.*;
-import java.util.Stack;
+import java.util.*;
/**
* This AttributeVisitor inlines short methods or methods that are only invoked
@@ -48,10 +49,8 @@ implements AttributeVisitor,
MemberVisitor
{
private static final int MAXIMUM_INLINED_CODE_LENGTH = Integer.parseInt(System.getProperty("maximum.inlined.code.length", "8"));
- private static final int MAXIMUM_RESULTING_CODE_LENGTH_JSE = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "8000"));
+ private static final int MAXIMUM_RESULTING_CODE_LENGTH_JSE = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "7000"));
private static final int MAXIMUM_RESULTING_CODE_LENGTH_JME = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "2000"));
- private static final int MAXIMUM_CODE_EXPANSION = 2;
- private static final int MAXIMUM_EXTRA_CODE_LENGTH = 128;
//*
private static final boolean DEBUG = false;
@@ -138,6 +137,42 @@ implements AttributeVisitor,
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
+ // TODO: Remove this when the method inliner has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while inlining method:");
+ System.err.println(" Target class = ["+targetClass.getName()+"]");
+ System.err.println(" Target method = ["+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
+ if (inlining)
+ {
+ System.err.println(" Inlined class = ["+clazz.getName()+"]");
+ System.err.println(" Inlined method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+ System.err.println("Not inlining this method");
+
+ if (DEBUG)
+ {
+ targetMethod.accept(targetClass, new ClassPrinter());
+ if (inlining)
+ {
+ method.accept(clazz, new ClassPrinter());
+ }
+
+ throw ex;
+ }
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
if (!inlining)
{
// codeAttributeComposer.DEBUG = DEBUG =
@@ -278,7 +313,7 @@ implements AttributeVisitor,
}
codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
- new VariableInstruction(opcode, variableOffset + parameterOffset + parameterIndex).shrink());
+ new VariableInstruction(opcode, variableOffset + parameterOffset + parameterIndex));
}
}
@@ -286,7 +321,7 @@ implements AttributeVisitor,
if (!isStatic)
{
codeAttributeComposer.appendInstruction(parameterSize,
- new VariableInstruction(InstructionConstants.OP_ASTORE, variableOffset).shrink());
+ new VariableInstruction(InstructionConstants.OP_ASTORE, variableOffset));
}
codeAttributeComposer.endCodeFragment();
@@ -305,12 +340,12 @@ implements AttributeVisitor,
// Copy the instructions.
codeAttribute.instructionsAccept(clazz, method, this);
- // Copy the exceptions.
- codeAttribute.exceptionsAccept(clazz, method, exceptionInfoAdder);
-
// Append a label just after the code.
codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+ // Copy the exceptions.
+ codeAttribute.exceptionsAccept(clazz, method, exceptionInfoAdder);
+
codeAttributeComposer.endCodeFragment();
}
@@ -319,7 +354,7 @@ implements AttributeVisitor,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
- codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, instruction);
}
@@ -346,7 +381,7 @@ implements AttributeVisitor,
codeAttribute.u4codeLength - offset);
codeAttributeComposer.appendInstruction(offset,
- branchInstruction.shrink());
+ branchInstruction);
}
else
{
@@ -359,7 +394,7 @@ implements AttributeVisitor,
}
}
- codeAttributeComposer.appendInstruction(offset, simpleInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, simpleInstruction);
}
@@ -372,7 +407,7 @@ implements AttributeVisitor,
variableInstruction.variableIndex += variableOffset;
}
- codeAttributeComposer.appendInstruction(offset, variableInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, variableInstruction);
}
@@ -430,7 +465,7 @@ implements AttributeVisitor,
constantAdder.addConstant(clazz, constantInstruction.constantIndex);
}
- codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, constantInstruction);
}
@@ -454,45 +489,48 @@ implements AttributeVisitor,
{
int accessFlags = programMethod.getAccessFlags();
- if (// Only inline the method if it is private, static, or final.
+ if (// Don't inline methods that must be preserved.
+ !KeepMarker.isKept(programMethod) &&
+
+ // Only inline the method if it is private, static, or final.
(accessFlags & (ClassConstants.INTERNAL_ACC_PRIVATE |
ClassConstants.INTERNAL_ACC_STATIC |
- ClassConstants.INTERNAL_ACC_FINAL)) != 0 &&
+ ClassConstants.INTERNAL_ACC_FINAL)) != 0 &&
// Only inline the method if it is not synchronized, etc.
(accessFlags & (ClassConstants.INTERNAL_ACC_SYNCHRONIZED |
ClassConstants.INTERNAL_ACC_NATIVE |
ClassConstants.INTERNAL_ACC_INTERFACE |
- ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 &&
+ ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 &&
// Don't inline an <init> method, except in an <init> method in the
// same class.
// (!programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ||
// (programClass.equals(targetClass) &&
// targetMethod.getName(targetClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))) &&
- !programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) &&
+ !programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) &&
// Don't inline a method into itself.
(!programMethod.equals(targetMethod) ||
- !programClass.equals(targetClass)) &&
+ !programClass.equals(targetClass)) &&
// Only inline the method if it isn't recursing.
- !inliningMethods.contains(programMethod) &&
+ !inliningMethods.contains(programMethod) &&
// Only inline the method if its target class has at least the
// same version number as the source class, in order to avoid
// introducing incompatible constructs.
- targetClass.u4version >= programClass.u4version &&
+ targetClass.u4version >= programClass.u4version &&
// Only inline the method if it doesn't invoke a super method, or if
// it is in the same class.
(!SuperInvocationMarker.invokesSuperMethods(programMethod) ||
- programClass.equals(targetClass)) &&
+ programClass.equals(targetClass)) &&
// Only inline the method if it doesn't branch backward while there
// are uninitialized objects.
(!BackwardBranchMarker.branchesBackward(programMethod) ||
- uninitializedObjectCount == 0) &&
+ uninitializedObjectCount == 0) &&
// Only inline if the code access of the inlined method allows it.
(allowAccessModification ||
@@ -501,47 +539,24 @@ implements AttributeVisitor,
(!AccessMethodMarker.accessesPackageCode(programMethod) ||
ClassUtil.internalPackageName(programClass.getName()).equals(
- ClassUtil.internalPackageName(targetClass.getName()))))) &&
+ ClassUtil.internalPackageName(targetClass.getName()))))) &&
// (!AccessMethodMarker.accessesProtectedCode(programMethod) ||
// targetClass.extends_(programClass) ||
// targetClass.implements_(programClass)) ||
(!AccessMethodMarker.accessesProtectedCode(programMethod) ||
- programClass.equals(targetClass)) &&
+ programClass.equals(targetClass)) &&
// Only inline the method if it doesn't catch exceptions, or if it
// is invoked with an empty stack.
(!CatchExceptionMarker.catchesExceptions(programMethod) ||
- emptyInvokingStack) &&
+ emptyInvokingStack) &&
- // Only inline the method if it comes from the same class or from
- // a class with a static initializer.
+ // Only inline the method if it comes from the a class with at most
+ // a subset of the initialized superclasses.
(programClass.equals(targetClass) ||
- programClass.findMethod(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
- ClassConstants.INTERNAL_METHOD_TYPE_CLINIT) == null))
- {
-// System.out.print("MethodInliner: inlining ");
-// programMethod.accept(programClass, new SimpleClassPrinter(true));
-// System.out.print(" in ");
-// targetMethod.accept(targetClass, new SimpleClassPrinter(true));
-//
-// System.out.println(" Private: "+
-// (!AccessMethodMarker.accessesPrivateCode(programMethod) ||
-// programClass.equals(targetClass)));
-//
-// System.out.println(" Package: "+
-// (!AccessMethodMarker.accessesPackageCode(programMethod) ||
-// ClassUtil.internalPackageName(programClass.getName()).equals(
-// ClassUtil.internalPackageName(targetClass.getName()))));
-//
-// System.out.println(" Protected: "+
-// ((!AccessMethodMarker.accessesProtectedCode(programMethod) ||
-// targetClass.extends_(programClass) ||
-// targetClass.implements_(programClass)) ||
-// ClassUtil.internalPackageName(programClass.getName()).equals(
-// ClassUtil.internalPackageName(targetClass.getName()))));
-
- boolean oldInlining = inlining;
+ initializedSuperClasses(targetClass).containsAll(initializedSuperClasses(programClass))))
+ { boolean oldInlining = inlining;
inlining = true;
inliningMethods.push(programMethod);
@@ -564,4 +579,21 @@ implements AttributeVisitor,
uninitializedObjectCount--;
}
}
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new ClassCollector(set)));
+
+ return set;
+ }
}
diff --git a/src/proguard/optimize/peephole/NopRemover.java b/src/proguard/optimize/peephole/NopRemover.java
index 69adb30..9396c40 100644
--- a/src/proguard/optimize/peephole/NopRemover.java
+++ b/src/proguard/optimize/peephole/NopRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/PeepholeOptimizer.java b/src/proguard/optimize/peephole/PeepholeOptimizer.java
index 98f8e8d..2a602ee 100644
--- a/src/proguard/optimize/peephole/PeepholeOptimizer.java
+++ b/src/proguard/optimize/peephole/PeepholeOptimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/ReachableCodeMarker.java b/src/proguard/optimize/peephole/ReachableCodeMarker.java
index d9dbf2d..b6fcf18 100644
--- a/src/proguard/optimize/peephole/ReachableCodeMarker.java
+++ b/src/proguard/optimize/peephole/ReachableCodeMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,6 +27,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor finds all instruction offsets, branch targets, and
* exception targets in the CodeAttribute objects that it visits.
@@ -91,10 +93,7 @@ implements AttributeVisitor,
else
{
// Reset the array.
- for (int index = 0; index < codeLength; index++)
- {
- isReachable[index] = false;
- }
+ Arrays.fill(isReachable, 0, codeLength, false);
}
// Mark the code, starting at the entry point.
diff --git a/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
index 6707a12..a67c6ff 100644
--- a/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
+++ b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,6 +28,8 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
+import java.util.Arrays;
+
/**
* This ClassVisitor removes InnerClasses and EnclosingMethod attributes in
* classes that are retargeted or that refer to classes that are retargeted.
@@ -70,12 +72,9 @@ implements ClassVisitor,
}
// Clean up any remaining array elements.
- for (int index = newAtributesCount; index < attributesCount; index++)
- {
- attributes[index] = null;
- }
+ Arrays.fill(attributes, newAtributesCount, attributesCount, null);
- // Update the number of attribuets.
+ // Update the number of attributes.
programClass.u2attributesCount = newAtributesCount;
}
@@ -90,8 +89,39 @@ implements ClassVisitor,
// Check whether the class itself is retargeted.
checkTarget(clazz);
- // Check whether the referenced classes are retargeted.
- innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ if (!retargeted)
+ {
+ // Check whether the referenced classes are retargeted.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ int classesCount = innerClassesAttribute.u2classesCount;
+ InnerClassesInfo[] classes = innerClassesAttribute.classes;
+
+ int newClassesCount = 0;
+
+ // Copy over all non-retargeted attributes.
+ for (int index = 0; index < classesCount; index++)
+ {
+ InnerClassesInfo classInfo = classes[index];
+
+ // Check if the outer class or inner class is a retargeted class.
+ retargeted = false;
+ classInfo.outerClassConstantAccept(clazz, this);
+ classInfo.innerClassConstantAccept(clazz, this);
+ if (!retargeted)
+ {
+ classes[newClassesCount++] = classInfo;
+ }
+ }
+
+ // Clean up any remaining array elements.
+ Arrays.fill(classes, newClassesCount, classesCount, null);
+
+ // Update the number of classes.
+ innerClassesAttribute.u2classesCount = newClassesCount;
+
+ // Remove the attribute altogether if it's empty.
+ retargeted = newClassesCount == 0;
+ }
}
diff --git a/src/proguard/optimize/peephole/TargetClassChanger.java b/src/proguard/optimize/peephole/TargetClassChanger.java
index 22fd83d..f997e03 100644
--- a/src/proguard/optimize/peephole/TargetClassChanger.java
+++ b/src/proguard/optimize/peephole/TargetClassChanger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -51,13 +51,13 @@ implements ClassVisitor,
AnnotationVisitor,
ElementValueVisitor
{
+ private static final boolean DEBUG = false;
+
+
// Implementations for ClassVisitor.
public void visitProgramClass(ProgramClass programClass)
{
- Clazz superClass = null;
- Clazz[] interfaceClasses = null;
-
// Change the references of the constant pool.
programClass.constantPoolEntriesAccept(this);
@@ -80,34 +80,39 @@ implements ClassVisitor,
programClass.getName(),
programClass);
+ // This class will loose all its interfaces.
+ programClass.u2interfacesCount = 0;
+
// This class will loose all its subclasses.
programClass.subClasses = null;
}
-
- // Remove interface classes that are pointing to this class.
- int newInterfacesCount = 0;
- for (int index = 0; index < programClass.u2interfacesCount; index++)
+ else
{
- Clazz interfaceClass = programClass.getInterface(index);
- if (!programClass.equals(interfaceClass))
+ // Remove interface classes that are pointing to this class.
+ int newInterfacesCount = 0;
+ for (int index = 0; index < programClass.u2interfacesCount; index++)
{
- programClass.u2interfaces[newInterfacesCount++] =
- programClass.u2interfaces[index];
+ Clazz interfaceClass = programClass.getInterface(index);
+ if (!programClass.equals(interfaceClass))
+ {
+ programClass.u2interfaces[newInterfacesCount++] =
+ programClass.u2interfaces[index];
+ }
}
- }
- programClass.u2interfacesCount = newInterfacesCount;
+ programClass.u2interfacesCount = newInterfacesCount;
- // Update the subclasses of the superclass and interfaces of the
- // target class.
- ConstantVisitor subclassAdder =
- new ReferencedClassVisitor(
- new SubclassFilter(programClass,
- new SubclassAdder(programClass)));
+ // Update the subclasses of the superclass and interfaces of the
+ // target class.
+ ConstantVisitor subclassAdder =
+ new ReferencedClassVisitor(
+ new SubclassFilter(programClass,
+ new SubclassAdder(programClass)));
- programClass.superClassConstantAccept(subclassAdder);
- programClass.interfaceConstantsAccept(subclassAdder);
+ programClass.superClassConstantAccept(subclassAdder);
+ programClass.interfaceConstantsAccept(subclassAdder);
- // TODO: Maybe restore private method references.
+ // TODO: Maybe restore private method references.
+ }
}
@@ -188,6 +193,12 @@ implements ClassVisitor,
Clazz newReferencedClass = updateReferencedClass(referencedClass);
if (referencedClass != newReferencedClass)
{
+ if (DEBUG)
+ {
+ System.out.println("TargetClassChanger:");
+ System.out.println(" ["+clazz.getName()+"] changing reference from ["+refConstant.referencedClass+"."+refConstant.referencedMember.getName(refConstant.referencedClass)+refConstant.referencedMember.getDescriptor(refConstant.referencedClass)+"]");
+ }
+
// Change the referenced class.
refConstant.referencedClass = newReferencedClass;
@@ -197,6 +208,11 @@ implements ClassVisitor,
refConstant.getName(clazz),
refConstant.getType(clazz),
newReferencedClass);
+
+ if (DEBUG)
+ {
+ System.out.println(" ["+clazz.getName()+"] to ["+refConstant.referencedClass+"."+refConstant.referencedMember.getName(refConstant.referencedClass)+refConstant.referencedMember.getDescriptor(refConstant.referencedClass)+"]");
+ }
}
}
diff --git a/src/proguard/optimize/peephole/UnreachableCodeRemover.java b/src/proguard/optimize/peephole/UnreachableCodeRemover.java
index e8a99ab..570b3ca 100644
--- a/src/proguard/optimize/peephole/UnreachableCodeRemover.java
+++ b/src/proguard/optimize/peephole/UnreachableCodeRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/UnreachableExceptionRemover.java b/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
index 048f5e3..8e77716 100644
--- a/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
+++ b/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/VariableShrinker.java b/src/proguard/optimize/peephole/VariableShrinker.java
index 45b694f..6c05944 100644
--- a/src/proguard/optimize/peephole/VariableShrinker.java
+++ b/src/proguard/optimize/peephole/VariableShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/VerticalClassMerger.java b/src/proguard/optimize/peephole/VerticalClassMerger.java
index 29ed6ff..825de94 100644
--- a/src/proguard/optimize/peephole/VerticalClassMerger.java
+++ b/src/proguard/optimize/peephole/VerticalClassMerger.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/preverify/CodePreverifier.java b/src/proguard/preverify/CodePreverifier.java
index fa60b9a..7c38259 100644
--- a/src/proguard/preverify/CodePreverifier.java
+++ b/src/proguard/preverify/CodePreverifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -42,8 +42,7 @@ import java.util.*;
*/
public class CodePreverifier
extends SimplifiedVisitor
-implements MemberVisitor,
- AttributeVisitor
+implements AttributeVisitor
{
//*
private static final boolean DEBUG = false;
@@ -54,8 +53,9 @@ implements MemberVisitor,
private final boolean microEdition;
- private final PartialEvaluator partialEvaluator = new PartialEvaluator();
- private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer(partialEvaluator);
+ private final PartialEvaluator partialEvaluator = new PartialEvaluator();
+ private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer(partialEvaluator);
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
/**
@@ -102,18 +102,27 @@ implements MemberVisitor,
ProgramClass programClass = (ProgramClass)clazz;
ProgramMethod programMethod = (ProgramMethod)method;
+ int codeLength = codeAttribute.u4codeLength;
+
// Evaluate the method.
//partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
livenessAnalyzer.visitCodeAttribute(clazz, method, codeAttribute);
+ // We may have to remove unreachable code.
+ codeAttributeEditor.reset(codeLength);
+
// Collect the stack map frames.
List stackMapFrameList = new ArrayList();
- for (int offset = 0; offset < codeAttribute.u4codeLength; offset++)
+ for (int offset = 0; offset < codeLength; offset++)
{
// Only store frames at the beginning of code blocks.
- if (partialEvaluator.isTraced(offset) &&
- partialEvaluator.isBranchOrExceptionTarget(offset))
+ if (!partialEvaluator.isTraced(offset))
+ {
+ // Mark the unreachable instruction for deletion.
+ codeAttributeEditor.deleteInstruction(offset);
+ }
+ else if (partialEvaluator.isBranchOrExceptionTarget(offset))
{
// Convert the variable values to types.
VerificationType[] variableTypes =
@@ -235,6 +244,9 @@ implements MemberVisitor,
stackMapAttribute.accept(programClass, programMethod, codeAttribute, new ClassPrinter());
}
}
+
+ // Apply code modifications, deleting unreachable code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
}
@@ -433,7 +445,7 @@ implements MemberVisitor,
isDupOrSwap(codeAttribute.code[producerOffset]))
{
producers = partialEvaluator.getStackBefore(producerOffset).getTopProducerValue(0).instructionOffsetValue();
- producerOffset = producers.instructionOffset(0);
+ producerOffset = producers.minimumValue();
}
// Are we in an instance initialization method,
diff --git a/src/proguard/preverify/CodeSubroutineInliner.java b/src/proguard/preverify/CodeSubroutineInliner.java
index 603eb75..c1549a3 100644
--- a/src/proguard/preverify/CodeSubroutineInliner.java
+++ b/src/proguard/preverify/CodeSubroutineInliner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -45,12 +45,12 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = System.getProperty("csi") != null;
//*/
private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
- private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(true);
+ private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(true, true);
private ExceptionInfoVisitor subroutineExceptionInliner = this;
private int clipStart = 0;
@@ -67,6 +67,7 @@ implements AttributeVisitor,
// DEBUG =
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
+// CodeAttributeComposer.DEBUG = DEBUG;
// TODO: Remove this when the subroutine inliner has stabilized.
// Catch any unexpected exceptions from the actual visiting method.
@@ -97,7 +98,7 @@ implements AttributeVisitor,
branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);
// Don't bother if there aren't any subroutines anyway.
- if (!containsSubroutines(codeAttribute))
+ if (!branchTargetFinder.containsSubroutines())
{
return;
}
@@ -161,23 +162,6 @@ implements AttributeVisitor,
/**
- * Returns whether the given code attribute contains any subroutines.
- */
- private boolean containsSubroutines(CodeAttribute codeAttribute)
- {
- for (int offset = 0; offset < codeAttribute.u4codeLength; offset++)
- {
- if (branchTargetFinder.isSubroutineInvocation(offset))
- {
- return true;
- }
- }
-
- return false;
- }
-
-
- /**
* Appends the specified subroutine.
*/
private void inlineSubroutine(Clazz clazz,
@@ -245,7 +229,7 @@ implements AttributeVisitor,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
// Append the instruction.
- codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, instruction);
}
@@ -275,7 +259,7 @@ implements AttributeVisitor,
// Replace the instruction by a branch.
Instruction replacementInstruction =
new BranchInstruction(InstructionConstants.OP_GOTO,
- branchTargetFinder.subroutineEnd(offset) - offset).shrink();
+ branchTargetFinder.subroutineEnd(offset) - offset);
codeAttributeComposer.appendInstruction(offset, replacementInstruction);
}
@@ -331,7 +315,7 @@ implements AttributeVisitor,
// Replace the subroutine invocation by a simple branch.
Instruction replacementInstruction =
new BranchInstruction(InstructionConstants.OP_GOTO,
- branchOffset).shrink();
+ branchOffset);
codeAttributeComposer.appendInstruction(offset, replacementInstruction);
}
diff --git a/src/proguard/preverify/Preverifier.java b/src/proguard/preverify/Preverifier.java
index e071c5c..da9649b 100644
--- a/src/proguard/preverify/Preverifier.java
+++ b/src/proguard/preverify/Preverifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -59,13 +59,12 @@ public class Preverifier
new AllAttributeVisitor(
new CodePreverifier(configuration.microEdition)));
- // In Java Standard Edition, only class files from Java 6 or higher
- // should be preverified.
+ // Classes from Java 6 may optionally be preverified.
+ // Classes from Java 7 or higher must be preverified.
if (!configuration.microEdition)
{
preverifier =
new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_6,
- Integer.MAX_VALUE,
preverifier);
}
diff --git a/src/proguard/preverify/SubroutineInliner.java b/src/proguard/preverify/SubroutineInliner.java
index e28512f..e21c469 100644
--- a/src/proguard/preverify/SubroutineInliner.java
+++ b/src/proguard/preverify/SubroutineInliner.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -65,7 +65,6 @@ public class SubroutineInliner
{
inliner =
new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_6,
- Integer.MAX_VALUE,
inliner);
}
diff --git a/src/proguard/retrace/ReTrace.java b/src/proguard/retrace/ReTrace.java
index bf6a145..91ab2a7 100644
--- a/src/proguard/retrace/ReTrace.java
+++ b/src/proguard/retrace/ReTrace.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -40,17 +40,14 @@ implements MappingProcessor
private static final String REGEX_OPTION = "-regex";
private static final String VERBOSE_OPTION = "-verbose";
- // BEGIN android-changed
- // Use regex from latest version (4.9) because it is
- // able to handle Android Bugreport format
+
public static final String STACK_TRACE_EXPRESSION = "(?:.*?\\bat\\s+%c.%m\\s*\\(.*?(?::%l)?\\)\\s*)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)";
- // END android-changed
private static final String REGEX_CLASS = "\\b(?:[A-Za-z0-9_$]+\\.)*[A-Za-z0-9_$]+\\b";
private static final String REGEX_CLASS_SLASH = "\\b(?:[A-Za-z0-9_$]+/)*[A-Za-z0-9_$]+\\b";
private static final String REGEX_LINE_NUMBER = "\\b[0-9]+\\b";
private static final String REGEX_TYPE = REGEX_CLASS + "(?:\\[\\])*";
- private static final String REGEX_MEMBER = "\\b[A-Za-z0-9_$]+\\b";
+ private static final String REGEX_MEMBER = "<?\\b[A-Za-z0-9_$]+\\b>?";
private static final String REGEX_ARGUMENTS = "(?:" + REGEX_TYPE + "(?:\\s*,\\s*" + REGEX_TYPE + ")*)?";
// The class settings.
diff --git a/src/proguard/shrink/AnnotationUsageMarker.java b/src/proguard/shrink/AnnotationUsageMarker.java
index 9aaae34..b9051a0 100644
--- a/src/proguard/shrink/AnnotationUsageMarker.java
+++ b/src/proguard/shrink/AnnotationUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -52,8 +52,7 @@ implements AttributeVisitor,
// Fields acting as a return parameters for several methods.
private boolean attributeUsed;
private boolean annotationUsed;
- private boolean elementValueUsed;
- private boolean classUsed;
+ private boolean allClassesUsed;
private boolean methodUsed;
@@ -151,9 +150,6 @@ implements AttributeVisitor,
markConstant(clazz, constantElementValue.u2elementNameIndex);
markConstant(clazz, constantElementValue.u2constantValueIndex);
-
- // The return value.
- elementValueUsed = true;
}
}
@@ -163,10 +159,10 @@ implements AttributeVisitor,
if (isReferencedMethodUsed(enumConstantElementValue))
{
// Check the referenced classes.
- classUsed = true;
- enumConstantElementValue.referencedClassesAccept(usageMarker);
+ allClassesUsed = true;
+ enumConstantElementValue.referencedClassesAccept(this);
- if (classUsed)
+ if (allClassesUsed)
{
// Mark the element value as being used.
usageMarker.markAsUsed(enumConstantElementValue);
@@ -174,9 +170,6 @@ implements AttributeVisitor,
markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
-
- // The return value.
- elementValueUsed = true;
}
}
}
@@ -186,21 +179,16 @@ implements AttributeVisitor,
{
if (isReferencedMethodUsed(classElementValue))
{
- // Check the referenced classes.
- classUsed = true;
- classElementValue.referencedClassesAccept(usageMarker);
-
- if (classUsed)
- {
- // Mark the element value as being used.
- usageMarker.markAsUsed(classElementValue);
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(classElementValue);
- markConstant(clazz, classElementValue.u2elementNameIndex);
- markConstant(clazz, classElementValue.u2classInfoIndex);
+ markConstant(clazz, classElementValue.u2elementNameIndex);
+ markConstant(clazz, classElementValue.u2classInfoIndex);
- // The return value.
- elementValueUsed = true;
- }
+ // Mark the referenced classes, since they can be retrieved from
+ // the annotation and then used.
+ // TODO: This could mark more annotation methods, affecting other annotations.
+ classElementValue.referencedClassesAccept(usageMarker);
}
}
@@ -221,9 +209,6 @@ implements AttributeVisitor,
usageMarker.markAsUsed(annotationElementValue);
markConstant(clazz, annotationElementValue.u2elementNameIndex);
-
- // The return value.
- elementValueUsed = true;
}
annotationUsed = oldAnnotationUsed;
@@ -235,26 +220,13 @@ implements AttributeVisitor,
{
if (isReferencedMethodUsed(arrayElementValue))
{
- boolean oldelementValueUsed = elementValueUsed;
-
// Check and mark the contained element values.
- elementValueUsed = false;
arrayElementValue.elementValuesAccept(clazz, annotation, this);
- if (elementValueUsed)
- {
- // Mark the element value as being used.
- usageMarker.markAsUsed(arrayElementValue);
-
- markConstant(clazz, arrayElementValue.u2elementNameIndex);
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(arrayElementValue);
- // The return value.
- //elementValueUsed = true;
- }
- else
- {
- elementValueUsed = oldelementValueUsed;
- }
+ markConstant(clazz, arrayElementValue.u2elementNameIndex);
}
}
@@ -269,17 +241,15 @@ implements AttributeVisitor,
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
- classUsed = usageMarker.isUsed(classConstant);
-
// Is the class constant marked as being used?
- if (!classUsed)
+ if (!usageMarker.isUsed(classConstant))
{
// Check the referenced class.
- classUsed = true;
+ allClassesUsed = true;
classConstant.referencedClassAccept(this);
// Is the referenced class marked as being used?
- if (classUsed)
+ if (allClassesUsed)
{
// Mark the class constant and its Utf8 constant.
usageMarker.markAsUsed(classConstant);
@@ -294,13 +264,12 @@ implements AttributeVisitor,
public void visitProgramClass(ProgramClass programClass)
{
- classUsed = usageMarker.isUsed(programClass);
+ allClassesUsed &= usageMarker.isUsed(programClass);
}
public void visitLibraryClass(LibraryClass libraryClass)
{
- classUsed = true;
}
@@ -314,7 +283,6 @@ implements AttributeVisitor,
public void visitLibraryMethod(LibraryClass LibraryClass, LibraryMethod libraryMethod)
{
- classUsed = true;
}
@@ -326,10 +294,10 @@ implements AttributeVisitor,
private boolean isReferencedClassUsed(Annotation annotation)
{
// Check if the referenced class is being used.
- classUsed = true;
+ allClassesUsed = true;
annotation.referencedClassAccept(this);
- return classUsed;
+ return allClassesUsed;
}
diff --git a/src/proguard/shrink/ClassShrinker.java b/src/proguard/shrink/ClassShrinker.java
index 0b5c5b7..f590c63 100644
--- a/src/proguard/shrink/ClassShrinker.java
+++ b/src/proguard/shrink/ClassShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -24,15 +24,17 @@ import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
import proguard.classfile.attribute.annotation.visitor.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.editor.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
+import java.util.Arrays;
+
/**
- * This ClassVisitor removes constant pool entries and class members that
- * are not marked as being used.
+ * This ClassVisitor removes constant pool entries, class members, and other
+ * class elements that are not marked as being used.
*
* @see UsageMarker
*
@@ -48,8 +50,7 @@ implements ClassVisitor,
{
private final UsageMarker usageMarker;
- private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
-
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
@@ -76,7 +77,7 @@ implements ClassVisitor,
programClass.u2interfacesCount);
// Shrinking the constant pool also sets up an index map.
- programClass.u2constantPoolCount =
+ int newConstantPoolCount =
shrinkConstantPool(programClass.constantPool,
programClass.u2constantPoolCount);
@@ -98,9 +99,15 @@ implements ClassVisitor,
programClass.methodsAccept(this);
programClass.attributesAccept(this);
- // Remap all constant pool references.
- constantPoolRemapper.setConstantIndexMap(constantIndexMap);
- constantPoolRemapper.visitProgramClass(programClass);
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
// Remove the unused interfaces from the class signature.
programClass.attributesAccept(new SignatureShrinker());
@@ -140,6 +147,15 @@ implements ClassVisitor,
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Shrink the array of BootstrapMethodInfo objects.
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount =
+ shrinkArray(bootstrapMethodsAttribute.bootstrapMethods,
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount);
+ }
+
+
public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
{
// Shrink the array of InnerClassesInfo objects.
@@ -173,6 +189,27 @@ implements ClassVisitor,
codeAttribute.u2attributesCount =
shrinkArray(codeAttribute.attributes,
codeAttribute.u2attributesCount);
+
+ // Shrink the attributes themselves.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Shrink the local variable info array.
+ localVariableTableAttribute.u2localVariableTableLength =
+ shrinkArray(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Shrink the local variable type info array.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength =
+ shrinkArray(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength);
}
@@ -349,10 +386,7 @@ implements ClassVisitor,
}
// Clear the remaining constant pool elements.
- for (int index = counter; index < length; index++)
- {
- constantPool[index] = null;
- }
+ Arrays.fill(constantPool, counter, length, null);
return counter;
}
@@ -377,10 +411,7 @@ implements ClassVisitor,
}
// Clear the remaining array elements.
- for (int index = counter; index < length; index++)
- {
- array[index] = 0;
- }
+ Arrays.fill(array, counter, length, 0);
return counter;
}
@@ -437,10 +468,10 @@ implements ClassVisitor,
}
}
- // Clear the remaining array elements.
- for (int index = counter; index < length; index++)
+ // Clear any remaining array elements.
+ if (counter < length)
{
- array[index] = null;
+ Arrays.fill(array, counter, length, null);
}
return counter;
diff --git a/src/proguard/shrink/InnerUsageMarker.java b/src/proguard/shrink/InnerUsageMarker.java
index b8ca801..6d77e81 100644
--- a/src/proguard/shrink/InnerUsageMarker.java
+++ b/src/proguard/shrink/InnerUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/InterfaceUsageMarker.java b/src/proguard/shrink/InterfaceUsageMarker.java
index 7599898..240838e 100644
--- a/src/proguard/shrink/InterfaceUsageMarker.java
+++ b/src/proguard/shrink/InterfaceUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/LocalVariableTypeUsageMarker.java b/src/proguard/shrink/LocalVariableTypeUsageMarker.java
new file mode 100644
index 0000000..573d8f6
--- /dev/null
+++ b/src/proguard/shrink/LocalVariableTypeUsageMarker.java
@@ -0,0 +1,178 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This AttributeVisitor recursively marks all information that points to used
+ * classes, in the LocalVariableTable and LocalVariableTypeTable attributes that
+ * it visits.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTypeUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ ClassVisitor,
+ ConstantVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as a return parameters for several methods.
+ private boolean tableUsed;
+ private boolean variableInfoUsed;
+
+
+ /**
+ * Creates a new LocalVariableTypeUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public LocalVariableTypeUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Check and mark the individual entries.
+ tableUsed = false;
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Mark the table if any of the entries is marked.
+ if (tableUsed)
+ {
+ usageMarker.markAsUsed(localVariableTableAttribute);
+
+ markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Check and mark the individual entries.
+ tableUsed = false;
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Mark the table if any of the entries is marked.
+ if (tableUsed)
+ {
+ usageMarker.markAsUsed(localVariableTypeTableAttribute);
+
+ markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Only keep the local variable info if all of its classes are used.
+ variableInfoUsed = true;
+ localVariableInfo.referencedClassAccept(this);
+
+ if (variableInfoUsed)
+ {
+ // We got a positive used flag, so the local variable info is useful.
+ usageMarker.markAsUsed(localVariableInfo);
+
+ markConstant(clazz, localVariableInfo.u2nameIndex);
+ markConstant(clazz, localVariableInfo.u2descriptorIndex);
+
+ tableUsed = true;
+ }
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Only keep the local variable info if all of its classes are used.
+ variableInfoUsed = true;
+ localVariableTypeInfo.referencedClassesAccept(this);
+
+ if (variableInfoUsed)
+ {
+ // We got a positive used flag, so the local variable info is useful.
+ usageMarker.markAsUsed(localVariableTypeInfo);
+
+ markConstant(clazz, localVariableTypeInfo.u2nameIndex);
+ markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
+
+ tableUsed = true;
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Don't keep the local variable info if one of its classes is not used.
+ if (!usageMarker.isUsed(programClass))
+ {
+ variableInfoUsed = false;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ usageMarker.markAsUsed(constant);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+}
diff --git a/src/proguard/shrink/ShortestUsageMark.java b/src/proguard/shrink/ShortestUsageMark.java
index 757c713..e2df7fa 100644
--- a/src/proguard/shrink/ShortestUsageMark.java
+++ b/src/proguard/shrink/ShortestUsageMark.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/ShortestUsageMarker.java b/src/proguard/shrink/ShortestUsageMarker.java
index da8fad3..1ac6e7e 100644
--- a/src/proguard/shrink/ShortestUsageMarker.java
+++ b/src/proguard/shrink/ShortestUsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/ShortestUsagePrinter.java b/src/proguard/shrink/ShortestUsagePrinter.java
index db42fe1..8740b9f 100644
--- a/src/proguard/shrink/ShortestUsagePrinter.java
+++ b/src/proguard/shrink/ShortestUsagePrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,7 +21,9 @@
package proguard.shrink;
import proguard.classfile.*;
-import proguard.classfile.util.ClassUtil;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
import java.io.PrintStream;
@@ -36,8 +38,10 @@ import java.io.PrintStream;
* @author Eric Lafortune
*/
public class ShortestUsagePrinter
+extends SimplifiedVisitor
implements ClassVisitor,
- MemberVisitor
+ MemberVisitor,
+ AttributeVisitor
{
private final ShortestUsageMarker shortestUsageMarker;
private final boolean verbose;
@@ -117,8 +121,7 @@ implements ClassVisitor,
ps.println(ClassUtil.externalClassName(programClass.getName()) +
(verbose ?
": " + ClassUtil.externalFullFieldDescription(0, name, type):
- "." + name) +
- lineNumberRange(programClass, programField));
+ "." + name));
// Print the reason for keeping this method.
printReason(programField);
@@ -131,11 +134,12 @@ implements ClassVisitor,
String name = programMethod.getName(programClass);
String type = programMethod.getDescriptor(programClass);
- ps.println(ClassUtil.externalClassName(programClass.getName()) +
- (verbose ?
- ": " + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, name, type):
- "." + name) +
- lineNumberRange(programClass, programMethod));
+ ps.print(ClassUtil.externalClassName(programClass.getName()) +
+ (verbose ?
+ ": " + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, name, type):
+ "." + name));
+ programMethod.attributesAccept(programClass, this);
+ ps.println();
// Print the reason for keeping this method.
printReason(programMethod);
@@ -174,6 +178,25 @@ implements ClassVisitor,
}
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ ps.print(" (" +
+ lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ")");
+ }
+
+
// Small utility methods.
private void printReason(VisitorAccepter visitorAccepter)
@@ -194,17 +217,4 @@ implements ClassVisitor,
ps.println(" is not being kept.\n");
}
}
-
-
- /**
- * Returns the line number range of the given class member, followed by a
- * colon, or just an empty String if no range is available.
- */
- private static String lineNumberRange(ProgramClass programClass, ProgramMember programMember)
- {
- String range = programMember.getLineNumberRange(programClass);
- return range != null ?
- (" (" + range + ")") :
- "";
- }
}
diff --git a/src/proguard/shrink/Shrinker.java b/src/proguard/shrink/Shrinker.java
index edbc27f..0472c3d 100644
--- a/src/proguard/shrink/Shrinker.java
+++ b/src/proguard/shrink/Shrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,7 +21,7 @@
package proguard.shrink;
import proguard.*;
-import proguard.classfile.ClassPool;
+import proguard.classfile.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.visitor.*;
@@ -67,9 +67,20 @@ public class Shrinker
new UsageMarker() :
new ShortestUsageMarker();
+ // Automatically mark the parameterless constructors of seed classes,
+ // mainly for convenience and for backward compatibility.
+ ClassVisitor classUsageMarker =
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ usageMarker,
+ new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_INIT,
+ usageMarker)
+ });
+
ClassPoolVisitor classPoolvisitor =
ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
- usageMarker,
+ classUsageMarker,
usageMarker,
true,
false,
@@ -89,6 +100,8 @@ public class Shrinker
{
new InnerUsageMarker(usageMarker),
new AnnotationUsageMarker(usageMarker),
+ new SignatureUsageMarker(usageMarker),
+ new LocalVariableTypeUsageMarker(usageMarker)
}))));
// Should we explain ourselves?
@@ -113,15 +126,21 @@ public class Shrinker
if (configuration.printUsage != null)
{
- PrintStream ps = isFile(configuration.printUsage) ?
- new PrintStream(new BufferedOutputStream(new FileOutputStream(configuration.printUsage))) :
- System.out;
+ PrintStream ps =
+ configuration.printUsage == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(configuration.printUsage)));
// Print out items that will be removed.
programClassPool.classesAcceptAlphabetically(
new UsagePrinter(usageMarker, true, ps));
- if (ps != System.out)
+ if (ps == System.out)
+ {
+ ps.flush();
+ }
+ else
{
ps.close();
}
@@ -157,14 +176,4 @@ public class Shrinker
return newProgramClassPool;
}
-
-
- /**
- * Returns whether the given file is actually a file, or just a placeholder
- * for the standard output.
- */
- private boolean isFile(File file)
- {
- return file.getPath().length() > 0;
- }
}
diff --git a/src/proguard/shrink/SignatureUsageMarker.java b/src/proguard/shrink/SignatureUsageMarker.java
new file mode 100644
index 0000000..9c5cd4d
--- /dev/null
+++ b/src/proguard/shrink/SignatureUsageMarker.java
@@ -0,0 +1,117 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This AttributeVisitor recursively marks all Signature attributes that it
+ * visits and that point to used classes.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class SignatureUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ ClassVisitor,
+ ConstantVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as a return parameters for several methods.
+ private boolean attributeUsed;
+
+
+ /**
+ * Creates a new SignatureUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public SignatureUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Only keep the signature if all of its classes are used.
+ attributeUsed = true;
+ signatureAttribute.referencedClassesAccept(this);
+
+ if (attributeUsed)
+ {
+ // We got a positive used flag, so the signature is useful.
+ usageMarker.markAsUsed(signatureAttribute);
+
+ markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ markConstant(clazz, signatureAttribute.u2signatureIndex);
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Don't keep the signature if one of its classes is not used.
+ if (!usageMarker.isUsed(programClass))
+ {
+ attributeUsed = false;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ usageMarker.markAsUsed(constant);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+}
diff --git a/src/proguard/shrink/UsageMarker.java b/src/proguard/shrink/UsageMarker.java
index e913046..51210b5 100644
--- a/src/proguard/shrink/UsageMarker.java
+++ b/src/proguard/shrink/UsageMarker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -27,10 +27,10 @@ import proguard.classfile.attribute.preverification.*;
import proguard.classfile.attribute.preverification.visitor.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.constant.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
@@ -65,18 +65,15 @@ implements ClassVisitor,
private static final Object USED = new Object();
- private final MyInterfaceUsageMarker interfaceUsageMarker = new MyInterfaceUsageMarker();
- private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker = new MyPossiblyUsedMemberUsageMarker();
-// private ClassVisitor dynamicClassMarker =
-// new MultiClassVisitor(
-// new ClassVisitor[]
-// {
-// this,
-// new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,
-// ClassConstants.INTERNAL_METHOD_TYPE_INIT,
-// this)
-// });
-
+ private final MyInterfaceUsageMarker interfaceUsageMarker = new MyInterfaceUsageMarker();
+ private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker = new MyPossiblyUsedMemberUsageMarker();
+ private final MemberVisitor nonEmptyMethodUsageMarker = new AllAttributeVisitor(
+ new MyNonEmptyMethodUsageMarker());
+ private final ConstantVisitor parameterlessConstructorMarker = new ConstantTagFilter(new int[] { ClassConstants.CONSTANT_String, ClassConstants.CONSTANT_Class },
+ new ReferencedClassVisitor(
+ new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_INIT,
+ this)));
// Implementations for ClassVisitor.
@@ -107,15 +104,10 @@ implements ClassVisitor,
programClass.hierarchyAccept(false, false, true, false,
interfaceUsageMarker);
- // Explicitly mark the <clinit> method.
+ // Explicitly mark the <clinit> method, if it's not empty.
programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
- this);
-
- // Explicitly mark the parameterless <init> method.
- programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT,
- ClassConstants.INTERNAL_METHOD_TYPE_INIT,
- this);
+ nonEmptyMethodUsageMarker);
// Process all class members that have already been marked as possibly used.
programClass.fieldsAccept(possiblyUsedMemberUsageMarker);
@@ -187,6 +179,10 @@ implements ClassVisitor,
}
+ /**
+ * This MemberVisitor marks ProgramField and ProgramMethod objects that
+ * have already been marked as possibly used.
+ */
private class MyPossiblyUsedMemberUsageMarker
extends SimplifiedVisitor
implements MemberVisitor
@@ -230,6 +226,28 @@ implements ClassVisitor,
}
+ /**
+ * This AttributeVisitor marks ProgramMethod objects of non-empty methods.
+ */
+ private class MyNonEmptyMethodUsageMarker
+ extends SimplifiedVisitor
+ implements AttributeVisitor
+ {
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (codeAttribute.u4codeLength > 1)
+ {
+ method.accept(clazz, UsageMarker.this);
+ }
+ }
+ }
+
+
// Implementations for MemberVisitor.
public void visitProgramField(ProgramClass programClass, ProgramField programField)
@@ -335,15 +353,26 @@ implements ClassVisitor,
*/
protected void markMethodHierarchy(Clazz clazz, Method method)
{
- if ((method.getAccessFlags() &
+ int accessFlags = method.getAccessFlags();
+ if ((accessFlags &
(ClassConstants.INTERNAL_ACC_PRIVATE |
- ClassConstants.INTERNAL_ACC_STATIC)) == 0)
+ ClassConstants.INTERNAL_ACC_STATIC)) == 0 &&
+ !ClassUtil.isInitializer(method.getName(clazz)))
{
+ // We can skip private and static methods in the hierarchy, and
+ // also abstract methods, unless they might widen a current
+ // non-public access.
+ int requiredUnsetAccessFlags =
+ ClassConstants.INTERNAL_ACC_PRIVATE |
+ ClassConstants.INTERNAL_ACC_STATIC |
+ ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0 ? 0 :
+ ClassConstants.INTERNAL_ACC_ABSTRACT);
+
clazz.accept(new ConcreteClassDownTraveler(
new ClassHierarchyTraveler(true, true, false, true,
new NamedMethodVisitor(method.getName(clazz),
method.getDescriptor(clazz),
- new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT,
+ new MemberAccessFilter(0, requiredUnsetAccessFlags,
this)))));
}
}
@@ -395,11 +424,7 @@ implements ClassVisitor,
markConstant(clazz, stringConstant.u2stringIndex);
- // Mark the referenced class and its parameterless constructor,
- // if the string is being used in a Class.forName construct.
- //stringConstant.referencedClassAccept(dynamicClassMarker);
-
- // Mark the referenced class or class member, if any.
+ // Mark the referenced class and class member, if any.
stringConstant.referencedClassAccept(this);
stringConstant.referencedMemberAccept(this);
}
@@ -415,6 +440,31 @@ implements ClassVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ if (shouldBeMarkedAsUsed(invokeDynamicConstant))
+ {
+ markAsUsed(invokeDynamicConstant);
+
+ markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
+
+ // Mark the bootstrap methods attribute.
+ clazz.attributesAccept(new MyBootStrapMethodUsageMarker(invokeDynamicConstant.u2bootstrapMethodAttributeIndex));
+ }
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ if (shouldBeMarkedAsUsed(methodHandleConstant))
+ {
+ markAsUsed(methodHandleConstant);
+
+ markConstant(clazz, methodHandleConstant.u2referenceIndex);
+ }
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
if (shouldBeMarkedAsUsed(refConstant))
@@ -450,6 +500,17 @@ implements ClassVisitor,
}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ if (shouldBeMarkedAsUsed(methodTypeConstant))
+ {
+ markAsUsed(methodTypeConstant);
+
+ markConstant(clazz, methodTypeConstant.u2descriptorIndex);
+ }
+ }
+
+
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
if (shouldBeMarkedAsUsed(nameAndTypeConstant))
@@ -462,6 +523,58 @@ implements ClassVisitor,
}
+ /**
+ * This AttributeVisitor marks the bootstrap methods attributes, their
+ * method entries, their method handles, and their arguments.
+ */
+ private class MyBootStrapMethodUsageMarker
+ extends SimplifiedVisitor
+ implements AttributeVisitor,
+ BootstrapMethodInfoVisitor
+ {
+ private int bootstrapMethodIndex;
+
+
+ private MyBootStrapMethodUsageMarker(int bootstrapMethodIndex)
+ {
+ this.bootstrapMethodIndex = bootstrapMethodIndex;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (shouldBeMarkedAsUsed(bootstrapMethodsAttribute))
+ {
+ markAsUsed(bootstrapMethodsAttribute);
+
+ markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
+ bootstrapMethodIndex,
+ this);
+ }
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ markAsUsed(bootstrapMethodInfo);
+
+ markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Mark the constant pool entries referenced by the arguments.
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, UsageMarker.this);
+ }
+ }
+
+
// Implementations for AttributeVisitor.
// Note that attributes are typically only referenced once, so we don't
// test if they have been marked already.
@@ -475,6 +588,13 @@ implements ClassVisitor,
}
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Don't mark the attribute and its name here. We may mark it in
+ // MyBootStrapMethodsAttributeUsageMarker.
+ }
+
+
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
markAsUsed(sourceFileAttribute);
@@ -538,10 +658,12 @@ implements ClassVisitor,
public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
{
- markAsUsed(signatureAttribute);
-
- markConstant(clazz, signatureAttribute.u2attributeNameIndex);
- markConstant(clazz, signatureAttribute.u2signatureIndex);
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in SignatureUsageMarker.
+ //markAsUsed(signatureAttribute);
+ //
+ //markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ //markConstant(clazz, signatureAttribute.u2signatureIndex);
}
@@ -611,23 +733,27 @@ implements ClassVisitor,
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
{
- markAsUsed(localVariableTableAttribute);
-
- markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
-
- // Mark the constant pool entries referenced by the local variables.
- localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in LocalVariableTypeUsageMarker.
+ //markAsUsed(localVariableTableAttribute);
+ //
+ //markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the local variables.
+ //localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
}
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
{
- markAsUsed(localVariableTypeTableAttribute);
-
- markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
-
- // Mark the constant pool entries referenced by the local variable types.
- localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in LocalVariableTypeUsageMarker.
+ //markAsUsed(localVariableTypeTableAttribute);
+ //
+ //markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the local variable types.
+ //localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
}
@@ -635,12 +761,12 @@ implements ClassVisitor,
{
// Don't mark the attribute and its contents yet. We may mark them later,
// in AnnotationUsageMarker.
-// markAsUsed(annotationsAttribute);
-//
-// markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
-//
-// // Mark the constant pool entries referenced by the annotations.
-// annotationsAttribute.annotationsAccept(clazz, this);
+ //markAsUsed(annotationsAttribute);
+ //
+ //markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the annotations.
+ //annotationsAttribute.annotationsAccept(clazz, this);
}
@@ -648,12 +774,12 @@ implements ClassVisitor,
{
// Don't mark the attribute and its contents yet. We may mark them later,
// in AnnotationUsageMarker.
-// markAsUsed(parameterAnnotationsAttribute);
-//
-// markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
-//
-// // Mark the constant pool entries referenced by the annotations.
-// parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ //markAsUsed(parameterAnnotationsAttribute);
+ //
+ //markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the annotations.
+ //parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
}
@@ -837,6 +963,12 @@ implements ClassVisitor,
public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
{
markConstant(clazz, constantInstruction.constantIndex);
+
+ // Also mark the parameterless constructor of the class, in case the
+ // string constant or class constant is being used in a Class.forName
+ // or a .class construct.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ parameterlessConstructorMarker);
}
@@ -915,6 +1047,6 @@ implements ClassVisitor,
*/
private void markConstant(Clazz clazz, int index)
{
- clazz.constantPoolEntryAccept(index, this);
+ clazz.constantPoolEntryAccept(index, this);
}
}
diff --git a/src/proguard/shrink/UsagePrinter.java b/src/proguard/shrink/UsagePrinter.java
index 294b9e1..69df7fa 100644
--- a/src/proguard/shrink/UsagePrinter.java
+++ b/src/proguard/shrink/UsagePrinter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,8 @@
package proguard.shrink;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;
@@ -38,7 +40,8 @@ import java.io.PrintStream;
public class UsagePrinter
extends SimplifiedVisitor
implements ClassVisitor,
- MemberVisitor
+ MemberVisitor,
+ AttributeVisitor
{
private final UsageMarker usageMarker;
private final boolean printUnusedItems;
@@ -121,7 +124,6 @@ implements ClassVisitor,
printClassNameHeader();
ps.println(" " +
- lineNumberRange(programClass, programField) +
ClassUtil.externalFullFieldDescription(
programField.getAccessFlags(),
programField.getName(programClass),
@@ -136,9 +138,10 @@ implements ClassVisitor,
{
printClassNameHeader();
- ps.println(" " +
- lineNumberRange(programClass, programMethod) +
- ClassUtil.externalFullMethodDescription(
+ ps.print("====");
+ ps.print(" ");
+ programMethod.attributesAccept(programClass, this);
+ ps.println(ClassUtil.externalFullMethodDescription(
programClass.getName(),
programMethod.getAccessFlags(),
programMethod.getName(programClass),
@@ -147,6 +150,24 @@ implements ClassVisitor,
}
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ ps.print(lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ":");
+ }
+
+
// Small utility methods.
/**
@@ -161,17 +182,4 @@ implements ClassVisitor,
className = null;
}
}
-
-
- /**
- * Returns the line number range of the given class member, followed by a
- * colon, or just an empty String if no range is available.
- */
- private static String lineNumberRange(ProgramClass programClass, ProgramMember programMember)
- {
- String range = programMember.getLineNumberRange(programClass);
- return range != null ?
- (range + ":") :
- "";
- }
}
diff --git a/src/proguard/shrink/UsedClassFilter.java b/src/proguard/shrink/UsedClassFilter.java
index ec180bd..7630b0b 100644
--- a/src/proguard/shrink/UsedClassFilter.java
+++ b/src/proguard/shrink/UsedClassFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/UsedMemberFilter.java b/src/proguard/shrink/UsedMemberFilter.java
index 755cfd1..f1a9c75 100644
--- a/src/proguard/shrink/UsedMemberFilter.java
+++ b/src/proguard/shrink/UsedMemberFilter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -39,7 +39,7 @@ implements MemberVisitor
/**
- * Creates a new UsedClassFilter.
+ * Creates a new UsedMemberFilter.
* @param usageMarker the usage marker that is used to mark the classes
* and class members.
* @param memberVisitor the member visitor to which the visiting will be
diff --git a/src/proguard/util/AndMatcher.java b/src/proguard/util/AndMatcher.java
index 94a37e5..1aa3726 100644
--- a/src/proguard/util/AndMatcher.java
+++ b/src/proguard/util/AndMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ArrayUtil.java b/src/proguard/util/ArrayUtil.java
new file mode 100644
index 0000000..8584700
--- /dev/null
+++ b/src/proguard/util/ArrayUtil.java
@@ -0,0 +1,960 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+
+/**
+ * This class contains utility methods operating on arrays.
+ */
+public class ArrayUtil
+{
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(byte[] array1, byte[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(short[] array1, short[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(int[] array1, int[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(Object[] array1, Object[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (!array1[index].equals(array2[index]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(byte[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(short[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(int[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(Object[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index].hashCode();
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(byte[] array1, int size1,
+ byte[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(short[] array1, int size1,
+ short[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(int[] array1, int size1,
+ int[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(Comparable[] array1, int size1,
+ Comparable[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ int comparison = ObjectUtil.compare(array1[index], array2[index]);
+ if (comparison != 0)
+ {
+ return comparison;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static boolean[] extendArray(boolean[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ boolean[] newArray = new boolean[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static boolean[] ensureArraySize(boolean[] array,
+ int size,
+ boolean initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new boolean[size];
+
+ if (initialValue)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] add(byte[] array, int size, byte element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] insert(byte[] array, int size, int index, byte element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(byte[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] extendArray(byte[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ byte[] newArray = new byte[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static byte[] ensureArraySize(byte[] array,
+ int size,
+ byte initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new byte[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] add(short[] array, int size, short element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] insert(short[] array, int size, int index, short element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(short[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] extendArray(short[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ short[] newArray = new short[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static short[] ensureArraySize(short[] array,
+ int size,
+ short initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new short[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] add(int[] array, int size, int element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] insert(int[] array, int size, int index, int element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(int[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] extendArray(int[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ int[] newArray = new int[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static int[] ensureArraySize(int[] array,
+ int size,
+ int initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new int[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] add(long[] array, int size, long element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] insert(long[] array, int size, int index, long element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(long[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] extendArray(long[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ long[] newArray = new long[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static long[] ensureArraySize(long[] array,
+ int size,
+ long initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new long[size];
+
+ if (initialValue != 0L)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] add(Object[] array, int size, Object element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] insert(Object[] array, int size, int index, Object element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(Object[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = null;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] extendArray(Object[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ Object[] newArray = (Object[])Array.newInstance(array.getClass().getComponentType(), size);
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static Object[] ensureArraySize(Object[] array,
+ int size,
+ Object initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = (Object[])Array.newInstance(array.getClass().getComponentType(), size);
+
+ if (initialValue != null)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+}
diff --git a/src/proguard/util/ClassNameParser.java b/src/proguard/util/ClassNameParser.java
index ee972f0..22a0703 100644
--- a/src/proguard/util/ClassNameParser.java
+++ b/src/proguard/util/ClassNameParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ConstantMatcher.java b/src/proguard/util/ConstantMatcher.java
index 1764caa..8c0f1e1 100644
--- a/src/proguard/util/ConstantMatcher.java
+++ b/src/proguard/util/ConstantMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/EmptyStringMatcher.java b/src/proguard/util/EmptyStringMatcher.java
index 543f446..f07c666 100644
--- a/src/proguard/util/EmptyStringMatcher.java
+++ b/src/proguard/util/EmptyStringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ExtensionMatcher.java b/src/proguard/util/ExtensionMatcher.java
index 5a9f658..eeb627a 100644
--- a/src/proguard/util/ExtensionMatcher.java
+++ b/src/proguard/util/ExtensionMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/FileNameParser.java b/src/proguard/util/FileNameParser.java
index 913f22d..9ec6d22 100644
--- a/src/proguard/util/FileNameParser.java
+++ b/src/proguard/util/FileNameParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/FixedStringMatcher.java b/src/proguard/util/FixedStringMatcher.java
index c1eb3f4..2f02271 100644
--- a/src/proguard/util/FixedStringMatcher.java
+++ b/src/proguard/util/FixedStringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ListMatcher.java b/src/proguard/util/ListMatcher.java
index b2559c8..e07bff0 100644
--- a/src/proguard/util/ListMatcher.java
+++ b/src/proguard/util/ListMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ListParser.java b/src/proguard/util/ListParser.java
index cec803b..b3b4518 100644
--- a/src/proguard/util/ListParser.java
+++ b/src/proguard/util/ListParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -68,7 +68,7 @@ public class ListParser implements StringParser
// Loop over all simple regular expressions, backward, creating a
// linked list of matchers.
- for (int index = regularExpressions.size()-1; index >=0; index--)
+ for (int index = regularExpressions.size()-1; index >= 0; index--)
{
String regularExpression = (String)regularExpressions.get(index);
diff --git a/src/proguard/util/ListUtil.java b/src/proguard/util/ListUtil.java
index 570dbe8..18bdce2 100644
--- a/src/proguard/util/ListUtil.java
+++ b/src/proguard/util/ListUtil.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -34,7 +34,7 @@ public class ListUtil
/**
* Creates a comma-separated String from the given List of String objects.
*/
- public static String commaSeparatedString(List list)
+ public static String commaSeparatedString(List list, boolean quoteStrings)
{
if (list == null)
{
@@ -50,7 +50,14 @@ public class ListUtil
buffer.append(',');
}
- buffer.append(quotedString((String)list.get(index)));
+ String string = (String)list.get(index);
+
+ if (quoteStrings)
+ {
+ string = quotedString(string);
+ }
+
+ buffer.append(string);
}
return buffer.toString();
@@ -165,7 +172,7 @@ public class ListUtil
System.out.println("["+list.get(index)+"]");
}
- String string = commaSeparatedString(list);
+ String string = commaSeparatedString(list, true);
System.out.println("Resulting string: ["+string+"]");
}
diff --git a/src/proguard/util/NameParser.java b/src/proguard/util/NameParser.java
index e311fbf..f25d52e 100644
--- a/src/proguard/util/NameParser.java
+++ b/src/proguard/util/NameParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/NotMatcher.java b/src/proguard/util/NotMatcher.java
index f2a9a51..af539d0 100644
--- a/src/proguard/util/NotMatcher.java
+++ b/src/proguard/util/NotMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ObjectUtil.java b/src/proguard/util/ObjectUtil.java
new file mode 100644
index 0000000..c5de36a
--- /dev/null
+++ b/src/proguard/util/ObjectUtil.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package proguard.util;
+
+/**
+ * This class contains utility methods operating on objects.
+ */
+public class ObjectUtil
+{
+ /**
+ * Returns whether the given objects are the same.
+ * @param object1 the first object, may be null.
+ * @param object2 the second object, may be null.
+ * @return whether the objects are the same.
+ */
+ public static boolean equal(Object object1, Object object2)
+ {
+ return object1 == null ?
+ object2 == null :
+ object1.equals(object2);
+ }
+
+
+ /**
+ * Returns the hash code of the given object, or 0 if it is null.
+ * @param object the object, may be null.
+ * @return the hash code.
+ */
+ public static int hashCode(Object object)
+ {
+ return object == null ? 0 : object.hashCode();
+ }
+
+
+ /**
+ * Returns a comparison of the two given objects.
+ * @param object1 the first object, may be null.
+ * @param object2 the second object, may be null.
+ * @return -1, 0, or 1.
+ * @see Comparable#compareTo(Object)
+ */
+ public static int compare(Comparable object1, Comparable object2)
+ {
+ return object1 == null ?
+ object2 == null ? 0 : -1 :
+ object2 == null ? 1 : object1.compareTo(object2);
+ }
+}
diff --git a/src/proguard/util/OrMatcher.java b/src/proguard/util/OrMatcher.java
index 097c6c6..7ad85c4 100644
--- a/src/proguard/util/OrMatcher.java
+++ b/src/proguard/util/OrMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/SettableMatcher.java b/src/proguard/util/SettableMatcher.java
index 9557f62..8650ccc 100644
--- a/src/proguard/util/SettableMatcher.java
+++ b/src/proguard/util/SettableMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/StringMatcher.java b/src/proguard/util/StringMatcher.java
index bd66dcc..146dbfc 100644
--- a/src/proguard/util/StringMatcher.java
+++ b/src/proguard/util/StringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/StringParser.java b/src/proguard/util/StringParser.java
index 29f4f16..39d04d5 100644
--- a/src/proguard/util/StringParser.java
+++ b/src/proguard/util/StringParser.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/VariableStringMatcher.java b/src/proguard/util/VariableStringMatcher.java
index 1e41323..5a07c2a 100644
--- a/src/proguard/util/VariableStringMatcher.java
+++ b/src/proguard/util/VariableStringMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/wtk/ProGuardObfuscator.java b/src/proguard/wtk/ProGuardObfuscator.java
index 4618437..b6f9ace 100644
--- a/src/proguard/wtk/ProGuardObfuscator.java
+++ b/src/proguard/wtk/ProGuardObfuscator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -71,7 +71,8 @@ public class ProGuardObfuscator implements Obfuscator
Configuration configuration = new Configuration();
// Parse the default configuration file.
- ConfigurationParser parser = new ConfigurationParser(this.getClass().getResource(DEFAULT_CONFIGURATION));
+ ConfigurationParser parser = new ConfigurationParser(this.getClass().getResource(DEFAULT_CONFIGURATION),
+ System.getProperties());
try
{